Major Update: (compiling but untested)

- Replace CBuffer with CRollingBuffer and CShiftBuffer
  ShiftBuffer is faster and simpler and always zero terminates
- Updated SelectableCore to use RollingBuffer
- Add Overwrite parameter to Push() and ReadFromFD() methods
- Add PeakDirect() method for fast direct access to buffer
This commit is contained in:
Charl Wentzel
2017-03-22 03:43:29 +02:00
parent bb07ef63bf
commit b5763d7f50
4 changed files with 587 additions and 136 deletions

View File

@@ -17,14 +17,20 @@
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
CBuffer::CBuffer( int BufferSize ) : BufSize( BufferSize ) /***** Rolling Buffer *****/
CRollingBuffer::CRollingBuffer( int BufferSize ) : BufSize( BufferSize )
{ {
// Create Buffer // Create Buffer
if (BufSize) { if (BufSize)
{
// Create Buffer
Buffer = (char *)malloc( BufSize+1 ); Buffer = (char *)malloc( BufSize+1 );
OutBuffer = (char *)malloc( BufSize+1 ); OutBuffer = (char *)malloc( BufSize+1 );
OutBuffer[0] = 0;
} }
else { else {
// No buffers created
Buffer = NULL; Buffer = NULL;
OutBuffer = NULL; OutBuffer = NULL;
} }
@@ -36,7 +42,7 @@ CBuffer::CBuffer( int BufferSize ) : BufSize( BufferSize )
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
CBuffer::~CBuffer() CRollingBuffer::~CRollingBuffer()
{ {
// Destroy Buffer // Destroy Buffer
if (Buffer) { if (Buffer) {
@@ -48,51 +54,92 @@ CBuffer::~CBuffer()
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// Over write existing buffer with new data // Clear all data from buffer
int CBuffer::Set( const char * Data, int Len ) int CRollingBuffer::Reset()
{ {
// Validate data int BytesCleared = 0;
if (!Data || !Len) {
return 0;
}
else if (Len == -1) {
Len = strlen( Data );
}
if (Len <= BufSize) { // Clear buffer
memcpy( Buffer, Data, Len ); BytesCleared = BufLen;
BufStart = 0;
BufEnd = Len; // Reset pointers
BufLen = Len; BufStart = 0;
} BufEnd = 0;
else { BufLen = 0;
memcpy( Buffer, &Data[Len-BufSize], BufSize );
BufStart = 0; return BytesCleared;
BufEnd = 0;
BufLen = BufSize;
}
return BufLen;
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// Return "stitched" buffer data in temporary buffer // Return specific character for current rolling data
int CBuffer::Peek( char ** Data, int PeekPos, int MaxLen ) char CRollingBuffer::PeekChar( int Pos )
{
char CharValue = 0;
// Validate buffer and Pos
if (!BufLen || (Pos < 0) || (Pos > BufLen)) {
return 0;
}
// Get char
if (BufStart + Pos < BufSize) {
CharValue = Buffer[ BufStart+Pos ];
}
else {
CharValue = Buffer[ BufStart+Pos-BufSize ];
}
// Return char
return CharValue;
}
//---------------------------------------------------------------------------
// Return pointer direct to buffer
// Data is not removed from buffer
// Return number of contiguous chars (cannot rollover)
int CRollingBuffer::PeekDirect( char ** Data, int PeekPos )
{ {
int BytesReturned = 0; int BytesReturned = 0;
int StartPos = 0; int StartPos = 0;
// Check if any data // Validate
if (!BufLen || !MaxLen) { if (!BufLen || !Data || (PeekPos >= BufLen)) {
*Data = NULL; *Data = NULL;
return 0; return 0;
} }
// Validate start position // Get reference
if (PeekPos >= BufLen) { if (BufStart + StartPos < BufSize) {
StartPos = BufStart + PeekPos;
BytesReturned = (StartPos + BufLen > BufSize)? BufSize - StartPos : BufLen;
}
else {
StartPos = BufStart + PeekPos - BufSize;
BytesReturned = (StartPos + BufLen > BufEnd) ? BufEnd - StartPos : BufLen;
}
// Return buffer pointer
*Data = &Buffer[StartPos];
return BytesReturned;
}
//---------------------------------------------------------------------------
// Return "stitched" buffer data copied to pointer
// Pointer is created if NULL passed
// Data is not removed from buffer
int CRollingBuffer::Peek( char ** Data, int PeekPos, int MaxLen )
{
int BytesReturned = 0;
int StartPos = 0;
// Validate
if (!BufLen || !*Data || !MaxLen || (PeekPos < 0) || (PeekPos > BufLen)) {
*Data = NULL; *Data = NULL;
return 0; return 0;
} }
else if (BufStart + StartPos < BufSize) {
// Get buffer start position
if (BufStart + StartPos < BufSize) {
StartPos = BufStart + PeekPos; StartPos = BufStart + PeekPos;
} }
else { else {
@@ -113,6 +160,8 @@ int CBuffer::Peek( char ** Data, int PeekPos, int MaxLen )
memcpy( OutBuffer, &Buffer[StartPos], BufSize-StartPos ); // Copy from end of buffer memcpy( OutBuffer, &Buffer[StartPos], BufSize-StartPos ); // Copy from end of buffer
memcpy( &OutBuffer[BufSize-StartPos], Buffer, (BytesReturned-(BufSize-StartPos)) ); // Copy rollover from start of buffer memcpy( &OutBuffer[BufSize-StartPos], Buffer, (BytesReturned-(BufSize-StartPos)) ); // Copy rollover from start of buffer
} }
// Zero terminate
OutBuffer[BytesReturned] = 0; OutBuffer[BytesReturned] = 0;
// Return Temp buffer // Return Temp buffer
@@ -122,25 +171,20 @@ int CBuffer::Peek( char ** Data, int PeekPos, int MaxLen )
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// Return "stitched" buffer data in temporary buffer // Return "stitched" buffer data in temporary buffer
int CBuffer::PeekCopy( char ** Data, int PeekPos, int MaxLen ) // Data is not removed from buffer
int CRollingBuffer::PeekCopy( char ** Data, int PeekPos, int MaxLen )
{ {
int BytesReturned = 0; int BytesReturned = 0;
int StartPos = 0; int StartPos = 0;
// Check if any data // Check if any data
if (!BufLen || !MaxLen) { if (!BufLen || !*Data || !MaxLen || (PeekPos < 0) || (PeekPos > BufLen)) {
if (*Data) if (*Data) (*Data)[0] = 0;
(*Data)[0] = 0;
return 0; return 0;
} }
// Validate start position // Get start position
if (PeekPos >= BufLen) { if (BufStart + StartPos < BufSize) {
if (*Data)
(*Data)[0] = 0;
return 0;
}
else if (BufStart + StartPos < BufSize) {
StartPos = BufStart + PeekPos; StartPos = BufStart + PeekPos;
} }
else { else {
@@ -171,7 +215,72 @@ int CBuffer::PeekCopy( char ** Data, int PeekPos, int MaxLen )
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
int CBuffer::Clear( int ClearLen ) // Look for first occurrence of character in buffer
bool CRollingBuffer::FindStr( const char * SearchStr, int SearchLen, int &FoundPos, int StartPos )
{
char * CheckPos = NULL;
char * CheckLimit = NULL;
char * MatchPos = NULL;
char * MatchLimit = NULL;
// Check if buffer exists
if (!BufLen || !SearchStr || !SearchLen) {
FoundPos = -1;
return false;
}
// Validate start Pos
if (StartPos >= BufLen) {
FoundPos = -1;
return false;
}
// Get Search start point and limit
CheckPos = (BufStart + StartPos < BufSize)? &Buffer[ BufStart+StartPos ] : &Buffer[ (BufStart+StartPos)-BufSize ];
CheckLimit = &Buffer[BufSize-1];
// Set Match start point and limit
MatchPos = (char*)SearchStr;
MatchLimit = (char*)&SearchStr[SearchLen-1];
// Search for char
FoundPos = StartPos;
while (FoundPos < BufLen)
{
// Check if char match
if (*CheckPos == *MatchPos) {
if (MatchPos == MatchLimit) {
// Full match found
FoundPos -= SearchLen;
return true;
}
else {
// Next char to match
MatchPos++;
}
}
else {
// Reset match point
MatchPos = (char*)SearchStr;
}
// Next char
FoundPos++;
if (CheckPos == CheckLimit) {
CheckPos = Buffer; // Roll-over, Start at beginning of buffer
} else {
CheckPos++;
}
}
// Not Found
FoundPos = -1;
return false;
}
//---------------------------------------------------------------------------
// Remove data from start of buffer
int CRollingBuffer::Clear( int ClearLen )
{ {
int BytesCleared; int BytesCleared;
@@ -193,40 +302,29 @@ int CBuffer::Clear( int ClearLen )
return 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 // Add bytes to end of buffer
// Return "stitched" buffer data in temporary buffer // Perform roll over if requied
int CBuffer::Push( const char * Data, int Len ) // Option to overwrite existing data if longer than buffer length
int CRollingBuffer::Push( bool Overwrite, const char * Data, int Len )
{ {
int BytesPushed = 0; int BytesPushed = 0;
int TotalPushed = 0; int TotalPushed = 0;
int BufRemain = 0; int BufRemain = 0;
int DataRemain = Len; int DataRemain;
// Validate Buffer and Len // Validate Buffer and Len
if (!BufSize || !Len) { if (!BufSize || !Data || !Len) {
return 0; return 0;
} }
else if (Len == -1) { else if (Len == -1) {
Len = strlen( Data ); Len = strlen( Data );
} }
// Prevent overwrite
DataRemain = (!Overwrite && (Len > BufSize-BufLen))? BufSize-BufLen : Len;
// Read Data into buffer // Read Data into buffer
while (TotalPushed < Len) while (TotalPushed < Len)
{ {
@@ -247,7 +345,7 @@ int CBuffer::Push( const char * Data, int Len )
BufEnd = 0; BufEnd = 0;
} }
if (BufLen > BufSize) { if (BufLen > BufSize) {
// Head is caught up with tail, move tail up // Head has caught up with tail, move tail up
BufLen = BufSize; BufLen = BufSize;
BufStart = BufEnd; BufStart = BufEnd;
} }
@@ -259,14 +357,12 @@ int CBuffer::Push( const char * Data, int Len )
// Read first-in bytes from buffer // Read first-in bytes from buffer
// Return "stitched" buffer data in temporary buffer // Return "stitched" buffer data in temporary buffer
int CBuffer::Pop( char ** Data, int MaxLen ) int CRollingBuffer::Pop( char ** Data, int MaxLen )
{ {
int BytesWritten = 0; int BytesWritten = 0;
// Read data // Read & clear data
BytesWritten = Peek( Data, MaxLen ); BytesWritten = Peek( Data, MaxLen );
// Clear bytes
Clear( BytesWritten ); Clear( BytesWritten );
// Return temp buffer // Return temp buffer
@@ -275,15 +371,13 @@ int CBuffer::Pop( char ** Data, int MaxLen )
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// Read first-in bytes from buffer // Read first-in bytes from buffer
// Return "stitched" buffer data in temporary buffer // Return "stitched" buffer data copied to pointer which if created if NULL
int CBuffer::PopCopy( char ** Data, int MaxLen ) int CRollingBuffer::PopCopy( char ** Data, int MaxLen )
{ {
int BytesWritten = 0; int BytesWritten = 0;
// Read data // Copy & clear data
BytesWritten = PeekCopy( Data, MaxLen ); BytesWritten = PeekCopy( Data, MaxLen );
// Clear bytes
Clear( BytesWritten ); Clear( BytesWritten );
// Return temp buffer // Return temp buffer
@@ -292,7 +386,7 @@ int CBuffer::PopCopy( char ** Data, int MaxLen )
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// Read File descriptor directly into rolling buffer // Read File descriptor directly into rolling buffer
int CBuffer::ReadFromFD( int Handle, int MaxRead ) int CRollingBuffer::ReadFromFD( int Handle, int MaxRead, bool Overwrite )
{ {
int BytesRead = 0; int BytesRead = 0;
int TotalRead = 0; int TotalRead = 0;
@@ -305,7 +399,12 @@ int CBuffer::ReadFromFD( int Handle, int MaxRead )
} }
// Read file descriptor into buffer // Read file descriptor into buffer
DataRemain = (MaxRead == -1)? BufSize : MaxRead; if (Overwrite && (MaxRead > BufLen)) {
DataRemain = MaxRead;
}
else {
DataRemain = BufLen;
}
while (DataRemain) while (DataRemain)
{ {
// Read from file descriptor // Read from file descriptor
@@ -335,7 +434,7 @@ int CBuffer::ReadFromFD( int Handle, int MaxRead )
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// Write given number of bytes directly from buffer to File descriptor // Write given number of bytes directly from buffer to File descriptor
int CBuffer::WriteToFD( int Handle, int MaxLen ) int CRollingBuffer::WriteToFD( int Handle, int MaxLen )
{ {
int BytesWritten = 0; int BytesWritten = 0;
int TotalWritten = 0; int TotalWritten = 0;
@@ -375,37 +474,146 @@ int CBuffer::WriteToFD( int Handle, int MaxLen )
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// Return specific character for current rolling data
char CBuffer::PeekChar( int Pos, bool ClearChar )
{
char CharValue = 0;
/***** Shifting Buffer *****/
CShiftBuffer::CShiftBuffer( int BufferSize ) : BufSize( BufferSize )
{
// Create Buffer
if (BufSize)
{
// Create Buffer
Buffer = (char *)malloc( BufSize+1 );
Buffer[0] = 0;
OutBuffer = (char *)malloc( BufSize+1 );
}
else {
// No buffers created
Buffer = NULL;
OutBuffer = NULL;
}
// Set vars
BufLen = 0;
}
//---------------------------------------------------------------------------
CShiftBuffer::~CShiftBuffer()
{
// Destroy Buffer
if (Buffer) {
free( Buffer );
}
if (OutBuffer) {
free( OutBuffer );
}
}
//---------------------------------------------------------------------------
// Clear all data from buffer
int CShiftBuffer::Reset()
{
int BytesCleared = 0;
// Reset buffer
BytesCleared = BufLen;
BufLen = 0;
Buffer[0] = 0;
return BytesCleared;
}
//---------------------------------------------------------------------------
// Return specific character for current rolling data
char CShiftBuffer::PeekChar( int Pos )
{
// Validate buffer and Pos // Validate buffer and Pos
if (!BufLen) { if (!BufLen || (Pos < 0) || (Pos > BufLen)) {
return 0; return 0;
} }
// Get char
if (BufStart + Pos < BufSize) {
CharValue = Buffer[ BufStart+Pos ];
}
else {
CharValue = Buffer[ BufStart+Pos-BufSize ];
}
// Clear Char
if (ClearChar && (Pos == 0)) {
BufStart++;
BufLen--;
}
// Return char // Return char
return CharValue; return Buffer[Pos];
}
//---------------------------------------------------------------------------
// Return pointer direct to buffer
// Return number of contiguous chars (cannot rollover)
int CShiftBuffer::PeekDirect( char ** Data, int PeekPos )
{
// Validate
if (!BufLen || !Data || (PeekPos >= BufLen)) {
*Data = NULL;
return 0;
}
// Return buffer pointer
*Data = &Buffer[PeekPos];
return (BufLen - PeekPos);
}
//---------------------------------------------------------------------------
// Copy data into temporary buffer
int CShiftBuffer::Peek( char ** Data, int PeekPos, int MaxLen )
{
int BytesReturned = 0;
// Validate
if (!BufLen || !Data || !MaxLen || (PeekPos < 0) || (PeekPos > BufLen)) {
*Data = NULL;
return 0;
}
// Calculate bytes to return
if ((MaxLen == -1) || (MaxLen > BufSize)) {
MaxLen = BufSize;
}
BytesReturned = (MaxLen > BufLen - PeekPos)? (BufLen - PeekPos) : MaxLen;
// Copy Data from Buffer
memcpy( OutBuffer, Buffer, BytesReturned );
OutBuffer[BytesReturned] = 0;
// Return Temp buffer
*Data = OutBuffer;
return BytesReturned;
}
//---------------------------------------------------------------------------
// Return "stitched" buffer data in temporary buffer
// Data is not removed from buffer
int CShiftBuffer::PeekCopy( char ** Data, int PeekPos, int MaxLen )
{
int BytesReturned = 0;
int StartPos = 0;
// Check if any data
if (!BufLen || !Data || !MaxLen || (PeekPos < 0) || (PeekPos > BufLen)) {
if (*Data) (*Data)[0] = 0;
return 0;
}
// Calculate bytes to return
if ((MaxLen == -1) || (MaxLen > BufSize)) {
MaxLen = BufSize;
}
BytesReturned = (MaxLen > BufLen - PeekPos)? (BufLen - PeekPos) : MaxLen;
// Allocate memory
if (!*Data)
*Data = (char*)malloc( BytesReturned + 1 );
// Copy Data from Buffer
memcpy( *Data, &Buffer[StartPos], BytesReturned );
(*Data)[BytesReturned] = 0;
return BytesReturned;
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// Look for first occurrence of character in buffer // Look for first occurrence of character in buffer
bool CBuffer::FindStr( const char * SearchStr, int SearchLen, int &FoundPos, int StartPos ) bool CShiftBuffer::FindStr( const char * SearchStr, int SearchLen, int &FoundPos, int StartPos )
{ {
char * CheckPos = NULL; char * CheckPos = NULL;
char * CheckLimit = NULL; char * CheckLimit = NULL;
@@ -425,8 +633,8 @@ bool CBuffer::FindStr( const char * SearchStr, int SearchLen, int &FoundPos, int
} }
// Get Search start point and limit // Get Search start point and limit
CheckPos = (BufStart + StartPos < BufSize)? &Buffer[ BufStart+StartPos ] : &Buffer[ (BufStart+StartPos)-BufSize ]; CheckPos = &Buffer[StartPos];
CheckLimit = &Buffer[BufSize-1]; CheckLimit = &Buffer[BufLen-1];
// Set Match start point and limit // Set Match start point and limit
MatchPos = (char*)SearchStr; MatchPos = (char*)SearchStr;
@@ -438,12 +646,15 @@ bool CBuffer::FindStr( const char * SearchStr, int SearchLen, int &FoundPos, int
{ {
// Check if char match // Check if char match
if (*CheckPos == *MatchPos) { if (*CheckPos == *MatchPos) {
if (MatchPos == MatchLimit) if (MatchPos == MatchLimit) {
// Full match found // Full match found
FoundPos -= SearchLen;
return true; return true;
else }
else {
// Next char to match // Next char to match
MatchPos++; MatchPos++;
}
} }
else { else {
// Reset match point // Reset match point
@@ -453,7 +664,7 @@ bool CBuffer::FindStr( const char * SearchStr, int SearchLen, int &FoundPos, int
// Next char // Next char
FoundPos++; FoundPos++;
if (CheckPos == CheckLimit) { if (CheckPos == CheckLimit) {
CheckPos = Buffer; // Roll-over, Start at beginning of buffer break;
} else { } else {
CheckPos++; CheckPos++;
} }
@@ -464,3 +675,179 @@ bool CBuffer::FindStr( const char * SearchStr, int SearchLen, int &FoundPos, int
return false; return false;
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// Remove data from start of buffer
int CShiftBuffer::Clear( int ClearLen )
{
int BytesCleared;
// Validate ClearLen
if ((ClearLen == -1) || (ClearLen >= BufLen))
{
// Clear all data
BytesCleared = BufLen;
BufLen = 0;
Buffer[0] = 0;
}
else {
// Shift remaining data
BytesCleared = ClearLen;
memcpy( Buffer, &Buffer[ClearLen], BufLen-ClearLen ); // Shift remaining old data left
BufLen -= ClearLen;
Buffer[BufLen] = 0;
}
return BytesCleared;
}
//---------------------------------------------------------------------------
// Add bytes to end of buffer
// Option to overwrite existing data if longer than buffer length
int CShiftBuffer::Push( bool Overwrite, const char * Data, int Len )
{
int BytesPushed = 0;
int BufRemain = 0;
// Validate Buffer and Len
if (!BufSize || !Data || !Len) {
return 0;
}
else if (Len == -1) {
Len = strlen( Data );
}
// Copy Data to buffer
BufRemain = BufSize - BufLen;
if (Overwrite && (Len > BufRemain))
{
if (Len < BufSize) {
memcpy( Buffer, &Buffer[Len-BufRemain], BufLen-(Len-BufRemain) ); // Shift remaining old data left
memcpy( &Buffer[BufSize-Len], Data, Len ); // Copy new data
BytesPushed = Len;
}
else {
memcpy( Buffer, &Data[Len-BufSize], BufSize ); // Copy last portion of new data
BytesPushed = Len;
}
// Update Pointers
BufLen = BufSize;
Buffer[BufLen] = 0;
}
else
{
// Copy first portion of new data to buffer
BytesPushed = (Len > BufRemain)? BufRemain : Len;
memcpy( &Buffer[BufLen], Data, BytesPushed );
// Update Buffer Pointers
BufLen += BytesPushed;
Buffer[BufLen] = 0;
}
return BytesPushed;
}
//---------------------------------------------------------------------------
// Read first-in bytes from buffer
// Return "stitched" buffer data in temporary buffer
int CShiftBuffer::Pop( char ** Data, int MaxLen )
{
int BytesWritten = 0;
// Read and clear bytes
BytesWritten = Peek( Data, MaxLen );
Clear( BytesWritten );
return BytesWritten;
}
//---------------------------------------------------------------------------
// Read first-in bytes from buffer
// Return "stitched" buffer data copied to pointer which if created if NULL
int CShiftBuffer::PopCopy( char ** Data, int MaxLen )
{
int BytesWritten = 0;
// Copy and clear bytes
BytesWritten = PeekCopy( Data, MaxLen );
Clear( BytesWritten );
// Return temp buffer
return BytesWritten;
}
//---------------------------------------------------------------------------
// Read File descriptor directly into buffer
int CShiftBuffer::ReadFromFD( int Handle, int MaxRead )
{
int BytesRead = 0;
int TotalRead = 0;
int DataRemain = 0;
// Check if buffer created
if (!BufSize) {
return 0;
}
// Read file descriptor into buffer
DataRemain = (MaxRead > BufSize-BufLen)? BufSize-BufLen : MaxRead;
while (DataRemain)
{
// Read from file descriptor
BytesRead = read( Handle, &Buffer[BufLen], DataRemain );
if (BytesRead <= 0) {
break;
}
// Update Buffer Pointers
DataRemain -= BytesRead;
TotalRead += BytesRead;
BufLen += BytesRead;
}
return TotalRead;
}
//---------------------------------------------------------------------------
// Write given number of bytes directly from buffer to File descriptor
int CShiftBuffer::WriteToFD( int Handle, int MaxLen )
{
int BytesWritten = 0;
int TotalWritten = 0;
int BufRemain = 0;
int DataRemain = 0;
int ReadPos = 0;
// Check if buffer created
if (!BufSize) {
return 0;
}
// Read Data into buffer
ReadPos = 0;
DataRemain = ((MaxLen == -1) || (MaxLen > BufLen))? BufLen : MaxLen;
while (DataRemain)
{
// Read from file descriptor
BufRemain = BufSize - ReadPos;
BytesWritten = write( Handle, &Buffer[ReadPos], ((BufRemain > DataRemain)? DataRemain : BufRemain) );
if (BytesWritten <= 0) {
break;
}
// Update Data Pointers
TotalWritten += BytesWritten;
DataRemain -= BytesWritten;
// Update Buffer Pointers
ReadPos += BytesWritten;
if (ReadPos >= BufSize) {
ReadPos = 0; // Rolling over end of buffer, start at beginning
}
}
return TotalWritten;
}
//---------------------------------------------------------------------------

View File

@@ -16,51 +16,115 @@
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
class CBuffer /** Shift and Rolling buffer class
*
* Shifting buffer:
* Data is either set at start of buffer or appended to buffer
* Start of buffered data is always at beginning of buffer
* Never rolls over (option to over overwrite if data longer than buffer)
* Shifts unsused data to left when clearing used data
* Always zero terminates buffer
* Can look directly at buffer
*
* Rolling buffer:
* Data is continuosly assigned to buffer
* Start of buffer is tracked by references (can be anywhere)
* Data rolls over to start of buffer if end of buffer reached (option to overwrite start)
* Data is never shifted/moved inside buffer, only references are adjusted
* Never zero terminates buffer
* Can only look at data by copying (stitching) to another buffer
*/
class CRollingBuffer
{ {
private: private:
// Buffer Definition // Buffer Definition
char * Buffer; // Memory allocated to buffer char * Buffer; // Memory allocated to buffer
const int BufSize; // Size of allocated buffer const int BufSize; // Size of allocated buffer
int BufLen; // Total unread characters in buffer
// Temporary output buffer
char * OutBuffer; // Temporary output buffer for "stitched" (rollover) data
// Buffer pointers // Buffer pointers
int BufStart; // First unread characters on buffer int BufStart; // First unread characters in buffer
int BufEnd; // Next write position for new data (End of unread data + 1) int BufEnd; // Next write position for new data (End of unread data + 1)
int BufLen; // Total unread characters on buffer
public:
// Life Cycle
CRollingBuffer( int BufferSize );
virtual ~CRollingBuffer();
// Direct Operations
int Reset(); // Clear buffer and reset all pointers to start of buffer
// Reading from buffer
char PeekChar( int Pos = 0 ); // Return one character from buffer (do not remove from buffer
int PeekDirect( char ** Data, int PeekPos = 0 ); // Return contiguous data pointer direct to buffer (continguous data couont returned)
int Peek( char ** Data, int PeekPos = 0, int MaxLen = -1 ); // Return stiched data copied to temporary output buffer
int PeekCopy( char ** Data, int PeekPos = 0, int MaxLen = -1 ); // Return stiched data copied to supplied pointer (create if not exist)
bool FindStr( const char * SearchStr, int SearchLen, int &FoundPos, int StartPos = 0 ); // Search buffer directly
// Change data on buffer
virtual int Push( bool Overwrite, const char * Data, int Len = -1 );
virtual int Clear( int ClearLen = -1 );
virtual int Pop( char ** Data, int MaxLen = -1 );
virtual int PopCopy( char ** Data, int MaxLen = -1 );
// File operations
virtual int ReadFromFD( int Handle, int MaxRead = -1, bool Overwrite = false );
virtual int WriteToFD( int Handle, int MaxWrite = -1 );
// Miscellaneous
int Size() { return BufSize; };
int Len() { return BufLen; };
};
//---------------------------------------------------------------------------
class CShiftBuffer
{
private:
// Buffer Definition
char * Buffer; // Memory allocated to buffer
const int BufSize; // Size of allocated buffer
int BufLen; // Total unread characters in buffer
// Temporary output buffer // Temporary output buffer
char * OutBuffer; // Temporary output buffer for "stitched" (rollover) data char * OutBuffer; // Temporary output buffer for "stitched" (rollover) data
public: public:
// Life Cycle // Life Cycle
CBuffer( int BufferSize ); CShiftBuffer( int BufferSize );
~CBuffer(); virtual ~CShiftBuffer();
// Direct Operations // Direct Operations
int Reset(); int Reset(); // Clear buffer and reset all pointers to start of buffer
int Set( const char * Data, int Len = -1 );
int Peek( char ** Data, int PeekPos = 0, int MaxLen = -1 );
int PeekCopy( char ** Data, int PeekPos = 0, int MaxLen = -1 );
int Clear( int ClearLen = -1 );
// FiFo operations // Reading from buffer
int Push( const char * Data, int Len = -1 ); char PeekChar( int Pos = 0 ); // Return one character from buffer (do not remove from buffer
int Pop( char ** Data, int MaxLen = -1 ); int PeekDirect( char ** Data, int PeekPos = 0 ); // Return contiguous data pointer direct to buffer (continguous data couont returned)
int PopCopy( char ** Data, int MaxLen = -1 ); int Peek( char ** Data, int PeekPos = 0, int MaxLen = -1 ); // Return stiched data copied to temporary output buffer
int PeekCopy( char ** Data, int PeekPos = 0, int MaxLen = -1 ); // Return stiched data copied to supplied pointer (create if not exist)
bool FindStr( const char * SearchStr, int SearchLen, int &FoundPos, int StartPos = 0 ); // Search buffer directly
// Chagne data on buffer
virtual int Push( bool Overwrite, const char * Data, int Len = -1 );
virtual int Clear( int ClearLen = -1 );
virtual int Pop( char ** Data, int MaxLen = -1 );
virtual int PopCopy( char ** Data, int MaxLen = -1 );
// File operations // File operations
int ReadFromFD( int Handle, int MaxRead = -1 ); virtual int ReadFromFD( int Handle, int MaxRead = -1 );
int WriteToFD( int Handle, int MaxWrite = -1 ); virtual int WriteToFD( int Handle, int MaxWrite = -1 );
// Character Operations
char PeekChar( int Pos = 0, bool ClearChar = false );
bool FindStr( const char * SearchStr, int SearchLen, int &FoundPos, int StartPos = 0 );
// Miscellaneous // Miscellaneous
inline int Size() { return BufSize; }; int Size() { return BufSize; };
inline int Len() { return BufLen; }; int Len() { return BufLen; };
}; };
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
#endif /* REDACORE_BUFFERCORE_H_ */ #endif /* REDACORE_BUFFERCORE_H_ */

View File

@@ -299,7 +299,7 @@ bool CSelectableCore::SetBuffers( THandle * Handle, int InBufSize, int OutBufSiz
Handle->InBuffer = NULL; Handle->InBuffer = NULL;
} }
if (InBufSize) { if (InBufSize) {
Handle->InBuffer = new CBuffer( InBufSize ); Handle->InBuffer = (CRollingBuffer*) new CRollingBuffer( InBufSize );
} }
// Output Buffer // Output Buffer
@@ -308,7 +308,7 @@ bool CSelectableCore::SetBuffers( THandle * Handle, int InBufSize, int OutBufSiz
Handle->OutBuffer = NULL; Handle->OutBuffer = NULL;
} }
if (OutBufSize) { if (OutBufSize) {
Handle->OutBuffer = new CBuffer( OutBufSize ); Handle->OutBuffer = (CRollingBuffer*) new CRollingBuffer( OutBufSize );
} }
// Set Input Timeout // Set Input Timeout
@@ -1060,7 +1060,7 @@ bool CSelectableCore::ProcessBuffer( THandle * Handle, bool Force )
while (Handle->InBuffer->FindStr( Handle->InMarker, Handle->InMarkerLen, Pos )) while (Handle->InBuffer->FindStr( Handle->InMarker, Handle->InMarkerLen, Pos ))
{ {
// Show Packet // Show Packet
Len = Handle->InBuffer->Peek( &Data, 0, Pos+1 ); Len = Handle->InBuffer->Peek( &Data, 0, Pos+Handle->InMarkerLen+1 );
if (Log) Log->Output( DebugLevel, dlHigh, OutputDisplay, Data, Len, "%s: Handle '%s' - IN-M:", Name, Handle->Name ); if (Log) Log->Output( DebugLevel, dlHigh, OutputDisplay, Data, Len, "%s: Handle '%s' - IN-M:", Name, Handle->Name );
// Write buffer to Outputs // Write buffer to Outputs
@@ -1181,7 +1181,7 @@ int CSelectableCore::Input( const char * ChannelName, const char * Data, int Len
if (ChildHandle->OutBuffer) if (ChildHandle->OutBuffer)
{ {
// Write to buffer // Write to buffer
BytesWritten = ChildHandle->OutBuffer->Push( Data, Len ); BytesWritten = ChildHandle->OutBuffer->Push( true, Data, Len );
// Add to select write list // Add to select write list
if (BytesWritten) { if (BytesWritten) {
@@ -1210,7 +1210,7 @@ int CSelectableCore::Input( const char * ChannelName, const char * Data, int Len
if (Handle->OutBuffer) if (Handle->OutBuffer)
{ {
// Write to buffer // Write to buffer
BytesWritten = Handle->OutBuffer->Push( Data, Len ); BytesWritten = Handle->OutBuffer->Push( true, Data, Len );
// Add to select write list // Add to select write list
if (BytesWritten) { if (BytesWritten) {

View File

@@ -92,8 +92,8 @@ struct SHandle {
bool KeepAlive; // Socket keep alive bool KeepAlive; // Socket keep alive
// Buffers // Buffers
CBuffer * InBuffer; CRollingBuffer * InBuffer;
CBuffer * OutBuffer; CRollingBuffer * OutBuffer;
// Input Markers // Input Markers
char * InMarker; char * InMarker;