[glib: 1/2] ghash: Add g_hash_table_new_similar()




commit 283d9e0c15ccfa54bb06e3f6d9e61763508e0bab
Author: Jonas Ã…dahl <jadahl gmail com>
Date:   Thu Dec 23 00:58:54 2021 +0100

    ghash: Add g_hash_table_new_similar()
    
    This function creates a new hash table, but inherits the functions used
    for the hash, comparison, and key/value memory management functions from
    another hash table.
    
    The primary use case is to implement a behaviour where you maintain a
    hash table by regenerating it, letting the values not migrated be freed.
    See the following pseudo code:
    
    ```
    GHashTable *ht;
    
    init(GList *resources) {
      ht = g_hash_table_new (g_str_hash, g_str_equal, g_free, g_free);
      for (r in resources)
        g_hash_table_insert (ht, strdup (resource_get_key (r)), create_value (r));
    }
    
    update(GList *resources) {
      GHashTable *new_ht = g_hash_table_new_similar (ht);
    
      for (r in resources) {
        if (g_hash_table_steal_extended (ht, resource_get_key (r), &key, &value))
          g_hash_table_insert (new_ht, key, value);
        else
          g_hash_table_insert (new_ht, strdup (resource_get_key (r)), create_value (r));
      }
      g_hash_table_unref (ht);
      ht = new_ht;
    }
    ```

 docs/reference/glib/glib-sections.txt |  1 +
 glib/ghash.c                          | 27 +++++++++++++++++++++
 glib/ghash.h                          |  2 ++
 glib/tests/hash.c                     | 44 +++++++++++++++++++++++++++++++++++
 4 files changed, 74 insertions(+)
---
diff --git a/docs/reference/glib/glib-sections.txt b/docs/reference/glib/glib-sections.txt
index c8681fa2f..ff080f711 100644
--- a/docs/reference/glib/glib-sections.txt
+++ b/docs/reference/glib/glib-sections.txt
@@ -2851,6 +2851,7 @@ g_trash_stack_height
 GHashTable
 g_hash_table_new
 g_hash_table_new_full
+g_hash_table_new_similar
 GHashFunc
 GEqualFunc
 g_hash_table_insert
diff --git a/glib/ghash.c b/glib/ghash.c
index 48a7db0e2..3d71643c7 100644
--- a/glib/ghash.c
+++ b/glib/ghash.c
@@ -1085,6 +1085,33 @@ g_hash_table_new_full (GHashFunc      hash_func,
   return hash_table;
 }
 
+/**
+ * g_hash_table_new_similar:
+ * @other_hash_table: (not nullable) (transfer none): Another #GHashTable
+ *
+ * Creates a new #GHashTable like g_hash_table_new_full() with a reference
+ * count of 1.
+ *
+ * It inherits the hash function, the key equal function, the key destroy function,
+ * as well as the value destroy function, from @other_hash_table.
+ *
+ * The returned hash table will be empty; it will not contain the keys
+ * or values from @other_hash_table.
+ *
+ * Returns: (transfer full) (not nullable): a new #GHashTable
+ * Since: 2.72
+ */
+GHashTable *
+g_hash_table_new_similar (GHashTable *other_hash_table)
+{
+  g_return_val_if_fail (other_hash_table, NULL);
+
+  return g_hash_table_new_full (other_hash_table->hash_func,
+                                other_hash_table->key_equal_func,
+                                other_hash_table->key_destroy_func,
+                                other_hash_table->value_destroy_func);
+}
+
 /**
  * g_hash_table_iter_init:
  * @iter: an uninitialized #GHashTableIter
diff --git a/glib/ghash.h b/glib/ghash.h
index e9ce64505..4e81d6263 100644
--- a/glib/ghash.h
+++ b/glib/ghash.h
@@ -61,6 +61,8 @@ GHashTable* g_hash_table_new_full          (GHashFunc       hash_func,
                                             GEqualFunc      key_equal_func,
                                             GDestroyNotify  key_destroy_func,
                                             GDestroyNotify  value_destroy_func);
+GLIB_AVAILABLE_IN_2_72
+GHashTable *g_hash_table_new_similar       (GHashTable     *other_hash_table);
 GLIB_AVAILABLE_IN_ALL
 void        g_hash_table_destroy           (GHashTable     *hash_table);
 GLIB_AVAILABLE_IN_ALL
diff --git a/glib/tests/hash.c b/glib/tests/hash.c
index fe72606f8..fe0811aff 100644
--- a/glib/tests/hash.c
+++ b/glib/tests/hash.c
@@ -1345,6 +1345,49 @@ test_lookup_extended (void)
   g_hash_table_unref (hash);
 }
 
+static void
+inc_state (gpointer user_data)
+{
+  int *state = user_data;
+  g_assert_cmpint (*state, ==, 0);
+  *state = 1;
+}
+
+static void
+test_new_similar (void)
+{
+  GHashTable *hash1;
+  GHashTable *hash2;
+  int state1;
+  int state2;
+
+  hash1 = g_hash_table_new_full (g_str_hash, g_str_equal,
+                                 g_free, inc_state);
+  state1 = 0;
+  g_hash_table_insert (hash1,
+                       g_strdup ("test"),
+                       &state1);
+  g_assert_true (g_hash_table_lookup (hash1, "test") == &state1);
+
+  hash2 = g_hash_table_new_similar (hash1);
+
+  g_assert_true (g_hash_table_lookup (hash1, "test") == &state1);
+  g_assert_null (g_hash_table_lookup (hash2, "test"));
+
+  state2 = 0;
+  g_hash_table_insert (hash2, g_strdup ("test"), &state2);
+  g_assert_true (g_hash_table_lookup (hash2, "test") == &state2);
+  g_hash_table_remove (hash2, "test");
+  g_assert_cmpint (state2, ==, 1);
+
+  g_assert_cmpint (state1, ==, 0);
+  g_hash_table_remove (hash1, "test");
+  g_assert_cmpint (state1, ==, 1);
+
+  g_hash_table_unref (hash1);
+  g_hash_table_unref (hash2);
+}
+
 struct _GHashTable
 {
   gsize            size;
@@ -1685,6 +1728,7 @@ main (int argc, char *argv[])
   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/lookup-extended", test_lookup_extended);
+  g_test_add_func ("/hash/new-similar", test_new_similar);
 
   /* 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]