/* * * Copyright (C) 2024 Brett Terpstra * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef BLT_FILESYSTEM_H #define BLT_FILESYSTEM_H #include #include namespace blt::fs { /** * A simple interface which provides a way of reading the next block of data from a resource. * The interface provides a single function "read" which will read a specified number of bytes into the buffer. * The implementation for this could be fstreams, zlib deflate, or any method filesystem access. * Reading of a large number of bytes ( > block size) is guaranteed to not significantly increase the read time and will likely result in a * direct passthrough to the underlying system. Small reads will be buffered, hence the name "block" reader. */ class block_reader { protected: // 32768 block size seems the fastest on my system unsigned long m_bufferSize; public: explicit block_reader(size_t bufferSize): m_bufferSize(bufferSize) {} /** * Reads bytes from the internal filesystem implementation * @param buffer buffer to copy the read bytes into * @param bytes number of bytes to read * @return status code. non-zero return codes indicates a failure has occurred. */ virtual int read(char* buffer, size_t bytes) = 0; virtual size_t gcount() = 0; virtual char get() { char c[1]; read(c, 1); return c[0]; } }; /** * A buffered block writer without a definite backend implementation. Exactly the same as a block_reader but for writing to the filesystem. */ class block_writer { protected: unsigned long m_bufferSize; public: explicit block_writer(unsigned long bufferSize): m_bufferSize(bufferSize) {} /** * Writes the bytes to the filesystem backend implementation * @param buffer bytes to write * @param bytes number of bytes to write * @return non-zero code if failure */ virtual int write(char* buffer, size_t bytes) = 0; virtual int put(char c) { char a[1]; a[0] = c; return write(a, 1); } /** * Ensures that the internal buffer is written to the filesystem. */ virtual void flush() = 0; }; /** * fstream implementation of the block reader. */ class fstream_block_reader : public block_reader { private: std::fstream& m_stream; char* m_buffer = nullptr; size_t readIndex = 0; public: explicit fstream_block_reader(std::fstream& stream, size_t bufferSize = 131072); explicit fstream_block_reader(fstream_block_reader& copy) = delete; explicit fstream_block_reader(fstream_block_reader&& move) = delete; fstream_block_reader& operator=(const fstream_block_reader& copy) = delete; fstream_block_reader& operator=(const fstream_block_reader&& move) = delete; int read(char* buffer, size_t bytes) override; size_t gcount() final { return m_stream.gcount(); } ~fstream_block_reader() { delete[] m_buffer; } }; class fstream_block_writer : public block_writer { private: std::fstream& m_stream; char* m_buffer; size_t writeIndex = 0; void flush_internal(); public: explicit fstream_block_writer(std::fstream& stream, size_t bufferSize = 131072): block_writer(bufferSize), m_stream(stream), m_buffer(new char[bufferSize]) {} explicit fstream_block_writer(fstream_block_writer& copy) = delete; explicit fstream_block_writer(fstream_block_writer&& move) = delete; fstream_block_writer& operator=(const fstream_block_writer& copy) = delete; fstream_block_writer& operator=(const fstream_block_writer&& move) = delete; int write(char* buffer, size_t bytes) override; inline void flush() override { flush_internal(); } ~fstream_block_writer() { flush_internal(); delete[] m_buffer; } }; } #endif //BLT_FILESYSTEM_H