mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-12-25 15:06:14 +01:00
ghash: Add functions to steal all keys and values preserving ownership
Add functions to steal all the keys or values from a ghash (especially useful when it's used as a set), passing the ownership of then to a GPtrArray container that preserves the destroy notify functions.
This commit is contained in:
parent
d2c3f7f513
commit
d68e7bc84a
@ -2578,6 +2578,8 @@ GHFunc
|
||||
g_hash_table_remove
|
||||
g_hash_table_steal
|
||||
g_hash_table_steal_extended
|
||||
g_hash_table_steal_all_keys
|
||||
g_hash_table_steal_all_values
|
||||
g_hash_table_foreach_remove
|
||||
g_hash_table_foreach_steal
|
||||
g_hash_table_remove_all
|
||||
|
74
glib/ghash.c
74
glib/ghash.c
@ -1942,6 +1942,80 @@ g_hash_table_steal_all (GHashTable *hash_table)
|
||||
g_hash_table_maybe_resize (hash_table);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_hash_table_steal_all_keys: (skip)
|
||||
* @hash_table: a #GHashTable
|
||||
*
|
||||
* Removes all keys and their associated values from a #GHashTable
|
||||
* without calling the key destroy functions, returning the keys
|
||||
* as a #GPtrArray with the free func set to the @hash_table key
|
||||
* destroy function.
|
||||
*
|
||||
* Returns: (transfer container): a #GPtrArray containing each key of
|
||||
* the table. Unref with with g_ptr_array_unref() when done.
|
||||
*
|
||||
* Since: 2.76
|
||||
*/
|
||||
GPtrArray *
|
||||
g_hash_table_steal_all_keys (GHashTable *hash_table)
|
||||
{
|
||||
GPtrArray *array;
|
||||
GDestroyNotify key_destroy_func;
|
||||
|
||||
g_return_val_if_fail (hash_table != NULL, NULL);
|
||||
|
||||
array = g_hash_table_get_keys_as_ptr_array (hash_table);
|
||||
|
||||
/* Ignore the key destroy notify calls during removal, and use it for the
|
||||
* array elements instead, but restore it after the hash table has been
|
||||
* cleared, so that newly added keys will continue using it.
|
||||
*/
|
||||
key_destroy_func = g_steal_pointer (&hash_table->key_destroy_func);
|
||||
g_ptr_array_set_free_func (array, key_destroy_func);
|
||||
|
||||
g_hash_table_remove_all (hash_table);
|
||||
hash_table->key_destroy_func = g_steal_pointer (&key_destroy_func);
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_hash_table_steal_all_values: (skip)
|
||||
* @hash_table: a #GHashTable
|
||||
*
|
||||
* Removes all keys and their associated values from a #GHashTable
|
||||
* without calling the value destroy functions, returning the values
|
||||
* as a #GPtrArray with the free func set to the @hash_table value
|
||||
* destroy function.
|
||||
*
|
||||
* Returns: (transfer container): a #GPtrArray containing each value of
|
||||
* the table. Unref with with g_ptr_array_unref() when done.
|
||||
*
|
||||
* Since: 2.76
|
||||
*/
|
||||
GPtrArray *
|
||||
g_hash_table_steal_all_values (GHashTable *hash_table)
|
||||
{
|
||||
GPtrArray *array;
|
||||
GDestroyNotify value_destroy_func;
|
||||
|
||||
g_return_val_if_fail (hash_table != NULL, NULL);
|
||||
|
||||
array = g_hash_table_get_values_as_ptr_array (hash_table);
|
||||
|
||||
/* Ignore the value destroy notify calls during removal, and use it for the
|
||||
* array elements instead, but restore it after the hash table has been
|
||||
* cleared, so that newly added values will continue using it.
|
||||
*/
|
||||
value_destroy_func = g_steal_pointer (&hash_table->value_destroy_func);
|
||||
g_ptr_array_set_free_func (array, value_destroy_func);
|
||||
|
||||
g_hash_table_remove_all (hash_table);
|
||||
hash_table->value_destroy_func = g_steal_pointer (&value_destroy_func);
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
/*
|
||||
* g_hash_table_foreach_remove_or_steal:
|
||||
* @hash_table: a #GHashTable
|
||||
|
@ -94,6 +94,10 @@ gboolean g_hash_table_steal_extended (GHashTable *hash_table,
|
||||
gpointer *stolen_value);
|
||||
GLIB_AVAILABLE_IN_ALL
|
||||
void g_hash_table_steal_all (GHashTable *hash_table);
|
||||
GLIB_AVAILABLE_IN_2_76
|
||||
GPtrArray * g_hash_table_steal_all_keys (GHashTable *hash_table);
|
||||
GLIB_AVAILABLE_IN_2_76
|
||||
GPtrArray * g_hash_table_steal_all_values (GHashTable *hash_table);
|
||||
GLIB_AVAILABLE_IN_ALL
|
||||
gpointer g_hash_table_lookup (GHashTable *hash_table,
|
||||
gconstpointer key);
|
||||
|
@ -1749,6 +1749,106 @@ test_set_get_values_as_ptr_array (void)
|
||||
g_clear_pointer (&array, g_ptr_array_unref);
|
||||
}
|
||||
|
||||
static void
|
||||
test_steal_all_keys (void)
|
||||
{
|
||||
GHashTable *table;
|
||||
GPtrArray *array;
|
||||
|
||||
table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
|
||||
g_hash_table_insert (table, g_strdup ("xyz"), GUINT_TO_POINTER (0));
|
||||
g_hash_table_insert (table, g_strdup ("xyz"), GUINT_TO_POINTER (1));
|
||||
g_hash_table_insert (table, g_strdup ("abc"), GUINT_TO_POINTER (2));
|
||||
|
||||
array = g_hash_table_steal_all_keys (table);
|
||||
g_assert_cmpuint (g_hash_table_size (table), ==, 0);
|
||||
|
||||
g_hash_table_insert (table, g_strdup ("do-not-leak-me"), GUINT_TO_POINTER (5));
|
||||
g_clear_pointer (&table, g_hash_table_unref);
|
||||
|
||||
g_assert_cmpint (array->len, ==, 2);
|
||||
g_ptr_array_add (array, NULL);
|
||||
|
||||
g_assert_true (
|
||||
g_strv_equal ((const gchar * const[]) { "xyz", "abc", NULL },
|
||||
(const gchar * const*) array->pdata) ||
|
||||
g_strv_equal ((const gchar * const[]) { "abc", "xyz", NULL },
|
||||
(const gchar * const*) array->pdata)
|
||||
);
|
||||
|
||||
g_clear_pointer (&array, g_ptr_array_unref);
|
||||
|
||||
table = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free);
|
||||
g_hash_table_insert (table, GUINT_TO_POINTER (0), g_strdup ("xyz"));
|
||||
g_hash_table_insert (table, GUINT_TO_POINTER (1), g_strdup ("xyz"));
|
||||
g_hash_table_insert (table, GUINT_TO_POINTER (2), g_strdup ("abc"));
|
||||
|
||||
array = g_hash_table_steal_all_keys (table);
|
||||
g_assert_cmpuint (g_hash_table_size (table), ==, 0);
|
||||
|
||||
g_hash_table_insert (table, GUINT_TO_POINTER (5), g_strdup ("do-not-leak-me"));
|
||||
g_clear_pointer (&table, g_hash_table_unref);
|
||||
|
||||
g_assert_cmpint (array->len, ==, 3);
|
||||
g_assert_true (g_ptr_array_find (array, GUINT_TO_POINTER (0), NULL));
|
||||
g_assert_true (g_ptr_array_find (array, GUINT_TO_POINTER (1), NULL));
|
||||
g_assert_true (g_ptr_array_find (array, GUINT_TO_POINTER (2), NULL));
|
||||
|
||||
g_clear_pointer (&array, g_ptr_array_unref);
|
||||
}
|
||||
|
||||
static void
|
||||
test_steal_all_values (void)
|
||||
{
|
||||
GHashTable *table;
|
||||
GPtrArray *array;
|
||||
|
||||
table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
|
||||
g_hash_table_insert (table, g_strdup ("xyz"), GUINT_TO_POINTER (0));
|
||||
g_hash_table_insert (table, g_strdup ("xyz"), GUINT_TO_POINTER (1));
|
||||
g_hash_table_insert (table, g_strdup ("abc"), GUINT_TO_POINTER (2));
|
||||
|
||||
array = g_hash_table_steal_all_values (table);
|
||||
g_assert_cmpuint (g_hash_table_size (table), ==, 0);
|
||||
|
||||
g_hash_table_insert (table, g_strdup ("do-not-leak-me"), GUINT_TO_POINTER (5));
|
||||
g_clear_pointer (&table, g_hash_table_unref);
|
||||
|
||||
g_assert_cmpint (array->len, ==, 2);
|
||||
g_assert_true (g_ptr_array_find (array, GUINT_TO_POINTER (1), NULL));
|
||||
g_assert_true (g_ptr_array_find (array, GUINT_TO_POINTER (2), NULL));
|
||||
|
||||
g_assert_true (
|
||||
memcmp ((gpointer []) { GUINT_TO_POINTER (1), GUINT_TO_POINTER (2) },
|
||||
array->pdata, array->len * sizeof (gpointer)) == 0 ||
|
||||
memcmp ((gpointer []) { GUINT_TO_POINTER (2), GUINT_TO_POINTER (1) },
|
||||
array->pdata, array->len * sizeof (gpointer)) == 0
|
||||
);
|
||||
|
||||
g_clear_pointer (&array, g_ptr_array_unref);
|
||||
|
||||
table = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free);
|
||||
g_hash_table_insert (table, GUINT_TO_POINTER (0), g_strdup ("xyz"));
|
||||
g_hash_table_insert (table, GUINT_TO_POINTER (1), g_strdup ("foo"));
|
||||
g_hash_table_insert (table, GUINT_TO_POINTER (2), g_strdup ("abc"));
|
||||
|
||||
array = g_hash_table_steal_all_values (table);
|
||||
g_assert_cmpuint (g_hash_table_size (table), ==, 0);
|
||||
|
||||
g_hash_table_insert (table, GUINT_TO_POINTER (5), g_strdup ("do-not-leak-me"));
|
||||
g_clear_pointer (&table, g_hash_table_unref);
|
||||
|
||||
g_assert_cmpint (array->len, ==, 3);
|
||||
g_assert_true (
|
||||
g_ptr_array_find_with_equal_func (array, "xyz", g_str_equal, NULL));
|
||||
g_assert_true (
|
||||
g_ptr_array_find_with_equal_func (array, "foo", g_str_equal, NULL));
|
||||
g_assert_true (
|
||||
g_ptr_array_find_with_equal_func (array, "abc", g_str_equal, NULL));
|
||||
|
||||
g_clear_pointer (&array, g_ptr_array_unref);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
is_prime (guint p)
|
||||
{
|
||||
@ -1821,6 +1921,8 @@ main (int argc, char *argv[])
|
||||
g_test_add_func ("/hash/foreach-steal", test_foreach_steal);
|
||||
g_test_add_func ("/hash/steal-extended", test_steal_extended);
|
||||
g_test_add_func ("/hash/steal-extended/optional", test_steal_extended_optional);
|
||||
g_test_add_func ("/hash/steal-all-keys", test_steal_all_keys);
|
||||
g_test_add_func ("/hash/steal-all-values", test_steal_all_values);
|
||||
g_test_add_func ("/hash/lookup-extended", test_lookup_extended);
|
||||
g_test_add_func ("/hash/new-similar", test_new_similar);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user