You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
configreader/sectionstore.c

283 lines
8.6 KiB

#include "sectionstore.h"
#include "containers/sectionmap.h"
#include "containers/sectionarray.h"
#include "containers/stringarray.h"
#include "containers/linearray.h"
#include "cregex/pattern.h"
#include <proto/exec.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#define RX_SECTION_LINE "^[ \t\n\r\f\v]*\\[([a-z0-9]+)([ \t\n\r\f\v]*\"(.+)\")*\\][ \t\n\r\f\v]*($|#|;)"
#define RX_VARIABLE_LINE "^[ \t\n\r\f\v]*([a-z][a-z0-9]+)[ \t\n\r\f\v]*=[ \t\n\r\f\v]*(.+)[ \t\n\r\f\v]*($|#|;)"
#define RX_INTEGER "^-?[1-9][0-9]*$"
#define RX_BLANK_LINE "^[ \t\n\r\f\v]*($|#|;)"
STATIC SECTIONPTR parseSection(LINEPTR line, PATTERNPTR sectionPatternProgram);
STATIC VARIABLEPTR parseVariable(LINEPTR line, PATTERNPTR variablePatternProgram);
STATIC BOOL parseBlank(LINEPTR line, PATTERNPTR blankPatternProgram);
STATIC BOOL parseBoolValue(CONST_STRPTR value, BOOL* outBool);
STATIC BOOL parseIntegerValue(CONST_STRPTR value, LONG* outInt, PATTERNPTR integerProgram);
struct SectionStore
{
SectionMap map;
SectionArray array;
// here so we only create them once not each line
PATTERNPTR sectionPatternProgram;
PATTERNPTR variablePatternProgram;
PATTERNPTR blankPatternProgram;
PATTERNPTR integerPatternProgram;
};
SECTIONSTOREPTR SectionStoreNew(VOID)
{
struct SectionStore* result = AllocVec(sizeof(struct SectionStore), MEMF_CLEAR);
result->map = SectionMapNew();
result->array = SectionArrayNew();
result->sectionPatternProgram = PatternNew(RX_SECTION_LINE);
result->variablePatternProgram = PatternNew(RX_VARIABLE_LINE);
result->blankPatternProgram = PatternNew(RX_BLANK_LINE);
result->integerPatternProgram = PatternNew(RX_INTEGER);
return result;
}
VOID SectionStoreFree(SECTIONSTOREPTR abstractSectionStore)
{
if( abstractSectionStore != NULL )
{
struct SectionStore* store = (struct SectionStore*)abstractSectionStore;
if( store->map != NULL ) SectionMapFree( store->map );
if( store->array != NULL ) SectionArrayFree( store->array, TRUE );//free teh sections
if( store->sectionPatternProgram != NULL ) PatternFree(store->sectionPatternProgram);
if( store->variablePatternProgram != NULL ) PatternFree(store->variablePatternProgram);
if( store->blankPatternProgram != NULL ) PatternFree(store->blankPatternProgram);
if( store->integerPatternProgram != NULL ) PatternFree(store->integerPatternProgram);
FreeVec(store);
}
}
VOID SectionStoreAddSection(SECTIONSTOREPTR abstractSectionStore, SECTIONPTR section)
{
struct SectionStore* store = (struct SectionStore*)abstractSectionStore;
if( store != NULL && section != NULL )
{
CONST_STRPTR canonicalName = SectionCanonicalName(section);
if( canonicalName != NULL )
{
// the array acts as storage as it can free its contents
SectionArrayAppend(store->array, section);
// the map will copy the string key and free it, but not the section
SectionMapSet(store->map, canonicalName, section);
//free the canonical name as the map has copied it.
FreeVec((STRPTR)canonicalName);
}
}
}
SECTIONPTR SectionStoreGetSection(SECTIONSTOREPTR abstractSectionStore, CONST_STRPTR canonicalName)
{
struct SectionStore* store = (struct SectionStore*)abstractSectionStore;
if( store != NULL && canonicalName != NULL )
{
return SectionMapGet(store->map, canonicalName);
}
}
SECTIONPTR SectionStoreCurrentSection(SECTIONSTOREPTR abstractSectionStore)
{
struct SectionStore* store = (struct SectionStore*)abstractSectionStore;
SECTIONPTR result = NULL;
if( store != NULL && SizeOfArray(store->array) > 0 )
{
result = ArrayBackValue(SECTIONPTR, store->array);
}
return result;
}
LineArray SectionStoreFindLines(SECTIONSTOREPTR sectionStore, CONST_STRPTR canonicalSectionName, CONST_STRPTR varKey)
{
LineArray result = LineArrayNew();
SECTIONPTR section = SectionStoreGetSection(sectionStore, canonicalSectionName);
if( section != NULL )
{
SectionCollectLinesForVariable(section, varKey, result);
}
return result;
}
VariableArray SectionStoreGetAll(SECTIONSTOREPTR sectionStore, CONST_STRPTR canonicalSectionName, CONST_STRPTR varKey)
{
VariableArray result = VariableArrayNew();
LineArray lines = SectionStoreFindLines(sectionStore, canonicalSectionName, varKey);
ULONG index = 0;
for( index = 0; index < SizeOfArray(lines); index++)
{
LINEPTR line = LineArrayValues(lines)[index];
VariableArrayAppend(result, LineGetVariable(line));
}
LineArrayFree(lines, FALSE);
return result;
}
VARIABLEPTR SectionStoreGet(SECTIONSTOREPTR sectionStore, CONST_STRPTR canonicalSectionName, CONST_STRPTR varKey)
{
VARIABLEPTR result = NULL;
LineArray lines = SectionStoreFindLines(sectionStore, canonicalSectionName, varKey);
result = LineGetVariable((LINEPTR)ArrayBackValue(LINEPTR, lines));
LineArrayFree(lines, FALSE);
return result;
}
VOID SectionStoreAddLineToCurrentSection(SECTIONSTOREPTR abstractSectionStore, LINEPTR line)
{
struct SectionStore* store = (struct SectionStore*)abstractSectionStore;
if( store != NULL )
{
// if its a new section, just add it and move on
SECTIONPTR section = parseSection(line, store->sectionPatternProgram);
if( section )
{
SectionStoreAddSection(store, section);
SectionAddSectionLine(section, line);
}
else
{
// if its a variable or blank, parse it and add to current section
VARIABLEPTR variable = NULL;
section = SectionStoreCurrentSection(store);
// if no current section, we're adding variables at the state so create a blank section
if( section == NULL )
{
section = SectionCreateWithName("");
SectionStoreAddSection(store, section);
}
if( variable = parseVariable(line, store->variablePatternProgram) )
{
LineSetInitialVariable(line, variable);
SectionAddLine(section, line);
}
else
{
if( parseBlank(line, store->blankPatternProgram) )
{
SectionAddLine(section, line);
}
else
{
// wasnt a section, a variable or a comment so ignore it or complain
}
}
}
}
}
ULONG SectionStoreSectionCount(SECTIONSTOREPTR abstractSectionStore)
{
ULONG result = 0;
struct SectionStore* store = (struct SectionStore*)abstractSectionStore;
if( store != NULL )
{
return SizeOfArray(store->array);
}
return result;
}
SECTIONPTR SectionStoreSectionAt(SECTIONSTOREPTR abstractSectionStore, ULONG index)
{
SECTIONPTR result = NULL;
struct SectionStore* store = (struct SectionStore*)abstractSectionStore;
if( store != NULL )
{
if( index < SizeOfArray(store->array) )
{
result = SectionArrayValues(store->array)[index];
}
}
return result;
}
// ---------------------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------
// PRIVATE
// ---------------------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------
STATIC VARIABLEPTR parseVariable(LINEPTR line, PATTERNPTR variablePatternProgram)
{
VARIABLEPTR result = NULL;
StringArray matches = NULL;
if( matches = PatternRun(LineGetRawText(line), variablePatternProgram) )
{
result = VariableCreate(StringArrayValues(matches)[1], StringArrayValues(matches)[2]);
StringArrayFree(matches, TRUE);
}
return result;
}
STATIC SECTIONPTR parseSection(LINEPTR line, PATTERNPTR sectionPatternProgram)
{
SECTIONPTR result = NULL;
StringArray matches = NULL;
if( matches = PatternRun(LineGetRawText(line), sectionPatternProgram) )
{
if( SizeOfArray(matches) == 3 )
{
result = SectionCreateWithName(StringArrayValues(matches)[1]);
}
else if( SizeOfArray(matches) == 5 )
{
result = SectionCreateWithNameAndSubname(StringArrayValues(matches)[1], StringArrayValues(matches)[3]);
}
StringArrayFree(matches, TRUE);
}
return result;
}
STATIC BOOL parseBoolValue(CONST_STRPTR value, BOOL* outBool)
{
BOOL result = FALSE;
if( strcmp(value, "yes") == 0 || strcmp(value, "true") == 0 || strcmp(value, "on") == 0 ) {
*outBool = TRUE;
result = TRUE;
}
if( strcmp(value, "no") == 0 || strcmp(value, "false") == 0 || strcmp(value, "off") == 0 ) {
*outBool = FALSE;
result = TRUE;
}
return result;
}
STATIC BOOL parseIntegerValue(CONST_STRPTR value, LONG* outInt, PATTERNPTR integerProgram)
{
BOOL result = FALSE;
StringArray matches = NULL;
if( matches = PatternRun(value, integerProgram) )
{
StringArrayFree(matches, TRUE);
*outInt = atol(value);
result = TRUE;
}
return result;
}
STATIC BOOL parseBlank(LINEPTR line, PATTERNPTR blankPatternProgram)
{
BOOL result = FALSE;
StringArray matches = NULL;
if( matches = PatternRun(LineGetRawText(line), blankPatternProgram) )
{
result = TRUE;
StringArrayFree(matches, TRUE);
}
return result;
}