mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-02-03 17:56:17 +01:00
ghash: Add APIs to get hash table keys and values as GPtrArray
GPtrArray's are faster than lists and provide more flexibility, so add APIs to get hash keys and values using these containers too. Given that we know the size at array initialization we can optimize the allocation quite a bit, making it faster than the API using GList both at creation time and for consumers.
This commit is contained in:
parent
a0dbaeed2f
commit
d2c3f7f513
@ -2584,7 +2584,9 @@ g_hash_table_remove_all
|
||||
g_hash_table_steal_all
|
||||
g_hash_table_get_keys
|
||||
g_hash_table_get_values
|
||||
g_hash_table_get_values_as_ptr_array
|
||||
g_hash_table_get_keys_as_array
|
||||
g_hash_table_get_keys_as_ptr_array
|
||||
GHRFunc
|
||||
g_hash_table_freeze
|
||||
g_hash_table_thaw
|
||||
|
78
glib/ghash.c
78
glib/ghash.c
@ -2273,6 +2273,45 @@ g_hash_table_get_keys_as_array (GHashTable *hash_table,
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_hash_table_get_keys_as_ptr_array: (skip)
|
||||
* @hash_table: a #GHashTable
|
||||
*
|
||||
* Retrieves every key inside @hash_table, as a #GPtrArray.
|
||||
* The returned data is valid until changes to the hash release those keys.
|
||||
*
|
||||
* This iterates over every entry in the hash table to build its return value.
|
||||
* To iterate over the entries in a #GHashTable more efficiently, use a
|
||||
* #GHashTableIter.
|
||||
*
|
||||
* You should always unref the returned array with g_ptr_array_unref().
|
||||
*
|
||||
* Returns: (transfer container): a #GPtrArray containing each key from
|
||||
* the table. Unref with with g_ptr_array_unref() when done.
|
||||
*
|
||||
* Since: 2.76
|
||||
**/
|
||||
GPtrArray *
|
||||
g_hash_table_get_keys_as_ptr_array (GHashTable *hash_table)
|
||||
{
|
||||
GPtrArray *array;
|
||||
|
||||
g_return_val_if_fail (hash_table != NULL, NULL);
|
||||
|
||||
array = g_ptr_array_sized_new (hash_table->size);
|
||||
for (gsize i = 0; i < hash_table->size; ++i)
|
||||
{
|
||||
if (HASH_IS_REAL (hash_table->hashes[i]))
|
||||
{
|
||||
g_ptr_array_add (array, g_hash_table_fetch_key_or_value (
|
||||
hash_table->keys, i, hash_table->have_big_keys));
|
||||
}
|
||||
}
|
||||
g_assert (array->len == (guint) hash_table->nnodes);
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_hash_table_get_values:
|
||||
* @hash_table: a #GHashTable
|
||||
@ -2309,6 +2348,45 @@ g_hash_table_get_values (GHashTable *hash_table)
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_hash_table_get_values_as_ptr_array: (skip)
|
||||
* @hash_table: a #GHashTable
|
||||
*
|
||||
* Retrieves every value inside @hash_table, as a #GPtrArray.
|
||||
* The returned data is valid until changes to the hash release those values.
|
||||
*
|
||||
* This iterates over every entry in the hash table to build its return value.
|
||||
* To iterate over the entries in a #GHashTable more efficiently, use a
|
||||
* #GHashTableIter.
|
||||
*
|
||||
* You should always unref the returned array with g_ptr_array_unref().
|
||||
*
|
||||
* Returns: (transfer container): a #GPtrArray containing each value from
|
||||
* the table. Unref with with g_ptr_array_unref() when done.
|
||||
*
|
||||
* Since: 2.76
|
||||
**/
|
||||
GPtrArray *
|
||||
g_hash_table_get_values_as_ptr_array (GHashTable *hash_table)
|
||||
{
|
||||
GPtrArray *array;
|
||||
|
||||
g_return_val_if_fail (hash_table != NULL, NULL);
|
||||
|
||||
array = g_ptr_array_sized_new (hash_table->size);
|
||||
for (gsize i = 0; i < hash_table->size; ++i)
|
||||
{
|
||||
if (HASH_IS_REAL (hash_table->hashes[i]))
|
||||
{
|
||||
g_ptr_array_add (array, g_hash_table_fetch_key_or_value (
|
||||
hash_table->values, i, hash_table->have_big_values));
|
||||
}
|
||||
}
|
||||
g_assert (array->len == (guint) hash_table->nnodes);
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
/* Hash functions.
|
||||
*/
|
||||
|
||||
|
@ -32,6 +32,7 @@
|
||||
#endif
|
||||
|
||||
#include <glib/gtypes.h>
|
||||
#include <glib/garray.h>
|
||||
#include <glib/glist.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
@ -129,6 +130,11 @@ GList * g_hash_table_get_values (GHashTable *hash_table);
|
||||
GLIB_AVAILABLE_IN_2_40
|
||||
gpointer * g_hash_table_get_keys_as_array (GHashTable *hash_table,
|
||||
guint *length);
|
||||
GLIB_AVAILABLE_IN_2_76
|
||||
GPtrArray * g_hash_table_get_keys_as_ptr_array (GHashTable *hash_table);
|
||||
|
||||
GLIB_AVAILABLE_IN_2_76
|
||||
GPtrArray * g_hash_table_get_values_as_ptr_array (GHashTable *hash_table);
|
||||
|
||||
GLIB_AVAILABLE_IN_ALL
|
||||
void g_hash_table_iter_init (GHashTableIter *iter,
|
||||
|
@ -1692,6 +1692,63 @@ test_set_to_strv (void)
|
||||
g_strfreev (strv);
|
||||
}
|
||||
|
||||
static void
|
||||
test_set_get_keys_as_ptr_array (void)
|
||||
{
|
||||
GHashTable *set;
|
||||
GPtrArray *array;
|
||||
|
||||
set = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
|
||||
g_hash_table_add (set, g_strdup ("xyz"));
|
||||
g_hash_table_add (set, g_strdup ("xyz"));
|
||||
g_hash_table_add (set, g_strdup ("abc"));
|
||||
|
||||
array = g_hash_table_get_keys_as_ptr_array (set);
|
||||
g_hash_table_steal_all (set);
|
||||
g_hash_table_unref (set);
|
||||
g_ptr_array_set_free_func (array, g_free);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
static void
|
||||
test_set_get_values_as_ptr_array (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_get_values_as_ptr_array (table);
|
||||
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);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
is_prime (guint p)
|
||||
{
|
||||
@ -1774,6 +1831,8 @@ main (int argc, char *argv[])
|
||||
g_test_add_func ("/hash/iter-replace", test_iter_replace);
|
||||
g_test_add_func ("/hash/set-insert-corruption", test_set_insert_corruption);
|
||||
g_test_add_func ("/hash/set-to-strv", test_set_to_strv);
|
||||
g_test_add_func ("/hash/get-keys-as-ptr-array", test_set_get_keys_as_ptr_array);
|
||||
g_test_add_func ("/hash/get-values-as-ptr-array", test_set_get_values_as_ptr_array);
|
||||
g_test_add_func ("/hash/primes", test_primes);
|
||||
|
||||
return g_test_run ();
|
||||
|
Loading…
Reference in New Issue
Block a user