settings section enumeration

printf style key lookup
This commit is contained in:
Martin Willi
2008-11-07 15:08:53 +00:00
parent 89d05ab5fb
commit c9ef4cee46
2 changed files with 136 additions and 34 deletions
+104 -16
View File
@@ -88,9 +88,50 @@ struct kv_t {
char *value; char *value;
}; };
static char *find(section_t *section, char *key) /**
* find a section by a given key
*/
static section_t *find_section(section_t *section, char *key, va_list args)
{ {
char *name, *pos, *value = NULL; char name[512], *pos;
enumerator_t *enumerator;
section_t *current, *found = NULL;
if (section == NULL)
{
return NULL;
}
if (vsnprintf(name, sizeof(name), key, args) >= sizeof(name))
{
return NULL;
}
pos = strchr(name, '.');
if (pos)
{
*pos = '\0';
pos++;
}
enumerator = section->sections->create_enumerator(section->sections);
while (enumerator->enumerate(enumerator, &current))
{
if (streq(current->name, name))
{
found = current;
break;
}
}
enumerator->destroy(enumerator);
if (found && pos)
{
return find_section(found, pos, args);
}
return found;
}
static char *find_value(section_t *section, char *key, va_list args)
{
char name[512], *pos, *value = NULL;
enumerator_t *enumerator; enumerator_t *enumerator;
kv_t *kv; kv_t *kv;
section_t *current, *found = NULL; section_t *current, *found = NULL;
@@ -100,7 +141,10 @@ static char *find(section_t *section, char *key)
return NULL; return NULL;
} }
name = strdupa(key); if (vsnprintf(name, sizeof(name), key, args) >= sizeof(name))
{
return NULL;
}
pos = strchr(name, '.'); pos = strchr(name, '.');
if (pos) if (pos)
@@ -119,7 +163,7 @@ static char *find(section_t *section, char *key)
enumerator->destroy(enumerator); enumerator->destroy(enumerator);
if (found) if (found)
{ {
return find(found, pos); return find_value(found, pos, args);
} }
} }
else else
@@ -141,11 +185,14 @@ static char *find(section_t *section, char *key)
/** /**
* Implementation of settings_t.get. * Implementation of settings_t.get.
*/ */
static char* get_str(private_settings_t *this, char *key, char *def) static char* get_str(private_settings_t *this, char *key, char *def, ...)
{ {
char *value; char *value;
va_list args;
value = find(this->top, key); va_start(args, def);
value = find_value(this->top, key, args);
va_end(args);
if (value) if (value)
{ {
return value; return value;
@@ -156,11 +203,14 @@ static char* get_str(private_settings_t *this, char *key, char *def)
/** /**
* Implementation of settings_t.get_bool. * Implementation of settings_t.get_bool.
*/ */
static bool get_bool(private_settings_t *this, char *key, bool def) static bool get_bool(private_settings_t *this, char *key, bool def, ...)
{ {
char *value; char *value;
va_list args;
value = find(this->top, key); va_start(args, def);
value = find_value(this->top, key, args);
va_end(args);
if (value) if (value)
{ {
if (strcasecmp(value, "true") == 0 || if (strcasecmp(value, "true") == 0 ||
@@ -184,12 +234,15 @@ static bool get_bool(private_settings_t *this, char *key, bool def)
/** /**
* Implementation of settings_t.get_int. * Implementation of settings_t.get_int.
*/ */
static int get_int(private_settings_t *this, char *key, int def) static int get_int(private_settings_t *this, char *key, int def, ...)
{ {
char *value; char *value;
int intval; int intval;
va_list args;
value = find(this->top, key); va_start(args, def);
value = find_value(this->top, key, args);
va_end(args);
if (value) if (value)
{ {
errno = 0; errno = 0;
@@ -205,12 +258,15 @@ static int get_int(private_settings_t *this, char *key, int def)
/** /**
* Implementation of settings_t.get_time. * Implementation of settings_t.get_time.
*/ */
static u_int32_t get_time(private_settings_t *this, char *key, u_int32_t def) static u_int32_t get_time(private_settings_t *this, char *key, u_int32_t def, ...)
{ {
char *value, *endptr; char *value, *endptr;
u_int32_t timeval; u_int32_t timeval;
va_list args;
value = find(this->top, key); va_start(args, def);
value = find_value(this->top, key, args);
va_end(args);
if (value) if (value)
{ {
errno = 0; errno = 0;
@@ -238,6 +294,37 @@ static u_int32_t get_time(private_settings_t *this, char *key, u_int32_t def)
return def; return def;
} }
/**
* Enumerate section names, not sections
*/
static bool section_filter(void *null, section_t **in, char **out)
{
*out = (*in)->name;
return TRUE;
}
/**
* Implementation of settings_t.create_section_enumerator
*/
static enumerator_t* create_section_enumerator(private_settings_t *this,
char *key, ...)
{
section_t *section;
va_list args;
va_start(args, key);
section = find_section(this->top, key, args);
va_end(args);
if (!section)
{
return enumerator_create_empty();
}
return enumerator_create_filter(
section->sections->create_enumerator(section->sections),
(void*)section_filter, NULL, NULL);
}
/** /**
* destroy a section * destroy a section
*/ */
@@ -400,10 +487,11 @@ settings_t *settings_create(char *file)
{ {
private_settings_t *this = malloc_thing(private_settings_t); private_settings_t *this = malloc_thing(private_settings_t);
this->public.get_str = (char*(*)(settings_t*, char *key, char* def))get_str; this->public.get_str = (char*(*)(settings_t*, char *key, char* def, ...))get_str;
this->public.get_int = (int(*)(settings_t*, char *key, int def))get_int; this->public.get_int = (int(*)(settings_t*, char *key, int def, ...))get_int;
this->public.get_time = (u_int32_t(*)(settings_t*, char *key, u_int32_t def))get_time; this->public.get_time = (u_int32_t(*)(settings_t*, char *key, u_int32_t def, ...))get_time;
this->public.get_bool = (bool(*)(settings_t*, char *key, bool def))get_bool; this->public.get_bool = (bool(*)(settings_t*, char *key, bool def, ...))get_bool;
this->public.create_section_enumerator = (enumerator_t*(*)(settings_t*,char *section, ...))create_section_enumerator;
this->public.destroy = (void(*)(settings_t*))destroy; this->public.destroy = (void(*)(settings_t*))destroy;
this->top = NULL; this->top = NULL;
+32 -18
View File
@@ -26,11 +26,12 @@
typedef struct settings_t settings_t; typedef struct settings_t settings_t;
#include <library.h> #include <library.h>
#include <utils/enumerator.h>
/** /**
* Generic configuration options read from a config file. * Generic configuration options read from a config file.
* *
* The sytax is quite simple: * The syntax is quite simple:
* *
* settings := (section|keyvalue)* * settings := (section|keyvalue)*
* section := name { settings } * section := name { settings }
@@ -38,8 +39,8 @@ typedef struct settings_t settings_t;
* *
* E.g.: * E.g.:
* @code * @code
a = b a = b
section-one { section-one {
somevalue = asdf somevalue = asdf
subsection { subsection {
othervalue = xxx othervalue = xxx
@@ -58,43 +59,56 @@ struct settings_t {
/** /**
* Get a settings value as a string. * Get a settings value as a string.
* *
* @param key key including sections * @param key key including sections, printf style format
* @param def value returned if key not found * @param def value returned if key not found
* @param ... argument list for key
* @return value pointing to internal string * @return value pointing to internal string
*/ */
char* (*get_str)(settings_t *this, char *key, char *def); char* (*get_str)(settings_t *this, char *key, char *def, ...);
/** /**
* Get a boolean yes|no, true|false value. * Get a boolean yes|no, true|false value.
* *
* @param jey key including sections * @param key key including sections, printf style format
* @param def default value returned if key not found * @param def value returned if key not found
* @param ... argument list for key
* @return value of the key * @return value of the key
*/ */
bool (*get_bool)(settings_t *this, char *key, bool def); bool (*get_bool)(settings_t *this, char *key, bool def, ...);
/** /**
* Get an integer value. * Get an integer value.
* *
* @param key key including sections * @param key key including sections, printf style format
* @param def default value to return if key not found * @param def value returned if key not found
* @param ... argument list for key
* @return value of the key * @return value of the key
*/ */
int (*get_int)(settings_t *this, char *key, int def); int (*get_int)(settings_t *this, char *key, int def, ...);
/** /**
* Get a time value. * Get a time value.
* *
* @param key key including sections * @param key key including sections, printf style format
* @param def default value to return if key not found * @param def value returned if key not found
* @param ... argument list for key
* @return value of the key * @return value of the key
*/ */
u_int32_t (*get_time)(settings_t *this, char *key, u_int32_t def); u_int32_t (*get_time)(settings_t *this, char *key, u_int32_t def, ...);
/** /**
* Destroy a settings instance. * Create an enumerator over subsection names of a section.
*/ *
void (*destroy)(settings_t *this); * @param section section including parents, printf style format
* @param ... argument list for key
* @return enumerator over subsection names
*/
enumerator_t* (*create_section_enumerator)(settings_t *this,
char *section, ...);
/**
* Destroy a settings instance.
*/
void (*destroy)(settings_t *this);
}; };
/** /**