diff options
Diffstat (limited to 'common/dconf-changeset.c')
-rw-r--r-- | common/dconf-changeset.c | 231 |
1 files changed, 168 insertions, 63 deletions
diff --git a/common/dconf-changeset.c b/common/dconf-changeset.c index 1dcee39..195841a 100644 --- a/common/dconf-changeset.c +++ b/common/dconf-changeset.c @@ -25,12 +25,38 @@ #include <string.h> #include <stdlib.h> +/** + * SECTION:changeset + * @title: DConfChangeset + * @Short_description: A set of changes to a dconf database + * + * #DConfChangeset represents a set of changes that can be made to a + * dconf database. Currently supported operations are writing new + * values to keys and resetting keys and dirs. + * + * Create the changeset with dconf_changeset_new() and populate it with + * dconf_changeset_set(). Submit it to dconf with + * dconf_client_change_fast() or dconf_client_change_sync(). + * dconf_changeset_new_write() is a convenience constructor for the + * common case of writing or resetting a single value. + **/ + +/** + * DConfChangeset: + * + * This is a reference counted opaque structure type. It is not a + * #GObject. + * + * Use dconf_changeset_ref() and dconf_changeset_unref() to manipuate + * references. + **/ + struct _DConfChangeset { GHashTable *table; gint ref_count; - gchar *root; + gchar *prefix; const gchar **paths; GVariant **values; }; @@ -52,47 +78,55 @@ unref_gvariant0 (gpointer data) DConfChangeset * dconf_changeset_new (void) { - DConfChangeset *change; + DConfChangeset *changeset; - change = g_slice_new0 (DConfChangeset); - change->table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, unref_gvariant0); - change->ref_count = 1; + changeset = g_slice_new0 (DConfChangeset); + changeset->table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, unref_gvariant0); + changeset->ref_count = 1; - return change; + return changeset; } /** * dconf_changeset_unref: - * @change: a #DConfChangeset + * @changeset: a #DConfChangeset * * Releases a #DConfChangeset reference. **/ void -dconf_changeset_unref (DConfChangeset *change) +dconf_changeset_unref (DConfChangeset *changeset) { - if (g_atomic_int_dec_and_test (&change->ref_count)) + if (g_atomic_int_dec_and_test (&changeset->ref_count)) { - g_free (change->root); - g_free (change->paths); - g_free (change->values); + g_free (changeset->prefix); + g_free (changeset->paths); + g_free (changeset->values); - g_hash_table_unref (change->table); + g_hash_table_unref (changeset->table); - g_slice_free (DConfChangeset, change); + g_slice_free (DConfChangeset, changeset); } } +/** + * dconf_changeset_ref: + * @changeset: a #DConfChangeset + * + * Increases the reference count on @changeset + * + * Returns: @changeset + **/ DConfChangeset * -dconf_changeset_ref (DConfChangeset *change) +dconf_changeset_ref (DConfChangeset *changeset) { - g_atomic_int_inc (&change->ref_count); + g_atomic_int_inc (&changeset->ref_count); - return change; + return changeset; } /** * dconf_changeset_set: - * @change: a #DConfChangeset + * @changeset: a #DConfChangeset * @path: a path to modify * @value: the value for the key, or %NULL to reset * @@ -105,11 +139,11 @@ dconf_changeset_ref (DConfChangeset *change) * %NULL. It is not permitted to assign a #GVariant value to a dir. **/ void -dconf_changeset_set (DConfChangeset *change, +dconf_changeset_set (DConfChangeset *changeset, const gchar *path, GVariant *value) { - g_return_if_fail (change->root == NULL); + g_return_if_fail (changeset->prefix == NULL); g_return_if_fail (dconf_is_path (path, NULL)); /* Check if we are performing a path reset */ @@ -123,23 +157,23 @@ dconf_changeset_set (DConfChangeset *change, /* When we reset a path we must also reset all keys within that * path. */ - g_hash_table_iter_init (&iter, change->table); + g_hash_table_iter_init (&iter, changeset->table); while (g_hash_table_iter_next (&iter, &key, NULL)) if (g_str_has_prefix (key, path)) g_hash_table_iter_remove (&iter); /* Record the reset itself. */ - g_hash_table_insert (change->table, g_strdup (path), NULL); + g_hash_table_insert (changeset->table, g_strdup (path), NULL); } /* else, just a normal value write or reset */ else - g_hash_table_insert (change->table, g_strdup (path), value ? g_variant_ref_sink (value) : NULL); + g_hash_table_insert (changeset->table, g_strdup (path), value ? g_variant_ref_sink (value) : NULL); } /** * dconf_changeset_get: - * @change: a #DConfChangeset + * @changeset: a #DConfChangeset * @key: the key to check * @value: a return location for the value, or %NULL * @@ -156,13 +190,13 @@ dconf_changeset_set (DConfChangeset *change, * Returns: %TRUE if the key is being modified by the change */ gboolean -dconf_changeset_get (DConfChangeset *change, +dconf_changeset_get (DConfChangeset *changeset, const gchar *key, GVariant **value) { gpointer tmp; - if (!g_hash_table_lookup_extended (change->table, key, NULL, &tmp)) + if (!g_hash_table_lookup_extended (changeset->table, key, NULL, &tmp)) return FALSE; if (value) @@ -173,10 +207,10 @@ dconf_changeset_get (DConfChangeset *change, /** * dconf_changeset_is_similar_to: - * @change: a #DConfChangeset + * @changeset: a #DConfChangeset * @other: another #DConfChangeset * - * Checks if @change is similar to @other. + * Checks if @changeset is similar to @other. * * Two changes are considered similar if they write to the exact same * set of keys. The values written are not considered. @@ -193,16 +227,16 @@ dconf_changeset_get (DConfChangeset *change, * Returns: %TRUE if the changes are similar **/ gboolean -dconf_changeset_is_similar_to (DConfChangeset *change, +dconf_changeset_is_similar_to (DConfChangeset *changeset, DConfChangeset *other) { GHashTableIter iter; gpointer key; - if (g_hash_table_size (change->table) != g_hash_table_size (other->table)) + if (g_hash_table_size (changeset->table) != g_hash_table_size (other->table)) return FALSE; - g_hash_table_iter_init (&iter, change->table); + g_hash_table_iter_init (&iter, changeset->table); while (g_hash_table_iter_next (&iter, &key, NULL)) if (!g_hash_table_contains (other->table, key)) return FALSE; @@ -211,9 +245,23 @@ dconf_changeset_is_similar_to (DConfChangeset *change, } /** + * DConfChangesetPredicate: + * @path: a path, as per dconf_is_path() + * @value: a #GVariant, or %NULL + * @user_data: user data pointer + * + * Callback function type for predicates over items in a + * #DConfChangeset. + * + * Use with dconf_changeset_all(). + * + * Returns: %TRUE if the predicate is met for the given @path and @value + **/ + +/** * dconf_changeset_all: - * @change: a #DConfChangeset - * @predicate: a #DConfChangePredicate + * @changeset: a #DConfChangeset + * @predicate: a #DConfChangesetPredicate * @user_data: user data to pass to @predicate * * Checks if all changes in the changeset satisfy @predicate. @@ -225,17 +273,17 @@ dconf_changeset_is_similar_to (DConfChangeset *change, * %FALSE. If not (including the case of no items) then this function * returns %TRUE. * - * Returns: %TRUE if all items in @change satisfy @predicate + * Returns: %TRUE if all items in @changeset satisfy @predicate */ gboolean -dconf_changeset_all (DConfChangeset *change, +dconf_changeset_all (DConfChangeset *changeset, DConfChangesetPredicate predicate, gpointer user_data) { GHashTableIter iter; gpointer key, value; - g_hash_table_iter_init (&iter, change->table); + g_hash_table_iter_init (&iter, changeset->table); while (g_hash_table_iter_next (&iter, &key, &value)) if (!(* predicate) (key, value, user_data)) return FALSE; @@ -254,12 +302,12 @@ dconf_changeset_string_ptr_compare (gconstpointer a_p, } static void -dconf_changeset_build_description (DConfChangeset *change) +dconf_changeset_build_description (DConfChangeset *changeset) { gsize prefix_length; gint n_items; - n_items = g_hash_table_size (change->table); + n_items = g_hash_table_size (changeset->table); /* If there are no items then what is there to describe? */ if (n_items == 0) @@ -291,7 +339,7 @@ dconf_changeset_build_description (DConfChangeset *change) const gchar *first; gpointer key; - g_hash_table_iter_init (&iter, change->table); + g_hash_table_iter_init (&iter, changeset->table); /* We checked above that we have at least one item. */ if (!g_hash_table_iter_next (&iter, &key, NULL)) @@ -329,7 +377,7 @@ dconf_changeset_build_description (DConfChangeset *change) prefix_length--; } - change->root = g_strndup (first, prefix_length); + changeset->prefix = g_strndup (first, prefix_length); } /* Pass 2: collect the list of keys, dropping the prefix */ @@ -338,63 +386,94 @@ dconf_changeset_build_description (DConfChangeset *change) gpointer key; gint i = 0; - change->paths = g_new (const gchar *, n_items + 1); + changeset->paths = g_new (const gchar *, n_items + 1); - g_hash_table_iter_init (&iter, change->table); + g_hash_table_iter_init (&iter, changeset->table); while (g_hash_table_iter_next (&iter, &key, NULL)) { const gchar *path = key; - change->paths[i++] = path + prefix_length; + changeset->paths[i++] = path + prefix_length; } - change->paths[i] = NULL; + changeset->paths[i] = NULL; g_assert (i == n_items); /* Sort the list of keys */ - qsort (change->paths, n_items, sizeof (const gchar *), dconf_changeset_string_ptr_compare); + qsort (changeset->paths, n_items, sizeof (const gchar *), dconf_changeset_string_ptr_compare); } /* Pass 3: collect the list of values */ { gint i; - change->values = g_new (GVariant *, n_items); + changeset->values = g_new (GVariant *, n_items); for (i = 0; i < n_items; i++) /* We dropped the prefix when collecting the array. * Bring it back temporarily, for the lookup. */ - change->values[i] = g_hash_table_lookup (change->table, change->paths[i] - prefix_length); + changeset->values[i] = g_hash_table_lookup (changeset->table, changeset->paths[i] - prefix_length); } } +/** + * dconf_changeset_describe: + * @changeset: a #DConfChangeset + * @prefix: the prefix under which changes have been requested + * @paths: the list of paths changed, relative to @prefix + * @values: the list of values changed + * + * Describes @changeset. + * + * @prefix and @paths are presented in the same way as they are for the + * DConfClient::changed signal. @values is an array of the same length + * as @paths. For each key described by an element in @paths, @values + * will contain either a #GVariant (the requested new value of that key) + * or %NULL (to reset a reset). + * + * The @paths array is returned in an order such that dir will always + * come before keys contained within those dirs. + * + * Returns: the number of changes (the length of @changes and @values). + **/ guint -dconf_changeset_describe (DConfChangeset *change, - const gchar **root, +dconf_changeset_describe (DConfChangeset *changeset, + const gchar **prefix, const gchar * const **paths, GVariant * const **values) { gint n_items; - n_items = g_hash_table_size (change->table); + n_items = g_hash_table_size (changeset->table); - if (n_items && !change->root) - dconf_changeset_build_description (change); + if (n_items && !changeset->prefix) + dconf_changeset_build_description (changeset); - if (root) - *root = change->root; + if (prefix) + *prefix = changeset->prefix; if (paths) - *paths = change->paths; + *paths = changeset->paths; if (values) - *values = change->values; + *values = changeset->values; return n_items; } +/** + * dconf_changeset_serialise: + * @changeset: a #DConfChangeset + * + * Serialises a #DConfChangeset. + * + * The returned value has no particular format and should only be passed + * to dconf_changeset_deserialise(). + * + * Returns: a floating #GVariant + **/ GVariant * -dconf_changeset_serialise (DConfChangeset *change) +dconf_changeset_serialise (DConfChangeset *changeset) { GVariantBuilder builder; GHashTableIter iter; @@ -402,22 +481,37 @@ dconf_changeset_serialise (DConfChangeset *change) g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{smv}")); - g_hash_table_iter_init (&iter, change->table); + g_hash_table_iter_init (&iter, changeset->table); while (g_hash_table_iter_next (&iter, &key, &value)) g_variant_builder_add (&builder, "{smv}", key, value); return g_variant_builder_end (&builder); } +/** + * dconf_changeset_deserialise: + * @serialised: a #GVariant from dconf_changeset_serialise() + * + * Creates a #DConfChangeset according to a serialised description + * returned from an earlier call to dconf_changeset_serialise(). + * + * @serialised has no particular format -- you should only pass a value + * that reasulted from an earlier serialise operation. + * + * This call never fails, even if @serialised is not in the correct + * format. Improperly-formatted parts are simply ignored. + * + * Returns: a new #DConfChangeset + **/ DConfChangeset * dconf_changeset_deserialise (GVariant *serialised) { - DConfChangeset *change; + DConfChangeset *changeset; GVariantIter iter; const gchar *key; GVariant *value; - change = dconf_changeset_new (); + changeset = dconf_changeset_new (); g_variant_iter_init (&iter, serialised); while (g_variant_iter_loop (&iter, "{&smv}", &key, &value)) { @@ -431,18 +525,29 @@ dconf_changeset_deserialise (GVariant *serialised) if (value == NULL) { if (dconf_is_path (key, NULL)) - g_hash_table_insert (change->table, g_strdup (key), NULL); + g_hash_table_insert (changeset->table, g_strdup (key), NULL); } else { if (dconf_is_key (key, NULL)) - g_hash_table_insert (change->table, g_strdup (key), g_variant_ref (value)); + g_hash_table_insert (changeset->table, g_strdup (key), g_variant_ref (value)); } } - return change; + return changeset; } +/** + * dconf_changeset_new_write: + * @path: a dconf path + * @value: a #GVariant, or %NULL + * + * Creates a new #DConfChangeset with one change. This is equivalent to + * calling dconf_changeset_new() and then dconf_changeset_set() with + * @path and @value. + * + * Returns: a new #DConfChangeset + **/ DConfChangeset * dconf_changeset_new_write (const gchar *path, GVariant *value) |