#define HASH_TABLE_MIN_SHIFT 3 /* 1 << 3 == 8 buckets */
+#define HASH_IS_UNUSED(h_) ((h_) == 0)
+#define HASH_IS_TOOMBSTONE(h_) ((h_) == 1)
+#define HASH_IS_REAL(h_) ((h_) >= 2)
+
typedef struct _GHashNode GHashNode;
struct _GHashNode
guint hash_value;
guint step = 0;
- /* Empty buckets have hash_value set to 0, and for tombstones, it's 1.
- * We need to make sure our hash value is not one of these. */
-
hash_value = (* hash_table->hash_func) (key);
- if (G_UNLIKELY (hash_value <= 1))
+ if (G_UNLIKELY (!HASH_IS_REAL (hash_value)))
hash_value = 2;
node_index = hash_value % hash_table->mod;
node = &hash_table->nodes [node_index];
- while (node->key_hash)
+ while (!HASH_IS_UNUSED (node->key_hash))
{
/* We first check if our full hash values
* are equal so we can avoid calling the full-blown
gboolean have_tombstone = FALSE;
guint step = 0;
- /* Empty buckets have hash_value set to 0, and for tombstones, it's 1.
- * We need to make sure our hash value is not one of these. */
-
hash_value = (* hash_table->hash_func) (key);
- if (G_UNLIKELY (hash_value <= 1))
+ if (G_UNLIKELY (!HASH_IS_REAL (hash_value)))
hash_value = 2;
*hash_return = hash_value;
node_index = hash_value % hash_table->mod;
node = &hash_table->nodes [node_index];
- while (node->key_hash)
+ while (!HASH_IS_UNUSED (node->key_hash))
{
/* We first check if our full hash values
* are equal so we can avoid calling the full-blown
return node_index;
}
}
- else if (node->key_hash == 1 && !have_tombstone)
+ else if (HASH_IS_TOOMBSTONE (node->key_hash) && !have_tombstone)
{
first_tombstone = node_index;
have_tombstone = TRUE;
{
GHashNode *node = &hash_table->nodes [i];
- if (node->key_hash > 1)
+ if (HASH_IS_REAL (node->key_hash))
{
if (hash_table->key_destroy_func != NULL)
hash_table->key_destroy_func (node->key);
guint hash_val;
guint step = 0;
- if (node->key_hash <= 1)
+ if (!HASH_IS_REAL (node->key_hash))
continue;
hash_val = node->key_hash % hash_table->mod;
new_node = &new_nodes [hash_val];
- while (new_node->key_hash)
+ while (!HASH_IS_UNUSED (new_node->key_hash))
{
step++;
hash_val += step;
node = &ri->hash_table->nodes [position];
}
- while (node->key_hash <= 1);
+ while (!HASH_IS_REAL (node->key_hash));
if (key != NULL)
*key = node->key;
node_index = g_hash_table_lookup_node (hash_table, key);
node = &hash_table->nodes [node_index];
- return node->key_hash ? node->value : NULL;
+ return HASH_IS_REAL (node->key_hash) ? node->value : NULL;
}
/**
node_index = g_hash_table_lookup_node (hash_table, lookup_key);
node = &hash_table->nodes [node_index];
- if (!node->key_hash)
+ if (!HASH_IS_REAL (node->key_hash))
return FALSE;
if (orig_key)
old_hash = node->key_hash;
- if (old_hash > 1)
+ if (HASH_IS_REAL (old_hash))
{
if (keep_new_key)
{
hash_table->nnodes++;
- if (old_hash == 0)
+ if (HASH_IS_UNUSED (old_hash))
{
/* We replaced an empty node, and not a tombstone */
hash_table->noccupied++;
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)
+ if (!HASH_IS_REAL (node->key_hash))
return FALSE;
g_hash_table_remove_node (hash_table, node, notify);
{
GHashNode *node = &hash_table->nodes [i];
- if (node->key_hash > 1 && (* func) (node->key, node->value, user_data))
+ if (HASH_IS_REAL (node->key_hash) &&
+ (* func) (node->key, node->value, user_data))
{
g_hash_table_remove_node (hash_table, node, notify);
deleted++;
{
GHashNode *node = &hash_table->nodes [i];
- if (node->key_hash > 1)
+ if (HASH_IS_REAL (node->key_hash))
(* func) (node->key, node->value, user_data);
}
}
{
GHashNode *node = &hash_table->nodes [i];
- if (node->key_hash > 1 && predicate (node->key, node->value, user_data))
+ if (HASH_IS_REAL (node->key_hash) &&
+ predicate (node->key, node->value, user_data))
return node->value;
}
{
GHashNode *node = &hash_table->nodes [i];
- if (node->key_hash > 1)
+ if (HASH_IS_REAL (node->key_hash))
retval = g_list_prepend (retval, node->key);
}
{
GHashNode *node = &hash_table->nodes [i];
- if (node->key_hash > 1)
+ if (HASH_IS_REAL (node->key_hash))
retval = g_list_prepend (retval, node->value);
}