diff --git a/common.c b/common.c index a72453b..d37192e 100644 --- a/common.c +++ b/common.c @@ -1935,61 +1935,77 @@ config_item_clone (struct config_item *self) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -static void +static struct config_item * config_schema_initialize_item (struct config_schema *schema, - struct config_item *parent, void *user_data) + struct config_item *parent, struct error **warning, struct error **e) { + hard_assert (parent->type == CONFIG_ITEM_OBJECT); struct config_item *item = str_map_find (&parent->value.object, schema->name); - bool replace = true; - if (item) + struct error *error = NULL; + if (item && config_item_validate_by_schema (item, schema, &error)) + goto keep_current; + + if (error) { - // FIXME: either do this silently or tell about it via a callback - // or just store it in an output vector; don't print it directly - 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); - } + error_set (warning, "resetting configuration item " + "`%s' to default: %s", schema->name, error->message); + error_free (error); + error = NULL; } - if (replace) + if (schema->default_) + item = config_item_parse + (schema->default_, strlen (schema->default_), true, &error); + else + item = config_item_null (); + + if (error || !config_item_validate_by_schema (item, schema, &error)) { - struct error *e = NULL; - if (schema->default_) - item = config_item_parse - (schema->default_, strlen (schema->default_), true, &e); - else - item = config_item_null (); + error_set (e, "invalid default for configuration item `%s': %s", + schema->name, error->message); + error_free (error); - if (e || !config_item_validate_by_schema (item, schema, &e)) - exit_fatal ("invalid default for `%s': %s", - schema->name, e->message); - - // This will free the old item if there was any - str_map_set (&parent->value.object, schema->name, item); + config_item_destroy (item); + return NULL; } + // This will free the old item if there was any + str_map_set (&parent->value.object, schema->name, item); + +keep_current: // 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; - item->user_data = user_data; + return item; } +/// Assign schemas and user_data to multiple items at once; +/// feel free to copy over and modify to suit your particular needs static void config_schema_apply_to_object (struct config_schema *schema_array, struct config_item *object, void *user_data) { - hard_assert (object->type == CONFIG_ITEM_OBJECT); while (schema_array->name) - config_schema_initialize_item (schema_array++, object, user_data); + { + struct error *warning = NULL, *e = NULL; + struct config_item *item = config_schema_initialize_item + (schema_array++, object, &warning, &e); + + if (warning) + { + print_warning ("%s", warning->message); + error_free (warning); + } + if (e) + print_fatal ("%s", e->message); + + item->user_data = user_data; + } } static void