/* * 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; } //---------------------------------------------------------------------------