mirror of
https://github.com/xcat2/xNBA.git
synced 2025-02-02 20:11:48 +00:00
[settings] Allow for autovivification of settings blocks
Allow for settings blocks to be created on demand. This allows for constructions such as set defaults/filename http://bootserver/bootfile set defaults/priority 0xff dhcp net0 chain ${filename} which will boot from the DHCP-provided filename, or from "http://bootserver/bootfile" if the DHCP server does not provide a filename. (Note that "priority" gets interpreted as a signed integer, so setting "defaults/priority" to 0xff will cause the "defaults" settings block to have an effective priority of -1.)
This commit is contained in:
parent
f95c919741
commit
ec24672db7
@ -117,6 +117,108 @@ struct simple_settings simple_settings_root = {
|
||||
/** Root settings block */
|
||||
#define settings_root simple_settings_root.settings
|
||||
|
||||
/**
|
||||
* Find child named settings block
|
||||
*
|
||||
* @v parent Parent settings block
|
||||
* @v name Name within this parent
|
||||
* @ret settings Settings block, or NULL
|
||||
*/
|
||||
static struct settings * find_child_settings ( struct settings *parent,
|
||||
const char *name ) {
|
||||
struct settings *settings;
|
||||
|
||||
/* Treat empty name as meaning "this block" */
|
||||
if ( ! *name )
|
||||
return parent;
|
||||
|
||||
/* Look for child with matching name */
|
||||
list_for_each_entry ( settings, &parent->children, siblings ) {
|
||||
if ( strcmp ( settings->name, name ) == 0 )
|
||||
return settings;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find or create child named settings block
|
||||
*
|
||||
* @v parent Parent settings block
|
||||
* @v name Name within this parent
|
||||
* @ret settings Settings block, or NULL
|
||||
*/
|
||||
static struct settings * autovivify_child_settings ( struct settings *parent,
|
||||
const char *name ) {
|
||||
struct {
|
||||
struct simple_settings simple;
|
||||
char name[ strlen ( name ) + 1 /* NUL */ ];
|
||||
} *new_child;
|
||||
struct settings *settings;
|
||||
|
||||
/* Return existing settings, if existent */
|
||||
if ( ( settings = find_child_settings ( parent, name ) ) != NULL )
|
||||
return settings;
|
||||
|
||||
/* Create new simple settings block */
|
||||
new_child = zalloc ( sizeof ( *new_child ) );
|
||||
if ( ! new_child ) {
|
||||
DBGC ( parent, "Settings %p could not create child %s\n",
|
||||
parent, name );
|
||||
return NULL;
|
||||
}
|
||||
memcpy ( new_child->name, name, sizeof ( new_child->name ) );
|
||||
simple_settings_init ( &new_child->simple, NULL, new_child->name );
|
||||
settings = &new_child->simple.settings;
|
||||
register_settings ( settings, parent );
|
||||
return settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse settings block name
|
||||
*
|
||||
* @v name Name
|
||||
* @v get_child Function to find or create child settings block
|
||||
* @ret settings Settings block, or NULL
|
||||
*/
|
||||
static struct settings *
|
||||
parse_settings_name ( const char *name,
|
||||
struct settings * ( * get_child ) ( struct settings *,
|
||||
const char * ) ) {
|
||||
struct settings *settings = &settings_root;
|
||||
char name_copy[ strlen ( name ) + 1 ];
|
||||
char *subname;
|
||||
char *remainder;
|
||||
|
||||
/* Create modifiable copy of name */
|
||||
memcpy ( name_copy, name, sizeof ( name_copy ) );
|
||||
remainder = name_copy;
|
||||
|
||||
/* Parse each name component in turn */
|
||||
while ( remainder ) {
|
||||
subname = remainder;
|
||||
remainder = strchr ( subname, '.' );
|
||||
if ( remainder )
|
||||
*(remainder++) = '\0';
|
||||
settings = get_child ( settings, subname );
|
||||
if ( ! settings )
|
||||
break;
|
||||
}
|
||||
|
||||
return settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find named settings block
|
||||
*
|
||||
* @v name Name
|
||||
* @ret settings Settings block, or NULL
|
||||
*/
|
||||
struct settings * find_settings ( const char *name ) {
|
||||
|
||||
return parse_settings_name ( name, find_child_settings );
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply all settings
|
||||
*
|
||||
@ -228,52 +330,6 @@ void unregister_settings ( struct settings *settings ) {
|
||||
apply_settings();
|
||||
}
|
||||
|
||||
/**
|
||||
* Find child named settings block
|
||||
*
|
||||
* @v parent Parent settings block
|
||||
* @v name Name within this parent
|
||||
* @ret settings Settings block, or NULL
|
||||
*/
|
||||
struct settings * find_child_settings ( struct settings *parent,
|
||||
const char *name ) {
|
||||
struct settings *settings;
|
||||
size_t len;
|
||||
|
||||
/* NULL parent => add to settings root */
|
||||
if ( parent == NULL )
|
||||
parent = &settings_root;
|
||||
|
||||
/* Look for a child whose name matches the initial component */
|
||||
list_for_each_entry ( settings, &parent->children, siblings ) {
|
||||
len = strlen ( settings->name );
|
||||
if ( strncmp ( name, settings->name, len ) != 0 )
|
||||
continue;
|
||||
if ( name[len] == 0 )
|
||||
return settings;
|
||||
if ( name[len] == '.' )
|
||||
return find_child_settings ( settings,
|
||||
( name + len + 1 ) );
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find named settings block
|
||||
*
|
||||
* @v name Name
|
||||
* @ret settings Settings block, or NULL
|
||||
*/
|
||||
struct settings * find_settings ( const char *name ) {
|
||||
|
||||
/* If name is empty, use the root */
|
||||
if ( ! *name )
|
||||
return &settings_root;
|
||||
|
||||
return find_child_settings ( &settings_root, name );
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Core settings routines
|
||||
@ -641,6 +697,7 @@ static struct setting_type * find_setting_type ( const char *name ) {
|
||||
* Parse setting name
|
||||
*
|
||||
* @v name Name of setting
|
||||
* @v get_child Function to find or create child settings block
|
||||
* @v settings Settings block to fill in
|
||||
* @v setting Setting to fill in
|
||||
* @ret rc Return status code
|
||||
@ -649,8 +706,11 @@ static struct setting_type * find_setting_type ( const char *name ) {
|
||||
* "[settings_name/]tag_name[:type_name]" and fills in the appropriate
|
||||
* fields.
|
||||
*/
|
||||
static int parse_setting_name ( const char *name, struct settings **settings,
|
||||
struct setting *setting ) {
|
||||
static int
|
||||
parse_setting_name ( const char *name,
|
||||
struct settings * ( * get_child ) ( struct settings *,
|
||||
const char * ),
|
||||
struct settings **settings, struct setting *setting ) {
|
||||
char tmp_name[ strlen ( name ) + 1 ];
|
||||
char *settings_name;
|
||||
char *setting_name;
|
||||
@ -677,7 +737,7 @@ static int parse_setting_name ( const char *name, struct settings **settings,
|
||||
|
||||
/* Identify settings block, if specified */
|
||||
if ( settings_name ) {
|
||||
*settings = find_settings ( settings_name );
|
||||
*settings = parse_settings_name ( settings_name, get_child );
|
||||
if ( *settings == NULL ) {
|
||||
DBG ( "Unrecognised settings block \"%s\" in \"%s\"\n",
|
||||
settings_name, name );
|
||||
@ -731,7 +791,8 @@ int storef_named_setting ( const char *name, const char *value ) {
|
||||
struct setting setting;
|
||||
int rc;
|
||||
|
||||
if ( ( rc = parse_setting_name ( name, &settings, &setting ) ) != 0 )
|
||||
if ( ( rc = parse_setting_name ( name, autovivify_child_settings,
|
||||
&settings, &setting ) ) != 0 )
|
||||
return rc;
|
||||
return storef_setting ( settings, &setting, value );
|
||||
}
|
||||
@ -749,7 +810,8 @@ int fetchf_named_setting ( const char *name, char *buf, size_t len ) {
|
||||
struct setting setting;
|
||||
int rc;
|
||||
|
||||
if ( ( rc = parse_setting_name ( name, &settings, &setting ) ) != 0 )
|
||||
if ( ( rc = parse_setting_name ( name, find_child_settings,
|
||||
&settings, &setting ) ) != 0 )
|
||||
return rc;
|
||||
return fetchf_setting ( settings, &setting, buf, len );
|
||||
}
|
||||
|
@ -193,8 +193,6 @@ extern int fetch_uuid_setting ( struct settings *settings,
|
||||
struct setting *setting, union uuid *uuid );
|
||||
extern int setting_cmp ( struct setting *a, struct setting *b );
|
||||
|
||||
extern struct settings * find_child_settings ( struct settings *parent,
|
||||
const char *name );
|
||||
extern struct settings * find_settings ( const char *name );
|
||||
|
||||
extern int storef_setting ( struct settings *settings,
|
||||
|
Loading…
x
Reference in New Issue
Block a user