mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-02-09 12:25:48 +01:00
Add iter_replace API to GHashTableIter
https://bugzilla.gnome.org/show_bug.cgi?id=652822
This commit is contained in:
parent
8f05da99cb
commit
f6ed357101
@ -2263,6 +2263,7 @@ GHashTableIter
|
|||||||
g_hash_table_iter_init
|
g_hash_table_iter_init
|
||||||
g_hash_table_iter_next
|
g_hash_table_iter_next
|
||||||
g_hash_table_iter_get_hash_table
|
g_hash_table_iter_get_hash_table
|
||||||
|
g_hash_table_iter_replace
|
||||||
g_hash_table_iter_remove
|
g_hash_table_iter_remove
|
||||||
g_hash_table_iter_steal
|
g_hash_table_iter_steal
|
||||||
|
|
||||||
|
152
glib/ghash.c
152
glib/ghash.c
@ -805,6 +805,112 @@ g_hash_table_iter_remove (GHashTableIter *iter)
|
|||||||
iter_remove_or_steal ((RealIter *) iter, TRUE);
|
iter_remove_or_steal ((RealIter *) iter, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* g_hash_table_insert_node:
|
||||||
|
* @hash_table: our #GHashTable
|
||||||
|
* @node_index: pointer to node to insert/replace
|
||||||
|
* @key_hash: key hash
|
||||||
|
* @key: key to replace with
|
||||||
|
* @value: value to replace with
|
||||||
|
*
|
||||||
|
* Inserts a value at @node_index in the hash table and updates it.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
g_hash_table_insert_node (GHashTable *hash_table,
|
||||||
|
guint node_index,
|
||||||
|
guint key_hash,
|
||||||
|
gpointer key,
|
||||||
|
gpointer value,
|
||||||
|
gboolean keep_new_key)
|
||||||
|
{
|
||||||
|
guint old_hash;
|
||||||
|
gpointer old_key;
|
||||||
|
gpointer old_value;
|
||||||
|
|
||||||
|
if (G_UNLIKELY (hash_table->keys == hash_table->values && key != value))
|
||||||
|
hash_table->values = g_memdup (hash_table->keys, sizeof (gpointer) * hash_table->size);
|
||||||
|
|
||||||
|
old_hash = hash_table->hashes[node_index];
|
||||||
|
old_key = hash_table->keys[node_index];
|
||||||
|
old_value = hash_table->values[node_index];
|
||||||
|
|
||||||
|
if (HASH_IS_REAL (old_hash))
|
||||||
|
{
|
||||||
|
if (keep_new_key)
|
||||||
|
hash_table->keys[node_index] = key;
|
||||||
|
hash_table->values[node_index] = value;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hash_table->keys[node_index] = key;
|
||||||
|
hash_table->values[node_index] = value;
|
||||||
|
hash_table->hashes[node_index] = key_hash;
|
||||||
|
|
||||||
|
hash_table->nnodes++;
|
||||||
|
|
||||||
|
if (HASH_IS_UNUSED (old_hash))
|
||||||
|
{
|
||||||
|
/* We replaced an empty node, and not a tombstone */
|
||||||
|
hash_table->noccupied++;
|
||||||
|
g_hash_table_maybe_resize (hash_table);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef G_DISABLE_ASSERT
|
||||||
|
hash_table->version++;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
if (HASH_IS_REAL (old_hash))
|
||||||
|
{
|
||||||
|
if (hash_table->key_destroy_func)
|
||||||
|
hash_table->key_destroy_func (keep_new_key ? old_key : key);
|
||||||
|
if (hash_table->value_destroy_func)
|
||||||
|
hash_table->value_destroy_func (old_value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_hash_table_iter_replace:
|
||||||
|
* @iter: an initialized #GHashTableIter.
|
||||||
|
* @value: the value to replace with
|
||||||
|
*
|
||||||
|
* Replaces the value currently pointed to by the iterator
|
||||||
|
* from its associated #GHashTable. Can only be called after
|
||||||
|
* g_hash_table_iter_next() returned %TRUE.
|
||||||
|
*
|
||||||
|
* If you supplied a @value_destroy_func when creating the #GHashTable,
|
||||||
|
* the old value is freed using that function.
|
||||||
|
*
|
||||||
|
* Since: 2.29.9
|
||||||
|
**/
|
||||||
|
void
|
||||||
|
g_hash_table_iter_replace (GHashTableIter *iter,
|
||||||
|
gpointer value)
|
||||||
|
{
|
||||||
|
RealIter *ri;
|
||||||
|
guint node_hash;
|
||||||
|
gpointer key;
|
||||||
|
|
||||||
|
ri = (RealIter *) iter;
|
||||||
|
|
||||||
|
g_return_if_fail (ri != NULL);
|
||||||
|
#ifndef G_DISABLE_ASSERT
|
||||||
|
g_return_if_fail (ri->version == ri->hash_table->version);
|
||||||
|
#endif
|
||||||
|
g_return_if_fail (ri->position >= 0);
|
||||||
|
g_return_if_fail (ri->position < ri->hash_table->size);
|
||||||
|
|
||||||
|
node_hash = ri->hash_table->hashes[ri->position];
|
||||||
|
key = ri->hash_table->keys[ri->position];
|
||||||
|
|
||||||
|
g_hash_table_insert_node (ri->hash_table, ri->position, node_hash, key, value, TRUE);
|
||||||
|
|
||||||
|
#ifndef G_DISABLE_ASSERT
|
||||||
|
ri->version++;
|
||||||
|
ri->hash_table->version++;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* g_hash_table_iter_steal:
|
* g_hash_table_iter_steal:
|
||||||
* @iter: an initialized #GHashTableIter.
|
* @iter: an initialized #GHashTableIter.
|
||||||
@ -985,56 +1091,14 @@ g_hash_table_insert_internal (GHashTable *hash_table,
|
|||||||
gpointer value,
|
gpointer value,
|
||||||
gboolean keep_new_key)
|
gboolean keep_new_key)
|
||||||
{
|
{
|
||||||
guint node_index;
|
|
||||||
guint key_hash;
|
guint key_hash;
|
||||||
guint old_hash;
|
guint node_index;
|
||||||
gpointer old_key;
|
|
||||||
gpointer old_value;
|
|
||||||
|
|
||||||
g_return_if_fail (hash_table != NULL);
|
g_return_if_fail (hash_table != NULL);
|
||||||
|
|
||||||
if (G_UNLIKELY (hash_table->keys == hash_table->values && key != value))
|
|
||||||
hash_table->values = g_memdup (hash_table->keys, sizeof (gpointer) * hash_table->size);
|
|
||||||
|
|
||||||
node_index = g_hash_table_lookup_node (hash_table, key, &key_hash);
|
node_index = g_hash_table_lookup_node (hash_table, key, &key_hash);
|
||||||
|
|
||||||
old_hash = hash_table->hashes[node_index];
|
g_hash_table_insert_node (hash_table, node_index, key_hash, key, value, keep_new_key);
|
||||||
old_key = hash_table->keys[node_index];
|
|
||||||
old_value = hash_table->values[node_index];
|
|
||||||
|
|
||||||
if (HASH_IS_REAL (old_hash))
|
|
||||||
{
|
|
||||||
if (keep_new_key)
|
|
||||||
hash_table->keys[node_index] = key;
|
|
||||||
hash_table->values[node_index] = value;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
hash_table->keys[node_index] = key;
|
|
||||||
hash_table->values[node_index] = value;
|
|
||||||
hash_table->hashes[node_index] = key_hash;
|
|
||||||
|
|
||||||
hash_table->nnodes++;
|
|
||||||
|
|
||||||
if (HASH_IS_UNUSED (old_hash))
|
|
||||||
{
|
|
||||||
/* We replaced an empty node, and not a tombstone */
|
|
||||||
hash_table->noccupied++;
|
|
||||||
g_hash_table_maybe_resize (hash_table);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef G_DISABLE_ASSERT
|
|
||||||
hash_table->version++;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
if (HASH_IS_REAL (old_hash))
|
|
||||||
{
|
|
||||||
if (hash_table->key_destroy_func)
|
|
||||||
hash_table->key_destroy_func (keep_new_key ? old_key : key);
|
|
||||||
if (hash_table->value_destroy_func)
|
|
||||||
hash_table->value_destroy_func (old_value);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -105,6 +105,8 @@ gboolean g_hash_table_iter_next (GHashTableIter *iter,
|
|||||||
gpointer *value);
|
gpointer *value);
|
||||||
GHashTable* g_hash_table_iter_get_hash_table (GHashTableIter *iter);
|
GHashTable* g_hash_table_iter_get_hash_table (GHashTableIter *iter);
|
||||||
void g_hash_table_iter_remove (GHashTableIter *iter);
|
void g_hash_table_iter_remove (GHashTableIter *iter);
|
||||||
|
void g_hash_table_iter_replace (GHashTableIter *iter,
|
||||||
|
gpointer value);
|
||||||
void g_hash_table_iter_steal (GHashTableIter *iter);
|
void g_hash_table_iter_steal (GHashTableIter *iter);
|
||||||
|
|
||||||
/* keeping hash tables alive */
|
/* keeping hash tables alive */
|
||||||
|
@ -382,6 +382,7 @@ g_hash_table_iter_init
|
|||||||
g_hash_table_iter_next
|
g_hash_table_iter_next
|
||||||
g_hash_table_iter_get_hash_table
|
g_hash_table_iter_get_hash_table
|
||||||
g_hash_table_iter_remove
|
g_hash_table_iter_remove
|
||||||
|
g_hash_table_iter_replace
|
||||||
g_hash_table_iter_steal
|
g_hash_table_iter_steal
|
||||||
g_hook_alloc
|
g_hook_alloc
|
||||||
g_hook_compare_ids
|
g_hook_compare_ids
|
||||||
|
@ -539,6 +539,7 @@ test_hash_misc (void)
|
|||||||
GHashTableIter iter;
|
GHashTableIter iter;
|
||||||
gpointer ikey, ivalue;
|
gpointer ikey, ivalue;
|
||||||
int result_array[10000];
|
int result_array[10000];
|
||||||
|
int n_array[1];
|
||||||
|
|
||||||
hash_table = g_hash_table_new (my_hash, my_hash_equal);
|
hash_table = g_hash_table_new (my_hash, my_hash_equal);
|
||||||
fill_hash_table_and_array (hash_table);
|
fill_hash_table_and_array (hash_table);
|
||||||
@ -594,6 +595,28 @@ test_hash_misc (void)
|
|||||||
|
|
||||||
g_hash_table_foreach (hash_table, my_hash_callback_remove_test, NULL);
|
g_hash_table_foreach (hash_table, my_hash_callback_remove_test, NULL);
|
||||||
g_hash_table_destroy (hash_table);
|
g_hash_table_destroy (hash_table);
|
||||||
|
|
||||||
|
hash_table = g_hash_table_new (my_hash, my_hash_equal);
|
||||||
|
fill_hash_table_and_array (hash_table);
|
||||||
|
|
||||||
|
n_array[0] = 1;
|
||||||
|
|
||||||
|
g_hash_table_iter_init (&iter, hash_table);
|
||||||
|
for (i = 0; i < 10000; i++)
|
||||||
|
{
|
||||||
|
g_assert (g_hash_table_iter_next (&iter, &ikey, &ivalue));
|
||||||
|
g_hash_table_iter_replace (&iter, &n_array[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_hash_table_iter_init (&iter, hash_table);
|
||||||
|
for (i = 0; i < 10000; i++)
|
||||||
|
{
|
||||||
|
g_assert (g_hash_table_iter_next (&iter, &ikey, &ivalue));
|
||||||
|
|
||||||
|
g_assert (ivalue == &n_array[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_hash_table_destroy (hash_table);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gint destroy_counter;
|
static gint destroy_counter;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user