1 1.5 simonb /* $NetBSD: hash.c,v 1.5 2007/03/03 00:09:30 simonb Exp $ */ 2 1.1 mrg 3 1.1 mrg /* 4 1.1 mrg * Copyright (c) 1988, 1989, 1990 The Regents of the University of California. 5 1.3 agc * All rights reserved. 6 1.3 agc * 7 1.3 agc * This code is derived from software contributed to Berkeley by 8 1.3 agc * Adam de Boor. 9 1.3 agc * 10 1.3 agc * Redistribution and use in source and binary forms, with or without 11 1.3 agc * modification, are permitted provided that the following conditions 12 1.3 agc * are met: 13 1.3 agc * 1. Redistributions of source code must retain the above copyright 14 1.3 agc * notice, this list of conditions and the following disclaimer. 15 1.3 agc * 2. Redistributions in binary form must reproduce the above copyright 16 1.3 agc * notice, this list of conditions and the following disclaimer in the 17 1.3 agc * documentation and/or other materials provided with the distribution. 18 1.3 agc * 3. Neither the name of the University nor the names of its contributors 19 1.3 agc * may be used to endorse or promote products derived from this software 20 1.3 agc * without specific prior written permission. 21 1.3 agc * 22 1.3 agc * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 1.3 agc * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 1.3 agc * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 1.3 agc * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 1.3 agc * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 1.3 agc * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 1.3 agc * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 1.3 agc * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 1.3 agc * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 1.3 agc * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 1.3 agc * SUCH DAMAGE. 33 1.3 agc */ 34 1.3 agc 35 1.3 agc /* 36 1.1 mrg * Copyright (c) 1988, 1989 by Adam de Boor 37 1.1 mrg * Copyright (c) 1989 by Berkeley Softworks 38 1.1 mrg * All rights reserved. 39 1.1 mrg * 40 1.1 mrg * This code is derived from software contributed to Berkeley by 41 1.1 mrg * Adam de Boor. 42 1.1 mrg * 43 1.1 mrg * Redistribution and use in source and binary forms, with or without 44 1.1 mrg * modification, are permitted provided that the following conditions 45 1.1 mrg * are met: 46 1.1 mrg * 1. Redistributions of source code must retain the above copyright 47 1.1 mrg * notice, this list of conditions and the following disclaimer. 48 1.1 mrg * 2. Redistributions in binary form must reproduce the above copyright 49 1.1 mrg * notice, this list of conditions and the following disclaimer in the 50 1.1 mrg * documentation and/or other materials provided with the distribution. 51 1.1 mrg * 3. All advertising materials mentioning features or use of this software 52 1.1 mrg * must display the following acknowledgement: 53 1.1 mrg * This product includes software developed by the University of 54 1.1 mrg * California, Berkeley and its contributors. 55 1.1 mrg * 4. Neither the name of the University nor the names of its contributors 56 1.1 mrg * may be used to endorse or promote products derived from this software 57 1.1 mrg * without specific prior written permission. 58 1.1 mrg * 59 1.1 mrg * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 60 1.1 mrg * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 61 1.1 mrg * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 62 1.1 mrg * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 63 1.1 mrg * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 64 1.1 mrg * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 65 1.1 mrg * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 66 1.1 mrg * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 67 1.1 mrg * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 68 1.1 mrg * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 69 1.1 mrg * SUCH DAMAGE. 70 1.1 mrg */ 71 1.1 mrg 72 1.1 mrg #ifdef MAKE_BOOTSTRAP 73 1.5 simonb static char rcsid[] = "$NetBSD: hash.c,v 1.5 2007/03/03 00:09:30 simonb Exp $"; 74 1.1 mrg #else 75 1.1 mrg #include <sys/cdefs.h> 76 1.1 mrg #ifndef lint 77 1.1 mrg #if 0 78 1.1 mrg static char sccsid[] = "@(#)hash.c 8.1 (Berkeley) 6/6/93"; 79 1.1 mrg #else 80 1.5 simonb __RCSID("$NetBSD: hash.c,v 1.5 2007/03/03 00:09:30 simonb Exp $"); 81 1.1 mrg #endif 82 1.1 mrg #endif /* not lint */ 83 1.1 mrg #endif 84 1.1 mrg 85 1.1 mrg #include <sys/types.h> 86 1.1 mrg 87 1.1 mrg #include <stdlib.h> 88 1.1 mrg #include <string.h> 89 1.1 mrg #include <unistd.h> 90 1.4 christos #include <err.h> 91 1.4 christos #include <util.h> 92 1.1 mrg 93 1.1 mrg /* hash.c -- 94 1.1 mrg * 95 1.1 mrg * This module contains routines to manipulate a hash table. 96 1.1 mrg * See hash.h for a definition of the structure of the hash 97 1.1 mrg * table. Hash tables grow automatically as the amount of 98 1.1 mrg * information increases. 99 1.1 mrg */ 100 1.1 mrg #include "hash.h" 101 1.1 mrg 102 1.1 mrg /* 103 1.1 mrg * Forward references to local procedures that are used before they're 104 1.1 mrg * defined: 105 1.1 mrg */ 106 1.1 mrg 107 1.2 lukem static void RebuildTable(Hash_Table *); 108 1.1 mrg 109 1.1 mrg /* 110 1.1 mrg * The following defines the ratio of # entries to # buckets 111 1.1 mrg * at which we rebuild the table to make it larger. 112 1.1 mrg */ 113 1.1 mrg 114 1.1 mrg #define rebuildLimit 8 115 1.1 mrg 116 1.1 mrg /* 117 1.1 mrg *--------------------------------------------------------- 118 1.1 mrg * 119 1.1 mrg * Hash_InitTable -- 120 1.1 mrg * 121 1.1 mrg * This routine just sets up the hash table. 122 1.1 mrg * 123 1.2 lukem * Input: 124 1.2 lukem * t Structure to use to hold table. 125 1.2 lukem * numBuckets How many buckets to create for starters. This number 126 1.2 lukem * is rounded up to a power of two. If <= 0, a reasonable 127 1.2 lukem * default is chosen. The table will grow in size later 128 1.2 lukem * as needed. 129 1.2 lukem * 130 1.1 mrg * Results: 131 1.1 mrg * None. 132 1.1 mrg * 133 1.1 mrg * Side Effects: 134 1.1 mrg * Memory is allocated for the initial bucket area. 135 1.1 mrg * 136 1.1 mrg *--------------------------------------------------------- 137 1.1 mrg */ 138 1.1 mrg 139 1.1 mrg void 140 1.2 lukem Hash_InitTable(Hash_Table *t, int numBuckets) 141 1.1 mrg { 142 1.2 lukem int i; 143 1.2 lukem struct Hash_Entry **hp; 144 1.1 mrg 145 1.1 mrg /* 146 1.1 mrg * Round up the size to a power of two. 147 1.1 mrg */ 148 1.1 mrg if (numBuckets <= 0) 149 1.1 mrg i = 16; 150 1.1 mrg else { 151 1.1 mrg for (i = 2; i < numBuckets; i <<= 1) 152 1.1 mrg continue; 153 1.1 mrg } 154 1.1 mrg t->numEntries = 0; 155 1.1 mrg t->size = i; 156 1.1 mrg t->mask = i - 1; 157 1.1 mrg t->bucketPtr = hp = (struct Hash_Entry **)emalloc(sizeof(*hp) * i); 158 1.1 mrg while (--i >= 0) 159 1.1 mrg *hp++ = NULL; 160 1.1 mrg } 161 1.1 mrg 162 1.1 mrg /* 163 1.1 mrg *--------------------------------------------------------- 164 1.1 mrg * 165 1.1 mrg * Hash_DeleteTable -- 166 1.1 mrg * 167 1.1 mrg * This routine removes everything from a hash table 168 1.1 mrg * and frees up the memory space it occupied (except for 169 1.1 mrg * the space in the Hash_Table structure). 170 1.1 mrg * 171 1.1 mrg * Results: 172 1.1 mrg * None. 173 1.1 mrg * 174 1.1 mrg * Side Effects: 175 1.1 mrg * Lots of memory is freed up. 176 1.1 mrg * 177 1.1 mrg *--------------------------------------------------------- 178 1.1 mrg */ 179 1.1 mrg 180 1.1 mrg void 181 1.2 lukem Hash_DeleteTable(Hash_Table *t) 182 1.1 mrg { 183 1.2 lukem struct Hash_Entry **hp, *h, *nexth; 184 1.2 lukem int i; 185 1.1 mrg 186 1.2 lukem nexth = NULL; 187 1.1 mrg for (hp = t->bucketPtr, i = t->size; --i >= 0;) { 188 1.1 mrg for (h = *hp++; h != NULL; h = nexth) { 189 1.1 mrg nexth = h->next; 190 1.5 simonb free(h); 191 1.1 mrg } 192 1.1 mrg } 193 1.5 simonb free(t->bucketPtr); 194 1.1 mrg 195 1.1 mrg /* 196 1.1 mrg * Set up the hash table to cause memory faults on any future access 197 1.1 mrg * attempts until re-initialization. 198 1.1 mrg */ 199 1.1 mrg t->bucketPtr = NULL; 200 1.1 mrg } 201 1.1 mrg 202 1.1 mrg /* 203 1.1 mrg *--------------------------------------------------------- 204 1.1 mrg * 205 1.1 mrg * Hash_FindEntry -- 206 1.1 mrg * 207 1.1 mrg * Searches a hash table for an entry corresponding to key. 208 1.1 mrg * 209 1.2 lukem * Input: 210 1.2 lukem * t Hash table to search. 211 1.2 lukem * key A hash key. 212 1.2 lukem * 213 1.1 mrg * Results: 214 1.1 mrg * The return value is a pointer to the entry for key, 215 1.1 mrg * if key was present in the table. If key was not 216 1.1 mrg * present, NULL is returned. 217 1.1 mrg * 218 1.1 mrg * Side Effects: 219 1.1 mrg * None. 220 1.1 mrg * 221 1.1 mrg *--------------------------------------------------------- 222 1.1 mrg */ 223 1.1 mrg 224 1.1 mrg Hash_Entry * 225 1.2 lukem Hash_FindEntry(Hash_Table *t, char *key) 226 1.1 mrg { 227 1.2 lukem Hash_Entry *e; 228 1.2 lukem unsigned h; 229 1.2 lukem char *p; 230 1.1 mrg 231 1.1 mrg for (h = 0, p = key; *p;) 232 1.1 mrg h = (h << 5) - h + *p++; 233 1.1 mrg p = key; 234 1.1 mrg for (e = t->bucketPtr[h & t->mask]; e != NULL; e = e->next) 235 1.1 mrg if (e->namehash == h && strcmp(e->name, p) == 0) 236 1.1 mrg return (e); 237 1.1 mrg return (NULL); 238 1.1 mrg } 239 1.1 mrg 240 1.1 mrg /* 241 1.1 mrg *--------------------------------------------------------- 242 1.1 mrg * 243 1.1 mrg * Hash_CreateEntry -- 244 1.1 mrg * 245 1.1 mrg * Searches a hash table for an entry corresponding to 246 1.1 mrg * key. If no entry is found, then one is created. 247 1.1 mrg * 248 1.2 lukem * Input: 249 1.2 lukem * t Hash table to search. 250 1.2 lukem * key A hash key. 251 1.2 lukem * newPtr Filled in with 1 if new entry created, 0 otherwise. 252 1.2 lukem * 253 1.1 mrg * Results: 254 1.1 mrg * The return value is a pointer to the entry. If *newPtr 255 1.1 mrg * isn't NULL, then *newPtr is filled in with TRUE if a 256 1.1 mrg * new entry was created, and FALSE if an entry already existed 257 1.1 mrg * with the given key. 258 1.1 mrg * 259 1.1 mrg * Side Effects: 260 1.1 mrg * Memory may be allocated, and the hash buckets may be modified. 261 1.1 mrg *--------------------------------------------------------- 262 1.1 mrg */ 263 1.1 mrg 264 1.1 mrg Hash_Entry * 265 1.2 lukem Hash_CreateEntry(Hash_Table *t, char *key, int *newPtr) 266 1.1 mrg { 267 1.2 lukem Hash_Entry *e; 268 1.2 lukem unsigned h; 269 1.2 lukem char *p; 270 1.1 mrg int keylen; 271 1.1 mrg struct Hash_Entry **hp; 272 1.1 mrg 273 1.1 mrg /* 274 1.1 mrg * Hash the key. As a side effect, save the length (strlen) of the 275 1.1 mrg * key in case we need to create the entry. 276 1.1 mrg */ 277 1.1 mrg for (h = 0, p = key; *p;) 278 1.1 mrg h = (h << 5) - h + *p++; 279 1.1 mrg keylen = p - key; 280 1.1 mrg p = key; 281 1.1 mrg for (e = t->bucketPtr[h & t->mask]; e != NULL; e = e->next) { 282 1.1 mrg if (e->namehash == h && strcmp(e->name, p) == 0) { 283 1.1 mrg if (newPtr != NULL) 284 1.2 lukem *newPtr = 0; 285 1.1 mrg return (e); 286 1.1 mrg } 287 1.1 mrg } 288 1.1 mrg 289 1.1 mrg /* 290 1.1 mrg * The desired entry isn't there. Before allocating a new entry, 291 1.1 mrg * expand the table if necessary (and this changes the resulting 292 1.1 mrg * bucket chain). 293 1.1 mrg */ 294 1.1 mrg if (t->numEntries >= rebuildLimit * t->size) 295 1.1 mrg RebuildTable(t); 296 1.1 mrg e = (Hash_Entry *) emalloc(sizeof(*e) + keylen); 297 1.1 mrg hp = &t->bucketPtr[h & t->mask]; 298 1.1 mrg e->next = *hp; 299 1.1 mrg *hp = e; 300 1.1 mrg e->clientData = NULL; 301 1.1 mrg e->namehash = h; 302 1.1 mrg (void) strcpy(e->name, p); 303 1.1 mrg t->numEntries++; 304 1.1 mrg 305 1.1 mrg if (newPtr != NULL) 306 1.2 lukem *newPtr = 1; 307 1.1 mrg return (e); 308 1.1 mrg } 309 1.1 mrg 310 1.1 mrg /* 311 1.1 mrg *--------------------------------------------------------- 312 1.1 mrg * 313 1.1 mrg * Hash_DeleteEntry -- 314 1.1 mrg * 315 1.1 mrg * Delete the given hash table entry and free memory associated with 316 1.1 mrg * it. 317 1.1 mrg * 318 1.1 mrg * Results: 319 1.1 mrg * None. 320 1.1 mrg * 321 1.1 mrg * Side Effects: 322 1.1 mrg * Hash chain that entry lives in is modified and memory is freed. 323 1.1 mrg * 324 1.1 mrg *--------------------------------------------------------- 325 1.1 mrg */ 326 1.1 mrg 327 1.1 mrg void 328 1.2 lukem Hash_DeleteEntry(Hash_Table *t, Hash_Entry *e) 329 1.1 mrg { 330 1.2 lukem Hash_Entry **hp, *p; 331 1.1 mrg 332 1.1 mrg if (e == NULL) 333 1.1 mrg return; 334 1.1 mrg for (hp = &t->bucketPtr[e->namehash & t->mask]; 335 1.1 mrg (p = *hp) != NULL; hp = &p->next) { 336 1.1 mrg if (p == e) { 337 1.1 mrg *hp = p->next; 338 1.5 simonb free(p); 339 1.1 mrg t->numEntries--; 340 1.1 mrg return; 341 1.1 mrg } 342 1.1 mrg } 343 1.1 mrg (void)write(2, "bad call to Hash_DeleteEntry\n", 29); 344 1.1 mrg abort(); 345 1.1 mrg } 346 1.1 mrg 347 1.1 mrg /* 348 1.1 mrg *--------------------------------------------------------- 349 1.1 mrg * 350 1.1 mrg * Hash_EnumFirst -- 351 1.1 mrg * This procedure sets things up for a complete search 352 1.1 mrg * of all entries recorded in the hash table. 353 1.1 mrg * 354 1.2 lukem * Input: 355 1.2 lukem * t Table to be searched. 356 1.2 lukem * searchPtr Area in which to keep state about search. 357 1.2 lukem * 358 1.1 mrg * Results: 359 1.1 mrg * The return value is the address of the first entry in 360 1.1 mrg * the hash table, or NULL if the table is empty. 361 1.1 mrg * 362 1.1 mrg * Side Effects: 363 1.1 mrg * The information in searchPtr is initialized so that successive 364 1.1 mrg * calls to Hash_Next will return successive HashEntry's 365 1.1 mrg * from the table. 366 1.1 mrg * 367 1.1 mrg *--------------------------------------------------------- 368 1.1 mrg */ 369 1.1 mrg 370 1.1 mrg Hash_Entry * 371 1.2 lukem Hash_EnumFirst(Hash_Table *t, Hash_Search *searchPtr) 372 1.1 mrg { 373 1.2 lukem 374 1.1 mrg searchPtr->tablePtr = t; 375 1.1 mrg searchPtr->nextIndex = 0; 376 1.1 mrg searchPtr->hashEntryPtr = NULL; 377 1.1 mrg return Hash_EnumNext(searchPtr); 378 1.1 mrg } 379 1.1 mrg 380 1.1 mrg /* 381 1.1 mrg *--------------------------------------------------------- 382 1.1 mrg * 383 1.1 mrg * Hash_EnumNext -- 384 1.1 mrg * This procedure returns successive entries in the hash table. 385 1.1 mrg * 386 1.1 mrg * Results: 387 1.1 mrg * The return value is a pointer to the next HashEntry 388 1.1 mrg * in the table, or NULL when the end of the table is 389 1.1 mrg * reached. 390 1.1 mrg * 391 1.1 mrg * Side Effects: 392 1.1 mrg * The information in searchPtr is modified to advance to the 393 1.1 mrg * next entry. 394 1.1 mrg * 395 1.1 mrg *--------------------------------------------------------- 396 1.1 mrg */ 397 1.1 mrg 398 1.1 mrg Hash_Entry * 399 1.2 lukem Hash_EnumNext(Hash_Search *searchPtr) 400 1.1 mrg { 401 1.2 lukem Hash_Entry *e; 402 1.1 mrg Hash_Table *t = searchPtr->tablePtr; 403 1.1 mrg 404 1.1 mrg /* 405 1.1 mrg * The hashEntryPtr field points to the most recently returned 406 1.1 mrg * entry, or is nil if we are starting up. If not nil, we have 407 1.1 mrg * to start at the next one in the chain. 408 1.1 mrg */ 409 1.1 mrg e = searchPtr->hashEntryPtr; 410 1.1 mrg if (e != NULL) 411 1.1 mrg e = e->next; 412 1.1 mrg /* 413 1.1 mrg * If the chain ran out, or if we are starting up, we need to 414 1.1 mrg * find the next nonempty chain. 415 1.1 mrg */ 416 1.1 mrg while (e == NULL) { 417 1.1 mrg if (searchPtr->nextIndex >= t->size) 418 1.1 mrg return (NULL); 419 1.1 mrg e = t->bucketPtr[searchPtr->nextIndex++]; 420 1.1 mrg } 421 1.1 mrg searchPtr->hashEntryPtr = e; 422 1.1 mrg return (e); 423 1.1 mrg } 424 1.1 mrg 425 1.1 mrg /* 426 1.1 mrg *--------------------------------------------------------- 427 1.1 mrg * 428 1.1 mrg * RebuildTable -- 429 1.1 mrg * This local routine makes a new hash table that 430 1.1 mrg * is larger than the old one. 431 1.1 mrg * 432 1.1 mrg * Results: 433 1.1 mrg * None. 434 1.1 mrg * 435 1.1 mrg * Side Effects: 436 1.1 mrg * The entire hash table is moved, so any bucket numbers 437 1.1 mrg * from the old table are invalid. 438 1.1 mrg * 439 1.1 mrg *--------------------------------------------------------- 440 1.1 mrg */ 441 1.1 mrg 442 1.1 mrg static void 443 1.2 lukem RebuildTable(Hash_Table *t) 444 1.1 mrg { 445 1.2 lukem Hash_Entry *e, *next, **hp, **xp; 446 1.2 lukem int i, mask; 447 1.2 lukem Hash_Entry **oldhp; 448 1.1 mrg int oldsize; 449 1.1 mrg 450 1.2 lukem next = NULL; 451 1.1 mrg oldhp = t->bucketPtr; 452 1.1 mrg oldsize = i = t->size; 453 1.1 mrg i <<= 1; 454 1.1 mrg t->size = i; 455 1.1 mrg t->mask = mask = i - 1; 456 1.1 mrg t->bucketPtr = hp = (struct Hash_Entry **) emalloc(sizeof(*hp) * i); 457 1.1 mrg while (--i >= 0) 458 1.1 mrg *hp++ = NULL; 459 1.1 mrg for (hp = oldhp, i = oldsize; --i >= 0;) { 460 1.1 mrg for (e = *hp++; e != NULL; e = next) { 461 1.1 mrg next = e->next; 462 1.1 mrg xp = &t->bucketPtr[e->namehash & mask]; 463 1.1 mrg e->next = *xp; 464 1.1 mrg *xp = e; 465 1.1 mrg } 466 1.1 mrg } 467 1.5 simonb free(oldhp); 468 1.1 mrg } 469