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

344 lines
8.0 KiB

1 year ago
#include "configmodel.h"
1 year ago
#include "cregex/cregex.h"
#include "arraytypes/stringarray.h"
#include "arraytypes/linearray.h"
1 year ago
#include <proto/exec.h>
#include <proto/dos.h>
#include <string.h>
#include <stdio.h>
1 year ago
#define ZERO ((BPTR)0)
1 year ago
cregex_program_t* InitialisePattern(CONST_STRPTR pattern);
Array RunPattern(CONST_STRPTR text, cregex_program_t* patternProgram);
SECTIONPTR SectionCreateWithName(CONST_STRPTR primary);
SECTIONPTR SectionCreateWithNameAndSubname(CONST_STRPTR primary, CONST_STRPTR secondary);
VOID SectionFree(SECTIONPTR abstractSection);
VARIABLEPTR VariableCreate(CONST_STRPTR key, CONST_STRPTR rawValue);
VOID VariableFree(VARIABLEPTR abstractVariable);
1 year ago
#define WHITESPACE "[ \\t\\n\\r\\f\\v]"
#define RX_BLANK_LINE "^[ \t\n\r\f\v]*($|#|;)"
#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]*$"
STATIC cregex_program_t* sectionPatternProgram = NULL;
STATIC cregex_program_t* variablePatternProgram = NULL;
STATIC cregex_program_t* blankPatternProgram = NULL;
STATIC cregex_program_t* integerPatternProgram = NULL;
1 year ago
struct ConfigFile
{
CONST_STRPTR filename;
LineArray lines;
};
1 year ago
struct Section
{
CONST_STRPTR primary_key;
CONST_STRPTR secondary_key;
1 year ago
LineArray lines;
1 year ago
};
enum VariableType
{
TypeBool=0,
TypeInteger=1,
TypeString=2,
};
struct Variable
{
enum VariableType type;
CONST_STRPTR name;
union
{
CONST_STRPTR stringValue;
BOOL boolValue;
LONG longValue;
} value;
};
struct Line
{
STRPTR rawText;
struct Variable* variable;
struct Section* section;
1 year ago
};
1 year ago
VOID ConfigFileFree(CONFIGFILEPTR abstractConfigFile)
{
struct ConfigFile* configFile = (struct ConfigFile*)abstractConfigFile;
if( configFile != NULL )
{
if( configFile->lines != NULL )
{
LineArrayFree(configFile->lines, TRUE); //also frees lines
}
FreeVec(configFile);
}
}
CONFIGFILEPTR ConfigFileRead(CONST_STRPTR filename)
{
struct ConfigFile* result = AllocVec(sizeof(struct ConfigFile), MEMF_CLEAR);
BPTR configFile = Open(filename, MODE_OLDFILE);
if( configFile != ZERO )
{
LINEPTR line = NULL;
result->lines = LineArrayNew();
InitialisePatterns();
while( (line = LineReadIncludingContinuation(configFile)) != NULL )
{
// Printf("successfully read line {%s}\n", LineGetRawText(line));
LineArrayAppend(result->lines, line);
}
ReleasePatterns();
Close(configFile);
}
return result;
}
VOID ConfigFileSave(CONFIGFILEPTR config)
{
}
LINEPTR LineCreate(CONST_STRPTR buffer, ULONG size)
{
struct Line* result = NULL;
StringArray matches = NULL;
if( size > 0 )
{
result = AllocVec(sizeof(struct Line), MEMF_CLEAR);
result->rawText = AllocVec(size+1, MEMF_CLEAR);
CopyMem(buffer, result->rawText, size);
if( matches = RunPattern(result->rawText, sectionPatternProgram) )
{
if( SizeOfArray(matches) == 3 )
{
Printf("\nsection {%s}\n", StringArrayValues(matches)[1]);
result->section = SectionCreateWithName(StringArrayValues(matches)[1]);
}
else if( SizeOfArray(matches) == 5 )
{
Printf("\nsection {%s.%s}\n", StringArrayValues(matches)[1], StringArrayValues(matches)[3]);
result->section = SectionCreateWithNameAndSubname(StringArrayValues(matches)[1], StringArrayValues(matches)[3]);
}
// Printf("\nsection size=%ld\n", SizeOfArray(stringArray));
// StringArrayForEach(stringArray, Printf("{{%s}}",aString););
StringArrayFree(matches);
}
else
{
if( matches = RunPattern(result->rawText, variablePatternProgram) )
{
Printf("\nvariable {%s} = {%s}\n", StringArrayValues(matches)[1], StringArrayValues(matches)[2]);
// StringArrayForEach(stringArray, Printf("{{%s}}",aString););
result->variable = VariableCreate(StringArrayValues(matches)[1], StringArrayValues(matches)[2]);
StringArrayFree(matches);
}
else
{
if( matches = RunPattern(result->rawText, blankPatternProgram) )
{
Printf("\nYY %s\n", result->rawText);
StringArrayFree(matches);
}
else
{
Printf("\nXX %s\n", result->rawText);
}
}
}
}
return result;
}
LINEPTR LineReadIncludingContinuation(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 )
{
result = LineCreate(buffer, bytesReadTotal);
}
FreeVec(buffer);
return result;
}
VOID LineFree(LINEPTR abstractLine)
{
struct Line* line = (struct Line*)abstractLine;
if( line != NULL )
{
if( line->rawText != NULL )
{
FreeVec(line->rawText);
}
if( line->section != NULL )
{
SectionFree(line->section);
}
if( line->variable != NULL )
{
VariableFree(line->variable);
}
FreeVec(line);
}
}
CONST_STRPTR LineGetRawText(LINEPTR abstractLine)
{
struct Line* line = (struct Line*)abstractLine;
if( line != NULL )
{
return (CONST_STRPTR)line->rawText;
}
else
{
return NULL;
}
}
1 year ago
SECTIONPTR SectionCreateWithName(CONST_STRPTR primary)
{
return NULL;
}
SECTIONPTR SectionCreateWithNameAndSubname(CONST_STRPTR primary, CONST_STRPTR secondary)
{
return NULL;
}
VOID SectionFree(SECTIONPTR abstractSection)
{
}
VARIABLEPTR VariableCreate(CONST_STRPTR key, CONST_STRPTR rawValue)
{
return NULL;
}
VOID VariableFree(VARIABLEPTR abstractVariable)
{
}
// ----------------------------------------------------
// ----------------------------------------------------
// ----------------------------------------------------
// ----------------------------------------------------
// ----------------------------------------------------
1 year ago
VOID InitialisePatterns(VOID)
{
sectionPatternProgram = InitialisePattern(RX_SECTION_LINE);
variablePatternProgram = InitialisePattern(RX_VARIABLE_LINE);
blankPatternProgram = InitialisePattern(RX_BLANK_LINE);
integerPatternProgram = InitialisePattern(RX_INTEGER);
}
VOID ReleasePatterns(VOID)
{
if( sectionPatternProgram != NULL ) cregex_compile_free( sectionPatternProgram );
if( variablePatternProgram != NULL ) cregex_compile_free( variablePatternProgram );
if( blankPatternProgram != NULL ) cregex_compile_free( blankPatternProgram );
if( integerPatternProgram != NULL ) cregex_compile_free( integerPatternProgram );
}
cregex_program_t* InitialisePattern(CONST_STRPTR pattern)
{
cregex_program_t* result = NULL;
cregex_node_t* patternNode = cregex_parse(pattern);
if( patternNode )
{
result = cregex_compile_node( patternNode );
if( result != NULL )
{
//Printf("successfully compiled %s\n", pattern);
}
else
{
Printf("failed to compile %s\n", pattern);
}
cregex_parse_free( patternNode );
}
else
{
Printf("could not parse %s\n", pattern);
}
return result;
}
Array RunPattern(CONST_STRPTR text, cregex_program_t* patternProgram)
{
Array result = NULL;
char* localMatches[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
if (cregex_program_run(patternProgram, text, localMatches, 20) > 0) {
int j = 0;
int nmatches = 0;
// count the matches
for (j = 0; j < 20; ++j)
if (localMatches[j])
nmatches = j;
if( nmatches > 0 )
{
result = StringArrayNew();
// loop the matches
for (j = 0; j <= nmatches; j += 2) {
if (localMatches[j] && localMatches[j + 1]) {
int len = (int)(localMatches[j + 1] - localMatches[j]);
STRPTR buffer = AllocVec(len+1, MEMF_CLEAR); // freed in the array
sprintf(buffer, "%.*s", len, localMatches[j]);
if( buffer[len-1] == '\n' )
{
buffer[len-1] = '\0';
}
StringArrayAppend(result, buffer);
} else {
//Printf("(NULL,NULL)\n");
}
}
}
// end
} else {
//Printf("\"%s\": no match\n", text);
}
return result;
}