/* * BufferCore.cpp * * Created on: 18 May 2016 * Author: wentzelc */ // redA Libraries #include "BufferCore.h" // Standard C/C++ Libraries #include #include #include #include //--------------------------------------------------------------------------- CBuffer::CBuffer( int BufferSize ) : BufSize( BufferSize ) { // Create Buffer if (BufSize) { Buffer = (char *)malloc( BufSize+1 ); OutBuffer = (char *)malloc( BufSize+1 ); } else { Buffer = NULL; OutBuffer = NULL; } // Set pointers BufStart = 0; BufEnd = 0; BufLen = 0; } //--------------------------------------------------------------------------- CBuffer::~CBuffer() { // Destroy Buffer if (Buffer) { free( Buffer ); } if (OutBuffer) { free( OutBuffer ); } } //--------------------------------------------------------------------------- // Over write existing buffer with new data int CBuffer::Set( char * Data, int Len ) { // Validate data if (!Data || !Len) return 0; if (Len <= BufSize) { memcpy( Buffer, Data, Len ); BufStart = 0; BufEnd = Len; BufLen = Len; } else { memcpy( Buffer, &Data[Len-BufSize], BufSize ); BufStart = 0; BufEnd = 0; BufLen = BufSize; } return BufLen; } //--------------------------------------------------------------------------- // Return "stitched" buffer data in temporary buffer int CBuffer::Get( char ** Data, int MaxLen ) { int BytesReturned = 0; // Check if any data if (!BufLen || !MaxLen) { *Data = NULL; return 0; } // Validate MaxLen if ((MaxLen == -1) || (MaxLen > BufSize)) { MaxLen = BufSize; } BytesReturned = (MaxLen > BufLen)? BufLen : MaxLen; // Copy Data from Buffer if (BufStart + BytesReturned < BufSize) { memcpy( OutBuffer, &Buffer[BufStart], BytesReturned ); } else { memcpy( OutBuffer, &Buffer[BufStart], BufSize-BufStart ); // Copy from end of buffer memcpy( &OutBuffer[BufSize-BufStart], Buffer, (BytesReturned-(BufSize-BufStart)) ); // Copy rollover from start of buffer } OutBuffer[BytesReturned] = 0; // Return Temp buffer *Data = OutBuffer; return BytesReturned; } //--------------------------------------------------------------------------- int CBuffer::Clear( int ClearLen ) { int BytesCleared; // Validate ClearLen BytesCleared = (ClearLen > BufSize)? BufSize : ClearLen; // Update Buffer pointers if (BufStart + BytesCleared < BufSize) { BufStart += BytesCleared; } else { BufStart = (BytesCleared-(BufSize-BufStart)); // Copy roll-over from start of buffer } BufLen -= BytesCleared; return BytesCleared; } //--------------------------------------------------------------------------- int CBuffer::Reset() { int BytesCleared = 0; // Clear all data BytesCleared = BufLen; BufStart = 0; BufEnd = 0; BufLen = 0; return BytesCleared; } //--------------------------------------------------------------------------- // Add bytes to end of buffer // Return "stitched" buffer data in temporary buffer int CBuffer::Push( char * Data, int Len ) { int BytesPushed = 0; int TotalPushed = 0; int BufRemain = 0; int DataRemain = Len; // Check if buffer created if (!BufSize) { return 0; } // Read Data into buffer while (TotalPushed < Len) { // Read from file descriptor BufRemain = BufSize - BufEnd; BytesPushed = ((BufRemain > DataRemain)? DataRemain : BufRemain); memcpy( &Buffer[BufEnd], &Data[TotalPushed], BytesPushed ); // Update Data Pointers TotalPushed += BytesPushed; DataRemain -= BytesPushed; // Update Buffer Pointers BufLen += BytesPushed; BufEnd += BytesPushed; if (BufEnd >= BufSize) { // Rolling over end of buffer, start at beginning BufEnd = 0; } if (BufLen > BufSize) { // Head is caught up with tail, move tail up BufLen = BufSize; BufStart = BufEnd; } } return TotalPushed; } //--------------------------------------------------------------------------- // Read first-in bytes from buffer // Return "stitched" buffer data in temporary buffer int CBuffer::Pop( char ** Data, int MaxLen ) { int BytesWritten = 0; // Read data BytesWritten = Get( Data, MaxLen ); // Clear bytes Clear( BytesWritten ); // Return temp buffer return BytesWritten; } //--------------------------------------------------------------------------- // Read File descriptor directly into rolling buffer int CBuffer::ReadFD( int Handle, int MaxRead ) { int BytesRead = 0; int TotalRead = 0; int BufRemain = 0; int DataRemain = 0; // Check if buffer created if (!BufSize) { return 0; } // Read file descriptor into buffer DataRemain = (MaxRead == -1)? BufSize : MaxRead; while (DataRemain) { // Read from file descriptor BufRemain = BufSize - BufEnd; BytesRead = read( Handle, &Buffer[BufEnd], ((BufRemain > DataRemain)? DataRemain : BufRemain) ); if (BytesRead <= 0) break; // Update Buffer Pointers DataRemain -= BytesRead; TotalRead += BytesRead; BufLen += BytesRead; BufEnd += BytesRead; if (BufEnd >= BufSize) { // Rolling over end of buffer, start at beginning BufEnd = 0; } if (BufLen > BufSize) { // Head is caught up with tail, move tail up BufLen = BufSize; BufStart = BufEnd; } } return TotalRead; } //--------------------------------------------------------------------------- // Write given number of bytes directly from buffer to File descriptor int CBuffer::WriteFD( int Handle, int MaxLen ) { int BytesWritten = 0; int TotalWritten = 0; int BufRemain = 0; int DataRemain = 0; // Check if buffer created if (!BufSize) { return 0; } // Read Data into buffer DataRemain = (MaxLen == -1)? BufLen : MaxLen; while ((TotalWritten < MaxLen) && (BufLen > 0)) { // Read from file descriptor BufRemain = BufSize - BufStart; BytesWritten = write( Handle, &Buffer[BufStart], ((BufRemain > DataRemain)? DataRemain : BufRemain) ); if (BytesWritten <= 0) break; // Update Data Pointers TotalWritten += BytesWritten; DataRemain -= BytesWritten; // Update Buffer Pointers BufLen -= BytesWritten; BufStart += BytesWritten; if (BufStart >= BufSize) { // Rolling over end of buffer, start at beginning BufStart = 0; } } return TotalWritten; } //--------------------------------------------------------------------------- // Return specific character for current rolling data char CBuffer::GetChar( int Pos ) { if (!BufLen) { return 0; } else if (BufStart + Pos < BufSize) { return Buffer[ BufStart+Pos ]; } else { return Buffer[ BufStart+Pos-BufSize ]; } } //--------------------------------------------------------------------------- // Look for first occureance of character in buffer bool CBuffer::FindChar( char SearchChar, int &Pos ) { char * CheckPos; char * Limit; // Check if buffer exists if (!BufLen) { return false; } // Search for char Pos = 0; CheckPos = &Buffer[BufStart]; Limit = &Buffer[BufSize-1]; while (Pos < BufLen) { if (*CheckPos == SearchChar) return true; // Next char Pos++; if (CheckPos == Limit) { CheckPos = Buffer; // Roll-over, Start at beginning of buffer } else { CheckPos++; } } return false; } //---------------------------------------------------------------------------