mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-02-03 17:56:17 +01:00
ghash: Add g_hash_table_steal_extended()
This is a combination of g_hash_table_lookup_extended() and g_hash_table_steal(), so that users can combine the two to reduce code and eliminate a pointless second hash table lookup by g_hash_table_steal(). Signed-off-by: Philip Withnall <withnall@endlessm.com> https://bugzilla.gnome.org/show_bug.cgi?id=795302
This commit is contained in:
parent
864cb71524
commit
6acece5074
@ -2453,6 +2453,7 @@ g_hash_table_find
|
||||
GHFunc
|
||||
g_hash_table_remove
|
||||
g_hash_table_steal
|
||||
g_hash_table_steal_extended
|
||||
g_hash_table_foreach_remove
|
||||
g_hash_table_foreach_steal
|
||||
g_hash_table_remove_all
|
||||
|
61
glib/ghash.c
61
glib/ghash.c
@ -1421,6 +1421,67 @@ g_hash_table_steal (GHashTable *hash_table,
|
||||
return g_hash_table_remove_internal (hash_table, key, FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_hash_table_steal_extended:
|
||||
* @hash_table: a #GHashTable
|
||||
* @lookup_key: the key to look up
|
||||
* @stolen_key: (out) (optional) (transfer full): return location for the
|
||||
* original key
|
||||
* @stolen_value: (out) (optional) (nullable) (transfer full): return location
|
||||
* for the value associated with the key
|
||||
*
|
||||
* Looks up a key in the #GHashTable, stealing the original key and the
|
||||
* associated value and returning %TRUE if the key was found. If the key was
|
||||
* not found, %FALSE is returned.
|
||||
*
|
||||
* If found, the stolen key and value are removed from the hash table without
|
||||
* calling the key and value destroy functions, and ownership is transferred to
|
||||
* the caller of this method; as with g_hash_table_steal().
|
||||
*
|
||||
* You can pass %NULL for @lookup_key, provided the hash and equal functions
|
||||
* of @hash_table are %NULL-safe.
|
||||
*
|
||||
* Returns: %TRUE if the key was found in the #GHashTable
|
||||
* Since: 2.58
|
||||
*/
|
||||
gboolean
|
||||
g_hash_table_steal_extended (GHashTable *hash_table,
|
||||
gconstpointer lookup_key,
|
||||
gpointer *stolen_key,
|
||||
gpointer *stolen_value)
|
||||
{
|
||||
guint node_index;
|
||||
guint node_hash;
|
||||
|
||||
g_return_val_if_fail (hash_table != NULL, FALSE);
|
||||
|
||||
node_index = g_hash_table_lookup_node (hash_table, lookup_key, &node_hash);
|
||||
|
||||
if (!HASH_IS_REAL (hash_table->hashes[node_index]))
|
||||
{
|
||||
if (stolen_key != NULL)
|
||||
*stolen_key = NULL;
|
||||
if (stolen_value != NULL)
|
||||
*stolen_value = NULL;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (stolen_key != NULL)
|
||||
*stolen_key = g_steal_pointer (&hash_table->keys[node_index]);
|
||||
|
||||
if (stolen_value != NULL)
|
||||
*stolen_value = g_steal_pointer (&hash_table->values[node_index]);
|
||||
|
||||
g_hash_table_remove_node (hash_table, node_index, FALSE);
|
||||
g_hash_table_maybe_resize (hash_table);
|
||||
|
||||
#ifndef G_DISABLE_ASSERT
|
||||
hash_table->version++;
|
||||
#endif
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_hash_table_remove_all:
|
||||
* @hash_table: a #GHashTable
|
||||
|
@ -82,6 +82,11 @@ void g_hash_table_remove_all (GHashTable *hash_table);
|
||||
GLIB_AVAILABLE_IN_ALL
|
||||
gboolean g_hash_table_steal (GHashTable *hash_table,
|
||||
gconstpointer key);
|
||||
GLIB_AVAILABLE_IN_2_58
|
||||
gboolean g_hash_table_steal_extended (GHashTable *hash_table,
|
||||
gconstpointer lookup_key,
|
||||
gpointer *stolen_key,
|
||||
gpointer *stolen_value);
|
||||
GLIB_AVAILABLE_IN_ALL
|
||||
void g_hash_table_steal_all (GHashTable *hash_table);
|
||||
GLIB_AVAILABLE_IN_ALL
|
||||
|
@ -1189,6 +1189,50 @@ test_foreach_steal (void)
|
||||
g_hash_table_unref (hash2);
|
||||
}
|
||||
|
||||
/* Test g_hash_table_steal_extended() works properly with existing and
|
||||
* non-existing keys. */
|
||||
static void
|
||||
test_steal_extended (void)
|
||||
{
|
||||
GHashTable *hash;
|
||||
gchar *stolen_key = NULL, *stolen_value = NULL;
|
||||
|
||||
hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
|
||||
|
||||
g_hash_table_insert (hash, g_strdup ("a"), g_strdup ("A"));
|
||||
g_hash_table_insert (hash, g_strdup ("b"), g_strdup ("B"));
|
||||
g_hash_table_insert (hash, g_strdup ("c"), g_strdup ("C"));
|
||||
g_hash_table_insert (hash, g_strdup ("d"), g_strdup ("D"));
|
||||
g_hash_table_insert (hash, g_strdup ("e"), g_strdup ("E"));
|
||||
g_hash_table_insert (hash, g_strdup ("f"), g_strdup ("F"));
|
||||
|
||||
g_assert_true (g_hash_table_steal_extended (hash, "a",
|
||||
(gpointer *) &stolen_key,
|
||||
(gpointer *) &stolen_value));
|
||||
g_assert_cmpstr (stolen_key, ==, "a");
|
||||
g_assert_cmpstr (stolen_value, ==, "A");
|
||||
g_clear_pointer (&stolen_key, g_free);
|
||||
g_clear_pointer (&stolen_value, g_free);
|
||||
|
||||
g_assert_cmpuint (g_hash_table_size (hash), ==, 5);
|
||||
|
||||
g_assert_false (g_hash_table_steal_extended (hash, "a",
|
||||
(gpointer *) &stolen_key,
|
||||
(gpointer *) &stolen_value));
|
||||
g_assert_null (stolen_key);
|
||||
g_assert_null (stolen_value);
|
||||
|
||||
g_assert_false (g_hash_table_steal_extended (hash, "never a key",
|
||||
(gpointer *) &stolen_key,
|
||||
(gpointer *) &stolen_value));
|
||||
g_assert_null (stolen_key);
|
||||
g_assert_null (stolen_value);
|
||||
|
||||
g_assert_cmpuint (g_hash_table_size (hash), ==, 5);
|
||||
|
||||
g_hash_table_unref (hash);
|
||||
}
|
||||
|
||||
struct _GHashTable
|
||||
{
|
||||
gint size;
|
||||
@ -1513,6 +1557,7 @@ main (int argc, char *argv[])
|
||||
g_test_add_func ("/hash/find", test_find);
|
||||
g_test_add_func ("/hash/foreach", test_foreach);
|
||||
g_test_add_func ("/hash/foreach-steal", test_foreach_steal);
|
||||
g_test_add_func ("/hash/steal-extended", test_steal_extended);
|
||||
|
||||
/* tests for individual bugs */
|
||||
g_test_add_func ("/hash/lookup-null-key", test_lookup_null_key);
|
||||
|
Loading…
Reference in New Issue
Block a user