[dconf/wip/reorg: 6/8] service: stop using gvdb_table_walk()



commit facae6ffcd5b2935f9b708eecb1fd5aa7c8ddf86
Author: Ryan Lortie <desrt desrt ca>
Date:   Mon Jul 9 15:18:49 2012 -0400

    service: stop using gvdb_table_walk()
    
    Use the new gvdb_table_get_names() instead.

 service/dconf-rebuilder.c |  240 ++++++++++++++++++--------------------------
 1 files changed, 98 insertions(+), 142 deletions(-)
---
diff --git a/service/dconf-rebuilder.c b/service/dconf-rebuilder.c
index 9cac1a7..3f170d6 100644
--- a/service/dconf-rebuilder.c
+++ b/service/dconf-rebuilder.c
@@ -25,42 +25,34 @@
 
 #include "../gvdb/gvdb-reader.h"
 #include "../gvdb/gvdb-builder.h"
-
-typedef struct
-{
-  const gchar *prefix;
-  gint prefix_len;
-
-  GHashTable *table;
-  const gchar *const*keys;
-  GVariant *const*values;
-  gint n_items;
-  gint index;
-
-  gchar name[4096];
-  gint name_len;
-} DConfRebuilderState;
+#include "../common/dconf-paths.h"
 
 static GvdbItem *
-dconf_rebuilder_get_parent (GHashTable *table,
-                            gchar      *key,
-                            gint        length)
+dconf_rebuilder_get_parent (GHashTable  *table,
+                            const gchar *key)
 {
   GvdbItem *grandparent, *parent;
+  gchar *parent_name;
+  gint len;
 
-  if (length == 1)
+  if (g_str_equal (key, "/"))
     return NULL;
 
-  while (key[--length - 1] != '/');
-  key[length] = '\0';
+  len = strlen (key);
+  if (key[len - 1] == '/')
+    len--;
+
+  while (key[len - 1] != '/')
+    len--;
 
-  parent = g_hash_table_lookup (table, key);
+  parent_name = g_strndup (key, len);
+  parent = g_hash_table_lookup (table, parent_name);
 
   if (parent == NULL)
     {
-      parent = gvdb_hash_table_insert (table, key);
+      parent = gvdb_hash_table_insert (table, parent_name);
 
-      grandparent = dconf_rebuilder_get_parent (table, key, length);
+      grandparent = dconf_rebuilder_get_parent (table, parent_name);
 
       if (grandparent != NULL)
         gvdb_item_set_parent (parent, grandparent);
@@ -69,143 +61,107 @@ dconf_rebuilder_get_parent (GHashTable *table,
   return parent;
 }
 
-static void
-dconf_rebuilder_insert (GHashTable  *table,
-                        const gchar *key,
-                        GVariant    *value)
+gboolean
+dconf_rebuilder_rebuild (const gchar          *filename,
+                         const gchar          *prefix,
+                         const gchar * const  *keys,
+                         GVariant * const     *values,
+                         int                   n_items,
+                         GError              **error)
 {
-  GvdbItem *item;
-  gchar *mykey;
-  gint length;
-
-  length = strlen (key);
-  mykey = g_alloca (length);
-  memcpy (mykey, key, length);
-
-  g_assert (g_hash_table_lookup (table, key) == NULL);
-  item = gvdb_hash_table_insert (table, key);
-
-  gvdb_item_set_parent (item,
-                        dconf_rebuilder_get_parent (table, mykey, length));
+  GHashTable *table;
+  gboolean success;
+  GHashTable *new;
+  GvdbTable *old;
+  gint i;
 
-  gvdb_item_set_value (item, value);
-}
+  table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_variant_unref);
 
-static void
-dconf_rebuilder_put_item (DConfRebuilderState *state)
-{
-  if (state->values[state->index] != NULL)
+  /* read in the old values */
+  if ((old = gvdb_table_new (filename, FALSE, NULL)))
     {
-      gchar *fullname;
+      gchar **names;
+      gint n_names;
+      gint i;
 
-      fullname = g_strconcat (state->prefix, state->keys[state->index], NULL);
-      dconf_rebuilder_insert (state->table, fullname, state->values[state->index]);
-      g_free (fullname);
-    }
+      names = gvdb_table_get_names (old, &n_names);
+      for (i = 0; i < n_names; i++)
+        {
+          if (dconf_is_key (names[i], NULL))
+            {
+              GVariant *value;
 
-  state->index++;
-}
+              value = gvdb_table_get_value (old, names[i]);
 
-static gboolean
-dconf_rebuilder_walk_name (DConfRebuilderState *state,
-                           const gchar         *name,
-                           gsize                name_len)
-{
-  gint cmp;
-
-  g_assert (state->name_len + name_len < sizeof state->name - 1);
-  memcpy (state->name + state->name_len, name, name_len);
-  state->name[state->name_len + name_len] = '\0';
-
-  if (state->index == state->n_items)
-    return TRUE;
+              if (value != NULL)
+                {
+                  g_hash_table_insert (table, names[i], value);
+                  names[i] = NULL;
+                }
+            }
 
-  if (state->name_len + name_len < state->prefix_len ||
-      memcmp (state->name, state->prefix, state->prefix_len) != 0)
-    return TRUE;
-
-  while ((cmp = strcmp (state->name + state->prefix_len,
-                        state->keys[state->index])) > 0)
-    {
-      dconf_rebuilder_put_item (state);
+          g_free (names[i]);
+        }
 
-      if (state->index == state->n_items)
-        return TRUE;
+      gvdb_table_unref (old);
+      g_free (names);
     }
 
-  return cmp != 0;
-}
-
-static void
-dconf_rebuilder_walk_value (const gchar *name,
-                            gsize        name_len,
-                            GVariant    *value,
-                            gpointer     user_data)
-{
-  DConfRebuilderState *state = user_data;
-
-  if (dconf_rebuilder_walk_name (state, name, name_len))
-    dconf_rebuilder_insert (state->table, state->name, value);
-
-  else
-    dconf_rebuilder_put_item (state);
-}
-
-static gboolean
-dconf_rebuilder_walk_open (const gchar *name,
-                           gsize        name_len,
-                           gpointer     user_data)
-{
-  DConfRebuilderState *state = user_data;
-
-  if (dconf_rebuilder_walk_name (state, name, name_len))
+  /* apply the requested changes */
+  for (i = 0; i < n_items; i++)
     {
-      state->name_len += name_len;
-      return TRUE;
+      gchar *path = g_strconcat (prefix, keys[i], NULL);
+
+      /* Check if we are performing a path reset */
+      if (g_str_has_suffix (path, "/"))
+        {
+          GHashTableIter iter;
+          gpointer key;
+
+          g_assert (values[i] == NULL);
+
+          /* A path reset is really a request to delete all keys that
+           * has a name starting with the reset path.
+           */
+          g_hash_table_iter_init (&iter, table);
+          while (g_hash_table_iter_next (&iter, &key, NULL))
+            if (g_str_has_prefix (key, path))
+              g_hash_table_iter_remove (&iter);
+        }
+
+      if (values[i] != NULL)
+        g_hash_table_insert (table, g_strdup (path), g_variant_ref (values[i]));
+      else
+        g_hash_table_remove (table, path);
+
+      g_free (path);
     }
 
-  return FALSE;
-}
+  /* convert back to GVDB format */
+  {
+    GHashTableIter iter;
+    gpointer key, value;
 
-static void
-dconf_rebuilder_walk_close (gsize    name_len,
-                            gpointer user_data)
-{
-  DConfRebuilderState *state = user_data;
+    new = gvdb_hash_table_new (NULL, NULL);
 
-  state->name_len -= name_len;
-}
-
-gboolean
-dconf_rebuilder_rebuild (const gchar  *filename,
-                         const gchar  *prefix,
-                         const gchar *const*keys,
-                         GVariant    *const*values,
-                         int           n_items,
-                         GError      **error)
-{
-  DConfRebuilderState state = { prefix, strlen (prefix),
-                                0, keys, values, n_items };
-  gboolean success;
-  GvdbTable *old;
+    g_hash_table_iter_init (&iter, table);
+    while (g_hash_table_iter_next (&iter, &key, &value))
+      {
+        GvdbItem *item;
 
-  state.table = gvdb_hash_table_new (NULL, NULL);
-
-  if ((old = gvdb_table_new (filename, FALSE, NULL)))
-    {
-      gvdb_table_walk (old, "/",
-                       dconf_rebuilder_walk_open,
-                       dconf_rebuilder_walk_value,
-                       dconf_rebuilder_walk_close,
-                       &state);
-      gvdb_table_unref (old);
-    }
+        g_assert (g_hash_table_lookup (new, key) == NULL);
+        item = gvdb_hash_table_insert (new, key);
+        gvdb_item_set_parent (item, dconf_rebuilder_get_parent (new, key));
+        gvdb_item_set_value (item, value);
+      }
+  }
 
-  while (state.index != state.n_items)
-    dconf_rebuilder_put_item (&state);
+  /* write the new file */
+  success = gvdb_table_write_contents (new, filename, FALSE, error);
 
-  success = gvdb_table_write_contents (state.table, filename, FALSE, error);
-  g_hash_table_unref (state.table);
+  /* clean up */
+  g_hash_table_unref (table);
+  g_hash_table_unref (new);
 
   return success;
 }



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]