Important Update:
- Still testing - Separate Rolling Buffer from PortCore to BufferCore - Implement BufferCore in PortCore - Add additional Rolling Buffer functions for future
This commit is contained in:
329
BufferCore.cpp
Normal file
329
BufferCore.cpp
Normal file
@@ -0,0 +1,329 @@
|
||||
/*
|
||||
* BufferCore.cpp
|
||||
*
|
||||
* Created on: 18 May 2016
|
||||
* Author: wentzelc
|
||||
*/
|
||||
|
||||
// redA Libraries
|
||||
#include "BufferCore.h"
|
||||
|
||||
// Standard C/C++ Libraries
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
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;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
64
BufferCore.h
Normal file
64
BufferCore.h
Normal file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* BufferCore.h
|
||||
*
|
||||
* Created on: 18 May 2016
|
||||
* Author: wentzelc
|
||||
*/
|
||||
|
||||
#ifndef REDACORE_BUFFERCORE_H_
|
||||
#define REDACORE_BUFFERCORE_H_
|
||||
|
||||
// redA Libraries
|
||||
/* none */
|
||||
|
||||
// Standard C/C++ Libraries
|
||||
/* none */
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
class CBuffer
|
||||
{
|
||||
private:
|
||||
// Buffer Definition
|
||||
char * Buffer; // Memory allocated to buffer
|
||||
int BufSize; // Size of allocated buffer
|
||||
|
||||
// Buffer pointers
|
||||
int BufStart; // First unread characters on buffer
|
||||
int BufEnd; // Next write position for new data (End of unread data + 1)
|
||||
int BufLen; // Total unread characters on buffer
|
||||
|
||||
// Temporary output buffer
|
||||
char * OutBuffer; // Temporary output buffer for "stitched" (rollover) data
|
||||
|
||||
public:
|
||||
// Life Cycle
|
||||
CBuffer( int BufferSize );
|
||||
~CBuffer();
|
||||
|
||||
// Direct Operations
|
||||
int Reset();
|
||||
int Set( char * Data, int Len );
|
||||
int Get( char ** Data, int MaxLen = -1 );
|
||||
int Clear( int ClearLen );
|
||||
|
||||
// FiFo operations
|
||||
int Push( char * Data, int Len );
|
||||
int Pop( char ** Data, int MaxLen = -1 );
|
||||
|
||||
// File operations
|
||||
int ReadFD( int Handle, int MaxRead = -1 );
|
||||
int WriteFD( int Handle, int MaxWrite = -1 );
|
||||
|
||||
// Character Operations
|
||||
char GetChar( int Pos );
|
||||
bool FindChar( char SearchChar, int &Pos );
|
||||
|
||||
// Miscellaneous
|
||||
int Size() { return BufSize; };
|
||||
int Len() { return BufLen; };
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
#endif /* REDACORE_BUFFERCORE_H_ */
|
||||
@@ -1,3 +1,3 @@
|
||||
PROJECT(lib_redAcore)
|
||||
|
||||
ADD_LIBRARY(redAcore LogCore.cpp SignalCore.cpp TimingCore.cpp PortCore.cpp SocketCore.cpp SelectCore.cpp)
|
||||
ADD_LIBRARY(redAcore TimingCore.cpp LogCore.cpp BufferCore.cpp SignalCore.cpp PortCore.cpp SocketCore.cpp SelectCore.cpp)
|
||||
|
||||
124
PortCore.cpp
124
PortCore.cpp
@@ -22,7 +22,7 @@
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
CPortCore::CPortCore( const char * PortName, const int PortInBufLen ) : InBufLen( PortInBufLen )
|
||||
CPortCore::CPortCore( const char * PortName, const int PortInBufSize )
|
||||
{
|
||||
// Port File Handle
|
||||
Handle = -1;
|
||||
@@ -37,14 +37,19 @@ CPortCore::CPortCore( const char * PortName, const int PortInBufLen ) : InBufLen
|
||||
}
|
||||
|
||||
// In buffer
|
||||
InBuffer = (char *)malloc( InBufLen );
|
||||
InLen = 0;
|
||||
BytesRead = 0;
|
||||
Buffer = new CBuffer( PortInBufSize );
|
||||
|
||||
// In buffer Timer
|
||||
// Input Timeout
|
||||
InStart.tv_sec = 0;
|
||||
InStart.tv_usec = 0;
|
||||
InTimeout = 100; // millisecs
|
||||
|
||||
// Input Markers
|
||||
InMarkers = NULL;
|
||||
InMarkerLen = 0;
|
||||
|
||||
// Output
|
||||
OutputHandle = -1;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
@@ -54,6 +59,10 @@ CPortCore::~CPortCore()
|
||||
if (Name) {
|
||||
free( Name );
|
||||
}
|
||||
|
||||
if (Buffer) {
|
||||
delete Buffer;
|
||||
}
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
@@ -107,8 +116,33 @@ bool CPortCore::Close()
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
// Configure general input options
|
||||
bool CPortCore::InputConfig( const long InputTimeout, const char * InputMarkers, int InputMarkerLen )
|
||||
{
|
||||
InTimeout = InputTimeout;
|
||||
if (InputMarkerLen && InputMarkers) {
|
||||
InMarkerLen = InputMarkerLen;
|
||||
InMarkers = (char *)malloc( InMarkerLen );
|
||||
memcpy( InMarkers, InputMarkers, InMarkerLen );
|
||||
}
|
||||
else {
|
||||
InMarkerLen = 0;
|
||||
InputMarkers = NULL;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
// Configure output options
|
||||
bool CPortCore::OutputConfig( int PortOutputHandle )
|
||||
{
|
||||
OutputHandle = PortOutputHandle;
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
// Set serial port configuration parameters
|
||||
bool CPortCore::Config( int Baud, short DataBits, short StopBits, short Parity, short FlowCtrl, int Wait )
|
||||
bool CPortCore::SerialConfig( int Baud, short DataBits, short StopBits, short Parity, short FlowCtrl, int Wait )
|
||||
{
|
||||
struct termios newtio;
|
||||
int flags = 0;
|
||||
@@ -246,51 +280,77 @@ bool CPortCore::Config( int Baud, short DataBits, short StopBits, short Parity,
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
bool CPortCore::Read()
|
||||
bool CPortCore::Read( const int MaxRead )
|
||||
{
|
||||
// Handle read event
|
||||
BytesRead = read( Handle, &InBuffer[InLen], InBufLen-InLen );
|
||||
if (BytesRead > 0)
|
||||
{
|
||||
// Process Reply
|
||||
InLen += BytesRead;
|
||||
int BytesRead = 0;
|
||||
|
||||
// Read File directly into buffer
|
||||
if (!(BytesRead = Buffer->ReadFD( Handle )))
|
||||
return false;
|
||||
|
||||
// Process Buffer
|
||||
ProcessBuffer( false );
|
||||
|
||||
// Reset timer
|
||||
SetStartTime( &InStart );
|
||||
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
bool CPortCore::ProcessBuffer( bool Force )
|
||||
{
|
||||
int Pos = 0;
|
||||
int Len = 0;
|
||||
char * Data = NULL;
|
||||
|
||||
// Check if buffered data
|
||||
if (!Buffer->Len()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if forced processed
|
||||
if (Force)
|
||||
{
|
||||
// Show Packet
|
||||
Len = Buffer->Get( &Data );
|
||||
ShowOutput( "Port In", OUT_NORMAL, Data, Len );
|
||||
|
||||
// Write buffer to Port
|
||||
Buffer->WriteFD( OutputHandle, Len );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Search for end of packet marker
|
||||
while (Buffer->FindChar( '\n', Pos ))
|
||||
{
|
||||
// Show Packet
|
||||
Len = Buffer->Get( &Data, Pos+1 );
|
||||
ShowOutput( "Port In", OUT_NORMAL, Data, Len );
|
||||
|
||||
// Write buffer to Port
|
||||
Buffer->WriteFD( OutputHandle, Len );
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
bool CPortCore::Maintain( int SocketHandle )
|
||||
bool CPortCore::Maintain()
|
||||
{
|
||||
// Misc
|
||||
long Duration = 0;
|
||||
int BytesWritten = 0;
|
||||
int StartWrite = 0;
|
||||
|
||||
if (InLen > 0)
|
||||
if (Buffer->Len() > 0)
|
||||
{
|
||||
// Check duration since last PortIn
|
||||
Duration = TimePassed( InStart );
|
||||
if (Duration > InTimeout)
|
||||
{
|
||||
// Handle buffer as packet
|
||||
InBuffer[ InLen ] = 0;
|
||||
ShowOutput( "Port In", OUT_NORMAL|OUT_HEX, InBuffer, InLen );
|
||||
// Process Input
|
||||
ProcessBuffer( true );
|
||||
|
||||
// Write output to Port
|
||||
BytesWritten = 0;
|
||||
StartWrite = 0;
|
||||
if (SocketHandle != -1) {
|
||||
while (StartWrite < InLen) {
|
||||
BytesWritten = write( SocketHandle, &InBuffer[StartWrite], InLen );
|
||||
StartWrite += BytesWritten;
|
||||
}
|
||||
}
|
||||
|
||||
// Reset buffer and timer
|
||||
InLen = 0;
|
||||
// Reset timer
|
||||
SetInterval( &InStart, 0 );
|
||||
}
|
||||
}
|
||||
|
||||
29
PortCore.h
29
PortCore.h
@@ -9,7 +9,7 @@
|
||||
#define REDACORE_PORTCORE_H_
|
||||
|
||||
// redA Libraries
|
||||
/* none */
|
||||
#include "BufferCore.h"
|
||||
|
||||
// Standard C/C++ Libraries
|
||||
#include <sys/time.h>
|
||||
@@ -36,27 +36,34 @@ private:
|
||||
int Handle;
|
||||
char * Name;
|
||||
|
||||
// PortIn buffer
|
||||
char * InBuffer;
|
||||
int InBufLen;
|
||||
int InLen;
|
||||
int BytesRead;
|
||||
// Port Buffer
|
||||
CBuffer * Buffer;
|
||||
|
||||
// PortIn Timer
|
||||
// Input Timer
|
||||
timeval InStart;
|
||||
long InTimeout; // millisecs
|
||||
|
||||
// Input Markers
|
||||
char * InMarkers;
|
||||
int InMarkerLen;
|
||||
|
||||
// Output
|
||||
int OutputHandle;
|
||||
|
||||
public:
|
||||
CPortCore( const char * PortName, const int PortInBufLen );
|
||||
CPortCore( const char * PortName, const int PortInBufSize );
|
||||
~CPortCore();
|
||||
|
||||
bool Open();
|
||||
bool Close();
|
||||
bool Config( int Baud, short DataBits, short StopBits, short Parity, short FlowCtrl, int Wait );
|
||||
bool InputConfig( long InputTimeout, const char * InputMarkers, int InputMarkerLen );
|
||||
bool SerialConfig( int Baud, short DataBits, short StopBits, short Parity, short FlowCtrl, int Wait );
|
||||
bool OutputConfig( int PortOutputHandle );
|
||||
int GetHandle() { return Handle; };
|
||||
|
||||
bool Read();
|
||||
bool Maintain( int SocketHandle );
|
||||
bool Read( int MaxRead );
|
||||
bool Maintain();
|
||||
bool ProcessBuffer( bool Force );
|
||||
};
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
||||
Reference in New Issue
Block a user