#include "InMemoryBuffer.h" #include "Text.h" #include "Either.h" using namespace Framework; InMemoryBuffer::InMemoryBuffer() : ReferenceCounter() { buffer = new char *[ 1 ]; buffer[ 0 ] = new char[ 256 ]; numBuffers = 1; readPos = 0; writePos = 0; maxWritePos = 0; } InMemoryBuffer::~InMemoryBuffer() { for( int i = 0; i < numBuffers; i++ ) delete[] buffer[ i ]; delete[]buffer; } //! Ließt aus der Datei //! \param bytes Ein Array, der mit Bytes aus der Resource gefüllt werden soll //! \param len Wie viele Bytes aus der Resource gelesen werden sollen void InMemoryBuffer::lese( char *bytes, int len ) { if( readPos < writePos ) { len = MIN( len, writePos - readPos ); int readCount = 0; do { int curPos = readPos % 256; int tmp = MIN( len, 256 - curPos ); memcpy( bytes + readCount, buffer[ readPos / 256 ] + curPos, tmp ); readCount += tmp; readPos += tmp; len -= tmp; } while( len > 0 ); } } //! Schreibt in die Resource //! \param bytes Ein Array, der die Bytes enthält, welche in die Resource geschrieben werden soll //! \param len Wie viele Bytes in die Resource geschrieben werden sollen void InMemoryBuffer::schreibe( const char *bytes, int len ) { if( numBuffers * 256 < writePos + len ) { int newSize = ( writePos + len ) / 256 + 1; char **newBuffer = new char *[ newSize ]; memcpy( newBuffer, buffer, sizeof( char * ) * numBuffers ); memset( newBuffer + sizeof( char * ) * numBuffers, 0, sizeof( char * ) * ( newSize - numBuffers ) ); delete[] buffer; buffer = newBuffer; numBuffers = newSize; } int writeCount = 0; do { int curPos = writePos % 256; int tmp = MIN( len, 256 - curPos ); if( !buffer[ writePos / 256 ] ) buffer[ writePos / 256 ] = new char[ 256 ]; memcpy( buffer[ writePos / 256 ] + curPos, bytes + writeCount, tmp ); writeCount += tmp; writePos += tmp; len -= tmp; } while( len > 0 ); maxWritePos = MAX( maxWritePos, writePos ); } //! Ließt die nächste zeile der Resource ein //! \return Die gelesene Zeile als Text mit zeilenumbruch Text *InMemoryBuffer::leseZeile() { if( istEnde() ) return 0; Text *ret = new Text( "" ); for( char c = 0; c != '\n' && readPos < writePos; ) { lese( &c, 1 ); if( c ) ret->append( (const char *)&c, 1 ); } return ret; } //! Prüft, ob die Resource vollständig gelesen wurde //! return 1, wenn die Resource vollständig gelesen wurde. 0, sonst bool InMemoryBuffer::istEnde() const { return readPos < writePos; } //! Setzt die Position des Bytes, das als nächstes gelesen werden soll //! \param pos Der Index des Bytes //! \param ende 1, wenn der Index vom ende der Resource zählt. 0, wenn der Index vom Beginn der Resource zählt void InMemoryBuffer::setLPosition( __int64 pos, bool ende ) { if( ende ) readPos = MAX( 0, maxWritePos - (int)pos ); else readPos = MIN( maxWritePos, (int)pos ); } //! Setzt die Position des Bytes, das als nächstes geschrieben werden soll //! \param pos Der Index des Bytes //! \param ende 1, wenn der Index vom ende der Resource zählt. 0, wenn der Index vom Beginn der Resource zählt void InMemoryBuffer::setSPosition( __int64 pos, bool ende ) { if( ende ) writePos = MAX( 0, maxWritePos - (int)pos ); else writePos = MIN( maxWritePos, (int)pos ); } //! Gibt den Index des Bytes aus der Resource zurück, welches als nächstes gelesen werden würde //! return -1, falls ein Fehler aufgetreten ist. Sonst die Position des Lesezeigers __int64 InMemoryBuffer::getLPosition() const { return readPos; } //! Gibt den Index des Bytes aus der Resource zurück, welches als nächstes geschrieben werden würde //! return -1, falls ein Fehler aufgetreten ist. Sonst die Position des Schreibzeigers __int64 InMemoryBuffer::getSPosition() const { return writePos; } //! Gibt die Anzahl der zu lesenden Bytes zurück __int64 InMemoryBuffer::getSize() const { return maxWritePos; }