aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--common.c110
1 files changed, 97 insertions, 13 deletions
diff --git a/common.c b/common.c
index 548de33..0981ed5 100644
--- a/common.c
+++ b/common.c
@@ -534,7 +534,7 @@ struct config_schema
bool (*validate) (struct config_item_ *, const struct config_item_ *);
/// The value has changed. Only appliable to objects.
- bool (*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);
@@ -542,12 +542,33 @@ struct config_schema
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-static void
-config_item_destroy (struct config_item_ *self)
+static const char *
+config_item_type_name (enum config_item_type type)
{
- if (self->schema && self->schema->on_destroy)
- self->schema->on_destroy (self);
+ switch (type)
+ {
+ case CONFIG_ITEM_NULL: return "null";
+ case CONFIG_ITEM_BOOLEAN: return "boolean";
+ case CONFIG_ITEM_INTEGER: return "integer";
+ case CONFIG_ITEM_STRING: return "string";
+ case CONFIG_ITEM_STRING_ARRAY: return "string array";
+
+ default:
+ hard_assert (!"invalid config item type value");
+ return NULL;
+ }
+}
+
+static bool
+config_item_type_is_string (enum config_item_type type)
+{
+ return type == CONFIG_ITEM_STRING
+ || type == CONFIG_ITEM_STRING_ARRAY;
+}
+static void
+config_item_free (struct config_item_ *self)
+{
switch (self->type)
{
case CONFIG_ITEM_STRING:
@@ -559,9 +580,32 @@ config_item_destroy (struct config_item_ *self)
default:
break;
}
+}
+
+static void
+config_item_destroy (struct config_item_ *self)
+{
+ if (self->schema && self->schema->on_destroy)
+ self->schema->on_destroy (self);
+
+ config_item_free (self);
free (self);
}
+/// Doesn't do any validations or handle schemas, just moves source data
+/// to the target item and destroys the source item
+static void
+config_item_move (struct config_item_ *self, struct config_item_ *source)
+{
+ // Not quite sure how to handle that
+ hard_assert (!source->schema);
+
+ config_item_free (self);
+ self->type = source->type;
+ memcpy (&self->value, &source->value, sizeof source->value);
+ free (source);
+}
+
static struct config_item_ *
config_item_new (enum config_item_type type)
{
@@ -618,19 +662,59 @@ config_item_object (void)
return self;
}
-/// Doesn't do any validations or such, only moves source data to the item
-static void
-config_item_move (struct config_item_ *self, struct config_item_ *source)
+static bool
+config_schema_accepts_type
+ (struct config_schema *self, enum config_item_type type)
{
- // TODO
+ if (self->type == type)
+ return true;
+ // This is a bit messy but it has its purpose
+ if (config_item_type_is_string (self->type)
+ && config_item_type_is_string (type))
+ return true;
+ return self->is_nullable && type == CONFIG_ITEM_NULL;
+
}
static bool
-config_item_set_from (struct config_item_ *self,
- struct config_item_ *source, struct error **e)
+config_item_set_from (struct config_item_ *self, struct config_item_ *source,
+ struct error **e)
{
- hard_assert (self->type == CONFIG_ITEM_OBJECT);
- // TODO
+ struct config_schema *schema = self->schema;
+ if (!schema)
+ {
+ // Easy, we don't know what this item is
+ config_item_move (self, source);
+ return true;
+ }
+
+ // Otherwise we check the type and validate the item
+ if (!config_schema_accepts_type (schema, source->type))
+ {
+ error_set (e, "invalid type of value, expected: %s%s",
+ config_item_type_name (schema->type),
+ schema->is_nullable ? " (or null)" : "");
+ return false;
+ }
+
+ if (schema->validate && !schema->validate (self, source))
+ {
+ // XXX: perhaps "schema->validate" could provide a message for us?
+ error_set (e, "invalid value");
+ return false;
+ }
+
+ // Make sure the string subtype fits the schema
+ if (config_item_type_is_string (self->type)
+ && config_item_type_is_string (source->type))
+ source->type = self->type;
+
+ config_item_move (self, source);
+
+ // Notify owner about the change so that they can apply it
+ if (schema->on_changed)
+ schema->on_changed (self);
+ return true;
}
static struct config_item_ *