diff -r 3c04e05ab24f -r 67b6ef6917ba src/bytestream.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/bytestream.cpp Wed Jul 17 18:46:47 2013 +0300 @@ -0,0 +1,225 @@ +#include "bytestream.h" +#include "misc.h" +#include + +union { + uint32 i; + float f; +} g_floatunion; + +Bytestream::Bytestream( ulong len ) { + m_data = null; + resize( len ); + clear(); +} + +Bytestream::Bytestream( const char* data, ulong len ) { + m_data = null; + init( data, len ); +} + +void Bytestream::resize( ulong newsize ) { + char* olddata = null; + ulong oldsize; + + if( m_data ) { + oldsize = m_size; + olddata = new char[oldsize]; + memcpy( olddata, m_data, oldsize ); + } + + delete[] m_data; + m_data = new uint8[newsize]; + m_size = newsize; + + if( olddata ) + memcpy( m_data, olddata, min ( oldsize, newsize )); +} + +void Bytestream::init( const char* data, ulong len ) { + resize( len ); + memcpy( m_data, data, len ); + m_ptr = &m_data[0]; + m_len = len; +} + +size_t Bytestream::len() const { + return m_len; +} + +void Bytestream::clear() { + m_ptr = &m_data[0]; + m_len = 0; +} + +uint8& Bytestream::subscript( ulong idx ) { + return m_data[idx]; +} + +const uint8& Bytestream::const_subscript( ulong idx ) const { + return m_data[idx]; +} + +void Bytestream::seek( ulong pos ) { + m_ptr = m_data + pos; +} + +// ============================================================================= +void Bytestream::rewind() { + m_ptr = m_data; +} + +ulong Bytestream::bytesLeft() const { + return ( m_len - ( m_ptr - &m_data[0] )); +} + +ulong Bytestream::spaceLeft() const { + return ( m_size - m_len ); +} + +// ============================================================================= +bool Bytestream::readByte( uint8& val ) { + if( bytesLeft() < 1 ) + return false; + + val = *m_ptr++; + return true; +} + +// ============================================================================= +bool Bytestream::readShort( uint16& val ) { + if( bytesLeft() < 2 ) + return false; + + val = 0; + + for( int i = 0; i < 2; ++i ) + val |= *m_ptr++ << ( i * 8 ); + + return true; +} + +// ============================================================================= +bool Bytestream::readLong( uint32& val ) { + if( bytesLeft() < 4 ) + return false; + + val = 0; + + for( int i = 0; i < 4; ++i ) + val |= *m_ptr++ << ( i * 8 ); + + return true; +} + +// ============================================================================= +bool Bytestream::readFloat( float& val ) { + if( !readLong( g_floatunion.i )) + return false; + + val = g_floatunion.f; + return true; +} + +// ============================================================================= +bool Bytestream::readString( str& val ) { + if( bytesLeft() < 1 ) // need at least the null terminator + return false; + + uint8_t c; + + while( readByte( c ) && c != '\0' ) + val += ( char ) c; + + return true; +} + +// ============================================================================= +void Bytestream::doWrite( uint8_t val ) { + *m_ptr++ = val; + m_len++; +} + +void Bytestream::growToFit( ulong bytes ) { + if( spaceLeft() < bytes ) + resize( m_size + bytes + 128 ); +} + +bool Bytestream::readBytes( uint8 numbytes, uint8* val ) { + while( numbytes-- ) + if( !readByte( *val++ )) + return false; + + return true; +} + +void Bytestream::writeBytes( uint8 numbytes, const uint8* val ) { + growToFit( numbytes ); + + while( numbytes-- ) + writeByte( *val++ ); +} + +// ============================================================================= +void Bytestream::writeByte( uint8 val ) { + growToFit( 1 ); + doWrite( val ); +} + +// ============================================================================= +void Bytestream::writeShort( uint16 val ) { + growToFit( 2 ); + + for( int i = 0; i < 2; ++i ) + doWrite(( val >> ( i * 8 )) & 0xFF ); +} + +// ============================================================================= +void Bytestream::writeLong( uint32 val ) { + growToFit( 4 ); + + for( int i = 0; i < 4; ++i ) + doWrite(( val >> ( i * 8 )) & 0xFF ); +} + +// ============================================================================= +void Bytestream::writeFloat( float val ) { + g_floatunion.f = val; + writeLong( g_floatunion.i ); +} + +// ============================================================================= +void Bytestream::writeString( str val ) { + growToFit( val.length() + 1 ); + + for( qchar c : val ) + doWrite( c.toAscii() ); + + doWrite( '\0' ); +} + +// ============================================================================= +bool Bytestream::tryMerge( const Bytestream& other ) { + if( spaceLeft() < other.len() ) + return false; + + for( ulong i = 0; i < other.len(); ++i ) + writeByte( other[i] ); + + return true; +} + +void Bytestream::merge( const Bytestream& other ) { + growToFit( other.len() ); + + if( !tryMerge( other )) { + // Shouldn't happen + fprint( stderr, "ByteStream: Not enough space for merge (%1 bytes left, need %2)", + spaceLeft(), other.len() ); + abort(); + } +} + +const uint8* Bytestream::data() const { + return m_data; +} \ No newline at end of file