Skip to content
FileIO.hpp 1.88 KiB
Newer Older
#pragma once

#include <cstddef>
#include <fstream>
#include <string>

#include "gsl/gsl"

#include "Util.hpp"
#include "state.hpp"

struct FileIO {
	static auto ReadHeader(std::istream& input) {
		std::size_t noCols{};
		std::size_t noRows{};
		input >> noCols >> noRows;
		if (noCols < 1 || noRows < 1)
			throw std::logic_error("File header corrupt");
		std::string dummy; // skip line break
		std::getline(input, dummy);
		const auto& headerSize = input.tellg();
		return Size{noCols, noRows};
	}

	static auto GetTileSize(Size globalSize, Size gridSize) {
		const auto& tileSizeCols = globalSize.Cols / gridSize.Cols;
		const auto& tileSizeRows = globalSize.Rows / gridSize.Rows;
		return Size{tileSizeCols, tileSizeRows};
	}

	static void StridedRead(std::istream& input, std::size_t inputChunkLength,
	                        std::size_t count, std::size_t inputStride,
	                        gsl::span<State> buf, std::size_t bufStride) {

		std::size_t writeOffset{0};
		for (size_t i{0}; i < count; ++i) {
			input.read(reinterpret_cast<char*>(buf.data()) + writeOffset,
			           inputChunkLength);
			input.seekg(inputStride - inputChunkLength, std::ios::cur);
			writeOffset += bufStride;
		}
	}

	static void ReadTile(std::istream& input, Size srcSize, Size gridSize,
	                      std::size_t rank, gsl::span<State> buf,
	                      std::size_t bufStride) {
		constexpr auto LF = 1; // linefeed chars

		const auto& tileSize = GetTileSize(srcSize, gridSize);

		const auto& tileX = rank % gridSize.Cols;
		const auto& tileY = rank / gridSize.Cols;

		// seek to the begin of the tile
		const auto& displacement =
		    (srcSize.Cols + LF) * (tileSize.Rows * tileY) +
		    (tileSize.Cols * tileX);
		input.seekg(displacement, std::ios::cur);

		const auto& tileStride = srcSize.Cols + LF;

		StridedRead(input, tileSize.Cols, tileSize.Rows, tileStride, buf,
		            bufStride);
	}
};