mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-08-30 21:04:13 +02:00
- Fixed bug that overwrote nodes in hash buckets instead of adding them to
Sat Jan 23 22:45:59 1999 Jeff Garzik <jgarzik@pobox.com> * ghash.c (g_hash_table_lookup_node, g_hash_table_lookup, g_hash_table_insert, g_hash_table_remove, g_hash_table_lookup_extended): - Fixed bug that overwrote nodes in hash buckets instead of adding them to the hash bucket node list. Hash tables now work as advertised. (g_hash_table_resize): - Use g_new0 instead of manual init. - Space out code a bit for readability. (g_hash_nodes_destroy): - Replaced "if (!hash_node) return;" with "if (hash_node) {do stuff}". Testing takes up less code space than explicit call to 'return' before end of function. (look at gcc -S) Updated module header copyright to 1999. New module macro G_HASH_BUCKET for (table,key)->bucket lookups. * tests/hash-test.c: - Add two new tests, one with strings as the keys and values, and one with ints as the keys and values. Tests indirect (strings) and direct (ints) hashing. - Cleanup unused junk left over from testglib.c. - Converted a g_print call to g_assert_not_reached. - Updated copyright to 1999. * testglib.c, tests/string-test.c: - Init 'tmp_string' var to NULL, silencing uninit-var warning.
This commit is contained in:
131
ghash.c
131
ghash.c
@@ -1,5 +1,6 @@
|
||||
/* GLIB - Library of useful routines for C programming
|
||||
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
* Copyright (C) 1999 The Free Software Foundation
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
@@ -49,13 +50,17 @@ struct _GHashTable
|
||||
|
||||
|
||||
static void g_hash_table_resize (GHashTable *hash_table);
|
||||
static GHashNode** g_hash_table_lookup_node (GHashTable *hash_table,
|
||||
gconstpointer key);
|
||||
static GHashNode* g_hash_table_lookup_node (GHashTable *hash_table,
|
||||
gconstpointer key,
|
||||
GHashNode **last_p,
|
||||
guint *bucket_p);
|
||||
static GHashNode* g_hash_node_new (gpointer key,
|
||||
gpointer value);
|
||||
static void g_hash_node_destroy (GHashNode *hash_node);
|
||||
static void g_hash_nodes_destroy (GHashNode *hash_node);
|
||||
|
||||
#define G_HASH_BUCKET(table,key) \
|
||||
((* (table)->hash_func) (key) % (table)->size)
|
||||
|
||||
G_LOCK_DECLARE_STATIC (g_hash_global);
|
||||
|
||||
@@ -98,14 +103,17 @@ g_hash_table_destroy (GHashTable *hash_table)
|
||||
g_free (hash_table);
|
||||
}
|
||||
|
||||
static inline GHashNode**
|
||||
g_hash_table_lookup_node (GHashTable *hash_table,
|
||||
gconstpointer key)
|
||||
static inline GHashNode*
|
||||
g_hash_table_lookup_node (GHashTable *hash_table,
|
||||
gconstpointer key,
|
||||
GHashNode **last_p,
|
||||
guint *bucket_p)
|
||||
{
|
||||
GHashNode **node;
|
||||
GHashNode *node, *last = NULL;
|
||||
guint bucket;
|
||||
|
||||
node = &hash_table->nodes
|
||||
[(* hash_table->hash_func) (key) % hash_table->size];
|
||||
bucket = G_HASH_BUCKET (hash_table, key);
|
||||
node = hash_table->nodes [bucket];
|
||||
|
||||
/* Hash table lookup needs to be fast.
|
||||
* We therefore remove the extra conditional of testing
|
||||
@@ -113,12 +121,23 @@ g_hash_table_lookup_node (GHashTable *hash_table,
|
||||
* the inner loop.
|
||||
*/
|
||||
if (hash_table->key_compare_func)
|
||||
while (*node && !(*hash_table->key_compare_func) ((*node)->key, key))
|
||||
node = &(*node)->next;
|
||||
while (node && !(*hash_table->key_compare_func) (node->key, key))
|
||||
{
|
||||
last = node;
|
||||
node = node->next;
|
||||
}
|
||||
else
|
||||
while (*node && (*node)->key != key)
|
||||
node = &(*node)->next;
|
||||
while (node && node->key != key)
|
||||
{
|
||||
last = node;
|
||||
node = node->next;
|
||||
}
|
||||
|
||||
if (last_p)
|
||||
*last_p = last;
|
||||
if (bucket_p)
|
||||
*bucket_p = bucket;
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
@@ -130,7 +149,7 @@ g_hash_table_lookup (GHashTable *hash_table,
|
||||
|
||||
g_return_val_if_fail (hash_table != NULL, NULL);
|
||||
|
||||
node = *g_hash_table_lookup_node (hash_table, key);
|
||||
node = g_hash_table_lookup_node (hash_table, key, NULL, NULL);
|
||||
|
||||
return node ? node->value : NULL;
|
||||
}
|
||||
@@ -140,13 +159,27 @@ g_hash_table_insert (GHashTable *hash_table,
|
||||
gpointer key,
|
||||
gpointer value)
|
||||
{
|
||||
GHashNode **node;
|
||||
GHashNode *node, *last;
|
||||
guint bucket;
|
||||
|
||||
g_return_if_fail (hash_table != NULL);
|
||||
|
||||
node = g_hash_table_lookup_node (hash_table, key, &last, &bucket);
|
||||
|
||||
node = g_hash_table_lookup_node (hash_table, key);
|
||||
|
||||
if (*node)
|
||||
if (node == NULL)
|
||||
{
|
||||
node = g_hash_node_new (key, value);
|
||||
|
||||
if (last == NULL)
|
||||
hash_table->nodes [bucket] = node;
|
||||
else
|
||||
last->next = node;
|
||||
|
||||
hash_table->nnodes++;
|
||||
if (!hash_table->frozen)
|
||||
g_hash_table_resize (hash_table);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* do not reset node->key in this place, keeping
|
||||
* the old key might be intended.
|
||||
@@ -154,35 +187,36 @@ g_hash_table_insert (GHashTable *hash_table,
|
||||
* can be used otherwise.
|
||||
*
|
||||
* node->key = key; */
|
||||
(*node)->value = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
*node = g_hash_node_new (key, value);
|
||||
hash_table->nnodes++;
|
||||
if (!hash_table->frozen)
|
||||
g_hash_table_resize (hash_table);
|
||||
node->value = value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
g_hash_table_remove (GHashTable *hash_table,
|
||||
gconstpointer key)
|
||||
{
|
||||
GHashNode **node, *dest;
|
||||
GHashNode *node, *last;
|
||||
guint bucket;
|
||||
|
||||
g_return_if_fail (hash_table != NULL);
|
||||
|
||||
while (*(node = g_hash_table_lookup_node (hash_table, key)))
|
||||
node = g_hash_table_lookup_node (hash_table, key, &last, &bucket);
|
||||
|
||||
if (node)
|
||||
{
|
||||
dest = *node;
|
||||
(*node) = dest->next;
|
||||
g_hash_node_destroy (dest);
|
||||
if (last == NULL)
|
||||
hash_table->nodes [bucket] = node->next;
|
||||
else
|
||||
last->next = node->next;
|
||||
|
||||
g_hash_node_destroy (node);
|
||||
|
||||
hash_table->nnodes--;
|
||||
}
|
||||
|
||||
if (!hash_table->frozen)
|
||||
g_hash_table_resize (hash_table);
|
||||
if (!hash_table->frozen)
|
||||
g_hash_table_resize (hash_table);
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
@@ -195,7 +229,7 @@ g_hash_table_lookup_extended (GHashTable *hash_table,
|
||||
|
||||
g_return_val_if_fail (hash_table != NULL, FALSE);
|
||||
|
||||
node = *g_hash_table_lookup_node (hash_table, lookup_key);
|
||||
node = g_hash_table_lookup_node (hash_table, lookup_key, NULL, NULL);
|
||||
|
||||
if (node)
|
||||
{
|
||||
@@ -320,16 +354,15 @@ g_hash_table_resize (GHashTable *hash_table)
|
||||
new_size = CLAMP(g_spaced_primes_closest (hash_table->nnodes),
|
||||
HASH_TABLE_MIN_SIZE,
|
||||
HASH_TABLE_MAX_SIZE);
|
||||
new_nodes = g_new (GHashNode*, new_size);
|
||||
|
||||
for (i = 0; i < new_size; i++)
|
||||
new_nodes[i] = NULL;
|
||||
new_nodes = g_new0 (GHashNode*, new_size);
|
||||
|
||||
for (i = 0; i < hash_table->size; i++)
|
||||
for (node = hash_table->nodes[i]; node; node = next)
|
||||
{
|
||||
next = node->next;
|
||||
|
||||
hash_val = (* hash_table->hash_func) (node->key) % new_size;
|
||||
|
||||
node->next = new_nodes[hash_val];
|
||||
new_nodes[hash_val] = node;
|
||||
}
|
||||
@@ -381,18 +414,16 @@ g_hash_node_destroy (GHashNode *hash_node)
|
||||
static void
|
||||
g_hash_nodes_destroy (GHashNode *hash_node)
|
||||
{
|
||||
GHashNode *node;
|
||||
if (hash_node)
|
||||
{
|
||||
GHashNode *node = hash_node;
|
||||
|
||||
if (!hash_node)
|
||||
return;
|
||||
while (node->next)
|
||||
node = node->next;
|
||||
|
||||
node = hash_node;
|
||||
|
||||
while (node->next)
|
||||
node = node->next;
|
||||
|
||||
G_LOCK (g_hash_global);
|
||||
node->next = node_free_list;
|
||||
node_free_list = hash_node;
|
||||
G_UNLOCK (g_hash_global);
|
||||
G_LOCK (g_hash_global);
|
||||
node->next = node_free_list;
|
||||
node_free_list = hash_node;
|
||||
G_UNLOCK (g_hash_global);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user