3 Routines for manipulating hash tables... */
6 * Copyright (c) 1995-2001 Internet Software Consortium.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of The Internet Software Consortium nor the names
19 * of its contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
23 * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
24 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
25 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
27 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
30 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
32 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
33 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * This software has been written for the Internet Software Consortium
37 * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
38 * To learn more about the Internet Software Consortium, see
39 * ``http://www.isc.org/''. To learn more about Vixie Enterprises,
40 * see ``http://www.vix.com''. To learn more about Nominum, Inc., see
41 * ``http://www.nominum.com''.
45 static char copyright[] =
46 "$Id: hash.c,v 1.1.2.5 2001/10/17 04:00:35 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium. All rights reserved.\n";
49 #include <omapip/omapip_p.h>
52 static int do_hash (const unsigned char *, unsigned, unsigned);
53 static int do_case_hash (const unsigned char *, unsigned, unsigned);
55 int new_hash_table (tp, count, file, line)
56 struct hash_table **tp;
61 struct hash_table *rval;
64 log_error ("%s(%d): new_hash_table called with null pointer.",
66 #if defined (POINTER_DEBUG)
72 log_error ("%s(%d): non-null target for new_hash_table.",
74 #if defined (POINTER_DEBUG)
78 rval = dmalloc (sizeof (struct hash_table) -
79 (DEFAULT_HASH_SIZE * sizeof (struct hash_bucket *)) +
80 (count * sizeof (struct hash_bucket *)), file, line);
83 rval -> hash_count = count;
88 void free_hash_table (tp, file, line)
89 struct hash_table **tp;
94 struct hash_bucket *hbc, *hbn = (struct hash_bucket *)0;
95 struct hash_table *ptr = *tp;
97 #if defined (DEBUG_MEMORY_LEAKAGE) || \
98 defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
99 for (i = 0; i < ptr -> hash_count; i++) {
100 for (hbc = ptr -> buckets [i]; hbc; hbc = hbn) {
102 if (ptr -> dereferencer && hbc -> value)
103 (*ptr -> dereferencer) (&hbc -> value, MDL);
105 for (hbc = ptr -> buckets [i]; hbc; hbc = hbn) {
107 free_hash_bucket (hbc, MDL);
109 ptr -> buckets [i] = (struct hash_bucket *)0;
113 dfree ((VOIDPTR)ptr, MDL);
114 *tp = (struct hash_table *)0;
117 struct hash_bucket *free_hash_buckets;
119 #if defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
120 struct hash_bucket *hash_bucket_hunks;
122 void relinquish_hash_bucket_hunks ()
124 struct hash_bucket *c, *n, **p;
126 /* Account for all the hash buckets on the free list. */
127 p = &free_hash_buckets;
128 for (c = free_hash_buckets; c; c = c -> next) {
129 for (n = hash_bucket_hunks; n; n = n -> next) {
130 if (c > n && c < n + 127) {
136 /* If we didn't delete the hash bucket from the free list,
137 advance the pointer. */
142 for (c = hash_bucket_hunks; c; c = n) {
144 if (c -> len != 126) {
145 log_info ("hashbucket %lx hash_buckets %d free %u",
146 (unsigned long)c, 127, c -> len);
153 struct hash_bucket *new_hash_bucket (file, line)
157 struct hash_bucket *rval;
159 if (!free_hash_buckets) {
160 rval = dmalloc (127 * sizeof (struct hash_bucket),
164 # if defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
165 rval -> next = hash_bucket_hunks;
166 hash_bucket_hunks = rval;
167 hash_bucket_hunks -> len = 0;
171 for (; i < 127; i++) {
172 rval -> next = free_hash_buckets;
173 free_hash_buckets = rval;
177 rval = free_hash_buckets;
178 free_hash_buckets = rval -> next;
182 void free_hash_bucket (ptr, file, line)
183 struct hash_bucket *ptr;
187 struct hash_bucket *hp;
188 #if defined (DEBUG_MALLOC_POOL)
189 for (hp = free_hash_buckets; hp; hp = hp -> next) {
191 log_error ("hash bucket freed twice!");
196 ptr -> next = free_hash_buckets;
197 free_hash_buckets = ptr;
200 int new_hash (struct hash_table **rp,
201 hash_reference referencer,
202 hash_dereference dereferencer,
203 int casep, const char *file, int line)
205 if (!new_hash_table (rp, DEFAULT_HASH_SIZE, file, line))
207 memset (&(*rp) -> buckets [0], 0,
208 DEFAULT_HASH_SIZE * sizeof (struct hash_bucket *));
209 (*rp) -> referencer = referencer;
210 (*rp) -> dereferencer = dereferencer;
212 (*rp) -> cmp = casecmp;
213 (*rp) -> do_hash = do_case_hash;
215 (*rp) -> cmp = (hash_comparator_t)memcmp;
216 (*rp) -> do_hash = do_hash;
221 static int do_case_hash (name, len, size)
222 const unsigned char *name;
226 register int accum = 0;
227 register const unsigned char *s = (const unsigned char *)name;
232 /* Make the hash case-insensitive. */
234 if (isascii (c) && isupper (c))
237 /* Add the character in... */
238 accum = (accum << 1) + c;
240 /* Add carry back in... */
241 while (accum > 65535) {
242 accum = (accum & 65535) + (accum >> 16);
248 static int do_hash (name, len, size)
249 const unsigned char *name;
253 register int accum = 0;
254 register const unsigned char *s = (const unsigned char *)name;
258 /* Add the character in... */
259 accum = (accum << 1) + *s++;
261 /* Add carry back in... */
262 while (accum > 65535) {
263 accum = (accum & 65535) + (accum >> 16);
269 void add_hash (table, name, len, pointer, file, line)
270 struct hash_table *table;
272 const unsigned char *name;
273 hashed_object_t *pointer;
278 struct hash_bucket *bp;
285 len = strlen ((const char *)name);
287 hashno = (*table -> do_hash) (name, len, table -> hash_count);
288 bp = new_hash_bucket (file, line);
291 log_error ("Can't add %s to hash table.", name);
295 if (table -> referencer) {
297 (*(table -> referencer)) (foo, pointer, file, line);
299 bp -> value = pointer;
300 bp -> next = table -> buckets [hashno];
302 table -> buckets [hashno] = bp;
305 void delete_hash_entry (table, name, len, file, line)
306 struct hash_table *table;
308 const unsigned char *name;
313 struct hash_bucket *bp, *pbp = (struct hash_bucket *)0;
320 len = strlen ((const char *)name);
322 hashno = (*table -> do_hash) (name, len, table -> hash_count);
324 /* Go through the list looking for an entry that matches;
325 if we find it, delete it. */
326 for (bp = table -> buckets [hashno]; bp; bp = bp -> next) {
328 !strcmp ((const char *)bp -> name, (const char *)name)) ||
330 !(*table -> cmp) (bp -> name, name, len))) {
332 pbp -> next = bp -> next;
334 table -> buckets [hashno] = bp -> next;
336 if (bp -> value && table -> dereferencer) {
338 (*(table -> dereferencer)) (foo, file, line);
340 free_hash_bucket (bp, file, line);
343 pbp = bp; /* jwg, 9/6/96 - nice catch! */
347 int hash_lookup (vp, table, name, len, file, line)
348 hashed_object_t **vp;
349 struct hash_table *table;
350 const unsigned char *name;
356 struct hash_bucket *bp;
361 len = strlen ((const char *)name);
363 hashno = (*table -> do_hash) (name, len, table -> hash_count);
365 for (bp = table -> buckets [hashno]; bp; bp = bp -> next) {
367 && !(*table -> cmp) (bp -> name, name, len)) {
368 if (table -> referencer)
369 (*table -> referencer) (vp, bp -> value,
379 int hash_foreach (struct hash_table *table, hash_foreach_func func)
382 struct hash_bucket *bp, *next;
388 for (i = 0; i < table -> hash_count; i++) {
389 bp = table -> buckets [i];
392 (*func) (bp -> name, bp -> len, bp -> value);
400 int casecmp (const void *v1, const void *v2, unsigned long len)
406 for (i = 0; i < len; i++)
409 if (isascii (s [i]) && isupper (s [i]))
410 c1 = tolower (s [i]);
414 if (isascii (t [i]) && isupper (t [i]))
415 c2 = tolower (t [i]);