config: simplify and mostly finish
What still sucks: - "on_change" callbacks have little information; maybe we could add a user-defined field to the schema; also config_schema_apply_to_object() might assign "user_data" - no idea how to generate the default configuration file
This commit is contained in:
parent
5a6b12245b
commit
f7c08fdace
110
common.c
110
common.c
@ -553,14 +553,11 @@ struct config_schema
|
|||||||
const char *default_; ///< Default as a configuration snippet
|
const char *default_; ///< Default as a configuration snippet
|
||||||
|
|
||||||
/// Check if the new value can be accepted.
|
/// Check if the new value can be accepted.
|
||||||
/// If this is not defined, only "type" and having a default is considered.
|
/// In addition to this, "type" and having a default is considered.
|
||||||
bool (*validate) (struct config_item_ *, const struct config_item_ *);
|
bool (*validate) (const struct config_item_ *, struct error **e);
|
||||||
|
|
||||||
/// The value has changed. Only appliable to objects.
|
/// The value has changed
|
||||||
void (*on_changed) (struct config_item_ *);
|
void (*on_changed) (struct config_item_ *);
|
||||||
|
|
||||||
/// Free any resources located in "item->user_data"
|
|
||||||
void (*on_destroy) (struct config_item_ *item);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
@ -608,9 +605,6 @@ config_item_free (struct config_item_ *self)
|
|||||||
static void
|
static void
|
||||||
config_item_destroy (struct config_item_ *self)
|
config_item_destroy (struct config_item_ *self)
|
||||||
{
|
{
|
||||||
if (self->schema && self->schema->on_destroy)
|
|
||||||
self->schema->on_destroy (self);
|
|
||||||
|
|
||||||
config_item_free (self);
|
config_item_free (self);
|
||||||
free (self);
|
free (self);
|
||||||
}
|
}
|
||||||
@ -703,16 +697,18 @@ config_schema_accepts_type
|
|||||||
|
|
||||||
static bool
|
static bool
|
||||||
config_item_validate_by_schema (struct config_item_ *self,
|
config_item_validate_by_schema (struct config_item_ *self,
|
||||||
struct config_item_ *source, struct config_schema *schema, struct error **e)
|
struct config_schema *schema, struct error **e)
|
||||||
{
|
{
|
||||||
// Otherwise we check the type and validate the item
|
struct error *error = NULL;
|
||||||
if (!config_schema_accepts_type (schema, source->type))
|
if (!config_schema_accepts_type (schema, self->type))
|
||||||
error_set (e, "invalid type of value, expected: %s%s",
|
error_set (e, "invalid type of value, expected: %s%s",
|
||||||
config_item_type_name (schema->type),
|
config_item_type_name (schema->type),
|
||||||
!schema->default_ ? " (or null)" : "");
|
!schema->default_ ? " (or null)" : "");
|
||||||
else if (schema->validate && !schema->validate (self, source))
|
else if (schema->validate && !schema->validate (self, &error))
|
||||||
// XXX: perhaps "schema->validate" could provide a message for us?
|
{
|
||||||
error_set (e, "invalid value");
|
error_set (e, "%s: %s", "invalid value", error->message);
|
||||||
|
error_free (error);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
@ -730,7 +726,7 @@ config_item_set_from (struct config_item_ *self, struct config_item_ *source,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!config_item_validate_by_schema (self, source, schema, e))
|
if (!config_item_validate_by_schema (source, schema, e))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Make sure the string subtype fits the schema
|
// Make sure the string subtype fits the schema
|
||||||
@ -1415,48 +1411,58 @@ end:
|
|||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
||||||
|
// XXX: this thing is ugly in concept
|
||||||
|
|
||||||
|
static void
|
||||||
|
config_schema_fix_value
|
||||||
|
(struct config_schema *schema, struct config_item_ *object)
|
||||||
|
{
|
||||||
|
struct config_item_ *item =
|
||||||
|
str_map_find (&object->value.object, schema->name);
|
||||||
|
|
||||||
|
bool replace = true;
|
||||||
|
if (item)
|
||||||
|
{
|
||||||
|
struct error *e = NULL;
|
||||||
|
replace = !config_item_validate_by_schema (item, schema, &e);
|
||||||
|
if (e)
|
||||||
|
{
|
||||||
|
print_error ("resetting configuration item "
|
||||||
|
"`%s' to default: %s", schema->name, e->message);
|
||||||
|
error_free (e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (replace)
|
||||||
|
{
|
||||||
|
struct error *e = NULL;
|
||||||
|
struct config_item_ *default_ = config_item_parse
|
||||||
|
(schema->default_, strlen (schema->default_), true, &e);
|
||||||
|
if (e || !config_item_validate_by_schema (default_, schema, &e))
|
||||||
|
exit_fatal ("invalid default for `%s': %s",
|
||||||
|
schema->name, e->message);
|
||||||
|
|
||||||
|
config_item_move (item, default_);
|
||||||
|
str_map_set (&object->value.object, schema->name, default_);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure the string subtype fits the schema
|
||||||
|
if (config_item_type_is_string (item->type)
|
||||||
|
&& config_item_type_is_string (schema->type))
|
||||||
|
item->type = schema->type;
|
||||||
|
|
||||||
|
item->schema = schema;
|
||||||
|
if (schema->on_changed)
|
||||||
|
schema->on_changed (item);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
config_schema_apply_to_object
|
config_schema_apply_to_object
|
||||||
(struct config_schema *schema_array, struct config_item_ *object)
|
(struct config_schema *schema_array, struct config_item_ *object)
|
||||||
{
|
{
|
||||||
hard_assert (object->type == CONFIG_ITEM_OBJECT);
|
hard_assert (object->type == CONFIG_ITEM_OBJECT);
|
||||||
while (schema_array->name)
|
while (schema_array->name)
|
||||||
{
|
config_schema_fix_value (schema_array++, object);
|
||||||
struct config_schema *schema = schema_array++;
|
|
||||||
struct config_item_ *item =
|
|
||||||
str_map_find (&object->value.object, schema->name);
|
|
||||||
|
|
||||||
bool make_new = true;
|
|
||||||
if (item)
|
|
||||||
{
|
|
||||||
struct error *e = NULL;
|
|
||||||
make_new = !config_item_validate_by_schema
|
|
||||||
(NULL, item, schema, &e);
|
|
||||||
if (e)
|
|
||||||
{
|
|
||||||
print_error ("resetting configuration item "
|
|
||||||
"`%s' to defaults: %s", schema->name, e->message);
|
|
||||||
error_free (e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (make_new)
|
|
||||||
{
|
|
||||||
struct error *e = NULL;
|
|
||||||
struct config_item_ *default_ = config_item_parse
|
|
||||||
(schema->default_, strlen (schema->default_), true, &e);
|
|
||||||
if (e)
|
|
||||||
exit_fatal ("invalid default: %s", e->message);
|
|
||||||
|
|
||||||
config_item_move (item, default_);
|
|
||||||
}
|
|
||||||
|
|
||||||
item->type = schema->type;
|
|
||||||
item->schema = schema;
|
|
||||||
|
|
||||||
if (schema->on_changed)
|
|
||||||
schema->on_changed (item);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
Loading…
Reference in New Issue
Block a user