#pragma once #include "util/File.h" #include #include class block_dev { std::size_t m_block_size = 0; std::size_t m_block_count = 0; public: virtual ~block_dev() = default; std::size_t block_size() const { return m_block_size; } std::size_t block_count() const { return m_block_count; } std::size_t size() const { return block_size() * block_count(); } virtual std::size_t read(std::size_t blockIndex, void* data, std::size_t blockCount) = 0; virtual std::size_t write(std::size_t blockIndex, const void* data, std::size_t blockCount) = 0; protected: void set_block_info(std::size_t size, std::size_t count) { m_block_size = size; m_block_count = count; } }; class file_block_dev final : public block_dev { fs::file m_file; public: explicit file_block_dev(fs::file file, std::size_t blockSize = 2048) : m_file(std::move(file)) { set_block_info(blockSize, m_file.size() / blockSize); } std::size_t read(std::size_t blockIndex, void* data, std::size_t blockCount) override { auto result = m_file.read_at(block_size() * blockIndex, data, blockCount * block_size()); return result / block_size(); } std::size_t write(std::size_t blockIndex, const void* data, std::size_t blockCount) override { auto result = m_file.write_at(block_size() * blockIndex, data, blockCount * block_size()); return result / block_size(); } fs::file& file() { return m_file; } fs::file release() { return std::exchange(m_file, {}); } }; class file_view_block_dev final : public block_dev { const fs::file* m_file; public: explicit file_view_block_dev(const fs::file& file, std::size_t blockSize = 2048) : m_file(&file) { set_block_info(blockSize, m_file->size() / blockSize); } std::size_t read(std::size_t blockIndex, void* data, std::size_t blockCount) override { auto result = m_file->read_at(block_size() * blockIndex, data, blockCount * block_size()); return result / block_size(); } std::size_t write(std::size_t blockIndex, const void* data, std::size_t blockCount) override { auto result = m_file->write_at(block_size() * blockIndex, data, blockCount * block_size()); return result / block_size(); } };