#ifndef _BINARY_FILE_H #define _BINARY_FILE_H #include #include #include "byte_order.h" #include "file.h" enum TerminalType { TT_INT = 4, TT_BYTE = 1, TT_SHORT = 2 }; /** * Holds the compiled semantic-string. */ struct DataSemantics { DataSemantics() { totalSize = 0; chunks = NULL; quantifier = 1; isTerminal = false; numChunkNodes = 0; } ~DataSemantics() { delete[] chunks; } int totalSize; int quantifier; int numChunkNodes; bool isTerminal; union { int type; DataSemantics **chunks; }; }; typedef DataSemantics *pDataSemantics; class BinaryFile : public File { public: BinaryFile() : File( "" ), byteorder( NATIVE_BYTEORDER ) { /* nothing to be done */ } BinaryFile( const std::string& _file ) : File( _file ), byteorder( NATIVE_BYTEORDER ) { /* nothing to be done */ } BinaryFile( const BinaryFile& _file ) : File( _file.name() ), byteorder( _file.getByteorder() ) { /* nothing to be done */ } /** * Reads a chunk of data based on the _semantics string. The string contains * a description of how the bytes are laid out in the file. If you want * to read out a struct which looks like this * struct { * int magic; * short size; * float x, y, z; * }; * then the semantics string is "isf3". If you want to read 5 of these * chunks, just put the whole string into paranthesis. "(isf3)5". Nifty, isn't * it? */ void read( const char *_semantics, void* _buf, size_t& _bytesRead ); /** * The same as the read above, but with the ability to read multiple * chunks once. Very useful if you don't know how many chunks you're * going to read at compile time. */ void read( const char *_semantics, int _chunks, void* _buf, size_t& _bytesRead ); /** * Writes a chunk of data based on the _semantics string. The string contains * a description of how the bytes should be laid out in the file. Have a look * at the description to read(). */ void write( const char *_semantics, void* _buf, size_t& _bytesWritten ); inline void seekg( int _pos ) { fseek( handle(), _pos, SEEK_SET ); } /** * @brief Sets the byteorder of the file. The order affects all subsequent * calls to write() and read(). It it is not wise to change the order * in the middle of reading a file. You're totally on your own. */ inline void setByteorder( ByteOrder _order ) { byteorder = _order; } /** * Returns the file's byte-order. */ inline ByteOrder getByteorder() const { return byteorder; } private: pDataSemantics compileSemantics( const char *_semantics ); ByteOrder byteorder; }; #endif