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/configfile.c

301 lines
8.4 KiB

#include "types.h"
#include "configfile.h"
#include "configmodel.h"
#include "sectionstore.h"
#include "containers/stringarray.h"
#include "containers/sectionarray.h"
#include "containers/linearray.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 LINEPTR configFileReadLine(BPTR file);
// - STRUCTS -----------------------------------------------------------------------------
struct ConfigFile
{
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);
}
if( configFile->filename != NULL )
{
FreeVec(configFile->filename);
}
FreeVec(configFile);
}
}
CONFIGFILEPTR ConfigFileReadName(CONST_STRPTR filename)
{
struct ConfigFile* result = NULL;
BPTR configFile = Open(filename, MODE_OLDFILE);
if( configFile != ZERO )
{
result = ConfigFileRead(configFile);
Close(configFile);
}
return result;
}
CONFIGFILEPTR ConfigFileRead(BPTR configFile)
{
struct ConfigFile* result = NULL;
LINEPTR line = NULL;
if( configFile != 0 )
{
UBYTE buffer[256];
if(NameFromFH(configFile, buffer, 256))// if we opened with a filename this is a waste, if not its necessary
{
result = AllocVec(sizeof(struct ConfigFile), MEMF_CLEAR);
result->sectionStore = SectionStoreNew();
result->filename = AllocVec(strlen(buffer)+1, MEMF_CLEAR);
CopyMem(buffer, result->filename, strlen(buffer));
while( (line = configFileReadLine(configFile)) != NULL )
{
SectionStoreAddLineToCurrentSection(result->sectionStore, line);
//LineDump(line);
}
}
}
return result;
}
VOID ConfigFileSaveOverwrite(CONFIGFILEPTR abstractConfigFile)
{
struct ConfigFile* configFile = (struct ConfigFile*)abstractConfigFile;
ConfigFileSaveCopyTo(abstractConfigFile, configFile->filename);
}
VOID ConfigFileSaveCopyTo(CONFIGFILEPTR abstractConfigFile, STRPTR newFilename)
{
BPTR file = Open(newFilename, MODE_NEWFILE);
if( file != 0 )
{
ConfigFileWrite(abstractConfigFile, file);
Close(file);
}
}
VOID ConfigFileWrite(CONFIGFILEPTR abstractConfigFile, BPTR file)
{
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);
SectionWrite(section, file);
}
}
}
StringArray ConfigFileSubsectionsForSection(CONFIGFILEPTR abstractConfigFile, CONST_STRPTR primarySection)
{
struct ConfigFile* configFile = (struct ConfigFile*)abstractConfigFile;
return SectionStoreSubsectionsForSection(configFile->sectionStore, primarySection);
}
STRPTR ConfigFileGet(CONFIGFILEPTR abstractConfigFile, CONST_STRPTR compoundKey)
{
STRPTR result = NULL;
struct ConfigFile* configFile = (struct ConfigFile*)abstractConfigFile;
if( configFile != NULL )
{
StringArray split = CompoundKeySplitKeyForVar(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 = CompoundKeySplitKeyForVar(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 ConfigFileAddVariable(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 = CompoundKeySplitKeyForVar(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 = SectionStoreFindOrCreateSection(configFile->sectionStore, compoundKey);
// add the line to the section
SectionAddLine(section, line, TRUE);
}
}
BOOL ConfigFileSet(CONFIGFILEPTR abstractConfigFile, CONST_STRPTR compoundKey, CONST_STRPTR stringValue)
{
BOOL result = FALSE;
struct ConfigFile* configFile = (struct ConfigFile*)abstractConfigFile;
if( configFile != NULL )
{
StringArray parts = CompoundKeySplitKeyForVar(compoundKey);
LineArray lines = SectionStoreFindLines(configFile->sectionStore, StringArrayValues(parts)[0], StringArrayValues(parts)[1]);
if( SizeOfArray(lines) == 0 )
{
ConfigFileAddVariable(abstractConfigFile, compoundKey, stringValue);
result = TRUE;
}
else if( SizeOfArray(lines) == 1 )
{
LINEPTR line = (LINEPTR)ArrayBackValue(LINEPTR, lines);
if( line )
{
VARIABLEPTR var = VariableCreate(StringArrayValues(parts)[1], stringValue);
if( var )
{
LineSetVariable(line, var);
result = TRUE;
}
}
}
else // more than one line, we error.
{
result = FALSE;
}
StringArrayFree(parts, TRUE);
LineArrayFree(lines, FALSE);
}
return result;
}
VOID ConfigFileReplaceAll(CONFIGFILEPTR abstractConfigFile, CONST_STRPTR compoundKey, CONST_STRPTR stringValue)
{
struct ConfigFile* configFile = (struct ConfigFile*)abstractConfigFile;
if( configFile != NULL )
{
StringArray parts = CompoundKeySplitKeyForVar(compoundKey);
SectionStoreRemoveLines(configFile->sectionStore, StringArrayValues(parts)[0], StringArrayValues(parts)[1]);
ConfigFileAddVariable( abstractConfigFile, compoundKey, stringValue);
StringArrayFree(parts, TRUE);
}
}
VOID ConfigFileUnset(CONFIGFILEPTR abstractConfigFile, CONST_STRPTR compoundKey, CONST_STRPTR stringValue)
{
struct ConfigFile* configFile = (struct ConfigFile*)abstractConfigFile;
if( configFile != NULL )
{
StringArray parts = CompoundKeySplitKeyCompletely(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 = CompoundKeySplitKeyCompletely(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;
}