class c_file {
private:
FILE *_c_file;
buffer _buffer; // Buffer object. Handles a surprising amount of underlying logic.
std::string _file;
uint32 _write_from; // What's our real position? this is the start of the current _buffer.
uint32 _size; // What's the size of our file?
uint32 _valid; // Are we invalid for some reason?
uint32 _open; // Is our file open?
uint32 _flush_needed; // How much we've written to _buffer since our last flush()
uint32 _file_buffer_start; // "Virtual" position (where in the file the _buffer is located)
// Opening attributes
uint32 _readonly;
uint32 _append;
uint32 _binary;
uint32 _create;
uint32 _write;
uint32 _read_fillbuf(); // Fills the rest of the buffer with a read
void _do_seek_needed(); // The macro was killing us! To DEATH!
c_file(const c_file& other ); // non construction-copyable
c_file& operator=( const c_file& ); // non copyable
public:
explicit c_file();
~c_file();
uint32 open(fattribute const ¶ms); // Opens
uint32 position() { return _file_buffer_start + _buffer.index(); }
uint32 close(); // Closes
uint32 flush();
uint32 set_buffer_size(uint32 size);
uint32 is_valid() { return _valid; } // C files are *only* valid when they are open. They can become invalid when certain functions fail like open() (because something is already open)
uint32 is_open() { return _open; } //
uint32 size() { return _size; }
uint32 seek(const uint32 whereto);
uint32 write(const void *buf, const uint32 length); // Writes
uint32 read(void *buf, const uint32 length); // Reads
// Read a line...The file should still be opened as binary! This is CR/LF neutral.
// NOTE THAT IT RETURNS maxlen IF IT FAILS (since the final byte will always be a c-str terminating NULL. 500 will read 499 bytes max.)
uint32 readline(uint8 *dest,uint32 maxlen);
// Write a line. Um, if it fails, well, you know.
uint32 writeline(std::string& line);
// Check if we're EOF
uint32 eof() { if (!_valid) return 2; if (_file_buffer_start + _buffer.index() >= _size) return 1; else return 0; }
};