/* * g_hash_table_foreach_remove_or_steal: * @hash_table: our #GHashTable * @func: the user's callback function * @user_data: data for @func * @notify: %TRUE if the destroy notify handlers are to be called * * Implements the common logic for g_hash_table_foreach_remove() and * g_hash_table_foreach_steal(). * * Iterates over every node in the table, calling @func with the key * and value of the node (and @user_data). If @func returns %TRUE the * node is removed from the table. * * If @notify is true then the destroy notify handlers will be called * for each removed node. */ static guint g_hash_table_foreach_remove_or_steal (GHashTable *hash_table, GHRFunc func, gpointer user_data, gboolean notify) { GHashNode *node, **node_ptr; guint deleted = 0; gint i; for (i = 0; i < hash_table->size; i++) for (node_ptr = &hash_table->nodes[i]; (node = *node_ptr) != NULL;) if ((* func) (node->key, node->value, user_data)) { g_hash_table_remove_node (hash_table, &node_ptr, notify); deleted++; } else node_ptr = &node->next; g_hash_table_maybe_resize (hash_table); #ifndef G_DISABLE_ASSERT if (deleted > 0) hash_table->version++; #endif return deleted; }
/* * g_hash_table_foreach_remove_or_steal: * @hash_table: our #GHashTable * @func: the user's callback function * @user_data: data for @func * @notify: %TRUE if the destroy notify handlers are to be called * * Implements the common logic for g_hash_table_foreach_remove() and * g_hash_table_foreach_steal(). * * Iterates over every node in the table, calling @func with the key * and value of the node (and @user_data). If @func returns %TRUE the * node is removed from the table. * * If @notify is true then the destroy notify handlers will be called * for each removed node. */ static guint g_hash_table_foreach_remove_or_steal (GHashTable *hash_table, GHRFunc func, gpointer user_data, gboolean notify) { guint deleted = 0; gint i; for (i = 0; i < hash_table->size; i++) { GHashNode *node = &hash_table->nodes [i]; if (node->key_hash > 1 && (* func) (node->key, node->value, user_data)) { g_hash_table_remove_node (hash_table, node, notify); deleted++; } } g_hash_table_maybe_resize (hash_table); #ifndef G_DISABLE_ASSERT if (deleted > 0) hash_table->version++; #endif return deleted; }
/* * g_hash_table_remove_internal: * @hash_table: our #GHashTable * @key: the key to remove * @notify: %TRUE if the destroy notify handlers are to be called * Return value: %TRUE if a node was found and removed, else %FALSE * * Implements the common logic for the g_hash_table_remove() and * g_hash_table_steal() functions. * * Do a lookup of @key and remove it if it is found, calling the * destroy notify handlers only if @notify is %TRUE. */ static gboolean g_hash_table_remove_internal (GHashTable *hash_table, gconstpointer key, gboolean notify) { GHashNode *node; guint node_index; g_return_val_if_fail (hash_table != NULL, FALSE); node_index = g_hash_table_lookup_node (hash_table, key); node = &hash_table->nodes [node_index]; /* g_hash_table_lookup_node() never returns a tombstone, so this is safe */ if (!node->key_hash) return FALSE; g_hash_table_remove_node (hash_table, node, notify); g_hash_table_maybe_resize (hash_table); #ifndef G_DISABLE_ASSERT hash_table->version++; #endif return TRUE; }
/* * g_hash_table_insert_internal: * @hash_table: our #GHashTable * @key: the key to insert * @value: the value to insert * @keep_new_key: if %TRUE and this key already exists in the table * then call the destroy notify function on the old key. If %FALSE * then call the destroy notify function on the new key. * * Implements the common logic for the g_hash_table_insert() and * g_hash_table_replace() functions. * * Do a lookup of @key. If it is found, replace it with the new * @value (and perhaps the new @key). If it is not found, create a * new node. */ static void g_hash_table_insert_internal (GHashTable *hash_table, gpointer key, gpointer value, gboolean keep_new_key) { GHashNode *node; guint node_index; guint key_hash; guint old_hash; g_return_if_fail (hash_table != NULL); g_return_if_fail (hash_table->ref_count > 0); node_index = g_hash_table_lookup_node_for_insertion (hash_table, key, &key_hash); node = &hash_table->nodes [node_index]; old_hash = node->key_hash; if (old_hash > 1) { if (keep_new_key) { if (hash_table->key_destroy_func) hash_table->key_destroy_func (node->key); node->key = key; } else { if (hash_table->key_destroy_func) hash_table->key_destroy_func (key); } if (hash_table->value_destroy_func) hash_table->value_destroy_func (node->value); node->value = value; } else { node->key = key; node->value = value; node->key_hash = key_hash; hash_table->nnodes++; if (old_hash == 0) { /* 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 } }
/* * 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, or %NULL * @value: value to replace with * @keep_new_key: whether to replace the key in the node with @key * @reusing_key: whether @key was taken out of the existing node * * Inserts a value at @node_index in the hash table and updates it. * * If @key has been taken out of the existing node (ie it is not * passed in via a g_hash_table_insert/replace) call, then @reusing_key * should be %TRUE. */ static void g_hash_table_insert_node (GHashTable *hash_table, guint node_index, guint key_hash, gpointer key, gpointer value, gboolean keep_new_key, gboolean reusing_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 && !reusing_key) 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_steal_all: * @hash_table: a #GHashTable. * * Removes all keys and their associated values from a #GHashTable * without calling the key and value destroy functions. * * Since: 2.12 **/ void g_hash_table_steal_all (GHashTable *hash_table) { g_return_if_fail (hash_table != NULL); #ifndef G_DISABLE_ASSERT if (hash_table->nnodes != 0) hash_table->version++; #endif g_hash_table_remove_all_nodes (hash_table, FALSE); g_hash_table_maybe_resize (hash_table); }
/* * g_hash_table_insert_internal: * @hash_table: our #GHashTable * @key: the key to insert * @value: the value to insert * @keep_new_key: if %TRUE and this key already exists in the table * then call the destroy notify function on the old key. If %FALSE * then call the destroy notify function on the new key. * * Implements the common logic for the g_hash_table_insert() and * g_hash_table_replace() functions. * * Do a lookup of @key. If it is found, replace it with the new * @value (and perhaps the new @key). If it is not found, create a * new node. */ static void g_hash_table_insert_internal (GHashTable *hash_table, gpointer key, gpointer value, gboolean keep_new_key) { GHashNode **node_ptr, *node; guint key_hash; g_return_if_fail (hash_table != NULL); g_return_if_fail (hash_table->ref_count > 0); node_ptr = g_hash_table_lookup_node (hash_table, key, &key_hash); if ((node = *node_ptr)) { if (keep_new_key) { if (hash_table->key_destroy_func) hash_table->key_destroy_func (node->key); node->key = key; } else { if (hash_table->key_destroy_func) hash_table->key_destroy_func (key); } if (hash_table->value_destroy_func) hash_table->value_destroy_func (node->value); node->value = value; } else { node = g_slice_new (GHashNode); node->key = key; node->value = value; node->key_hash = key_hash; node->next = NULL; *node_ptr = node; hash_table->nnodes++; g_hash_table_maybe_resize (hash_table); #ifndef G_DISABLE_ASSERT hash_table->version++; #endif } }
/* * g_hash_table_remove_internal: * @hash_table: our #GHashTable * @key: the key to remove * @notify: %TRUE if the destroy notify handlers are to be called * Return value: %TRUE if a node was found and removed, else %FALSE * * Implements the common logic for the g_hash_table_remove() and * g_hash_table_steal() functions. * * Do a lookup of @key and remove it if it is found, calling the * destroy notify handlers only if @notify is %TRUE. */ static gboolean g_hash_table_remove_internal (GHashTable *hash_table, gconstpointer key, gboolean notify) { GHashNode **node_ptr; g_return_val_if_fail (hash_table != NULL, FALSE); node_ptr = g_hash_table_lookup_node (hash_table, key, NULL); if (*node_ptr == NULL) return FALSE; g_hash_table_remove_node (hash_table, &node_ptr, notify); g_hash_table_maybe_resize (hash_table); #ifndef G_DISABLE_ASSERT hash_table->version++; #endif return TRUE; }
/* * g_hash_table_foreach_remove_or_steal: * @hash_table: our #GHashTable * @func: the user's callback function * @user_data: data for @func * @notify: %TRUE if the destroy notify handlers are to be called * * Implements the common logic for g_hash_table_foreach_remove() and * g_hash_table_foreach_steal(). * * Iterates over every node in the table, calling @func with the key * and value of the node (and @user_data). If @func returns %TRUE the * node is removed from the table. * * If @notify is true then the destroy notify handlers will be called * for each removed node. */ static guint g_hash_table_foreach_remove_or_steal (GHashTable *hash_table, GHRFunc func, gpointer user_data, gboolean notify) { guint deleted = 0; gint i; #ifndef G_DISABLE_ASSERT gint version = hash_table->version; #endif for (i = 0; i < hash_table->size; i++) { guint node_hash = hash_table->hashes[i]; gpointer node_key = hash_table->keys[i]; gpointer node_value = hash_table->values[i]; if (HASH_IS_REAL (node_hash) && (* func) (node_key, node_value, user_data)) { g_hash_table_remove_node (hash_table, i, notify); deleted++; } #ifndef G_DISABLE_ASSERT g_return_val_if_fail (version == hash_table->version, 0); #endif } g_hash_table_maybe_resize (hash_table); #ifndef G_DISABLE_ASSERT if (deleted > 0) hash_table->version++; #endif return deleted; }
/* * g_hash_table_remove_internal: * @hash_table: our #GHashTable * @key: the key to remove * @notify: %TRUE if the destroy notify handlers are to be called * Return value: %TRUE if a node was found and removed, else %FALSE * * Implements the common logic for the g_hash_table_remove() and * g_hash_table_steal() functions. * * Do a lookup of @key and remove it if it is found, calling the * destroy notify handlers only if @notify is %TRUE. */ static gboolean g_hash_table_remove_internal (GHashTable *hash_table, gconstpointer key, gboolean notify) { guint node_index; guint node_hash; g_return_val_if_fail (hash_table != NULL, FALSE); node_index = g_hash_table_lookup_node (hash_table, key, &node_hash); if (!HASH_IS_REAL (hash_table->hashes[node_index])) return FALSE; g_hash_table_remove_node (hash_table, node_index, notify); g_hash_table_maybe_resize (hash_table); #ifndef G_DISABLE_ASSERT hash_table->version++; #endif return TRUE; }
void g_hash_table_remove_all (GHashTable *hash_table) { g_hash_table_remove_all_nodes (hash_table, TRUE); g_hash_table_maybe_resize (hash_table); }
static gboolean g_hash_table_insert_node (GHashTable *hash_table, guint node_index, guint key_hash, gpointer new_key, gpointer new_value, gboolean keep_new_key, gboolean reusing_key) { gboolean already_exists; guint old_hash; gpointer key_to_free = NULL; gpointer value_to_free = NULL; old_hash = hash_table->hashes[node_index]; already_exists = HASH_IS_REAL (old_hash); if (already_exists) { value_to_free = hash_table->values[node_index]; if (keep_new_key) { key_to_free = hash_table->keys[node_index]; hash_table->keys[node_index] = new_key; } else key_to_free = new_key; } else { hash_table->hashes[node_index] = key_hash; hash_table->keys[node_index] = new_key; } if (G_UNLIKELY (hash_table->keys == hash_table->values && hash_table->keys[node_index] != new_value)) hash_table->values = g_memdup (hash_table->keys, sizeof (gpointer) * hash_table->size); hash_table->values[node_index] = new_value; if (!already_exists) { hash_table->nnodes++; if (HASH_IS_UNUSED (old_hash)) { hash_table->noccupied++; g_hash_table_maybe_resize (hash_table); } } if (already_exists) { if (hash_table->key_destroy_func && !reusing_key) (* hash_table->key_destroy_func) (key_to_free); if (hash_table->value_destroy_func) (* hash_table->value_destroy_func) (value_to_free); } return !already_exists; }