diff options
Diffstat (limited to 'libihash/ihash.c')
-rw-r--r-- | libihash/ihash.c | 60 |
1 files changed, 49 insertions, 11 deletions
diff --git a/libihash/ihash.c b/libihash/ihash.c index 598d3412..451f8db6 100644 --- a/libihash/ihash.c +++ b/libihash/ihash.c @@ -1,5 +1,5 @@ /* ihash.c - Integer-keyed hash table functions. - Copyright (C) 1993-1997, 2001, 2003, 2004, 2006 + Copyright (C) 1993-1997, 2001, 2003, 2004, 2006, 2014, 2015 Free Software Foundation, Inc. Written by Michael I. Bushnell. Revised by Miles Bader <miles@gnu.org>. @@ -32,6 +32,23 @@ #include "ihash.h" +/* This function is used to hash the key. */ +static inline hurd_ihash_key_t +hash (hurd_ihash_t ht, hurd_ihash_key_t k) +{ + return ht->fct_hash ? ht->fct_hash ((const void *) k) : k; +} + +/* This function is used to compare the key. Returns true if A is + equal to B. */ +static inline int +compare (hurd_ihash_t ht, hurd_ihash_key_t a, hurd_ihash_key_t b) +{ + return + ht->fct_cmp ? (a && ht->fct_cmp ((const void *) a, (const void *) b)) + : a == b; +} + /* Return 1 if the slot with the index IDX in the hash table HT is empty, and 0 otherwise. */ static inline int @@ -46,7 +63,7 @@ index_empty (hurd_ihash_t ht, unsigned int idx) static inline int index_valid (hurd_ihash_t ht, unsigned int idx, hurd_ihash_key_t key) { - return !index_empty (ht, idx) && ht->items[idx].key == key; + return !index_empty (ht, idx) && compare (ht, ht->items[idx].key, key); } @@ -60,9 +77,10 @@ find_index (hurd_ihash_t ht, hurd_ihash_key_t key) unsigned int up_idx; unsigned int mask = ht->size - 1; - idx = key & mask; + idx = hash (ht, key) & mask; - if (ht->items[idx].value == _HURD_IHASH_EMPTY || ht->items[idx].key == key) + if (ht->items[idx].value == _HURD_IHASH_EMPTY + || compare (ht, ht->items[idx].key, key)) return idx; up_idx = idx; @@ -71,7 +89,7 @@ find_index (hurd_ihash_t ht, hurd_ihash_key_t key) { up_idx = (up_idx + 1) & mask; if (ht->items[up_idx].value == _HURD_IHASH_EMPTY - || ht->items[up_idx].key == key) + || compare (ht, ht->items[up_idx].key, key)) return up_idx; } while (up_idx != idx); @@ -88,9 +106,11 @@ find_index (hurd_ihash_t ht, hurd_ihash_key_t key) static inline void locp_remove (hurd_ihash_t ht, hurd_ihash_locp_t locp) { + struct _hurd_ihash_item *item = locp; if (ht->cleanup) - (*ht->cleanup) (*locp, ht->cleanup_data); - *locp = _HURD_IHASH_DELETED; + (*ht->cleanup) (item->value, ht->cleanup_data); + item->value = _HURD_IHASH_DELETED; + item->key = 0; ht->nr_items--; } @@ -106,6 +126,8 @@ hurd_ihash_init (hurd_ihash_t ht, intptr_t locp_offs) ht->locp_offset = locp_offs; ht->max_load = HURD_IHASH_MAX_LOAD_DEFAULT; ht->cleanup = 0; + ht->fct_hash = NULL; + ht->fct_cmp = NULL; } @@ -166,6 +188,21 @@ hurd_ihash_set_cleanup (hurd_ihash_t ht, hurd_ihash_cleanup_t cleanup, } +/* Use the generalized key interface. Must be called before any item + is inserted into the table. */ +void +hurd_ihash_set_gki (hurd_ihash_t ht, + hurd_ihash_fct_hash_t fct_hash, + hurd_ihash_fct_cmp_t fct_cmp) +{ + assert (ht->size == 0 || !"called after insertion"); + assert (fct_hash); + assert (fct_cmp); + ht->fct_hash = fct_hash; + ht->fct_cmp = fct_cmp; +} + + /* Set the maximum load factor in binary percent to MAX_LOAD, which should be between 64 and 128. The default is HURD_IHASH_MAX_LOAD_DEFAULT. New elements are only added to the @@ -199,10 +236,11 @@ add_one (hurd_ihash_t ht, hurd_ihash_key_t key, hurd_ihash_value_t value) unsigned int first_free; unsigned int mask = ht->size - 1; - idx = key & mask; + idx = hash (ht, key) & mask; first_free = idx; - if (ht->items[idx].value != _HURD_IHASH_EMPTY && ht->items[idx].key != key) + if (ht->items[idx].value != _HURD_IHASH_EMPTY + && ! compare (ht, ht->items[idx].key, key)) { unsigned int up_idx = idx; @@ -210,7 +248,7 @@ add_one (hurd_ihash_t ht, hurd_ihash_key_t key, hurd_ihash_value_t value) { up_idx = (up_idx + 1) & mask; if (ht->items[up_idx].value == _HURD_IHASH_EMPTY - || ht->items[up_idx].key == key) + || compare (ht, ht->items[up_idx].key, key)) { idx = up_idx; break; @@ -278,7 +316,7 @@ hurd_ihash_locp_add (hurd_ihash_t ht, hurd_ihash_locp_t locp, } else { - assert (item->key == key); + assert (compare (ht, item->key, key)); if (ht->cleanup) (*ht->cleanup) (locp, ht->cleanup_data); } |