parent
3002564ccd
commit
d1d26c96d1
@ -0,0 +1,331 @@ |
||||
#include "types.h" |
||||
#include "configfile.h" |
||||
#include "configmodel.h" |
||||
#include "sectionstore.h" |
||||
|
||||
#include "containers/stringarray.h" |
||||
#include "containers/sectionarray.h" |
||||
#include <proto/exec.h> |
||||
#include <proto/dos.h> |
||||
#include <string.h> |
||||
// #include <stdio.h>
|
||||
// #include <stdlib.h>
|
||||
// #include <ctype.h>
|
||||
|
||||
#define ZERO ((BPTR)0) |
||||
|
||||
STATIC SECTIONPTR findOrCreateSection(SECTIONSTOREPTR sectionStore, CONST_STRPTR compoundKey); |
||||
STATIC LINEPTR configFileReadLine(BPTR file); |
||||
|
||||
|
||||
// - STRUCTS -----------------------------------------------------------------------------
|
||||
struct ConfigFile |
||||
{ |
||||
CONST_STRPTR filename; |
||||
SECTIONSTOREPTR sectionStore; |
||||
}; |
||||
|
||||
// ---------------------------------------------------------------------------------------
|
||||
// - CONFIG FILE -------------------------------------------------------------------------
|
||||
// ---------------------------------------------------------------------------------------
|
||||
|
||||
VOID ConfigFileFree(CONFIGFILEPTR abstractConfigFile) |
||||
{ |
||||
struct ConfigFile* configFile = (struct ConfigFile*)abstractConfigFile; |
||||
if( configFile != NULL ) |
||||
{ |
||||
if( configFile->sectionStore != NULL ) |
||||
{ |
||||
SectionStoreFree(configFile->sectionStore); |
||||
} |
||||
FreeVec(configFile); |
||||
} |
||||
} |
||||
|
||||
CONFIGFILEPTR ConfigFileRead(CONST_STRPTR filename) |
||||
{ |
||||
struct ConfigFile* result = NULL; |
||||
BPTR configFile = Open(filename, MODE_OLDFILE); |
||||
if( configFile != ZERO ) |
||||
{ |
||||
|
||||
LINEPTR line = NULL; |
||||
result = AllocVec(sizeof(struct ConfigFile), MEMF_CLEAR); |
||||
result->sectionStore = SectionStoreNew(); |
||||
while( (line = configFileReadLine(configFile)) != NULL ) |
||||
{ |
||||
SectionStoreAddLineToCurrentSection(result->sectionStore, line); |
||||
//LineDump(line);
|
||||
} |
||||
Close(configFile); |
||||
} |
||||
|
||||
return result; |
||||
} |
||||
|
||||
|
||||
// a key is "foo.bar.baz.blah" where "foo" is the primary section name
|
||||
// "bar.baz" is the secondary section name and "blah" is the variable name.
|
||||
// this splits foo.bar.baz.blah into foo, bar.baz amd blah.
|
||||
// section, subsection and variable.
|
||||
// we'll get empty strings for the parts that arent present
|
||||
StringArray ConfigFileSplitKeyCompletely(CONST_STRPTR key) |
||||
{ |
||||
StringArray result = StringArrayNew(); |
||||
StringArray parts = StringArrayNew(); |
||||
ULONG numberOfParts = 0; |
||||
|
||||
STRPTR token = NULL; |
||||
// we need to make a copy of the key because strtok modifies it.
|
||||
STRPTR keyCopy = AllocVec(strlen(key)+1, MEMF_CLEAR); |
||||
CopyMem(key, keyCopy, strlen(key)); |
||||
|
||||
token = strtok(keyCopy, "."); |
||||
while (token != NULL) |
||||
{ |
||||
StringArrayAppendAndRetain(parts, token); |
||||
token = strtok(NULL, "."); |
||||
} |
||||
FreeVec(keyCopy); |
||||
|
||||
// now we join all but the first and last part
|
||||
numberOfParts = SizeOfArray(parts); |
||||
if( numberOfParts == 1 ) //just a variable ["","","var"]
|
||||
{ |
||||
StringArrayAppendAndRetain(result, ""); |
||||
StringArrayAppendAndRetain(result, ""); |
||||
StringArrayAppendAndRetain(result, (STRPTR)ArrayBackValue(STRPTR, parts)); |
||||
} |
||||
else if( numberOfParts == 2 ) // section and variable ["section","","var"]
|
||||
{ |
||||
StringArrayAppendAndRetain(result, StringArrayValues(parts)[0]); |
||||
StringArrayAppendAndRetain(result, ""); |
||||
StringArrayAppendAndRetain(result, StringArrayValues(parts)[1]); |
||||
} |
||||
else if( numberOfParts == 3 ) // section and subsection and variable ["section","subsec","var"]
|
||||
{ |
||||
StringArrayAppendAndRetain(result, StringArrayValues(parts)[0]); |
||||
StringArrayAppendAndRetain(result, StringArrayValues(parts)[1]); |
||||
StringArrayAppendAndRetain(result, StringArrayValues(parts)[2]); |
||||
} |
||||
else if( numberOfParts > 3 ) // subsections needs dotted ["section", "subsec1.subsec2", "var""]
|
||||
{ |
||||
StringArrayAppendAndRetain(result, StringArrayValues(parts)[0]); //section
|
||||
|
||||
// start at index 1, and add (size -2 (start+end)) parts
|
||||
StringArrayAppend(result, StringArrayJoinedParts(parts, '.', 1, SizeOfArray(parts)-2)); |
||||
|
||||
StringArrayAppendAndRetain(result, (STRPTR)ArrayBackValue(STRPTR, parts)); // variable
|
||||
} |
||||
StringArrayFree(parts, TRUE); |
||||
return result; |
||||
} |
||||
|
||||
StringArray ConfigFileSplitKeyForVar(CONST_STRPTR key) |
||||
{ |
||||
// a key is "foo.bar.baz.blah" where "foo" is the primary section name
|
||||
// "bar.baz" is the secondary section name and "blah" is the variable name.
|
||||
// In this case we'll just break it down into the canonical section name,
|
||||
// foo.bar.baz and the variable name blah.
|
||||
|
||||
StringArray result = StringArrayNew(); |
||||
StringArray parts = StringArrayNew(); |
||||
STRPTR sectionPart = NULL; |
||||
STRPTR varPart = NULL; |
||||
|
||||
STRPTR token = NULL; |
||||
// we need to make a copy of the key because strtok modifies it.
|
||||
STRPTR keyCopy = AllocVec(strlen(key)+1, MEMF_CLEAR); |
||||
CopyMem(key, keyCopy, strlen(key)); |
||||
|
||||
token = strtok(keyCopy, "."); |
||||
while (token != NULL) |
||||
{ |
||||
StringArrayAppendAndRetain(parts, token); |
||||
token = strtok(NULL, "."); |
||||
} |
||||
FreeVec(keyCopy); |
||||
|
||||
// now we join all but the last part
|
||||
sectionPart = StringArrayJoinedParts(parts, '.', 0, SizeOfArray(parts)-1); |
||||
StringArrayAppend(result, sectionPart); // its been alloced so dont copy
|
||||
varPart = (STRPTR)ArrayBackValue(STRPTR, parts); |
||||
StringArrayAppendAndRetain(result, varPart); // its a reference so copy
|
||||
StringArrayFree(parts, TRUE); |
||||
return result; |
||||
} |
||||
|
||||
STRPTR ConfigFileGet(CONFIGFILEPTR abstractConfigFile, CONST_STRPTR compoundKey) |
||||
{ |
||||
STRPTR result = NULL; |
||||
struct ConfigFile* configFile = (struct ConfigFile*)abstractConfigFile; |
||||
if( configFile != NULL ) |
||||
{ |
||||
StringArray split = ConfigFileSplitKeyForVar(compoundKey); |
||||
VARIABLEPTR var = SectionStoreGet(configFile->sectionStore, StringArrayValues(split)[0], StringArrayValues(split)[1]); |
||||
if( var != NULL ) |
||||
{ |
||||
CONST_STRPTR value = VariableGetRawValue(var); |
||||
result = AllocVec(strlen(value)+1, MEMF_CLEAR); |
||||
CopyMem(value, result, strlen(value)); |
||||
} |
||||
StringArrayFree(split, TRUE); |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
StringArray ConfigFileGetAll(CONFIGFILEPTR abstractConfigFile, CONST_STRPTR compoundKey) |
||||
{ |
||||
StringArray result = StringArrayNew(); |
||||
ULONG index = 0; |
||||
struct ConfigFile* configFile = (struct ConfigFile*)abstractConfigFile; |
||||
if( configFile != NULL ) |
||||
{ |
||||
StringArray split = ConfigFileSplitKeyForVar(compoundKey); |
||||
VariableArray vars = SectionStoreGetAll(configFile->sectionStore, StringArrayValues(split)[0], StringArrayValues(split)[1]); |
||||
for( index = 0; index < SizeOfArray(vars); index++ ) |
||||
{ |
||||
StringArrayAppendAndRetain(result, VariableGetRawValue(VariableArrayValues(vars)[index])); |
||||
} |
||||
VariableArrayFree(vars, FALSE); |
||||
StringArrayFree(split, TRUE); |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
VOID ConfigFileAdd(CONFIGFILEPTR abstractConfigFile, CONST_STRPTR compoundKey, CONST_STRPTR stringValue) |
||||
{ |
||||
struct ConfigFile* configFile = (struct ConfigFile*)abstractConfigFile; |
||||
if( configFile != NULL ) |
||||
{ |
||||
SECTIONPTR section = NULL; |
||||
VARIABLEPTR var = NULL; |
||||
CONST_STRPTR varLine = NULL; |
||||
LINEPTR line = NULL; |
||||
|
||||
StringArray canonicalParts = ConfigFileSplitKeyForVar(compoundKey); |
||||
var = VariableCreate(StringArrayValues(canonicalParts)[1], stringValue); |
||||
varLine = VariableSerialize(var); |
||||
line = LineNew(varLine); |
||||
LineSetInitialVariable(line, var); |
||||
FreeVec((STRPTR)varLine); |
||||
StringArrayFree(canonicalParts, TRUE); |
||||
|
||||
// now get the section
|
||||
section = findOrCreateSection(configFile->sectionStore, compoundKey); |
||||
// add the line to the section
|
||||
SectionAddLine(section, line);
|
||||
} |
||||
} |
||||
|
||||
VOID ConfigFileSet(CONFIGFILEPTR abstractConfigFile, CONST_STRPTR compoundKey, CONST_STRPTR stringValue) |
||||
{ |
||||
struct ConfigFile* configFile = (struct ConfigFile*)abstractConfigFile; |
||||
if( configFile != NULL ) |
||||
{ |
||||
StringArray parts = ConfigFileSplitKeyCompletely(compoundKey); |
||||
|
||||
StringArrayFree(parts, TRUE); |
||||
} |
||||
} |
||||
|
||||
VOID ConfigFileReplaceAll(CONFIGFILEPTR abstractConfigFile, CONST_STRPTR compoundKey, CONST_STRPTR stringValue) |
||||
{ |
||||
struct ConfigFile* configFile = (struct ConfigFile*)abstractConfigFile; |
||||
if( configFile != NULL ) |
||||
{ |
||||
StringArray parts = ConfigFileSplitKeyCompletely(compoundKey); |
||||
|
||||
StringArrayFree(parts, TRUE); |
||||
} |
||||
} |
||||
|
||||
VOID ConfigFileUnset(CONFIGFILEPTR abstractConfigFile, CONST_STRPTR compoundKey, CONST_STRPTR stringValue) |
||||
{ |
||||
struct ConfigFile* configFile = (struct ConfigFile*)abstractConfigFile; |
||||
if( configFile != NULL ) |
||||
{ |
||||
StringArray parts = ConfigFileSplitKeyCompletely(compoundKey); |
||||
|
||||
StringArrayFree(parts, TRUE); |
||||
} |
||||
} |
||||
|
||||
VOID ConfigFileUnsetAll(CONFIGFILEPTR abstractConfigFile, CONST_STRPTR compoundKey, CONST_STRPTR stringValue) |
||||
{ |
||||
struct ConfigFile* configFile = (struct ConfigFile*)abstractConfigFile; |
||||
if( configFile != NULL ) |
||||
{ |
||||
StringArray parts = ConfigFileSplitKeyCompletely(compoundKey); |
||||
|
||||
StringArrayFree(parts, TRUE); |
||||
} |
||||
} |
||||
|
||||
VOID ConfigFileDump(CONFIGFILEPTR abstractConfigFile) |
||||
{ |
||||
ULONG index = 0; |
||||
ULONG count = 0; |
||||
struct ConfigFile* configFile = (struct ConfigFile*)abstractConfigFile; |
||||
if( configFile != NULL ) |
||||
{ |
||||
count = SectionStoreSectionCount(configFile->sectionStore); |
||||
for( index = 0; index < count; index++ ) |
||||
{ |
||||
SECTIONPTR section = SectionStoreSectionAt(configFile->sectionStore, index); |
||||
SectionDump(section); |
||||
} |
||||
} |
||||
} |
||||
|
||||
STATIC LINEPTR configFileReadLine(BPTR file) |
||||
{ |
||||
UBYTE* buffer = AllocVec(512, MEMF_CLEAR); |
||||
ULONG bufLength = 512; |
||||
ULONG bytesReadTotal = 0; |
||||
UBYTE* read = NULL; |
||||
struct Line* result = NULL; |
||||
|
||||
// read the whole line including continuation
|
||||
do |
||||
{ |
||||
read = FGets(file, &(buffer[bytesReadTotal]), bufLength-bytesReadTotal); |
||||
bytesReadTotal = strlen(buffer); |
||||
}
|
||||
while( read != NULL && bytesReadTotal >= 2 && bytesReadTotal < bufLength && buffer[bytesReadTotal-1] == '\n' && buffer[bytesReadTotal-2] == '\\' ); |
||||
|
||||
|
||||
// make a line
|
||||
if( bytesReadTotal > 0 ) |
||||
{ |
||||
buffer[bytesReadTotal] = '\0'; |
||||
result = LineNew(buffer); |
||||
} |
||||
|
||||
FreeVec(buffer); |
||||
return result;
|
||||
} |
||||
|
||||
STATIC SECTIONPTR findOrCreateSection(SECTIONSTOREPTR sectionStore, CONST_STRPTR compoundKey) |
||||
{ |
||||
// now get the section
|
||||
StringArray canonicalParts = ConfigFileSplitKeyForVar(compoundKey); |
||||
SECTIONPTR section = section = SectionStoreGetSection(sectionStore, StringArrayValues(canonicalParts)[0]); |
||||
if( section == NULL ) |
||||
{ |
||||
StringArray separateParts = ConfigFileSplitKeyCompletely(compoundKey); |
||||
CONST_STRPTR sectionLineText = NULL; |
||||
LINEPTR sectionLine = NULL; |
||||
|
||||
section = SectionCreateWithNameAndSubname(StringArrayValues(separateParts)[0], StringArrayValues(separateParts)[1]); |
||||
sectionLineText = SectionSerialize(section); |
||||
sectionLine = LineNew(sectionLineText); |
||||
SectionAddSectionLine(section, sectionLine); |
||||
FreeVec((STRPTR)sectionLineText); |
||||
SectionStoreAddSection(sectionStore, section); //section store will free it for us
|
||||
StringArrayFree(separateParts, TRUE); |
||||
} |
||||
StringArrayFree(canonicalParts, TRUE); |
||||
return section; |
||||
} |
||||
|
Loading…
Reference in new issue