Implement config_item_set_from()
This commit is contained in:
parent
d4deb31a17
commit
b4dab3489d
110
common.c
110
common.c
|
@ -534,7 +534,7 @@ struct config_schema
|
||||||
bool (*validate) (struct config_item_ *, const struct config_item_ *);
|
bool (*validate) (struct config_item_ *, const struct config_item_ *);
|
||||||
|
|
||||||
/// The value has changed. Only appliable to objects.
|
/// 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"
|
/// Free any resources located in "item->user_data"
|
||||||
void (*on_destroy) (struct config_item_ *item);
|
void (*on_destroy) (struct config_item_ *item);
|
||||||
|
@ -542,12 +542,33 @@ struct config_schema
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
||||||
static void
|
static const char *
|
||||||
config_item_destroy (struct config_item_ *self)
|
config_item_type_name (enum config_item_type type)
|
||||||
{
|
{
|
||||||
if (self->schema && self->schema->on_destroy)
|
switch (type)
|
||||||
self->schema->on_destroy (self);
|
{
|
||||||
|
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)
|
switch (self->type)
|
||||||
{
|
{
|
||||||
case CONFIG_ITEM_STRING:
|
case CONFIG_ITEM_STRING:
|
||||||
|
@ -559,9 +580,32 @@ config_item_destroy (struct config_item_ *self)
|
||||||
default:
|
default:
|
||||||
break;
|
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);
|
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_ *
|
static struct config_item_ *
|
||||||
config_item_new (enum config_item_type type)
|
config_item_new (enum config_item_type type)
|
||||||
{
|
{
|
||||||
|
@ -618,19 +662,59 @@ config_item_object (void)
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Doesn't do any validations or such, only moves source data to the item
|
static bool
|
||||||
static void
|
config_schema_accepts_type
|
||||||
config_item_move (struct config_item_ *self, struct config_item_ *source)
|
(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
|
static bool
|
||||||
config_item_set_from (struct config_item_ *self,
|
config_item_set_from (struct config_item_ *self, struct config_item_ *source,
|
||||||
struct config_item_ *source, struct error **e)
|
struct error **e)
|
||||||
{
|
{
|
||||||
hard_assert (self->type == CONFIG_ITEM_OBJECT);
|
struct config_schema *schema = self->schema;
|
||||||
// TODO
|
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_ *
|
static struct config_item_ *
|
||||||
|
|
Loading…
Reference in New Issue