00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #ifdef HAVE_CONFIG_H
00039 #include "config.h"
00040 #endif
00041
00042 #include <sys/types.h>
00043
00044 #ifdef HAVE_STDLIB_H
00045 #include <stdlib.h>
00046 #endif
00047
00048 #ifdef HAVE_STRING_H
00049 #include <string.h>
00050 #endif
00051
00052 #if ! defined(BUILD_OS_DARWIN)
00053 #ifdef HAVE_MALLOC_H
00054 #include <malloc.h>
00055 #endif
00056 #endif
00057
00058 #include <stdio.h>
00059
00060 #include "libiberty.h"
00061 #include "hashtab.h"
00062
00063
00064
00065 #define EMPTY_ENTRY ((PTR) 0)
00066
00067
00068
00069
00070 #define DELETED_ENTRY ((PTR) 1)
00071
00072 static unsigned long higher_prime_number PARAMS ((unsigned long));
00073 static hashval_t hash_pointer PARAMS ((const void *));
00074 static int eq_pointer PARAMS ((const void *, const void *));
00075 static int htab_expand PARAMS ((htab_t));
00076 static PTR *find_empty_slot_for_expand PARAMS ((htab_t, hashval_t));
00077
00078
00079
00080
00081 htab_hash htab_hash_pointer = hash_pointer;
00082 htab_eq htab_eq_pointer = eq_pointer;
00083
00084
00085
00086
00087 static unsigned long
00088 higher_prime_number (n)
00089 unsigned long n;
00090 {
00091
00092
00093 static const unsigned long primes[] = {
00094 (unsigned long) 7,
00095 (unsigned long) 13,
00096 (unsigned long) 31,
00097 (unsigned long) 61,
00098 (unsigned long) 127,
00099 (unsigned long) 251,
00100 (unsigned long) 509,
00101 (unsigned long) 1021,
00102 (unsigned long) 2039,
00103 (unsigned long) 4093,
00104 (unsigned long) 8191,
00105 (unsigned long) 16381,
00106 (unsigned long) 32749,
00107 (unsigned long) 65521,
00108 (unsigned long) 131071,
00109 (unsigned long) 262139,
00110 (unsigned long) 524287,
00111 (unsigned long) 1048573,
00112 (unsigned long) 2097143,
00113 (unsigned long) 4194301,
00114 (unsigned long) 8388593,
00115 (unsigned long) 16777213,
00116 (unsigned long) 33554393,
00117 (unsigned long) 67108859,
00118 (unsigned long) 134217689,
00119 (unsigned long) 268435399,
00120 (unsigned long) 536870909,
00121 (unsigned long) 1073741789,
00122 (unsigned long) 2147483647,
00123
00124 ((unsigned long) 2147483647) + ((unsigned long) 2147483644),
00125 };
00126
00127 const unsigned long *low = &primes[0];
00128 const unsigned long *high = &primes[sizeof(primes) / sizeof(primes[0])];
00129
00130 while (low != high)
00131 {
00132 const unsigned long *mid = low + (high - low) / 2;
00133 if (n > *mid)
00134 low = mid + 1;
00135 else
00136 high = mid;
00137 }
00138
00139
00140 if (n > *low)
00141 {
00142 fprintf (stderr, "Cannot find prime bigger than %lu\n", n);
00143 abort ();
00144 }
00145
00146 return *low;
00147 }
00148
00149
00150
00151 static hashval_t
00152 hash_pointer (p)
00153 const PTR p;
00154 {
00155 return (hashval_t) ((long)p >> 3);
00156 }
00157
00158
00159
00160 static int
00161 eq_pointer (p1, p2)
00162 const PTR p1;
00163 const PTR p2;
00164 {
00165 return p1 == p2;
00166 }
00167
00168
00169
00170
00171
00172
00173 htab_t
00174 htab_create_alloc (size, hash_f, eq_f, del_f, alloc_f, free_f)
00175 size_t size;
00176 htab_hash hash_f;
00177 htab_eq eq_f;
00178 htab_del del_f;
00179 htab_alloc alloc_f;
00180 htab_free free_f;
00181 {
00182 htab_t result;
00183
00184 size = higher_prime_number (size);
00185 result = (htab_t) (*alloc_f) (1, sizeof (struct htab));
00186 if (result == NULL)
00187 return NULL;
00188 result->entries = (PTR *) (*alloc_f) (size, sizeof (PTR));
00189 if (result->entries == NULL)
00190 {
00191 if (free_f != NULL)
00192 (*free_f) (result);
00193 return NULL;
00194 }
00195 result->size = size;
00196 result->hash_f = hash_f;
00197 result->eq_f = eq_f;
00198 result->del_f = del_f;
00199 result->alloc_f = alloc_f;
00200 result->free_f = free_f;
00201 return result;
00202 }
00203
00204
00205
00206 #undef htab_create
00207 htab_t
00208 htab_create (size, hash_f, eq_f, del_f)
00209 size_t size;
00210 htab_hash hash_f;
00211 htab_eq eq_f;
00212 htab_del del_f;
00213 {
00214 return htab_create_alloc (size, hash_f, eq_f, del_f, xcalloc, free);
00215 }
00216
00217 htab_t
00218 htab_try_create (size, hash_f, eq_f, del_f)
00219 size_t size;
00220 htab_hash hash_f;
00221 htab_eq eq_f;
00222 htab_del del_f;
00223 {
00224 return htab_create_alloc (size, hash_f, eq_f, del_f, calloc, free);
00225 }
00226
00227
00228
00229
00230 void
00231 htab_delete (htab)
00232 htab_t htab;
00233 {
00234 int i;
00235
00236 if (htab->del_f)
00237 for (i = htab->size - 1; i >= 0; i--)
00238 if (htab->entries[i] != EMPTY_ENTRY
00239 && htab->entries[i] != DELETED_ENTRY)
00240 (*htab->del_f) (htab->entries[i]);
00241
00242 if (htab->free_f != NULL)
00243 {
00244 (*htab->free_f) (htab->entries);
00245 (*htab->free_f) (htab);
00246 }
00247 }
00248
00249
00250
00251 void
00252 htab_empty (htab)
00253 htab_t htab;
00254 {
00255 int i;
00256
00257 if (htab->del_f)
00258 for (i = htab->size - 1; i >= 0; i--)
00259 if (htab->entries[i] != EMPTY_ENTRY
00260 && htab->entries[i] != DELETED_ENTRY)
00261 (*htab->del_f) (htab->entries[i]);
00262
00263 memset (htab->entries, 0, htab->size * sizeof (PTR));
00264 }
00265
00266
00267
00268
00269
00270
00271
00272
00273 static PTR *
00274 find_empty_slot_for_expand (htab, hash)
00275 htab_t htab;
00276 hashval_t hash;
00277 {
00278 size_t size = htab->size;
00279 unsigned int index = hash % size;
00280 PTR *slot = htab->entries + index;
00281 hashval_t hash2;
00282
00283 if (*slot == EMPTY_ENTRY)
00284 return slot;
00285 else if (*slot == DELETED_ENTRY)
00286 abort ();
00287
00288 hash2 = 1 + hash % (size - 2);
00289 for (;;)
00290 {
00291 index += hash2;
00292 if (index >= size)
00293 index -= size;
00294
00295 slot = htab->entries + index;
00296 if (*slot == EMPTY_ENTRY)
00297 return slot;
00298 else if (*slot == DELETED_ENTRY)
00299 abort ();
00300 }
00301 }
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311 static int
00312 htab_expand (htab)
00313 htab_t htab;
00314 {
00315 PTR *oentries;
00316 PTR *olimit;
00317 PTR *p;
00318 PTR *nentries;
00319 size_t nsize;
00320
00321 oentries = htab->entries;
00322 olimit = oentries + htab->size;
00323
00324 nsize = higher_prime_number (htab->size * 2);
00325
00326 nentries = (PTR *) (*htab->alloc_f) (nsize, sizeof (PTR));
00327 if (nentries == NULL)
00328 return 0;
00329 htab->entries = nentries;
00330 htab->size = nsize;
00331
00332 htab->n_elements -= htab->n_deleted;
00333 htab->n_deleted = 0;
00334
00335 p = oentries;
00336 do
00337 {
00338 PTR x = *p;
00339
00340 if (x != EMPTY_ENTRY && x != DELETED_ENTRY)
00341 {
00342 PTR *q = find_empty_slot_for_expand (htab, (*htab->hash_f) (x));
00343
00344 *q = x;
00345 }
00346
00347 p++;
00348 }
00349 while (p < olimit);
00350
00351 if (htab->free_f != NULL)
00352 (*htab->free_f) (oentries);
00353 return 1;
00354 }
00355
00356
00357
00358
00359 PTR
00360 htab_find_with_hash (htab, element, hash)
00361 htab_t htab;
00362 const PTR element;
00363 hashval_t hash;
00364 {
00365 unsigned int index;
00366 hashval_t hash2;
00367 size_t size;
00368 PTR entry;
00369
00370 htab->searches++;
00371 size = htab->size;
00372 index = hash % size;
00373
00374 entry = htab->entries[index];
00375 if (entry == EMPTY_ENTRY
00376 || (entry != DELETED_ENTRY && (*htab->eq_f) (entry, element)))
00377 return entry;
00378
00379 hash2 = 1 + hash % (size - 2);
00380
00381 for (;;)
00382 {
00383 htab->collisions++;
00384 index += hash2;
00385 if (index >= size)
00386 index -= size;
00387
00388 entry = htab->entries[index];
00389 if (entry == EMPTY_ENTRY
00390 || (entry != DELETED_ENTRY && (*htab->eq_f) (entry, element)))
00391 return entry;
00392 }
00393 }
00394
00395
00396
00397
00398 PTR
00399 htab_find (htab, element)
00400 htab_t htab;
00401 const PTR element;
00402 {
00403 return htab_find_with_hash (htab, element, (*htab->hash_f) (element));
00404 }
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414 PTR *
00415 htab_find_slot_with_hash (htab, element, hash, insert)
00416 htab_t htab;
00417 const PTR element;
00418 hashval_t hash;
00419 enum insert_option insert;
00420 {
00421 PTR *first_deleted_slot;
00422 unsigned int index;
00423 hashval_t hash2;
00424 size_t size;
00425 PTR entry;
00426
00427 if (insert == INSERT && htab->size * 3 <= htab->n_elements * 4
00428 && htab_expand (htab) == 0)
00429 return NULL;
00430
00431 size = htab->size;
00432 index = hash % size;
00433
00434 htab->searches++;
00435 first_deleted_slot = NULL;
00436
00437 entry = htab->entries[index];
00438 if (entry == EMPTY_ENTRY)
00439 goto empty_entry;
00440 else if (entry == DELETED_ENTRY)
00441 first_deleted_slot = &htab->entries[index];
00442 else if ((*htab->eq_f) (entry, element))
00443 return &htab->entries[index];
00444
00445 hash2 = 1 + hash % (size - 2);
00446 for (;;)
00447 {
00448 htab->collisions++;
00449 index += hash2;
00450 if (index >= size)
00451 index -= size;
00452
00453 entry = htab->entries[index];
00454 if (entry == EMPTY_ENTRY)
00455 goto empty_entry;
00456 else if (entry == DELETED_ENTRY)
00457 {
00458 if (!first_deleted_slot)
00459 first_deleted_slot = &htab->entries[index];
00460 }
00461 else if ((*htab->eq_f) (entry, element))
00462 return &htab->entries[index];
00463 }
00464
00465 empty_entry:
00466 if (insert == NO_INSERT)
00467 return NULL;
00468
00469 htab->n_elements++;
00470
00471 if (first_deleted_slot)
00472 {
00473 *first_deleted_slot = EMPTY_ENTRY;
00474 return first_deleted_slot;
00475 }
00476
00477 return &htab->entries[index];
00478 }
00479
00480
00481
00482
00483 PTR *
00484 htab_find_slot (htab, element, insert)
00485 htab_t htab;
00486 const PTR element;
00487 enum insert_option insert;
00488 {
00489 return htab_find_slot_with_hash (htab, element, (*htab->hash_f) (element),
00490 insert);
00491 }
00492
00493
00494
00495
00496
00497 void
00498 htab_remove_elt (htab, element)
00499 htab_t htab;
00500 PTR element;
00501 {
00502 PTR *slot;
00503
00504 slot = htab_find_slot (htab, element, NO_INSERT);
00505 if (*slot == EMPTY_ENTRY)
00506 return;
00507
00508 if (htab->del_f)
00509 (*htab->del_f) (*slot);
00510
00511 *slot = DELETED_ENTRY;
00512 htab->n_deleted++;
00513 }
00514
00515
00516
00517
00518
00519 void
00520 htab_clear_slot (htab, slot)
00521 htab_t htab;
00522 PTR *slot;
00523 {
00524 if (slot < htab->entries || slot >= htab->entries + htab->size
00525 || *slot == EMPTY_ENTRY || *slot == DELETED_ENTRY)
00526 abort ();
00527
00528 if (htab->del_f)
00529 (*htab->del_f) (*slot);
00530
00531 *slot = DELETED_ENTRY;
00532 htab->n_deleted++;
00533 }
00534
00535
00536
00537
00538
00539
00540 void
00541 htab_traverse (htab, callback, info)
00542 htab_t htab;
00543 htab_trav callback;
00544 PTR info;
00545 {
00546 PTR *slot = htab->entries;
00547 PTR *limit = slot + htab->size;
00548
00549 do
00550 {
00551 PTR x = *slot;
00552
00553 if (x != EMPTY_ENTRY && x != DELETED_ENTRY)
00554 if (!(*callback) (slot, info))
00555 break;
00556 }
00557 while (++slot < limit);
00558 }
00559
00560
00561
00562 size_t
00563 htab_size (htab)
00564 htab_t htab;
00565 {
00566 return htab->size;
00567 }
00568
00569
00570
00571 size_t
00572 htab_elements (htab)
00573 htab_t htab;
00574 {
00575 return htab->n_elements - htab->n_deleted;
00576 }
00577
00578
00579
00580
00581 double
00582 htab_collisions (htab)
00583 htab_t htab;
00584 {
00585 if (htab->searches == 0)
00586 return 0.0;
00587
00588 return (double) htab->collisions / (double) htab->searches;
00589 }
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616 hashval_t
00617 htab_hash_string (p)
00618 const PTR p;
00619 {
00620 const unsigned char *str = (const unsigned char *) p;
00621 hashval_t r = 0;
00622 unsigned char c;
00623
00624 while ((c = *str++) != 0)
00625 r = r * 67 + c - 113;
00626
00627 return r;
00628 }