[glib] ghash: Add g_hash_table_steal_extended()
- From: Philip Withnall <pwithnall src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib] ghash: Add g_hash_table_steal_extended()
- Date: Tue, 8 May 2018 12:16:08 +0000 (UTC)
commit 6acece5074d00f54c65a018498d9913664fa52ba
Author: Philip Withnall <withnall endlessm com>
Date: Mon Apr 16 16:02:13 2018 +0100
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
docs/reference/glib/glib-sections.txt | 1 +
glib/ghash.c | 61 +++++++++++++++++++++++++++++++++++
glib/ghash.h | 5 +++
glib/tests/hash.c | 45 ++++++++++++++++++++++++++
4 files changed, 112 insertions(+)
---
diff --git a/docs/reference/glib/glib-sections.txt b/docs/reference/glib/glib-sections.txt
index 47baf5eb8..f4b8dba54 100644
--- a/docs/reference/glib/glib-sections.txt
+++ b/docs/reference/glib/glib-sections.txt
@@ -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
diff --git a/glib/ghash.c b/glib/ghash.c
index 6bb04a50d..87218114f 100644
--- a/glib/ghash.c
+++ b/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
diff --git a/glib/ghash.h b/glib/ghash.h
index 5c8cb9195..0256d5411 100644
--- a/glib/ghash.h
+++ b/glib/ghash.h
@@ -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
diff --git a/glib/tests/hash.c b/glib/tests/hash.c
index 0513d6558..963cef894 100644
--- a/glib/tests/hash.c
+++ b/glib/tests/hash.c
@@ -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);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]