diff --git a/CMakeLists.txt b/CMakeLists.txt index 261847f..8d9b8e8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,3 +1,3 @@ PROJECT(lib_redAcore) -ADD_LIBRARY(redAcore TimingCore.cpp DateTimeCore.cpp LogCore.cpp SignalCore.cpp BufferCore.cpp FunctionCore.cpp DeviceCore.cpp FileCore.cpp SelectCore.cpp SelectableCore.cpp) +ADD_LIBRARY(redAcore TimingCore.cpp DateTimeCore.cpp LogCore.cpp SignalCore.cpp ConfigCore.cpp BufferCore.cpp FunctionCore.cpp DeviceCore.cpp FileCore.cpp SelectCore.cpp SelectableCore.cpp) diff --git a/ConfigCore.cpp b/ConfigCore.cpp new file mode 100644 index 0000000..8b4d3ad --- /dev/null +++ b/ConfigCore.cpp @@ -0,0 +1,475 @@ +/* + * ConfigCore.cpp + * + * Created on: 5 Mar 2017 + * Author: wentzelc + */ + +// redA Libraries +#include "ConfigCore.h" + +// Standard C/C++ Libraries +#include +#include +#include +#include +#include + +//--------------------------------------------------------------------------- + +CConfigCore::CConfigCore() +{ + FirstParam = NULL; +} +//--------------------------------------------------------------------------- + +CConfigCore::~CConfigCore() +{ + // Destroy Params + while (FirstParam) + DestroyParam( &FirstParam ); +} +//--------------------------------------------------------------------------- + +bool CConfigCore::DestroyParam( TConfigParam ** Param ) +{ + TConfigParam * NextParam; + + // Valdate + if (!Param || !*Param) + return false; + + // Get next param in list + NextParam = (*Param)->Next; + + // Destroy + if ((*Param)->Name) + free( (*Param)->Name ); + if ((*Param)->Value) + free( (*Param)->Value ); + + free( *Param ); + + // Restore list integrity + *Param = NextParam; + + return true; +} +//--------------------------------------------------------------------------- + +bool CConfigCore::DeleteParam( const char * Name ) +{ + TConfigParam ** Param; + + // Check if exists + if (!(Param = GetParamPtr( Name ))) + return false; + + // Destory + DestroyParam( Param ); + return true; +} +//--------------------------------------------------------------------------- + +bool CConfigCore::DeleteAll() +{ + while (FirstParam) + DestroyParam( &FirstParam ); + return true; +} +//--------------------------------------------------------------------------- + +bool CConfigCore::SetParam( TConfigParam * Param, EJSONtype Type, const char * Value, const int Len ) +{ + // Clear previous value + if (Param->Value != NULL) + free( Param->Value ); + + // Set type + Param->Type = Type; + + // Set new value + if (Value == NULL) { + Param->Len = 0; + Param->Value = NULL; + } + else { + Param->Len = (Len == -1)? strlen(Value) : Len; + Param->Value = (char *)calloc( 1, sizeof(Param->Len+1) ); + memcpy( Param->Value, Value, Param->Len+1 ); + } + + return true; +} +//--------------------------------------------------------------------------- + +bool CConfigCore::SetParamStr( const char * Name, const char * Value, const int Len ) +{ + TConfigParam * Param; + + // Create new param if it doesn't exist + Param = FindCreateParam( Name ); + SetParam( Param, jtString, Value, Len ); + + return true; +} +//--------------------------------------------------------------------------- + +bool CConfigCore::SetParamInt( const char * Name, const long Value ) +{ + TConfigParam * Param = NULL; + char ValueStr[50]; + + // Create new param if it doesn't exist + Param = FindCreateParam( Name ); + sprintf( ValueStr, "%ld", Value ); + SetParam( Param, jtInt, ValueStr, -1 ); + + return false; +} +//--------------------------------------------------------------------------- + +bool CConfigCore::SetParamFloat( const char * Name, const double Value ) +{ + TConfigParam * Param = NULL; + char ValueStr[50]; + + // Create new param if it doesn't exist + Param = FindCreateParam( Name ); + sprintf( ValueStr, "%lf", Value ); + SetParam( Param, jtFloat, ValueStr, -1 ); + return false; +} +//--------------------------------------------------------------------------- + +bool CConfigCore::SetParamBool( const char * Name, const bool Value ) +{ + TConfigParam * Param = NULL; + + // Create new param if it doesn't exist + Param = FindCreateParam( Name ); + SetParam( Param, jtBool, ((Value == 0)? "false" : "true"), -1 ); + return false; +} +//--------------------------------------------------------------------------- + +const EJSONtype CConfigCore::GetParamType( const char * Name ) +{ + TConfigParam * Param; + + if ((Param = GetParam( Name ))) { + return Param->Type; + } + else { + return jtNone; + } +} +//--------------------------------------------------------------------------- + +const char * CConfigCore::GetParamStr( const char * Name, const char * Default ) +{ + TConfigParam * Param; + + if ((Param = GetParam( Name ))) { + return Param->Value; + } + else { + return Default; + } +} +//--------------------------------------------------------------------------- + +const char * CConfigCore::GetParamStr( const char * Name, int &Len, const char * Default ) +{ + TConfigParam * Param; + + if ((Param = GetParam( Name ))) { + Len = Param->Len; + return Param->Value; + } + else { + Len = strlen( Default ); + return Default; + } +} +//--------------------------------------------------------------------------- + +const long CConfigCore::GetParamInt( const char * Name, long Default ) +{ + TConfigParam * Param; + + if ((Param = GetParam( Name ))) { + return strtol( Param->Value, NULL, 10 ); + } + else { + return Default; + } +} +//--------------------------------------------------------------------------- + +const double CConfigCore::GetParamFloat( const char * Name, double Default ) +{ + TConfigParam * Param; + + if ((Param = GetParam( Name ))) { + return strtod( Param->Value, NULL ); + } + else { + return Default; + } +} +//--------------------------------------------------------------------------- + +const bool CConfigCore::GetParamBool( const char * Name, bool Default ) +{ + TConfigParam * Param; + + if ((Param = GetParam( Name ))) { + return ((!strcasecmp( Param->Value, "true" ))? true : false ); + } + else { + return Default; + } +} +//--------------------------------------------------------------------------- + +bool CConfigCore::LoadFile( const char * FilePath ) +{ + FILE * InputFile = NULL; + char InputStr[500]; + char * StrPos; + char * Mark = NULL; + char * EndMark = NULL; + char * LineMark = NULL; + int LineNo = 1; + char ParamName[50] = ""; + long IntVal = 0; + double FloatVal = 0.0; + bool Error = false; + char ErrorText[50] = ""; + int BufCount = 0; + + // Validate + if (!FilePath || !FilePath[0]) + return false; + + // Open file + if (!(InputFile = fopen( FilePath, "r" ))) + return false; + + while (!Error && (BufCount = fread( InputStr, 1, 500, InputFile ))) + { + // Read Param Name + StrPos = InputStr; + LineMark = StrPos-1; + + // Process string + while (!Error && (StrPos < InputStr + BufCount)) + { + // Skip white space + while (isspace(*StrPos)) { + if (*StrPos == '\n') { + LineMark = StrPos; + LineNo++; + } + StrPos++; + } + if (*StrPos == 0) { + break; + } + + // Check for opening quote + if (*StrPos != '"') { + Error = true; + sprintf( ErrorText, "Expect opening '\"' for param name on line %d [%ld]", LineNo, StrPos-LineMark ); + break; + } + + // Mark start of param name + StrPos++; + Mark = StrPos; + + // Check for closing quote + if (!(StrPos = strchr( StrPos, '"' ))) { + Error = true; + sprintf( ErrorText, "Expect closing '\"' for param name on line %d [%ld]", LineNo, Mark-LineMark ); + break; + } + + // Validate size of Param name + if (StrPos - Mark == 0) { + Error = true; + sprintf( ErrorText, "Empty parameter name on line %d [%ld]", LineNo, StrPos-LineMark ); + break; + } + + // Copy Parameter name + memcpy( ParamName, Mark, (StrPos-Mark) ); + ParamName[(StrPos-Mark)] = 0; + StrPos++; + + // Skip white space + while (isspace(*StrPos)) { + if (*StrPos == '\n') { + LineMark = StrPos; + LineNo++; + } + StrPos++; + } + + // Check for delimiter + if (*StrPos != ':') { + Error = true; + sprintf( ErrorText, "Expected ':' delimiter on line %d [%ld]", LineNo, StrPos-LineMark ); + break; + } + StrPos++; + + // Skip white space + while (isspace(*StrPos)) { + if (*StrPos == '\n') { + LineMark = StrPos; + LineNo++; + } + StrPos++; + } + + // Mark start value + Mark = StrPos; + + // Get Value + if (*StrPos == '"') + { + // Quoted values + // Check for closing quote + StrPos++; + if (!(StrPos = strchr( StrPos, '"' ))) { + Error = true; + sprintf( ErrorText, "Expect closing '\"' for param value on line %d [%ld]", LineNo, Mark-LineMark ); + break; + } + + // Create new string Parameter + SetParamStr( ParamName, Mark+1, StrPos-Mark-2 ); + StrPos++; + } + else + { + // Primitive Values + // Get end of value + while ((*StrPos != 0) && !isspace(*StrPos) && (*StrPos != ',')) { + StrPos++; + } + + // Analyze value + if (StrPos - Mark == 0) { + Error = true; + sprintf( ErrorText, "Missing param value on line %d [%ld]", LineNo, Mark-LineMark ); + break; + } + else if ((StrPos-Mark == 4) && !strncasecmp( Mark, "true", 4 )) { + // Create new boolean Parameter + SetParamBool( ParamName, true ); + } + else if ((StrPos-Mark == 5) && !strncasecmp( Mark, "false", 4 )) { + // Create new boolean Parameter + SetParamBool( ParamName, false ); + } + else { + // Try conversion to int + IntVal = strtol( Mark, &EndMark, 10 ); + if (EndMark == StrPos) { + // Create new integer Parameter + SetParamInt( ParamName, IntVal ); + } + else { + // Try conversion to float + FloatVal = strtod( Mark, &EndMark ); + if (EndMark == StrPos) { + // Create new float Parameter + SetParamFloat( ParamName, FloatVal ); + } + else { + Error = true; + sprintf( ErrorText, "Invalid primitive param value on line %d [%ld]", LineNo, Mark-LineMark ); + break; + } + } + } + } + + // Skip white space + while (isspace(*StrPos)) { + if (*StrPos == '\n') { + LineMark = StrPos; + LineNo++; + } + StrPos++; + } + + // Check if more parameters to follow + if ((*StrPos != ',') && (*StrPos != 0)) { + Error = true; + sprintf( ErrorText, "Parameter separator ',' expected on line %d [%ld]", LineNo, StrPos-LineMark ); + break; + } + StrPos++; + } + } + + return ((Error)? false : true); +} +//--------------------------------------------------------------------------- + +bool CConfigCore::SaveFile( const char * FilePath, const int ValueTab ) +{ + FILE * OutputFile = NULL; + TConfigParam * Param; + int SpacerLen; + char Spacer[50]; + + // Validate + if (!FilePath || !FilePath[0]) + return false; + + // Open file + if (!(OutputFile = fopen( FilePath, "w" ))) + return false; + + // Save parameters + for (Param = FirstParam; Param != NULL; (Param = Param->Next)) + { + // Write parameter name + fprintf( OutputFile, "\"%s\":", Param->Name ); + + // Create fixed offset for values + SpacerLen = ValueTab - (strlen(Param->Name) + 3); + if (SpacerLen > 0) { + memset( Spacer, ' ', SpacerLen ); + Spacer[SpacerLen] = 0; + fwrite( Spacer, 1, SpacerLen, OutputFile ); + } + + switch (Param->Type) + { + case jtBool : + case jtInt : + case jtFloat : + fprintf( OutputFile, "%s,\n", Param->Value ); + break; + + case jtString : + fprintf( OutputFile, "\"%s\",\n", Param->Value ); + break; + + default : + break; + } + } + + // Close file + fclose( OutputFile ); + return false; +} +//--------------------------------------------------------------------------- + diff --git a/ConfigCore.h b/ConfigCore.h new file mode 100644 index 0000000..27fc100 --- /dev/null +++ b/ConfigCore.h @@ -0,0 +1,97 @@ +/* + * ConfigCore.h + * + * Created on: 5 Mar 2017 + * Author: wentzelc + */ + +#ifndef REDACORE_CONFIGCORE_H_ +#define REDACORE_CONFIGCORE_H_ + +// redA Libraries +/* none */ + +// Standard C/C++ Libraries +#include +#include + +//--------------------------------------------------------------------------- + +typedef enum { jtNone = 0, jtBool = 1, jtInt = 2, jtFloat = 3, jtString = 4, jtArray = 5, jtObject = 6 } EJSONtype; + +//--------------------------------------------------------------------------- + +// Structure prototypes +typedef struct SConfigParam TConfigParam; + +// One Config Parameters +struct SConfigParam { + char * Name; + EJSONtype Type; + char * Value; + int Len; + + TConfigParam * Next; +}; + +//--------------------------------------------------------------------------- + +class CConfigCore +{ +private: + TConfigParam * FirstParam; + + // Find Param + inline TConfigParam * GetParam( const char * Name ) { + TConfigParam * Param = FirstParam; + while (Param && strcasecmp( Param->Name, Name )) + Param = Param->Next; + return Param; + } + inline TConfigParam ** GetParamPtr( const char * Name ) { + TConfigParam ** Param = &FirstParam; + while (*Param && strcasecmp( (*Param)->Name, Name )) + Param = &((*Param)->Next); + return Param; + } + + // Create Param + inline TConfigParam * FindCreateParam( const char * Name ) { + TConfigParam ** Param = NULL; + if (!*(Param = GetParamPtr( Name ))) { + *Param = (TConfigParam *)calloc( 1, sizeof(TConfigParam) ); + (*Param)->Name = (char *)calloc( 1, strlen( Name )+1 ); + strcpy( (*Param)->Name, Name ); + } + return (*Param); + } + + // Manage Parameters + bool SetParam( TConfigParam * Param, EJSONtype Type, const char * Value, const int Len ); + bool DestroyParam( TConfigParam ** Param ); + +public: + CConfigCore(); + ~CConfigCore(); + + bool SetParamStr( const char * Name, const char * Value = NULL, const int Len = -1 ); + bool SetParamInt( const char * Name, const long Value ); + bool SetParamFloat( const char * Name, const double Value ); + bool SetParamBool( const char * Name, const bool Value ); + + const EJSONtype GetParamType( const char * Name ); + + const char * GetParamStr( const char * Name, const char * Default = NULL ); + const char * GetParamStr( const char * Name, int &Len, const char * Default = NULL ); + const long GetParamInt( const char * Name, long Default = 0 ); + const double GetParamFloat( const char * Name, double Default = 0.0 ); + const bool GetParamBool( const char * Name, bool Default = false ); + + bool DeleteParam( const char * Name ); + bool DeleteAll(); + + bool LoadFile( const char * FilePath ); + bool SaveFile( const char * FilePath, const int ValueTab = 20 ); +}; + +#endif /* REDACORE_CONFIGCORE_H_ */ diff --git a/SignalCore.cpp b/SignalCore.cpp index 82bb19e..190ab2c 100644 --- a/SignalCore.cpp +++ b/SignalCore.cpp @@ -21,7 +21,7 @@ // Global vars extern CLogCore * Log; -extern char ProcessName[]; +extern char ProcessName[]; // Termination Vars bool Terminate = false;