fence-virt/config/simpleconfig.c
Lon Hohberger 2643994886 Better config query & multiple value/tag support
Signed-off-by: Lon Hohberger <lon@users.sourceforge.net>
2010-01-08 16:40:31 -05:00

440 lines
6.6 KiB
C

#include <stdio.h>
#include <pthread.h>
#include <string.h>
#include <malloc.h>
#include <stdlib.h>
#include <assert.h>
#include "simpleconfig.h"
#include "config-stack.h"
static pthread_mutex_t parser_mutex = PTHREAD_MUTEX_INITIALIZER;
static int
print_value(struct value *v, int depth, FILE *fp)
{
int x;
if (v->val == NULL)
return 0;
for (x = 0; x < depth; x++)
fprintf(fp, "\t");
fprintf(fp, "%s = \"%s\";\n", v->id, v->val);
return 0;
}
static void
_sc_dump_d(struct node *node, int depth, FILE *fp)
{
struct node *n;
struct value *v;
int x;
if (!node) {
//printf("Empty node\n");
return;
}
for (x = 0; x < depth; x++)
fprintf(fp, "\t");
if (node->val) {
fprintf(fp, "%s = \"%s\" {\n", node->id, node->val);
} else {
fprintf(fp, "%s {\n", node->id);
}
for (n = node->nodes; n; n = n->next) {
_sc_dump_d(n, depth+1, fp);
}
for (v = node->values; v; v = v->next) {
print_value(v, depth+1, fp);
}
for (x = 0; x < depth; x++)
fprintf(fp, "\t");
fprintf(fp, "}\n\n");
}
static void
_sc_dump(config_info_t *config, FILE *fp)
{
struct node *n, *node;
struct value *v, *values;
if (!config)
return;
values = ((struct parser_context *)config)->val_list;
node = ((struct parser_context *)config)->node_list;
for (n = node; n; n = n->next) {
_sc_dump_d(n, 0, fp);
}
for (v = values; v; v = v->next) {
print_value(v, 0, fp);
}
}
static int
free_value(struct value *v)
{
int x;
if (v) {
free(v->id);
free(v->val);
free(v);
}
return 0;
}
static void
_sc_free_node(struct node *node)
{
struct node *n;
struct value *v;
int x;
if (!node)
return;
while (node->nodes) {
n = node->nodes;
if (n) {
node->nodes = node->nodes->next;
_sc_free_node(n);
}
}
while (node->values) {
v = node->values;
node->values = node->values->next;
free_value(v);
}
free(node->id);
free(node);
}
static int
_sc_free(config_info_t *config)
{
struct node *n, *nlist;
struct value *v, *vlist;
if (!config)
return -1;
vlist = ((struct parser_context *)config)->val_list;
nlist = ((struct parser_context *)config)->node_list;
while (nlist) {
n = nlist;
nlist = nlist->next;
_sc_free_node(n);
}
((struct parser_context *)config)->node_list = NULL;
while (vlist) {
v = vlist;
vlist = vlist->next;
free_value(v);
}
((struct parser_context *)config)->val_list = NULL;
free(config);
return 0;
}
static int
_sc_get(config_info_t *config, const char *key, char *value, size_t valuesz)
{
char buf[1024];
struct node *n, *node = ((struct parser_context *)config)->node_list;
struct value *v, *values = ((struct parser_context *)config)->val_list;
char *ptr;
char *slash;
char *bracket;
char *id;
int req_index = 0;
int curr_index = 0;
int found;
if (!config)
return -1;
assert(strlen(key) < sizeof(buf));
ptr = (char *)key;
top:
while ((slash = strchr(ptr, '/'))) {
memset(buf, 0, sizeof(buf));
strncpy(buf, ptr, (slash - ptr));
ptr = ++slash;
id = NULL;
bracket = strchr(buf, '[');
if (bracket) {
*bracket = 0;
++bracket;
id = bracket;
bracket = strchr(bracket, ']');
if (!bracket)
return 1;
*bracket = 0;
if (id[0] == '@') {
++id;
if (!strlen(id)) {
return 1;
}
} else {
req_index = atoi(id);
if (req_index <= 0)
return 1;
id = NULL;
}
}
found = 0;
curr_index = 0;
for (n = node; n; n = n->next) {
if (strcasecmp(n->id, buf))
continue;
++curr_index;
if (req_index && (curr_index != req_index)) {
continue;
} else if (id && strcasecmp(n->val, id)) {
continue;
}
node = n->nodes;
values = n->values;
found = 1;
break;
}
if (!found)
return 1;
}
if (ptr[0] != '@') {
if (node->val) {
strncpy(value, node->val, valuesz);
return 0;
}
return 1;
}
++ptr;
found = 0;
id = NULL;
strncpy(buf, ptr, sizeof(buf));
bracket = strchr(buf, '[');
req_index = 0;
curr_index = 0;
if (bracket) {
*bracket = 0;
++bracket;
id = bracket;
bracket = strchr(bracket, ']');
if (!bracket)
return 1;
*bracket = 0;
req_index = atoi(id);
if (req_index <= 0)
return 1;
id = NULL;
}
for (v = values; v; v = v->next) {
if (strcasecmp(v->id, buf))
continue;
++curr_index;
if (req_index && (curr_index != req_index))
continue;
snprintf(value, valuesz, "%s", v->val);
return 0;
}
return 1;
}
static int
_sc_set(config_info_t *config, const char *key, const char *value)
{
char buf[1024];
struct node *n, **nodes = &((struct parser_context *)config)->node_list;
struct value *v, **values = &((struct parser_context *)config)->val_list;
char *ptr;
char *slash;
char *id_dup, *val_dup;
int found = 0;
ptr = (char *)key;
while ((slash = strchr(ptr, '/'))) {
memset(buf, 0, sizeof(buf));
strncpy(buf, ptr, (slash - ptr));
ptr = ++slash;
found = 0;
for (n = *nodes; n; n = n->next) {
if (strcasecmp(n->id, buf))
continue;
nodes = &n->nodes;
values = &n->values;
found = 1;
break;
}
if (!found) {
id_dup = strdup(buf);
if (!id_dup)
return -1;
_sc_node_add(id_dup, NULL, NULL, NULL, nodes);
n = *nodes;
nodes = &n->nodes;
values = &n->values;
}
}
if (ptr[0] != '@')
return 1;
++ptr;
for (v = *values; v; v = v->next) {
if (strcasecmp(v->id, ptr))
continue;
ptr = v->val;
if (value) {
v->val = strdup(value);
if (!v->val) {
v->val = ptr;
return -1;
}
} else {
v->val = NULL;
}
free(ptr);
return 0;
}
if (!value)
return 0;
id_dup = strdup(ptr);
if (!id_dup)
return -1;
val_dup = strdup(value);
if (!val_dup)
return -1;
_sc_value_add(id_dup, val_dup, values);
return 0;
}
static int
_sc_parse(const char *filename, config_info_t **config)
{
struct parser_context *c;
FILE *fp = NULL;
int ret = 0;
if (!config)
return -1;
pthread_mutex_lock(&parser_mutex);
if (filename) {
fp = fopen(filename, "r");
yyin = fp;
if (fp)
ret = yyparse();
else
ret = 1;
} else {
ret = 1;
}
c = malloc(sizeof(*c));
if (!c)
return -1;
c->node_list = node_list;
c->val_list = val_list;
c->next = NULL;
val_list = NULL;
node_list = NULL;
*config = (config_info_t *)c;
if (fp)
fclose(fp);
pthread_mutex_unlock(&parser_mutex);
return ret;
}
static const config_object_t sc_object = {
.get = _sc_get,
.set = _sc_set,
.parse = _sc_parse,
.free = _sc_free,
.dump = _sc_dump,
.info = NULL
};
config_object_t *
sc_init(void)
{
config_object_t *o;
o = malloc(sizeof(*o));
if (!o)
return NULL;
memset(o, 0, sizeof(*o));
memcpy(o, &sc_object, sizeof(*o));
return o;
}
void
sc_release(config_object_t *c)
{
sc_free(c);
free(c);
}