Permalink
Browse files

Implement GHashTable iterators.

  • Loading branch information...
1 parent 054b22b commit 04fd3736149a643db661787e4196d34659bc2e71 @vargaz vargaz committed May 4, 2011
Showing with 107 additions and 0 deletions.
  1. +68 −0 eglib/src/ghashtable.c
  2. +11 −0 eglib/src/glib.h
  3. +28 −0 eglib/test/hashtable.c
@@ -51,6 +51,12 @@ struct _GHashTable {
GDestroyNotify value_destroy_func, key_destroy_func;
};
+typedef struct {
+ GHashTable *ht;
+ int slot_index;
+ Slot *slot;
+} Iter;
+
static const guint prime_tbl[] = {
11, 19, 37, 73, 109, 163, 251, 367, 557, 823, 1237,
1861, 2777, 4177, 6247, 9371, 14057, 21089, 31627,
@@ -422,6 +428,68 @@ g_hash_table_destroy (GHashTable *hash)
g_free (hash);
}
+void
+g_hash_table_print_stats (GHashTable *table)
+{
+ int i, max_chain_index, chain_size, max_chain_size;
+ Slot *node;
+
+ max_chain_size = 0;
+ max_chain_index = -1;
+ for (i = 0; i < table->table_size; i++) {
+ chain_size = 0;
+ for (node = table->table [i]; node; node = node->next)
+ chain_size ++;
+ if (chain_size > max_chain_size) {
+ max_chain_size = chain_size;
+ max_chain_index = i;
+ }
+ }
+
+ printf ("Size: %d Table Size: %d Max Chain Length: %d at %d\n", table->in_use, table->table_size, max_chain_size, max_chain_index);
+}
+
+void
+g_hash_table_iter_init (GHashTableIter *it, GHashTable *hash_table)
+{
+ Iter *iter = (Iter*)it;
+
+ memset (iter, 0, sizeof (Iter));
+ iter->ht = hash_table;
+ iter->slot_index = -1;
+}
+
+gboolean g_hash_table_iter_next (GHashTableIter *it, gpointer *key, gpointer *value)
+{
+ Iter *iter = (Iter*)it;
+
+ GHashTable *hash = iter->ht;
+
+ g_assert (iter->slot_index != -2);
+ g_assert (sizeof (Iter) <= sizeof (GHashTableIter));
+
+ if (!iter->slot) {
+ while (TRUE) {
+ iter->slot_index ++;
+ if (iter->slot_index >= hash->table_size) {
+ iter->slot_index = -2;
+ return FALSE;
+ }
+ if (hash->table [iter->slot_index])
+ break;
+ }
+ iter->slot = hash->table [iter->slot_index];
+ }
+
+ if (key)
+ *key = iter->slot->key;
+ if (value)
+ *value = iter->slot->value;
+ iter->slot = iter->slot->next;
+
+ return TRUE;
+}
+
gboolean
g_direct_equal (gconstpointer v1, gconstpointer v2)
{
View
@@ -158,6 +158,14 @@ gchar* g_win32_getlocale(void);
* Hashtables
*/
typedef struct _GHashTable GHashTable;
+typedef struct _GHashTableIter GHashTableIter;
+
+/* Private, but needed for stack allocation */
+struct _GHashTableIter
+{
+ gpointer dummy [8];
+};
+
typedef void (*GFunc) (gpointer data, gpointer user_data);
typedef gint (*GCompareFunc) (gconstpointer a, gconstpointer b);
typedef gint (*GCompareDataFunc) (gconstpointer a, gconstpointer b, gpointer user_data);
@@ -182,6 +190,9 @@ guint g_hash_table_foreach_remove (GHashTable *hash, GHRFunc func, gp
guint g_hash_table_foreach_steal (GHashTable *hash, GHRFunc func, gpointer user_data);
void g_hash_table_destroy (GHashTable *hash);
+void g_hash_table_iter_init (GHashTableIter *iter, GHashTable *hash_table);
+gboolean g_hash_table_iter_next (GHashTableIter *iter, gpointer *key, gpointer *value);
+
guint g_spaced_primes_closest (guint x);
#define g_hash_table_insert(h,k,v) g_hash_table_insert_replace ((h),(k),(v),FALSE)
@@ -131,12 +131,40 @@ RESULT hash_grow (void)
return NULL;
}
+RESULT hash_iter (void)
+{
+ GHashTable *hash = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, NULL);
+ GHashTableIter iter;
+ int i, sum, keys_sum, values_sum;
+ gpointer key, value;
+
+ sum = 0;
+ for (i = 0; i < 1000; i++) {
+ sum += i;
+ g_hash_table_insert (hash, GUINT_TO_POINTER (i), GUINT_TO_POINTER (i));
+ }
+
+ keys_sum = values_sum = 0;
+ g_hash_table_iter_init (&iter, hash);
+ while (g_hash_table_iter_next (&iter, &key, &value)) {
+ if (key != value)
+ return FAILED ("key != value");
+ keys_sum += GPOINTER_TO_UINT (key);
+ values_sum += GPOINTER_TO_UINT (value);
+ }
+ if (keys_sum != sum || values_sum != sum)
+ return FAILED ("Did not find all key-value pairs");
+ g_hash_table_destroy (hash);
+ return NULL;
+}
+
static Test hashtable_tests [] = {
{"t1", hash_t1},
{"t2", hash_t2},
{"grow", hash_grow},
{"default", hash_default},
{"null_lookup", hash_null_lookup},
+ {"iter", hash_iter},
{NULL, NULL}
};

0 comments on commit 04fd373

Please sign in to comment.