After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 52084 - PATCH API GHashIter - Hash Iterator
PATCH API GHashIter - Hash Iterator
Status: RESOLVED DUPLICATE of bug 83729
Product: glib
Classification: Platform
Component: general
1.3.x
Other Linux
: Normal enhancement
: ---
Assigned To: gtkdev
gtkdev
Depends on:
Blocks:
 
 
Reported: 2001-03-13 23:59 UTC by Tim Hockin
Modified: 2011-02-18 16:13 UTC
See Also:
GNOME target: ---
GNOME version: Unversioned Enhancement



Description Tim Hockin 2001-03-13 23:59:03 UTC
This patch implements an iterator widget for GHashTables.  Because they are
opaque, the only way to iterate (currently) is g_hash_table_foreach(). 
This provides an alternative.  We've found it tremendously useful.  By
standardizing it, we will not have to maintain a patched glib, which will
make us and our customers happy :)

I hope this doesn't mangle the patch.

thockin@sun.com
Sun Microsystems, Inc.
Cobalt Server Appliances



diff -ruN glib-1.3.2/ghash.c our-1.3.2/ghash.c
--- glib-1.3.2/ghash.c  Mon Oct 30 08:09:03 2000
+++ our-1.3.2/ghash.c   Tue Mar 13 14:24:27 2001
@@ -53,6 +53,12 @@
   GEqualFunc key_equal_func;
 };
 
+struct _GHashIter
+{
+  GHashTable *hash;
+  gint i;
+  GHashNode *node;
+};
 
 static void            g_hash_table_resize      (GHashTable   
*hash_table);
 static GHashNode**     g_hash_table_lookup_node (GHashTable   
*hash_table,
@@ -414,4 +420,80 @@
       node_free_list = hash_node;
       G_UNLOCK (g_hash_global);
     }
+}
+
+/* 
+ * a thread-safe iterator object -- make the iterator
+ * local to your thread and you're safe.  This iterator
+ * might be preferable to "foreach" if you want to avoid
+ * pass a lot of data about. 
+ */
+GHashIter *
+g_hash_iter_new(GHashTable *t)
+{
+  GHashIter *it;
+  gpointer key, val;
+
+  if (!t) {
+    return NULL;
+  }
+
+  it = g_new(GHashIter, 1);
+  it->hash = t;
+  it->node = NULL;
+  g_hash_iter_first(it, &key, &val);
+
+  return it;
+}
+
+void 
+g_hash_iter_destroy(GHashIter *it)
+{
+  g_free(it);
+}
+
+gpointer 
+g_hash_iter_first(GHashIter *it, gpointer *key, gpointer *val)
+{
+  *key = NULL;
+  *val = NULL;
+
+  it->i = 0;
+
+  while (it->i < it->hash->size) {
+    it->node = it->hash->nodes[it->i];
+    if (it->node) {
+      *key = it->node->key;
+      *val = it->node->value;
+      return *key;
+    }
+    (it->i)++;
+  }
+
+  return NULL;
+}
+
+gpointer 
+g_hash_iter_next(GHashIter *it, gpointer *key, gpointer *val)
+{
+  *key = NULL;
+  *val = NULL;
+  it->node = it->node->next;
+
+  while (1) {
+    if (it->node) {
+      *key = it->node->key;
+      *val = it->node->value;
+      return *key;
+    } else {
+      it->i++;
+      if (it->i < it->hash->size) {
+        it->node = it->hash->nodes[it->i];
+      } else {
+        break;
+      }
+    }
+  }
+
+  return NULL;
 }
diff -ruN glib-1.3.2/ghash.h our-1.3.2/ghash.h
--- glib-1.3.2/ghash.h  Mon Oct 30 08:09:03 2000
+++ our-1.3.2/ghash.h   Tue Mar 13 13:19:09 2001
@@ -32,6 +32,7 @@
 G_BEGIN_DECLS
 
 typedef struct _GHashTable     GHashTable;
+typedef struct _GHashIter      GHashIter;
 
 typedef gboolean       (*GHRFunc)              (gpointer       key,
                                                 gpointer       value,
@@ -85,6 +86,13 @@
 guint    g_direct_hash  (gconstpointer v) G_GNUC_CONST;
 gboolean g_direct_equal (gconstpointer v,
                          gconstpointer v2) G_GNUC_CONST;
+
+/* GHashIter - alternate iterator for GHashTable objects
+ */
+GHashIter *g_hash_iter_new (GHashTable *hash_table);
+gpointer g_hash_iter_first (GHashIter *i, gpointer *key, gpointer *val);
+gpointer g_hash_iter_next  (GHashIter *i, gpointer *key, gpointer *val);
+void g_hash_iter_destroy (GHashIter *i);
 
 G_END_DECLS
 diff -ruN glib-1.3.2/tests/hash-test.c our-1.3.2/tests/hash-test.c
--- glib-1.3.2/tests/hash-test.c        Mon Oct 30 08:09:05 2000
+++ our-1.3.2/tests/hash-test.c Tue Mar 13 13:58:17 2001
@@ -325,7 +325,59 @@
     g_hash_table_destroy (h);
 }
 
+int
+hash_iter_test (void)
+{
+    GHashTable *hash_table;
+    gint i;
+    int keyarr[10000];
+    int valarr[10000];
+  
+    /* initialize hash */
+    hash_table = g_hash_table_new(my_hash, my_hash_equal);
+    for (i = 0; i < 10000; i++)
+    {
+        keyarr[i] = i;
+        valarr[i] = i + 100;
+        g_hash_table_insert(hash_table, &keyarr[i], &valarr[i]);
+    }
+  
+    {
+        int count;
+        gpointer key, val;
+        GHashIter *it;
+
+        count = 0;
+        it = g_hash_iter_new(hash_table);
+
+        g_hash_iter_first(it, &key, &val); 
+        for (; key; g_hash_iter_next(it, &key, &val)) {
+            int *iP = val;
+            (*iP)++;
+            count++;
+        }
+        g_hash_iter_destroy(it);
+        g_assert(count == 10000);
+    }
+  
+    { 
+        int errs = 0;
+        for (i = 0; i < 10000; i++) {
+            if (valarr[i] != 100+i+1) {
+                if (errs < 20) {
+                    fprintf(stderr,"%d: %d = %d ( != %d )\n", 
+                        i, keyarr[i], valarr[i], 100+i+1 );
+               }
+                errs++;
+            }
+        }
+        g_assert(errs == 0);
+    }
+       
+    g_hash_table_destroy(hash_table);
 
+    return 0;
+}
 
 int
 main (int   argc,
@@ -367,7 +419,9 @@
   second_hash_test (TRUE);
   second_hash_test (FALSE);
   direct_hash_test ();
+  hash_iter_test ();
 
   return 0;
 
 }
+
Comment 1 Owen Taylor 2001-04-18 14:20:28 UTC
See:
 
http://mail.gnome.org/archives/gtk-devel-list/2001-April/msg00247.html

For something along the same lines, though more generalized. Both
of these are post 2.0.0 issues, since we are currently in a slushy
API freeze and trying to get scheduled improvements nailed down.
Comment 2 Matthias Clasen 2002-06-07 08:44:48 UTC

*** This bug has been marked as a duplicate of 83729 ***