#include "binary_file.h" #include #include int bytesize( const char _c ) { switch( _c) { case 'f': case 'i': return 4; case 'b': return 1; case 's': return 2; default: return 0; } } pDataSemantics BinaryFile::compileSemantics( const char *_semantics ) { const char *curr = _semantics; char *tmp = new char[strlen(_semantics)]; //Find out how many subchunks exist. pDataSemantics chunk = new DataSemantics(); bool terminated = false; int open = 0; while ( *curr ) { switch( *curr ) { case 'i': case 'f': case 'b': case 's': chunk->numChunkNodes++; break; case '(': terminated = false; chunk->numChunkNodes++; while ( *curr && terminated == false ) { if ( *curr == ')' ) terminated = true; curr++; } if ( !terminated ) { printf( "Syntax error: ')' is missing" ); delete chunk; return NULL; } break; default: break; } curr++; } //Compile the chunks... chunk->chunks = new pDataSemantics[chunk->numChunkNodes]; int currChunk = 0; curr = _semantics; while ( *curr ) { switch( *curr ) { case 'i': case 'f': case 'b': case 's': chunk->chunks[currChunk] = new DataSemantics(); chunk->chunks[currChunk]->isTerminal = true; chunk->chunks[currChunk]->type = bytesize( *curr ); chunk->chunks[currChunk]->totalSize = bytesize( *curr ); currChunk++; break; case '(': curr++; open = 0; memset( tmp, 0, strlen( _semantics ) ); char * cp = tmp; while ( *curr ) { if ( *curr == '(' ) open++; if ( *curr == ')' ) { if ( open ) open--; else break; } *cp = *curr; cp++; curr++; } *cp = '\0'; chunk->chunks[currChunk] = compileSemantics( tmp ); currChunk++; break; case ')': printf( "Syntax error: ')' shouldn't appear here\n" ); delete[] tmp; delete chunk; return NULL; break; default: int multiplier = 1, quantifier = 0; const char *start = curr; const char *end = curr; while ( isdigit( *end ) ) { end++; } for ( const char *d = end-1; d >=start; --d ) { quantifier+=multiplier*(*d-'0'); multiplier*=10; } if ( start == end ) { printf( "Syntax error: '%c' is not known.\n", *curr ); delete[] tmp; delete chunk; return NULL; } if ( currChunk ) { chunk->chunks[currChunk-1]->quantifier = quantifier; chunk->chunks[currChunk-1]->totalSize*= quantifier; } else { printf( "Syntax error: Quantifier without a preceding type\n" ); delete[] tmp; delete chunk; return NULL; } curr = end-1; break; } curr++; } for ( int i = 0; i < chunk->numChunkNodes; ++i ) { chunk->totalSize+= chunk->chunks[i]->totalSize; } delete[] tmp; return chunk; } void convert_data( pDataSemantics _comp, void *_data ) { char *ptr = (char*)_data; short *sptr; int *iptr; if ( _comp->isTerminal ) { switch( _comp->type ) { case TT_INT: iptr = (int*)ptr; for ( int i = 0; i < _comp->quantifier; ++i ) { swap32( iptr ); iptr++; } break; case TT_SHORT: sptr = (short*)ptr; for ( int i = 0; i < _comp->quantifier; ++i ) { swap16( sptr ); sptr++; } break; case TT_BYTE: break; } } else { for ( int j = 0; j < _comp->quantifier; ++j ) { for ( int i = 0; i < _comp->numChunkNodes; ++i ) { convert_data( _comp->chunks[i], ptr ); ptr+= _comp->chunks[i]->totalSize; } } } } void BinaryFile::read( const char *_semantics, int _chunks, void* _buf, size_t& _bytesRead ) { pDataSemantics comp = compileSemantics( _semantics ); fread( _buf, comp->totalSize, _chunks, this->handle() ); if ( byteorder != NATIVE_BYTEORDER ) { for ( int i = 0; i < _chunks; ++i ) { convert_data( comp, (char*)_buf+i*comp->totalSize ); } } _bytesRead = comp->totalSize*_chunks; delete comp; } void BinaryFile::read( const char *_semantics, void* _buf, size_t& _bytesRead ) { pDataSemantics comp = compileSemantics( _semantics ); fread( _buf, comp->totalSize, 1, this->handle() ); if ( byteorder != NATIVE_BYTEORDER ) { convert_data( comp, _buf ); } delete comp; } void BinaryFile::write( const char *_semantics, void* _buf, size_t& _bytesWritten ) { pDataSemantics comp = compileSemantics( _semantics ); if ( byteorder != NATIVE_BYTEORDER ) { convert_data( comp, _buf ); } _bytesWritten = comp->totalSize; fwrite( _buf, comp->totalSize, 1, this->handle() ); delete comp; }