/****************************************************** * Rapid Embedded Development Architecture (redA) * * Copyright (C) 2008 RecoSys * * -------------- * * TLiteProtcol: * * Simplified protocol object to allow for fast * * communications between componets * * * * Contents: * * CLiteProtocol - Object Functions & Procedures * * * ******************************************************/ using namespace std; // LAStronic Libraries #include "LiteProtocolCore.h" // Standard C/C++ Libraries #include #include #include #include //--------------------------------------------------------------------------- CLiteProtocol::CLiteProtocol( int pBufferInc, char pStartChar, char pEndChar, char pSeparator ) { // Set Buffer increment if (pBufferInc < 1) BufferInc = 100; else BufferInc = pBufferInc; // Set Protocol markers StartChar = pStartChar; EndChar = pEndChar; Separator = pSeparator; // Reset Buffer and protocol parameters CommandStr = NULL; BufferSize = 0; ClearCommandStr(); } //--------------------------------------------------------------------------- CLiteProtocol::~CLiteProtocol() { // Destroy string if exist if (CommandStr) free (CommandStr); } //--------------------------------------------------------------------------- bool CLiteProtocol::IncCommandStr( int pLength ) { // Calculate new buffer length pLength = BufferInc * (pLength/BufferInc + 1); // Allocate memory if (!CommandStr) CommandStr = (char*)malloc(sizeof(char)*(pLength+1)); // Allow one more for zero termination else if (BufferSize < pLength) CommandStr = (char*)realloc(CommandStr, sizeof(char)*(pLength+1)); // Allow one more for zero termination else return true; // Check if successful if (!CommandStr) { strcpy( Error, "Memory allocation error"); Verified = false; return false; } // Update Buffer size and clear appended buffer BufferSize = pLength; memset( &CommandStr[Length], 0, pLength-Length+1 ); return true; } //--------------------------------------------------------------------------- bool CLiteProtocol::UpdateCommandStr() { // Check if command sting exists if (!CommandStr) return false; // Set Size & No of Params sprintf( &CommandStr[1], "%06ld", Length ); CommandStr[7] = Separator; sprintf( &CommandStr[8], "%04d", NoOfParams ); CommandStr[12] = Separator; return true; } //--------------------------------------------------------------------------- bool CLiteProtocol::VerifyStr( const char * pString, int pLength, int &ParamCount, char * pError ) { char * Mark; long tmpLen; int tmpParams; long Pos; long ParamLen; // Validate buffer if (!pString) { strcpy( pError, "NULL Protocol string" ); return false; } // Validate buffer if (!pLength) { strcpy( pError, "Empty Protocol string" ); return false; } // Verify Start and end if (pString[0] != StartChar) { strcpy( pError, "Invalid Start character" ); return false; } // Verify Start and end if (pString[pLength-1] != EndChar) { strcpy( pError, "Invalid End character" ); return false; } // Verify Length Mark = (char*)memchr( &pString[1], Separator, 7 ); if ((Mark && (Mark-pString-1 != 6)) || ((tmpLen = atol(&pString[1])) != pLength)) { strcpy( pError, "Invalid Protocol length" ); return false; } // Verify no of parameters Mark = (char*)memchr( &pString[8], Separator, 5 ); if ((Mark && (Mark-pString-8 != 4)) || ((tmpParams = atoi(&pString[8])) < 1)) { strcpy( pError, "Invalid Parameter count" ); return false; }; // Count parameters Pos = 13; ParamCount = 0; while ((pString[Pos] != EndChar) && (Pos < tmpLen-1)) { // Get param length & move to next param if (!(Mark = (char*)memchr( &pString[Pos], Separator, tmpLen-Pos ))) break; ParamLen = Mark-pString-Pos; Pos = Pos + ParamLen + 1; ParamCount++; }; // Check if match if (ParamCount != tmpParams){ strcpy( pError, "Invalid No of Parameters" ); return false; }; return true; } //--------------------------------------------------------------------------- bool CLiteProtocol::ClearCommandStr() { // Set to empty buffers if (CommandStr){ free( CommandStr ); CommandStr = NULL; BufferSize = 0; }; // Reset Parameters Length = 0; NoOfParams = 0; // No string to verify Verified = false; strcpy( Error, "Empty String" ); // Set references to zero CurrPos = 0; CurrParam = 0; return true; } //--------------------------------------------------------------------------- bool CLiteProtocol::NewCommandStr() { // First clear existing command string if (CommandStr){ free( CommandStr ); CommandStr = NULL; BufferSize = 0; }; IncCommandStr( 14 ); // Build basic string NoOfParams = 0; Length = 14; CommandStr[0] = StartChar; CommandStr[13] = EndChar; UpdateCommandStr(); // Not verified Verified = false; strcpy( Error, "No Parameters" ); // Set references CurrParam = 1; CurrPos = 13; return true; } //--------------------------------------------------------------------------- char* CLiteProtocol::GetCommandStr( char ** pString, int * pLength ) { // Set return values if (pString) *pString = CommandStr; if (pLength) *pLength = Length; return CommandStr; } //--------------------------------------------------------------------------- bool CLiteProtocol::SetCommandStr( const char * pString, const int pLength ) { int ParamCount; // Verify new string if (!VerifyStr( pString, pLength, ParamCount, Error )) return false; // Allocate memory ClearCommandStr(); if (!IncCommandStr( pLength )) return false; // Copy string memcpy( CommandStr, pString, pLength ); Length = pLength; NoOfParams = ParamCount; // Verified Verified = true; Error[0] = 0; // Set all pointers to start position GotoParam( 1 ); return true; } //--------------------------------------------------------------------------- bool CLiteProtocol::AppendCommandStr( char * pString, int &pLength ) { long Pos = 0; long Start = pLength; long End = pLength; long newLen = 0; // Check if valid parameters if (!pString || (pLength < 1)) return false; // Clear if last string is already verified if (Verified) ClearCommandStr(); // if partial string already received mark start position if (Length != 0) Start = 0; // Look for other markers while (Pos < pLength) { // Check if start character if (pString[Pos] == StartChar) { // Mark start point Start = Pos; } // Check if end character with valid start else if ((pString[Pos] == EndChar) && (Start < pLength)) { // Mark end and continue End = Pos+1; break; } // next char Pos++; }; // Check if anything available if (Start < pLength) { // Calculate length newLen = End - Start; // Increase buffer size IncCommandStr( Length + newLen ); // negative value -> add length // Copy buffer section memcpy( &CommandStr[Length], &pString[Start], newLen ); Length = Length + newLen; CommandStr[Length] = 0; // Check if complete string if ((pString[End-1] == EndChar)) VerifyCommandStr(); }; // Shift buffer if (End < pLength) memmove( pString, &pString[End], pLength-End ); memset( &pString[pLength-End], 0, End ); pLength = pLength - End; return Verified; } //--------------------------------------------------------------------------- bool CLiteProtocol::VerifyCommandStr() { // Check command string if (VerifyStr( CommandStr, Length, NoOfParams, Error )) { Verified = true; Error[0] = 0; } // Move reference to first parameter GotoParam( 1 ); return Verified; } //--------------------------------------------------------------------------- bool CLiteProtocol::AppendParam( const char * pString, const int pLength ) { int StringLen; // Check if valid if (!pString) return false; // Increase string length if required StringLen = (pLength < 0)? strlen(pString) : pLength; IncCommandStr( Length + StringLen+1 ); // Copy string memcpy( &CommandStr[CurrPos], (char*)pString, StringLen ); CommandStr[CurrPos+StringLen] = Separator; Length = Length + StringLen + 1; // Allow for separator character // Move pointer to end and set end char CurrParam++; CurrPos = CurrPos + StringLen + 1; // Allow for separator character CommandStr[CurrPos] = EndChar; // Update references NoOfParams++; UpdateCommandStr(); // String now verified - at least one parameter Verified = true; Error[0] = 0; return true; } //--------------------------------------------------------------------------- bool CLiteProtocol::AppendParam( long pValue ) { char TempStr[10]; // Create string representation sprintf( TempStr, "%ld", pValue ); // Insert if (AppendParam( TempStr, strlen(TempStr) )) return true; else return false; } //--------------------------------------------------------------------------- bool CLiteProtocol::AppendParam( double pValue, int pDigits ) { char ConvStr[10]; char TempStr[20]; // Check if command sting valid if (!Verified) return false; // Create string representation if (pDigits) sprintf( ConvStr, "%%.%df", pDigits ); else strcpy( ConvStr, "%f" ); sprintf( TempStr, ConvStr, pValue ); // Insert if (AppendParam( TempStr, strlen(TempStr) )) return true; else return false; } //--------------------------------------------------------------------------- char const * CLiteProtocol::GetParamNo( int ParamNo, char ** pString, int * pLength ) { char * Mark = NULL; // Check if valid parameter no if (!Verified || (ParamNo < 1) || (ParamNo > NoOfParams)) return NULL; // Set Starting point if (ParamNo < CurrParam) GotoParam( 1 ); // Jump until parameter found while ((CurrParam != ParamNo) && NextParam()) {}; // Check if found if (CurrParam != ParamNo) return NULL; // Return reference to parameter if (pString) *pString = &CommandStr[CurrPos]; if (pLength) { if (!(Mark = (char*)memchr( &CommandStr[CurrPos], Separator, Length-CurrPos ))) *pLength = 0; else *pLength = Mark - &CommandStr[CurrPos]; } return (&CommandStr[CurrPos]); } //--------------------------------------------------------------------------- bool CLiteProtocol::GotoParam( int ParamNo ) { // Check if command sting valid if (!Verified || (ParamNo < 1) || (ParamNo > NoOfParams+1)) return false; // Goto Param one CurrPos = 13; CurrParam = 1; // Find Parameter while ((CurrParam < ParamNo) && NextParam()) {}; return ((ParamNo == CurrParam)? true : false); } //--------------------------------------------------------------------------- bool CLiteProtocol::NextParam() { int ParamLen; char * Mark = NULL; // Check if command sting valid if (!Verified || (CurrParam == NoOfParams)) return false; // Get Current parameter length if (!(Mark = (char*)memchr( &CommandStr[CurrPos], Separator, Length-CurrPos ))) return false; ParamLen = Mark - &CommandStr[CurrPos]; // Move reference CurrPos = CurrPos + ParamLen + 1; CurrParam++; return true; } //--------------------------------------------------------------------------- char const * CLiteProtocol::GetParam( char ** pString, int * pLength ) { char * Mark = NULL; // Check if valid parameter no if (!Verified) { if (pString) *pString = NULL; if (pLength) pLength = 0; return NULL; }; // Return reference to parameter if (pString) *pString = &CommandStr[CurrPos]; if (pLength) { if (!(Mark = (char*)memchr( &CommandStr[CurrPos], Separator, Length-CurrPos ))) *pLength = 0; else *pLength = Mark - &CommandStr[CurrPos]; } return (&CommandStr[CurrPos]); } //--------------------------------------------------------------------------- // Create command bool CLiteProtocol::CreateCommand( char const * From, char const * To, char const * Command ) { // Create new command if (!NewCommandStr()) return false; // Insert Parameters in correct order if (!AppendParam( From ) || !AppendParam( To ) || !AppendParam( Command )) { ClearCommandStr(); return false; }; // All is well return true; } //--------------------------------------------------------------------------- // Read command bool CLiteProtocol::ReadCommand( char ** From, char ** To, char ** Command, int * DataParams, int * FromLen, int * ToLen, int * CommandLen ) { // Check if parameters available if (!Verified || (NoOfParams < 3)) return false; // Read parameters one by one GotoParam( 1 ); GetParam( From, FromLen ); NextParam(); GetParam( To, ToLen ); NextParam(); GetParam( Command, CommandLen ); if (DataParams) *DataParams = NoOfParams - 3; return true; } //---------------------------------------------------------------------------