2 * Sherlock Library -- Universal Hash Table
4 * (c) 2002--2004 Martin Mares <mj@ucw.cz>
5 * (c) 2002 Robert Spalek <robert@ucw.cz>
7 * This software may be freely distributed and used according to the terms
8 * of the GNU Lesser General Public License.
12 * This is not a normal header file, it's a generator of hash tables.
13 * Each time you include it with parameters set in the corresponding
14 * preprocessor macros, it generates a hash table with the parameters
17 * You need to specify:
19 * HASH_NODE data type where a node dwells (usually a struct).
20 * HASH_PREFIX(x) macro to add a name prefix (used on all global names
21 * defined by the hash table generator).
23 * Then decide on type of keys:
25 * HASH_KEY_ATOMIC=f use node->f as a key of an atomic type (i.e.,
26 * a type which can be compared using `==')
27 * HASH_ATOMIC_TYPE (defaults to int).
28 * | HASH_KEY_STRING=f use node->f as a string key, allocated
29 * separately from the rest of the node.
30 * | HASH_KEY_ENDSTRING=f use node->f as a string key, allocated
31 * automatically at the end of the node struct
32 * (to be declared as "char f[1]" at the end).
33 * | HASH_KEY_COMPLEX use a multi-component key; as the name suggests,
34 * the passing of parameters is a bit complex then.
35 * The HASH_KEY_COMPLEX(x) macro should expand to
36 * `x k1, x k2, ... x kn' and you should also define:
37 * HASH_KEY_DECL declaration of function parameters in which key
38 * should be passed to all hash table operations.
39 * That is, `type1 k1, type2 k2, ... typen kn'.
40 * With complex keys, HASH_GIVE_HASHFN and HASH_GIVE_EQ
43 * Then specify what operations you request (all names are automatically
44 * prefixed by calling HASH_PREFIX):
46 * <always defined> init() -- initialize the hash table.
47 * HASH_WANT_CLEANUP cleanup() -- deallocate the hash table.
48 * HASH_WANT_FIND node *find(key) -- find first node with the specified
49 * key, return NULL if no such node exists.
50 * HASH_WANT_FIND_NEXT node *find(node *start) -- find next node with the
51 * specified key, return NULL if no such node exists.
52 * HASH_WANT_NEW node *new(key) -- create new node with given key.
53 * Doesn't check whether it already exists.
54 * HASH_WANT_LOOKUP node *lookup(key) -- find node with given key,
55 * if it doesn't exist, create it. Defining
56 * HASH_GIVE_INIT_DATA is strongly recommended.
57 * HASH_WANT_DELETE int delete(key) -- delete and deallocate node
58 * with given key. Returns success.
59 * HASH_WANT_REMOVE remove(node *) -- delete and deallocate given node.
61 * You can also supply several functions:
63 * HASH_GIVE_HASHFN unsigned int hash(key) -- calculate hash value of key.
64 * We have sensible default hash functions for strings
66 * HASH_GIVE_EQ int eq(key1, key2) -- return whether keys are equal.
67 * By default, we use == for atomic types and either
68 * strcmp or strcasecmp for strings.
69 * HASH_GIVE_EXTRA_SIZE int extra_size(key) -- returns how many bytes after the
70 * node should be allocated for dynamic data. Default=0
71 * or length of the string with HASH_KEY_ENDSTRING.
72 * HASH_GIVE_INIT_KEY void init_key(node *,key) -- initialize key in a newly
73 * created node. Defaults: assignment for atomic keys
74 * and static strings, strcpy for end-allocated strings.
75 * HASH_GIVE_INIT_DATA void init_data(node *) -- initialize data fields in a
76 * newly created node. Very useful for lookup operations.
77 * HASH_GIVE_ALLOC void *alloc(unsigned int size) -- allocate space for
78 * a node. Default is xmalloc() or pooled allocation, depending
79 * on HASH_USE_POOL and HASH_AUTO_POOL switches.
80 * void free(void *) -- the converse.
82 * ... and a couple of extra parameters:
84 * HASH_NOCASE string comparisons should be case-insensitive.
85 * HASH_DEFAULT_SIZE=n initially, use hash table of approx. `n' entries.
86 * HASH_CONSERVE_SPACE use as little space as possible.
87 * HASH_FN_BITS=n The hash function gives only `n' significant bits.
88 * HASH_ATOMIC_TYPE=t Atomic values are of type `t' instead of int.
89 * HASH_USE_POOL=pool Allocate all nodes from given mempool. Note, however, that
90 * deallocation is not supported by mempools, so delete/remove
91 * will leak pool memory.
92 * HASH_AUTO_POOL=size Create a pool of the given block size automatically.
93 * HASH_TABLE_ALLOC The hash table itself will be allocated and freed using
94 * the same allocation functions as the nodes instead of
95 * the default xmalloc().
97 * You also get a iterator macro at no extra charge:
99 * HASH_FOR_ALL(hash_prefix, variable)
101 * // node *variable gets declared automatically
102 * do_something_with_node(variable);
103 * // use HASH_BREAK and HASH_CONTINUE instead of break and continue
104 * // you must not alter contents of the hash table here
108 * Then include "lib/hashtable.h" and voila, you have a hash table
109 * suiting all your needs (at least those which you've revealed :) ).
111 * After including this file, all parameter macros are automatically
115 #ifndef _SHERLOCK_HASHFUNC_H
116 #include "lib/hashfunc.h"
121 /* Initial setup of parameters */
123 #if !defined(HASH_NODE) || !defined(HASH_PREFIX)
124 #error Some of the mandatory configuration macros are missing.
127 #if defined(HASH_KEY_ATOMIC) && !defined(HASH_CONSERVE_SPACE)
128 #define HASH_CONSERVE_SPACE
131 #define P(x) HASH_PREFIX(x)
133 /* Declare buckets and the hash table */
135 typedef HASH_NODE P(node);
137 typedef struct P(bucket) {
138 struct P(bucket) *next;
139 #ifndef HASH_CONSERVE_SPACE
147 uns hash_count, hash_max, hash_min, hash_hard_max;
153 /* Preset parameters */
155 #if defined(HASH_KEY_ATOMIC)
157 #define HASH_KEY(x) x HASH_KEY_ATOMIC
159 #ifndef HASH_ATOMIC_TYPE
160 # define HASH_ATOMIC_TYPE int
162 #define HASH_KEY_DECL HASH_ATOMIC_TYPE HASH_KEY( )
164 #ifndef HASH_GIVE_HASHFN
165 # define HASH_GIVE_HASHFN
166 static inline int P(hash) (HASH_ATOMIC_TYPE x)
167 { return hash_int(x); }
171 # define HASH_GIVE_EQ
172 static inline int P(eq) (HASH_ATOMIC_TYPE x, HASH_ATOMIC_TYPE y)
176 #ifndef HASH_GIVE_INIT_KEY
177 # define HASH_GIVE_INIT_KEY
178 static inline void P(init_key) (P(node) *n, HASH_ATOMIC_TYPE k)
179 { HASH_KEY(n->) = k; }
182 #elif defined(HASH_KEY_STRING) || defined(HASH_KEY_ENDSTRING)
184 #ifdef HASH_KEY_STRING
185 # define HASH_KEY(x) x HASH_KEY_STRING
186 # ifndef HASH_GIVE_INIT_KEY
187 # define HASH_GIVE_INIT_KEY
188 static inline void P(init_key) (P(node) *n, char *k)
189 { HASH_KEY(n->) = k; }
192 # define HASH_KEY(x) x HASH_KEY_ENDSTRING
193 # define HASH_GIVE_EXTRA_SIZE
194 static inline int P(extra_size) (char *k)
195 { return strlen(k); }
196 # ifndef HASH_GIVE_INIT_KEY
197 # define HASH_GIVE_INIT_KEY
198 static inline void P(init_key) (P(node) *n, char *k)
199 { strcpy(HASH_KEY(n->), k); }
202 #define HASH_KEY_DECL char *HASH_KEY( )
204 #ifndef HASH_GIVE_HASHFN
205 #define HASH_GIVE_HASHFN
206 static inline uns P(hash) (char *k)
209 return hash_string_nocase(k);
211 return hash_string(k);
217 # define HASH_GIVE_EQ
218 static inline int P(eq) (char *x, char *y)
221 return !strcasecmp(x,y);
228 #elif defined(HASH_KEY_COMPLEX)
230 #define HASH_KEY(x) HASH_KEY_COMPLEX(x)
233 #error You forgot to set the hash key type.
236 /* Defaults for missing parameters */
238 #ifndef HASH_GIVE_HASHFN
239 #error Unable to determine which hash function to use.
243 #error Unable to determine how to compare two keys.
246 #ifdef HASH_GIVE_EXTRA_SIZE
247 /* This trickery is needed to avoid `unused parameter' warnings */
248 #define HASH_EXTRA_SIZE P(extra_size)
251 * Beware, C macros are expanded iteratively, not recursively,
252 * hence we get only a _single_ argument, although the expansion
253 * of HASH_KEY contains commas.
255 #define HASH_EXTRA_SIZE(x) 0
258 #ifndef HASH_GIVE_INIT_KEY
259 #error Unable to determine how to initialize keys.
262 #ifndef HASH_GIVE_INIT_DATA
263 static inline void P(init_data) (P(node) *n UNUSED)
270 #ifdef HASH_GIVE_ALLOC
271 /* If the caller has requested to use his own allocation functions, do so */
272 static inline void P(init_alloc) (void) { }
273 static inline void P(cleanup_alloc) (void) { }
275 #elif defined(HASH_USE_POOL)
276 /* If the caller has requested to use his mempool, do so */
277 #include "lib/mempool.h"
278 static inline void * P(alloc) (unsigned int size) { return mp_alloc_fast(HASH_USE_POOL, size); }
279 static inline void P(free) (void *x UNUSED) { }
280 static inline void P(init_alloc) (void) { }
281 static inline void P(cleanup_alloc) (void) { }
283 #elif defined(HASH_AUTO_POOL)
284 /* Use our own pools */
285 #include "lib/mempool.h"
286 static struct mempool *P(pool);
287 static inline void * P(alloc) (unsigned int size) { return mp_alloc_fast(P(pool), size); }
288 static inline void P(free) (void *x UNUSED) { }
289 static inline void P(init_alloc) (void) { P(pool) = mp_new(HASH_AUTO_POOL); }
290 static inline void P(cleanup_alloc) (void) { mp_delete(P(pool)); }
293 /* The default allocation method */
294 static inline void * P(alloc) (unsigned int size) { return xmalloc(size); }
295 static inline void P(free) (void *x) { xfree(x); }
296 static inline void P(init_alloc) (void) { }
297 static inline void P(cleanup_alloc) (void) { }
301 #ifdef HASH_TABLE_ALLOC
302 static inline void * P(table_alloc) (unsigned int size) { return P(alloc)(size); }
303 static inline void P(table_free) (void *x) { P(free)(x); }
305 static inline void * P(table_alloc) (unsigned int size) { return xmalloc(size); }
306 static inline void P(table_free) (void *x) { xfree(x); }
309 #ifndef HASH_DEFAULT_SIZE
310 #define HASH_DEFAULT_SIZE 32
314 #define HASH_FN_BITS 32
317 /* Now the operations */
319 static void P(alloc_table) (void)
321 T.hash_size = nextprime(T.hash_size);
322 T.ht = P(table_alloc)(sizeof(void *) * T.hash_size);
323 bzero(T.ht, sizeof(void *) * T.hash_size);
324 if (2*T.hash_size < T.hash_hard_max)
325 T.hash_max = 2*T.hash_size;
328 if (T.hash_size/2 > HASH_DEFAULT_SIZE)
329 T.hash_min = T.hash_size/4;
334 static void P(init) (void)
337 T.hash_size = HASH_DEFAULT_SIZE;
338 #if HASH_FN_BITS < 28
339 T.hash_hard_max = 1 << HASH_FN_BITS;
341 T.hash_hard_max = 1 << 28;
347 #ifdef HASH_WANT_CLEANUP
348 static void P(cleanup) (void)
350 #ifndef HASH_USE_POOL
354 for (i=0; i<T.hash_size; i++)
355 for (b=T.ht[i]; b; b=bb)
366 static inline uns P(bucket_hash) (P(bucket) *b)
368 #ifdef HASH_CONSERVE_SPACE
369 return P(hash)(HASH_KEY(b->n.));
375 static void P(rehash) (uns size)
378 P(bucket) **oldt = T.ht, **newt;
379 uns oldsize = T.hash_size;
382 DBG("Rehashing %d->%d at count %d", oldsize, size, T.hash_count);
386 for (i=0; i<oldsize; i++)
392 h = P(bucket_hash)(b) % T.hash_size;
401 #ifdef HASH_WANT_FIND
402 static P(node) * P(find) (HASH_KEY_DECL)
404 uns h0 = P(hash) (HASH_KEY( ));
405 uns h = h0 % T.hash_size;
408 for (b=T.ht[h]; b; b=b->next)
411 #ifndef HASH_CONSERVE_SPACE
414 P(eq)(HASH_KEY( ), HASH_KEY(b->n.)))
421 #ifdef HASH_WANT_FIND_NEXT
422 static P(node) * P(find_next) (P(node) *start)
424 #ifndef HASH_CONSERVE_SPACE
425 uns h0 = P(hash) (HASH_KEY(start->));
427 P(bucket) *b = SKIP_BACK(P(bucket), n, start);
429 for (b=b->next; b; b=b->next)
432 #ifndef HASH_CONSERVE_SPACE
435 P(eq)(HASH_KEY(start->), HASH_KEY(b->n.)))
443 static P(node) * P(new) (HASH_KEY_DECL)
448 h0 = P(hash) (HASH_KEY( ));
449 h = h0 % T.hash_size;
450 b = P(alloc) (sizeof(struct P(bucket)) + HASH_EXTRA_SIZE(HASH_KEY( )));
453 #ifndef HASH_CONSERVE_SPACE
456 P(init_key)(&b->n, HASH_KEY( ));
458 if (T.hash_count++ >= T.hash_max)
459 P(rehash)(2*T.hash_size);
464 #ifdef HASH_WANT_LOOKUP
465 static P(node) * P(lookup) (HASH_KEY_DECL)
467 uns h0 = P(hash) (HASH_KEY( ));
468 uns h = h0 % T.hash_size;
471 for (b=T.ht[h]; b; b=b->next)
474 #ifndef HASH_CONSERVE_SPACE
477 P(eq)(HASH_KEY( ), HASH_KEY(b->n.)))
481 b = P(alloc) (sizeof(struct P(bucket)) + HASH_EXTRA_SIZE(HASH_KEY( )));
484 #ifndef HASH_CONSERVE_SPACE
487 P(init_key)(&b->n, HASH_KEY( ));
489 if (T.hash_count++ >= T.hash_max)
490 P(rehash)(2*T.hash_size);
495 #ifdef HASH_WANT_DELETE
496 static int P(delete) (HASH_KEY_DECL)
498 uns h0 = P(hash) (HASH_KEY( ));
499 uns h = h0 % T.hash_size;
502 for (bb=&T.ht[h]; b=*bb; bb=&b->next)
505 #ifndef HASH_CONSERVE_SPACE
508 P(eq)(HASH_KEY( ), HASH_KEY(b->n.)))
512 if (--T.hash_count < T.hash_min)
513 P(rehash)(T.hash_size/2);
521 #ifdef HASH_WANT_REMOVE
522 static void P(remove) (P(node) *n)
524 P(bucket) *x = SKIP_BACK(struct P(bucket), n, n);
525 uns h0 = P(bucket_hash)(x);
526 uns h = h0 % T.hash_size;
529 for (bb=&T.ht[h]; (b=*bb) && b != x; bb=&b->next)
534 if (--T.hash_count < T.hash_min)
535 P(rehash)(T.hash_size/2);
539 /* And the iterator */
543 #define HASH_FOR_ALL(h_px, h_var) \
546 struct GLUE_(h_px,bucket) *h_buck; \
547 for (h_slot=0; h_slot < GLUE_(h_px,table).hash_size; h_slot++) \
548 for (h_buck = GLUE_(h_px,table).ht[h_slot]; h_buck; h_buck = h_buck->next) \
550 GLUE_(h_px,node) *h_var = &h_buck->n;
551 #define HASH_END_FOR } } while(0)
553 #define HASH_CONTINUE continue
557 /* Finally, undefine all the parameters */
562 #undef HASH_ATOMIC_TYPE
563 #undef HASH_CONSERVE_SPACE
564 #undef HASH_DEFAULT_SIZE
565 #undef HASH_EXTRA_SIZE
567 #undef HASH_GIVE_ALLOC
569 #undef HASH_GIVE_EXTRA_SIZE
570 #undef HASH_GIVE_HASHFN
571 #undef HASH_GIVE_INIT_DATA
572 #undef HASH_GIVE_INIT_KEY
574 #undef HASH_KEY_ATOMIC
575 #undef HASH_KEY_COMPLEX
577 #undef HASH_KEY_ENDSTRING
578 #undef HASH_KEY_STRING
583 #undef HASH_AUTO_POOL
584 #undef HASH_WANT_CLEANUP
585 #undef HASH_WANT_DELETE
586 #undef HASH_WANT_FIND
587 #undef HASH_WANT_FIND_NEXT
588 #undef HASH_WANT_LOOKUP
590 #undef HASH_WANT_REMOVE
591 #undef HASH_TABLE_ALLOC