From 900a756e8fb70bcd6e725f0696d8094a7208f905 Mon Sep 17 00:00:00 2001 From: Ryan Lortie Date: Tue, 29 Jun 2010 14:41:04 -0400 Subject: [PATCH] GSettings: new tags 'extends', 'list-of' Add support for extends='' and list-of='' tags to the element. The attributes are parsed and some sanity-checking is done but currently nothing happens as a result. Add some tests. --- gio/gschema-compile.c | 124 ++++++++++++++++-- gio/tests/Makefile.am | 10 +- gio/tests/gschema-compile.c | 11 +- .../schema-tests/extend-missing.gschema.xml | 3 + .../schema-tests/extend-nonlist.gschema.xml | 4 + .../schema-tests/extend-self.gschema.xml | 3 + .../extend-wrong-list-indirect.gschema.xml | 6 + .../extend-wrong-list.gschema.xml | 5 + gio/tests/schema-tests/extending.gschema.xml | 21 +++ .../key-in-list-indirect.gschema.xml | 8 ++ .../schema-tests/key-in-list.gschema.xml | 6 + .../schema-tests/list-of-missing.gschema.xml | 3 + 12 files changed, 192 insertions(+), 12 deletions(-) create mode 100644 gio/tests/schema-tests/extend-missing.gschema.xml create mode 100644 gio/tests/schema-tests/extend-nonlist.gschema.xml create mode 100644 gio/tests/schema-tests/extend-self.gschema.xml create mode 100644 gio/tests/schema-tests/extend-wrong-list-indirect.gschema.xml create mode 100644 gio/tests/schema-tests/extend-wrong-list.gschema.xml create mode 100644 gio/tests/schema-tests/extending.gschema.xml create mode 100644 gio/tests/schema-tests/key-in-list-indirect.gschema.xml create mode 100644 gio/tests/schema-tests/key-in-list.gschema.xml create mode 100644 gio/tests/schema-tests/list-of-missing.gschema.xml diff --git a/gio/gschema-compile.c b/gio/gschema-compile.c index 3ec262104..004a3b1e5 100644 --- a/gio/gschema-compile.c +++ b/gio/gschema-compile.c @@ -671,23 +671,34 @@ is_valid_keyname (const gchar *key, } /* Handling of {{{1 */ -typedef struct +typedef struct _SchemaState SchemaState; +struct _SchemaState { - gchar *path; - gchar *gettext_domain; + SchemaState *extends; - GHashTable *keys; -} SchemaState; + gchar *path; + gchar *gettext_domain; + gchar *extends_name; + gchar *list_of; + + GHashTable *keys; +}; static SchemaState * schema_state_new (const gchar *path, - const gchar *gettext_domain) + const gchar *gettext_domain, + SchemaState *extends, + const gchar *extends_name, + const gchar *list_of) { SchemaState *state; state = g_slice_new (SchemaState); state->path = g_strdup (path); state->gettext_domain = g_strdup (gettext_domain); + state->extends = extends; + state->extends_name = g_strdup (extends_name); + state->list_of = g_strdup (list_of); state->keys = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, key_state_free); @@ -740,6 +751,14 @@ schema_state_add_key (SchemaState *state, GString *enum_data; KeyState *key; + if (state->list_of) + { + g_set_error_literal (error, G_MARKUP_ERROR, + G_MARKUP_ERROR_INVALID_CONTENT, + "can not add keys to a list-of schema"); + return NULL; + } + if (!is_valid_keyname (name, error)) return NULL; @@ -809,13 +828,34 @@ typedef struct GString *string; /* non-NULL when accepting text */ } ParseState; +static gboolean +is_subclass (const gchar *class_name, + const gchar *possible_parent, + GHashTable *schema_table) +{ + SchemaState *class; + + if (strcmp (class_name, possible_parent) == 0) + return TRUE; + + class = g_hash_table_lookup (schema_table, class_name); + g_assert (class != NULL); + + return class->extends_name && + is_subclass (class->extends_name, possible_parent, schema_table); +} + static void parse_state_start_schema (ParseState *state, const gchar *id, const gchar *path, const gchar *gettext_domain, + const gchar *extends_name, + const gchar *list_of, GError **error) { + SchemaState *extends; + if (g_hash_table_lookup (state->schema_table, id)) { g_set_error (error, G_MARKUP_ERROR, @@ -824,6 +864,66 @@ parse_state_start_schema (ParseState *state, return; } + if (extends_name) + { + extends = g_hash_table_lookup (state->schema_table, extends_name); + + if (extends == NULL) + { + g_set_error (error, G_MARKUP_ERROR, + G_MARKUP_ERROR_INVALID_CONTENT, + " extends not yet " + "existing schema '%s'", id, extends_name); + return; + } + } + else + extends = NULL; + + if (list_of) + { + if (!g_hash_table_lookup (state->schema_table, list_of)) + { + g_set_error (error, G_MARKUP_ERROR, + G_MARKUP_ERROR_INVALID_CONTENT, + " is list of not yet " + "existing schema '%s'", id, list_of); + return; + } + } + + if (extends) + { + if (list_of) + { + if (extends->list_of == NULL) + { + g_set_error (error, G_MARKUP_ERROR, + G_MARKUP_ERROR_INVALID_CONTENT, + " is a list, extending " + " which is not a list", + id, extends_name); + return; + } + + if (!is_subclass (list_of, extends->list_of, state->schema_table)) + { + g_set_error (error, G_MARKUP_ERROR, + G_MARKUP_ERROR_INVALID_CONTENT, + " extends but '%s' does not extend '%s'", + id, list_of, extends_name, extends->list_of, + list_of, extends->list_of); + return; + } + } + else + /* by default we are a list of the same thing that the schema + * we are extending is a list of (which might be nothing) + */ + list_of = extends->list_of; + } + if (path && !(g_str_has_prefix (path, "/") && g_str_has_suffix (path, "/"))) { g_set_error (error, G_MARKUP_ERROR, @@ -833,7 +933,8 @@ parse_state_start_schema (ParseState *state, return; } - state->schema_state = schema_state_new (path, gettext_domain); + state->schema_state = schema_state_new (path, gettext_domain, + extends, extends_name, list_of); g_hash_table_insert (state->schema_table, g_strdup (id), state->schema_state); } @@ -900,11 +1001,14 @@ start_element (GMarkupParseContext *context, { if (strcmp (element_name, "schema") == 0) { - const gchar *id, *path, *gettext_domain; + const gchar *id, *path, *gettext_domain, *extends, *list_of; if (COLLECT (STRING, "id", &id, OPTIONAL | STRING, "path", &path, - OPTIONAL | STRING, "gettext-domain", &gettext_domain)) - parse_state_start_schema (state, id, path, gettext_domain, error); + OPTIONAL | STRING, "gettext-domain", &gettext_domain, + OPTIONAL | STRING, "extends", &extends, + OPTIONAL | STRING, "list-of", &list_of)) + parse_state_start_schema (state, id, path, gettext_domain, + extends, list_of, error); return; } diff --git a/gio/tests/Makefile.am b/gio/tests/Makefile.am index 4cfbb6e6a..4ddf0d350 100644 --- a/gio/tests/Makefile.am +++ b/gio/tests/Makefile.am @@ -302,9 +302,18 @@ schema_tests = \ schema-tests/enum-with-repeated-alias.gschema.xml \ schema-tests/enum-with-shadow-alias.gschema.xml \ schema-tests/enum.gschema.xml \ + schema-tests/extend-missing.gschema.xml \ + schema-tests/extend-nonlist.gschema.xml \ + schema-tests/extend-self.gschema.xml \ + schema-tests/extend-wrong-list-indirect.gschema.xml \ + schema-tests/extend-wrong-list.gschema.xml \ + schema-tests/extending.gschema.xml \ schema-tests/from-docs.gschema.xml \ schema-tests/incomplete-list.gschema.xml \ schema-tests/invalid-path.gschema.xml \ + schema-tests/key-in-list-indirect.gschema.xml \ + schema-tests/key-in-list.gschema.xml \ + schema-tests/list-of-missing.gschema.xml \ schema-tests/missing-quotes.gschema.xml \ schema-tests/no-default.gschema.xml \ schema-tests/overflow.gschema.xml \ @@ -320,7 +329,6 @@ schema_tests = \ schema-tests/range.gschema.xml \ schema-tests/wrong-category.gschema.xml - EXTRA_DIST += \ socket-common.c \ org.gtk.test.gschema \ diff --git a/gio/tests/gschema-compile.c b/gio/tests/gschema-compile.c index 48d0ffbd4..c3961d155 100644 --- a/gio/tests/gschema-compile.c +++ b/gio/tests/gschema-compile.c @@ -92,7 +92,16 @@ static const SchemaTest tests[] = { { "range-default-low", NULL, "* is not contained in the specified range*" }, { "range-default-high", NULL, "* is not contained in the specified range*" }, { "range-parse-error", NULL, "*invalid character in number*" }, - { "from-docs", NULL, NULL } + { "from-docs", NULL, NULL }, + { "extending", NULL, NULL }, + { "extend-missing", NULL, "*extends not yet existing schema*" }, + { "extend-nonlist", NULL, "*which is not a list*" }, + { "extend-self", NULL, "*not yet existing*" }, + { "extend-wrong-list-indirect", NULL, "*'y' does not extend 'x'*" }, + { "extend-wrong-list", NULL, "*'y' does not extend 'x'*" }, + { "key-in-list-indirect", NULL, "*can not add keys to a list*" }, + { "key-in-list", NULL, "*can not add keys to a list*" }, + { "list-of-missing", NULL, "*is list of not yet existing schema*" } }; int diff --git a/gio/tests/schema-tests/extend-missing.gschema.xml b/gio/tests/schema-tests/extend-missing.gschema.xml new file mode 100644 index 000000000..675803ad0 --- /dev/null +++ b/gio/tests/schema-tests/extend-missing.gschema.xml @@ -0,0 +1,3 @@ + + + diff --git a/gio/tests/schema-tests/extend-nonlist.gschema.xml b/gio/tests/schema-tests/extend-nonlist.gschema.xml new file mode 100644 index 000000000..7008cee90 --- /dev/null +++ b/gio/tests/schema-tests/extend-nonlist.gschema.xml @@ -0,0 +1,4 @@ + + + + diff --git a/gio/tests/schema-tests/extend-self.gschema.xml b/gio/tests/schema-tests/extend-self.gschema.xml new file mode 100644 index 000000000..f5b0c3de0 --- /dev/null +++ b/gio/tests/schema-tests/extend-self.gschema.xml @@ -0,0 +1,3 @@ + + + diff --git a/gio/tests/schema-tests/extend-wrong-list-indirect.gschema.xml b/gio/tests/schema-tests/extend-wrong-list-indirect.gschema.xml new file mode 100644 index 000000000..a336db729 --- /dev/null +++ b/gio/tests/schema-tests/extend-wrong-list-indirect.gschema.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/gio/tests/schema-tests/extend-wrong-list.gschema.xml b/gio/tests/schema-tests/extend-wrong-list.gschema.xml new file mode 100644 index 000000000..4232dc2d2 --- /dev/null +++ b/gio/tests/schema-tests/extend-wrong-list.gschema.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/gio/tests/schema-tests/extending.gschema.xml b/gio/tests/schema-tests/extending.gschema.xml new file mode 100644 index 000000000..98882c7b4 --- /dev/null +++ b/gio/tests/schema-tests/extending.gschema.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/gio/tests/schema-tests/key-in-list-indirect.gschema.xml b/gio/tests/schema-tests/key-in-list-indirect.gschema.xml new file mode 100644 index 000000000..6f0bea1d2 --- /dev/null +++ b/gio/tests/schema-tests/key-in-list-indirect.gschema.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/gio/tests/schema-tests/key-in-list.gschema.xml b/gio/tests/schema-tests/key-in-list.gschema.xml new file mode 100644 index 000000000..e2a967ae2 --- /dev/null +++ b/gio/tests/schema-tests/key-in-list.gschema.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/gio/tests/schema-tests/list-of-missing.gschema.xml b/gio/tests/schema-tests/list-of-missing.gschema.xml new file mode 100644 index 000000000..f5ef476ea --- /dev/null +++ b/gio/tests/schema-tests/list-of-missing.gschema.xml @@ -0,0 +1,3 @@ + + +