mirror of
https://github.com/gnif/LookingGlass.git
synced 2024-11-22 13:37:22 +00:00
[common] added config file loading capability
This commit is contained in:
parent
522bacb1f0
commit
785bc33192
@ -68,6 +68,9 @@ bool option_get_bool (const char * module, const char * name);
|
|||||||
// called by the main application to parse the command line arguments
|
// called by the main application to parse the command line arguments
|
||||||
bool option_parse(int argc, char * argv[]);
|
bool option_parse(int argc, char * argv[]);
|
||||||
|
|
||||||
|
// called by the main application to load configuration from a file
|
||||||
|
bool option_load(const char * filename);
|
||||||
|
|
||||||
// called by the main application to validate the option values
|
// called by the main application to validate the option values
|
||||||
bool option_validate();
|
bool option_validate();
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA
|
|||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
@ -132,6 +133,35 @@ void option_free()
|
|||||||
state.gCount = 0;
|
state.gCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool option_set(struct OptionValue * v, const char * value)
|
||||||
|
{
|
||||||
|
switch(v->type)
|
||||||
|
{
|
||||||
|
case OPTION_TYPE_INT:
|
||||||
|
v->v.x_int = atol(value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OPTION_TYPE_STRING:
|
||||||
|
free(v->v.x_string);
|
||||||
|
v->v.x_string = strdup(value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OPTION_TYPE_BOOL:
|
||||||
|
v->v.x_bool =
|
||||||
|
strcmp(value, "1" ) == 0 ||
|
||||||
|
strcmp(value, "yes" ) == 0 ||
|
||||||
|
strcmp(value, "true") == 0 ||
|
||||||
|
strcmp(value, "on" ) == 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
DEBUG_ERROR("BUG: Invalid option type, this should never happen");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool option_parse(int argc, char * argv[])
|
bool option_parse(int argc, char * argv[])
|
||||||
{
|
{
|
||||||
for(int a = 1; a < argc; ++a)
|
for(int a = 1; a < argc; ++a)
|
||||||
@ -173,29 +203,11 @@ bool option_parse(int argc, char * argv[])
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(o->value.type)
|
if (!option_set(&o->value, value))
|
||||||
{
|
{
|
||||||
case OPTION_TYPE_INT:
|
DEBUG_ERROR("Failed to set the option value");
|
||||||
o->value.v.x_int = atol(value);
|
free(arg);
|
||||||
break;
|
continue;
|
||||||
|
|
||||||
case OPTION_TYPE_STRING:
|
|
||||||
free(o->value.v.x_string);
|
|
||||||
o->value.v.x_string = strdup(value);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case OPTION_TYPE_BOOL:
|
|
||||||
o->value.v.x_bool =
|
|
||||||
strcmp(value, "1" ) == 0 ||
|
|
||||||
strcmp(value, "yes" ) == 0 ||
|
|
||||||
strcmp(value, "true") == 0 ||
|
|
||||||
strcmp(value, "on" ) == 0;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
DEBUG_ERROR("BUG: Invalid option type, this should never happen");
|
|
||||||
assert(false);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
free(arg);
|
free(arg);
|
||||||
@ -204,6 +216,171 @@ bool option_parse(int argc, char * argv[])
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char * file_parse_module(FILE * fp)
|
||||||
|
{
|
||||||
|
char * module = NULL;
|
||||||
|
int len = 0;
|
||||||
|
|
||||||
|
for(int c = fgetc(fp); !feof(fp); c = fgetc(fp))
|
||||||
|
{
|
||||||
|
switch(c)
|
||||||
|
{
|
||||||
|
case ']':
|
||||||
|
if (module)
|
||||||
|
module[len] = '\0';
|
||||||
|
return module;
|
||||||
|
|
||||||
|
case '\r':
|
||||||
|
case '\n':
|
||||||
|
free(module);
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
default:
|
||||||
|
if (len % 32 == 0)
|
||||||
|
module = realloc(module, len + 32 + 1);
|
||||||
|
module[len++] = c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (module)
|
||||||
|
free(module);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool option_load(const char * filename)
|
||||||
|
{
|
||||||
|
FILE * fp = fopen(filename, "r");
|
||||||
|
if (!fp)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
bool result = true;
|
||||||
|
int lineno = 1;
|
||||||
|
char * module = NULL;
|
||||||
|
bool line = true;
|
||||||
|
bool expectLine = false;
|
||||||
|
bool expectValue = false;
|
||||||
|
char * name = NULL;
|
||||||
|
int nameLen = 0;
|
||||||
|
char * value = NULL;
|
||||||
|
int valueLen = 0;
|
||||||
|
|
||||||
|
char ** p = &name;
|
||||||
|
int * len = &nameLen;
|
||||||
|
|
||||||
|
for(int c = fgetc(fp); !feof(fp); c = fgetc(fp))
|
||||||
|
{
|
||||||
|
switch(c)
|
||||||
|
{
|
||||||
|
case '[':
|
||||||
|
if (expectLine)
|
||||||
|
{
|
||||||
|
DEBUG_ERROR("Syntax error on line %d, expected new line", lineno);
|
||||||
|
result = false;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (line)
|
||||||
|
{
|
||||||
|
free(module);
|
||||||
|
module = file_parse_module(fp);
|
||||||
|
if (!module)
|
||||||
|
{
|
||||||
|
DEBUG_ERROR("Syntax error on line %d, failed to parse the module", lineno);
|
||||||
|
result = false;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
line = false;
|
||||||
|
expectLine = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*len % 32 == 0)
|
||||||
|
*p = realloc(*p, *len + 32 + 1);
|
||||||
|
(*p)[(*len)++] = c;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '\r':
|
||||||
|
continue;
|
||||||
|
|
||||||
|
case '\n':
|
||||||
|
if (name)
|
||||||
|
{
|
||||||
|
struct OptionValue * o = option_get(module, name);
|
||||||
|
if (!o)
|
||||||
|
DEBUG_WARN("Ignored unknown option %s:%s", module, name);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!option_set(o, value))
|
||||||
|
DEBUG_ERROR("Failed to set the option value");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
line = true;
|
||||||
|
expectLine = false;
|
||||||
|
expectValue = false;
|
||||||
|
++lineno;
|
||||||
|
|
||||||
|
p = &name;
|
||||||
|
len = &nameLen;
|
||||||
|
|
||||||
|
free(name);
|
||||||
|
name = NULL;
|
||||||
|
nameLen = 0;
|
||||||
|
free(value);
|
||||||
|
value = NULL;
|
||||||
|
valueLen = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '=':
|
||||||
|
if (!expectValue)
|
||||||
|
{
|
||||||
|
if (!name)
|
||||||
|
{
|
||||||
|
DEBUG_ERROR("Syntax error on line %d, expected option name", lineno);
|
||||||
|
result = false;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
name[nameLen] = '\0';
|
||||||
|
expectValue = true;
|
||||||
|
|
||||||
|
p = &value;
|
||||||
|
len = &valueLen;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*len % 32 == 0)
|
||||||
|
*p = realloc(*p, *len + 32 + 1);
|
||||||
|
(*p)[(*len)++] = c;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
if (expectLine)
|
||||||
|
{
|
||||||
|
DEBUG_ERROR("Syntax error on line %d, expected new line", lineno);
|
||||||
|
result = false;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
line = false;
|
||||||
|
|
||||||
|
if (*len % 32 == 0)
|
||||||
|
*p = realloc(*p, *len + 32 + 1);
|
||||||
|
(*p)[(*len)++] = c;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exit:
|
||||||
|
fclose(fp);
|
||||||
|
|
||||||
|
free(module);
|
||||||
|
free(name );
|
||||||
|
free(value );
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
bool option_validate()
|
bool option_validate()
|
||||||
{
|
{
|
||||||
if (state.doHelp)
|
if (state.doHelp)
|
||||||
|
Loading…
Reference in New Issue
Block a user