diff options
| author | Přemysl Janouch <p.janouch@gmail.com> | 2015-05-01 21:48:43 +0200 | 
|---|---|---|
| committer | Přemysl Janouch <p.janouch@gmail.com> | 2015-05-01 21:48:43 +0200 | 
| commit | b4dab3489dfb4a1368f489acd880cb5a31a035e0 (patch) | |
| tree | 2dde0fbb096787f867df61a700d42c62d244b4e2 | |
| parent | d4deb31a17421dc89217149c1dafd85fb414c2a0 (diff) | |
| download | xK-b4dab3489dfb4a1368f489acd880cb5a31a035e0.tar.gz xK-b4dab3489dfb4a1368f489acd880cb5a31a035e0.tar.xz xK-b4dab3489dfb4a1368f489acd880cb5a31a035e0.zip | |
Implement config_item_set_from()
| -rw-r--r-- | common.c | 110 | 
1 files changed, 97 insertions, 13 deletions
| @@ -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_ * | 
