settings section enumeration
printf style key lookup
This commit is contained in:
+104
-16
@@ -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, ¤t))
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
|||||||
@@ -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);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user