diff --git a/ChangeLog b/ChangeLog index 1b52cf1e2..c39be1ef1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +Sun Sep 20 02:09:44 1998 Josh MacDonald + + * glib.h: New function g_hash_table_foreach_remove is similar to + g_hash_table_foreach, but the callback's return value indicates + whether to remove the element (if TRUE) or not (if FALSE). + Returns the number of elements deleted. + Fri Sep 18 11:31:50 PDT 1998 Manish Singh * glib.h diff --git a/ChangeLog.pre-2-0 b/ChangeLog.pre-2-0 index 1b52cf1e2..c39be1ef1 100644 --- a/ChangeLog.pre-2-0 +++ b/ChangeLog.pre-2-0 @@ -1,3 +1,10 @@ +Sun Sep 20 02:09:44 1998 Josh MacDonald + + * glib.h: New function g_hash_table_foreach_remove is similar to + g_hash_table_foreach, but the callback's return value indicates + whether to remove the element (if TRUE) or not (if FALSE). + Returns the number of elements deleted. + Fri Sep 18 11:31:50 PDT 1998 Manish Singh * glib.h diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index 1b52cf1e2..c39be1ef1 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,10 @@ +Sun Sep 20 02:09:44 1998 Josh MacDonald + + * glib.h: New function g_hash_table_foreach_remove is similar to + g_hash_table_foreach, but the callback's return value indicates + whether to remove the element (if TRUE) or not (if FALSE). + Returns the number of elements deleted. + Fri Sep 18 11:31:50 PDT 1998 Manish Singh * glib.h diff --git a/ChangeLog.pre-2-12 b/ChangeLog.pre-2-12 index 1b52cf1e2..c39be1ef1 100644 --- a/ChangeLog.pre-2-12 +++ b/ChangeLog.pre-2-12 @@ -1,3 +1,10 @@ +Sun Sep 20 02:09:44 1998 Josh MacDonald + + * glib.h: New function g_hash_table_foreach_remove is similar to + g_hash_table_foreach, but the callback's return value indicates + whether to remove the element (if TRUE) or not (if FALSE). + Returns the number of elements deleted. + Fri Sep 18 11:31:50 PDT 1998 Manish Singh * glib.h diff --git a/ChangeLog.pre-2-2 b/ChangeLog.pre-2-2 index 1b52cf1e2..c39be1ef1 100644 --- a/ChangeLog.pre-2-2 +++ b/ChangeLog.pre-2-2 @@ -1,3 +1,10 @@ +Sun Sep 20 02:09:44 1998 Josh MacDonald + + * glib.h: New function g_hash_table_foreach_remove is similar to + g_hash_table_foreach, but the callback's return value indicates + whether to remove the element (if TRUE) or not (if FALSE). + Returns the number of elements deleted. + Fri Sep 18 11:31:50 PDT 1998 Manish Singh * glib.h diff --git a/ChangeLog.pre-2-4 b/ChangeLog.pre-2-4 index 1b52cf1e2..c39be1ef1 100644 --- a/ChangeLog.pre-2-4 +++ b/ChangeLog.pre-2-4 @@ -1,3 +1,10 @@ +Sun Sep 20 02:09:44 1998 Josh MacDonald + + * glib.h: New function g_hash_table_foreach_remove is similar to + g_hash_table_foreach, but the callback's return value indicates + whether to remove the element (if TRUE) or not (if FALSE). + Returns the number of elements deleted. + Fri Sep 18 11:31:50 PDT 1998 Manish Singh * glib.h diff --git a/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6 index 1b52cf1e2..c39be1ef1 100644 --- a/ChangeLog.pre-2-6 +++ b/ChangeLog.pre-2-6 @@ -1,3 +1,10 @@ +Sun Sep 20 02:09:44 1998 Josh MacDonald + + * glib.h: New function g_hash_table_foreach_remove is similar to + g_hash_table_foreach, but the callback's return value indicates + whether to remove the element (if TRUE) or not (if FALSE). + Returns the number of elements deleted. + Fri Sep 18 11:31:50 PDT 1998 Manish Singh * glib.h diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index 1b52cf1e2..c39be1ef1 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -1,3 +1,10 @@ +Sun Sep 20 02:09:44 1998 Josh MacDonald + + * glib.h: New function g_hash_table_foreach_remove is similar to + g_hash_table_foreach, but the callback's return value indicates + whether to remove the element (if TRUE) or not (if FALSE). + Returns the number of elements deleted. + Fri Sep 18 11:31:50 PDT 1998 Manish Singh * glib.h diff --git a/ghash.c b/ghash.c index b2c3838dd..065f88956 100644 --- a/ghash.c +++ b/ghash.c @@ -194,6 +194,52 @@ g_hash_table_thaw (GHashTable *hash_table) g_hash_table_resize (hash_table); } +gint +g_hash_table_foreach_remove (GHashTable *hash_table, + GHRFunc func, + gpointer user_data) +{ + gint deleted = 0, i; + GHashNode *node, *prev; + + g_return_val_if_fail (hash_table && func, -1); + + for (i = 0; i < hash_table->size; i++) + { + restart: + + prev = NULL; + + for (node = hash_table->nodes[i]; node; prev = node, node = node->next) + { + if ((* func) (node->key, node->value, user_data)) + { + deleted += 1; + + hash_table->nnodes -= 1; + + if (prev) + { + prev->next = node->next; + g_hash_node_destroy (node); + node = prev; + } + else + { + hash_table->nodes[i] = node->next; + g_hash_node_destroy (node); + goto restart; + } + } + } + } + + if (! hash_table->frozen) + g_hash_table_resize (hash_table); + + return deleted; +} + void g_hash_table_foreach (GHashTable *hash_table, GHFunc func, diff --git a/glib.h b/glib.h index c52179ed4..6b199cbbc 100644 --- a/glib.h +++ b/glib.h @@ -659,6 +659,9 @@ typedef guint (*GHashFunc) (gconstpointer key); typedef void (*GHFunc) (gpointer key, gpointer value, gpointer user_data); +typedef gboolean (*GHRFunc) (gpointer key, + gpointer value, + gpointer user_data); typedef void (*GLogFunc) (const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, @@ -851,6 +854,9 @@ void g_hash_table_thaw (GHashTable *hash_table); void g_hash_table_foreach (GHashTable *hash_table, GHFunc func, gpointer user_data); +gint g_hash_table_foreach_remove (GHashTable *hash_table, + GHRFunc func, + gpointer user_data); gint g_hash_table_size (GHashTable *hash_table); diff --git a/glib/ghash.c b/glib/ghash.c index b2c3838dd..065f88956 100644 --- a/glib/ghash.c +++ b/glib/ghash.c @@ -194,6 +194,52 @@ g_hash_table_thaw (GHashTable *hash_table) g_hash_table_resize (hash_table); } +gint +g_hash_table_foreach_remove (GHashTable *hash_table, + GHRFunc func, + gpointer user_data) +{ + gint deleted = 0, i; + GHashNode *node, *prev; + + g_return_val_if_fail (hash_table && func, -1); + + for (i = 0; i < hash_table->size; i++) + { + restart: + + prev = NULL; + + for (node = hash_table->nodes[i]; node; prev = node, node = node->next) + { + if ((* func) (node->key, node->value, user_data)) + { + deleted += 1; + + hash_table->nnodes -= 1; + + if (prev) + { + prev->next = node->next; + g_hash_node_destroy (node); + node = prev; + } + else + { + hash_table->nodes[i] = node->next; + g_hash_node_destroy (node); + goto restart; + } + } + } + } + + if (! hash_table->frozen) + g_hash_table_resize (hash_table); + + return deleted; +} + void g_hash_table_foreach (GHashTable *hash_table, GHFunc func, diff --git a/glib/glib.h b/glib/glib.h index c52179ed4..6b199cbbc 100644 --- a/glib/glib.h +++ b/glib/glib.h @@ -659,6 +659,9 @@ typedef guint (*GHashFunc) (gconstpointer key); typedef void (*GHFunc) (gpointer key, gpointer value, gpointer user_data); +typedef gboolean (*GHRFunc) (gpointer key, + gpointer value, + gpointer user_data); typedef void (*GLogFunc) (const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, @@ -851,6 +854,9 @@ void g_hash_table_thaw (GHashTable *hash_table); void g_hash_table_foreach (GHashTable *hash_table, GHFunc func, gpointer user_data); +gint g_hash_table_foreach_remove (GHashTable *hash_table, + GHRFunc func, + gpointer user_data); gint g_hash_table_size (GHashTable *hash_table); diff --git a/testglib.c b/testglib.c index d0440224d..1dd6efa80 100644 --- a/testglib.c +++ b/testglib.c @@ -177,6 +177,30 @@ g_node_test (void) g_print ("ok\n"); } +gboolean +my_hash_callback_remove (gpointer key, + gpointer value, + gpointer user_data) +{ + int *d = value; + + if ((*d) % 2) + return TRUE; + + return FALSE; +} + +void +my_hash_callback_remove_test (gpointer key, + gpointer value, + gpointer user_data) +{ + int *d = value; + + if ((*d) % 2) + g_print ("bad!\n"); +} + void my_hash_callback (gpointer key, gpointer value, @@ -522,6 +546,19 @@ main (int argc, for (i = 0; i < 10000; i++) g_hash_table_remove (hash_table, &array[i]); + for (i = 0; i < 10000; i++) + { + array[i] = i; + g_hash_table_insert (hash_table, &array[i], &array[i]); + } + + if (g_hash_table_foreach_remove (hash_table, my_hash_callback_remove, NULL) != 5000 || + g_hash_table_size (hash_table) != 5000) + g_print ("bad!\n"); + + g_hash_table_foreach (hash_table, my_hash_callback_remove_test, NULL); + + g_hash_table_destroy (hash_table); g_print ("ok\n"); diff --git a/tests/testglib.c b/tests/testglib.c index d0440224d..1dd6efa80 100644 --- a/tests/testglib.c +++ b/tests/testglib.c @@ -177,6 +177,30 @@ g_node_test (void) g_print ("ok\n"); } +gboolean +my_hash_callback_remove (gpointer key, + gpointer value, + gpointer user_data) +{ + int *d = value; + + if ((*d) % 2) + return TRUE; + + return FALSE; +} + +void +my_hash_callback_remove_test (gpointer key, + gpointer value, + gpointer user_data) +{ + int *d = value; + + if ((*d) % 2) + g_print ("bad!\n"); +} + void my_hash_callback (gpointer key, gpointer value, @@ -522,6 +546,19 @@ main (int argc, for (i = 0; i < 10000; i++) g_hash_table_remove (hash_table, &array[i]); + for (i = 0; i < 10000; i++) + { + array[i] = i; + g_hash_table_insert (hash_table, &array[i], &array[i]); + } + + if (g_hash_table_foreach_remove (hash_table, my_hash_callback_remove, NULL) != 5000 || + g_hash_table_size (hash_table) != 5000) + g_print ("bad!\n"); + + g_hash_table_foreach (hash_table, my_hash_callback_remove_test, NULL); + + g_hash_table_destroy (hash_table); g_print ("ok\n");