2023-01-29 22:27:48 -05:00
|
|
|
/*
|
|
|
|
* Created by Brett on 29/01/23.
|
|
|
|
* Licensed under GNU General Public License V3.0
|
|
|
|
* See LICENSE file for license detail
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef BLT_FILESYSTEM_H
|
|
|
|
#define BLT_FILESYSTEM_H
|
|
|
|
|
|
|
|
#include <fstream>
|
|
|
|
#include <ios>
|
2023-02-08 13:40:28 -05:00
|
|
|
#include "memory.h"
|
2023-01-29 22:27:48 -05:00
|
|
|
|
2023-08-25 03:41:43 -04:00
|
|
|
namespace blt::fs
|
|
|
|
{
|
2023-01-29 22:27:48 -05:00
|
|
|
|
|
|
|
/**
|
|
|
|
* 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.
|
|
|
|
*/
|
2023-08-25 03:41:43 -04:00
|
|
|
class block_reader
|
|
|
|
{
|
2023-01-29 22:27:48 -05:00
|
|
|
protected:
|
2023-01-29 23:36:42 -05:00
|
|
|
// 32768 block size seems the fastest on my system
|
2023-01-29 22:27:48 -05:00
|
|
|
unsigned long m_bufferSize;
|
|
|
|
public:
|
2023-08-25 03:41:43 -04:00
|
|
|
explicit block_reader(size_t bufferSize): m_bufferSize(bufferSize)
|
|
|
|
{}
|
2023-01-29 22:27:48 -05:00
|
|
|
|
|
|
|
/**
|
|
|
|
* 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;
|
2023-08-25 03:41:43 -04:00
|
|
|
|
2023-08-31 21:47:32 -04:00
|
|
|
virtual size_t gcount() = 0;
|
2023-08-25 03:41:43 -04:00
|
|
|
|
|
|
|
virtual char get()
|
|
|
|
{
|
2023-07-26 13:09:41 -04:00
|
|
|
char c[1];
|
|
|
|
read(c, 1);
|
|
|
|
return c[0];
|
|
|
|
}
|
2023-01-29 22:27:48 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* A buffered block writer without a definite backend implementation. Exactly the same as a block_reader but for writing to the filesystem.
|
|
|
|
*/
|
2023-08-25 03:41:43 -04:00
|
|
|
class block_writer
|
|
|
|
{
|
2023-01-29 22:27:48 -05:00
|
|
|
protected:
|
|
|
|
unsigned long m_bufferSize;
|
|
|
|
public:
|
2023-08-25 03:41:43 -04:00
|
|
|
explicit block_writer(unsigned long bufferSize): m_bufferSize(bufferSize)
|
|
|
|
{}
|
2023-01-29 22:27:48 -05:00
|
|
|
|
|
|
|
/**
|
|
|
|
* 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;
|
2023-08-25 03:41:43 -04:00
|
|
|
|
|
|
|
virtual int put(char c)
|
|
|
|
{
|
2023-07-26 13:09:41 -04:00
|
|
|
char a[1];
|
|
|
|
a[0] = c;
|
|
|
|
return write(a, 1);
|
|
|
|
}
|
2023-01-29 22:27:48 -05:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Ensures that the internal buffer is written to the filesystem.
|
|
|
|
*/
|
|
|
|
virtual void flush() = 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* fstream implementation of the block reader.
|
|
|
|
*/
|
2023-08-25 03:41:43 -04:00
|
|
|
class fstream_block_reader : public block_reader
|
|
|
|
{
|
2023-01-29 22:27:48 -05:00
|
|
|
private:
|
|
|
|
std::fstream& m_stream;
|
2023-07-28 01:35:01 -04:00
|
|
|
char* m_buffer = nullptr;
|
2023-01-29 22:27:48 -05:00
|
|
|
size_t readIndex = 0;
|
|
|
|
public:
|
2023-07-28 01:35:01 -04:00
|
|
|
explicit fstream_block_reader(std::fstream& stream, size_t bufferSize = 131072);
|
2023-01-29 22:27:48 -05:00
|
|
|
|
|
|
|
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;
|
|
|
|
|
2023-09-13 16:49:56 -04:00
|
|
|
size_t gcount() final
|
|
|
|
{
|
2023-08-25 03:41:43 -04:00
|
|
|
return m_stream.gcount();
|
|
|
|
}
|
|
|
|
|
|
|
|
~fstream_block_reader()
|
|
|
|
{
|
2023-01-29 22:27:48 -05:00
|
|
|
delete[] m_buffer;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2023-08-25 03:41:43 -04:00
|
|
|
class fstream_block_writer : public block_writer
|
|
|
|
{
|
2023-01-29 22:27:48 -05:00
|
|
|
private:
|
|
|
|
std::fstream& m_stream;
|
|
|
|
char* m_buffer;
|
|
|
|
size_t writeIndex = 0;
|
2023-08-25 03:41:43 -04:00
|
|
|
|
2023-07-27 01:47:11 -04:00
|
|
|
void flush_internal();
|
2023-08-25 03:41:43 -04:00
|
|
|
|
2023-01-29 22:27:48 -05:00
|
|
|
public:
|
2023-07-27 01:47:11 -04:00
|
|
|
explicit fstream_block_writer(std::fstream& stream, size_t bufferSize = 131072):
|
2023-08-25 03:41:43 -04:00
|
|
|
block_writer(bufferSize), m_stream(stream), m_buffer(new char[bufferSize])
|
|
|
|
{}
|
2023-01-29 22:27:48 -05:00
|
|
|
|
|
|
|
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;
|
2023-08-25 03:41:43 -04:00
|
|
|
|
|
|
|
inline void flush() override
|
|
|
|
{
|
2023-07-27 01:47:11 -04:00
|
|
|
flush_internal();
|
|
|
|
}
|
2023-01-29 22:27:48 -05:00
|
|
|
|
2023-08-25 03:41:43 -04:00
|
|
|
~fstream_block_writer()
|
|
|
|
{
|
2023-07-27 01:47:11 -04:00
|
|
|
flush_internal();
|
2023-01-29 22:27:48 -05:00
|
|
|
delete[] m_buffer;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif //BLT_FILESYSTEM_H
|