/*=========================================================================== * * File: GenCFG.CPP * Author: Dave Humphrey (uesp@m0use.net) * Created On: Friday, December 08, 2000 * * Implements the CConfigFile class, a general config loading/parsing/saving * class for handling text configuration files easily. * *=========================================================================*/ /* Include Files */ #include "gencfg.h" #undef __FUNC__ #define __FUNC__ "CConfigRecord::CConfigRecord()" /*=========================================================================== * * Class CConfigRecord Constructor * *=========================================================================*/ CConfigRecord::CConfigRecord (void) { pName = NULL; NumValues = 0; } /*=========================================================================== * End of Class CConfigRecord Constructor *=========================================================================*/ #undef __FUNC__ #define __FUNC__ "CConfigRecord::Destroy()" /*=========================================================================== * * Class CConfigRecord Destructor * *=========================================================================*/ void CConfigRecord::Destroy (void) { int LoopCounter; /* Delete all the parameter values */ for (LoopCounter = 0; LoopCounter < NumValues; LoopCounter++) { DestroyPointer(pValues[LoopCounter]); } /* Unallocate the parameter name */ DestroyPointerArray(pName); NumValues = 0; } /*=========================================================================== * End of Class CConfigRecord Destructor *=========================================================================*/ #undef __FUNC__ #define __FUNC__ "CConfigRecord::AddValue()" /*=========================================================================== * * Class CConfigRecord Method - boolean AddValue (pString); * * Attempts to add a value to the parameter record. Returns * FALSE on any error. * *=========================================================================*/ boolean CConfigRecord::AddValue (const char* pString) { /* Make sure the values are valid */ ASSERT(pString != NULL); /* Is there enough room in array to fit new record? */ CHECK_MAXINDEX(NumValues, MAX_CFG_VALUES, FALSE); /* Allocate the new item */ CreatePointer(pValues[NumValues], CVariant); /* Set the contents of the new value */ pValues[NumValues]->SetPChar(pString); /* Return success */ NumValues++; return (TRUE); } /*=========================================================================== * End of Class Method CConfigRecord::AddValue() *=========================================================================*/ #undef __FUNC__ #define __FUNC__ "CConfigRecord::MatchName()" /*=========================================================================== * * Class CConfigRecord Method - boolean MatchName (pString, CaseSensitive); * * Compares the given string and the variable name returning TRUE if * they are identical. Use the case sensitivity flag to specify whether * character case matters. * *=========================================================================*/ boolean CConfigRecord::MatchName (const char* pString, const boolean CaseSensitive) { return MatchString(pName, pString, CaseSensitive); } /*=========================================================================== * End of Class Method CConfigRecord::MatchName() *=========================================================================*/ #undef __FUNC__ #define __FUNC__ "CConfigRecord::SetValue()" /*=========================================================================== * * Class CConfigRecord Method - boolean SetValue (Index, pString); * * Sets the parameter value if present to the appropiate value. Returns * FALSE on any error. * *=========================================================================*/ boolean CConfigRecord::SetValue (const int Index, const char* pString) { /* Is the index valid? */ CHECK_VALIDINDEX(Index, NumValues, FALSE); /* Set the value */ pValues[Index]->SetPChar(pString); return (TRUE); } /*=========================================================================== * End of Class Method CConfigRecord::SetValue() *=========================================================================*/ #undef __FUNC__ #define __FUNC__ "CConfigFile::CConfigFile()" /*=========================================================================== * * Class CConfigFile Constructor * *=========================================================================*/ CConfigFile::CConfigFile () { NumVariables = 0; LineCount = 0; VariableSepChar = '='; ValueSepChar = ','; CommentSepChar = '#'; pFilename = NULL; } /*=========================================================================== * End of CConfigFile Constructor *=========================================================================*/ #undef __FUNC__ #define __FUNC__ "CConfigFile::Destroy()" /*=========================================================================== * * Class CConfigFile Destructor * *=========================================================================*/ void CConfigFile::Destroy (void) { LineCount = 0; /* Delete any allocated variable records */ DELETE_POINTERARRAY(pVariables, NumVariables); } /*=========================================================================== * End of Class CConfigFile Destructor *=========================================================================*/ #undef __FUNC__ #define __FUNC__ "CConfigFile::AddVariable()" /*=========================================================================== * * Class CConfigFile Method - int AddVariable (pName); * * Attempts to add the reference to a variable. Returns the index of the * variable record or NULL_VAR_INDEX on error. * *=========================================================================*/ int CConfigFile::AddVariable (const char* pName) { /* Is the input valid? */ ASSERT(pName != NULL); /* Ignore an empty variable name */ if (*pName == NULL_CHAR) return (-1); /* Is there enough room in array to add record? */ CHECK_MAXINDEX(NumVariables, MAX_CFG_VARS, NULL_VAR_INDEX); /* Create the array record */ CreatePointer(pVariables[NumVariables], CConfigRecord); /* Set the new variable contents */ pVariables[NumVariables]->SetName(pName); NumVariables++; /* Return the new variable index */ return (NumVariables - 1); } /*=========================================================================== * End of Class Method CConfigFile::AddVariable() *=========================================================================*/ #undef __FUNC__ #define __FUNC__ "CConfigFile::FindVariable()" /*=========================================================================== * * Class CConfigFile Method - int FindVariable (pString); * * Attempts to find the specified variable name. Returns NULL_VAR_INDEX * on error or the found variable index on success * *=========================================================================*/ int CConfigFile::FindVariable (const char* pString) { int LoopCounter; /* Loop counter */ /* Ensure valid input */ CHECK_NULLPOINTER(pString, NULL_VAR_INDEX); /* Look for a match in the current records */ for (LoopCounter = 0; LoopCounter < NumVariables; LoopCounter++) { if (pVariables[LoopCounter]->MatchName(pString)) return (LoopCounter); } /* Nothing found? */ return (NULL_VAR_INDEX); } /*=========================================================================== * End of Class Method CConfigFile::FindVariable() *=========================================================================*/ #undef __FUNC__ #define __FUNC__ "CConfigFile::FindVariable()" /*=========================================================================== * * Class CConfigFile Method - boolean Load (pFilename); * * Attempts to load and parse the specified config filename. Returns * FALSE on any error. If the given filename is NULL, the current member * filename is used. * *=========================================================================*/ boolean CConfigFile::Load (const char* pCFGFilename) { char LineBuffer[CFG_LINE_SIZE+1]; /* Input buffer string */ FILE* pFileHandle; int Result; /* Attempt to open file with a valid filename */ if (pCFGFilename == NULL) pCFGFilename = pFilename; pFileHandle = openfile(pFilename, "rt"); if (!pFileHandle) return (FALSE); /* Delete any current contents */ Destroy(); /* Change the filename if required */ if (pCFGFilename != pFilename) SetFilename(pCFGFilename); /* Read in entire file line-by-line */ while (!feof(pFileHandle)) { /* Read the next line from the file */ Result = read_eol(pFileHandle, LineBuffer, CFG_LINE_SIZE); if (Result == READ_MSL) read_eol(pFileHandle); LineCount++; Result = ParseLine(LineBuffer); } /* Close file and return success */ fclose (pFileHandle); return (TRUE); } /*=========================================================================== * End of Class Method CONFIG_Class::load() *=========================================================================*/ #undef __FUNC__ #define __FUNC__ "CConfigFile::ParseLine()" /*=========================================================================== * * Class CConfigFile Method - boolean ParseLine (char* pString) * * Parses a line from the config file into the appropiate variable and * its values. * *=========================================================================*/ boolean CConfigFile::ParseLine (char* pString) { char* pParse; boolean Result; /* Remove any trailing/leading whitespace */ pParse = trim(pString); /* Parse out the variable name from the string */ Result = ParseVariable(&pString); if (!Result) return (FALSE); /* Parse all the values from the string */ while (*pString != NULL_CHAR) { Result = ParseValue(&pString); if (!Result) return (FALSE); } return (TRUE); } /*=========================================================================== * End of Class Method CConfigFile::ParseLine() *=========================================================================*/ #undef __FUNC__ #define __FUNC__ "CConfigFile::ParseVariable()" /*=========================================================================== * * Class CConfigFile Method - boolean ParseVariable (char** ppString) * * Parses the variable from the given line buffer. Returns FALSE on * any error. Protected class method. * *=========================================================================*/ boolean CConfigFile::ParseVariable (char** ppString) { char* pParse = *ppString; boolean Result; /* Parse until the variable or the end of string is reached */ while (*pParse != NULL_CHAR) { /* Check for invalid characters */ if (*pParse == '\'' || *pParse == '"' || *pParse == ValueSepChar) { SET_EXT_ERROR4(ERR_CUSTOM, "\t%5ld: Found invalid character '%c' in variable name!", LineCount, *pParse); return (FALSE); } /* Check for the end of the variable name */ else if (*pParse == VariableSepChar || *pParse == CommentSepChar) { if (*pParse == CommentSepChar) *(pParse + 1) = NULL_CHAR; /* Create the variable name */ *pParse = NULL_CHAR; *ppString = rtrim(*ppString); /* Attempt to add variable to class */ Result = AddVariable(*ppString); if (Result < 0) return (FALSE); *ppString = ltrim(pParse + 1); return (TRUE); } pParse++; } /* Variable name reached EOF */ *ppString = rtrim(*ppString); Result = AddVariable(*ppString); *ppString = pParse; return (Result); } /*=========================================================================== * End of Class Method CConfigFile::ParseVariable() *=========================================================================*/ #undef __FUNC__ #define __FUNC__ "CConfigFile::ParseValue()" /*=========================================================================== * * Class CConfigFile Method - boolean ParseValue (char** ppString) * * Parses out the next value from the string and adds it to the last * variable in the array. Returns FALSE on any error. Protected class * method. * *=========================================================================*/ boolean CConfigFile::ParseValue (char** ppString) { char* pValue = *ppString; char* pParse = *ppString; char LastQuote = NULL_CHAR; boolean Result; boolean NoTrim = FALSE; /* Parse until the value or the end of string is reached */ while (*pParse != NULL_CHAR) { /* Check for quotation characters */ if ((*pParse == '\'' || *pParse == '"')) { if (LastQuote == *pParse) { LastQuote = NULL; *pParse = NULL_CHAR; } else if (LastQuote == NULL_CHAR) { LastQuote = *pParse; pValue = pParse + 1; NoTrim = TRUE; } } /* Do nothing if inside a quote */ else if (LastQuote != NULL_CHAR) { } /* Check for the end of the value */ else if (*pParse == CommentSepChar || *pParse == ValueSepChar) { if (*pParse == CommentSepChar) *(pParse + 1) = NULL_CHAR; /* Create the value string */ *pParse = NULL_CHAR; if (!NoTrim) pValue = trim(pValue); /* Attempt to add the value to the current variable */ Result = pVariables[NumVariables - 1]->AddValue(pValue); *ppString = ltrim(pParse + 1); return (Result); } pParse++; } /* Value reached EOF */ if (!NoTrim) pValue = trim(pValue); Result = pVariables[NumVariables - 1]->AddValue(pValue); *ppString = pParse; return (Result); } /*=========================================================================== * End of Class Method CConfigFile::ParseValue() *=========================================================================*/