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
00039
00040
00041
#include <stdio.h>
00042
#include <string.h>
00043
#include "blah.h"
00044
00045
#define PRIME_TESTS 10
00046
00047
00048
00049
00050 struct HashtableEntryStruct {
00051 Pointer
key;
00052 Pointer
value;
00053 struct HashtableEntryStruct *
next;
00054 };
00055
00056
00057
00058
00059 struct HashtableStruct {
00060 int count;
00061 int threshold;
00062 int capacity;
00063 double loadFactor;
00064 IntFunction *
keyEqualFunction;
00065 IntFunction *
hashFunction;
00066 HashtableEntry *
entries;
00067 };
00068
00069
00070
00071
00072 struct HashIteratorStruct {
00073 Hashtable
hashtable;
00074 int index;
00075 HashtableEntry
entry;
00076 };
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086 void rehashHashtable(Hashtable ht)
00087 {
00088 HashtableEntry *newEntries;
00089 HashtableEntry entry, old;
00090
int i, index;
00091
int newCapacity =
primeNext(ht->capacity * 2, PRIME_TESTS);
00092
00093
#ifdef DEBUG
00094
printf(
"DEBUG: rehashHashtable %d --> %d...", ht->capacity, newCapacity);
00095
#endif
00096
newEntries =
00097 (HashtableEntry *)memMalloc(
sizeof(
HashtableEntryStruct) * newCapacity);
00098
for (i = 0; i < newCapacity; i++)
00099 newEntries[i] = (HashtableEntry)NULL;
00100
for (i = 0; i < ht->capacity; i++)
00101
for (old = ht->entries[i]; old != NULL; ) {
00102 entry = old;
00103 old = old->next;
00104
00105 index = (((*ht->hashFunction)(entry->key)) & 0x7fffffff) % newCapacity;
00106
00107 entry->next = newEntries[index];
00108 newEntries[index] = entry;
00109 }
00110
00111 ht->threshold = (
int)(newCapacity * ht->loadFactor);
00112 ht->capacity = newCapacity;
00113 memFree(ht->entries);
00114 ht->entries = newEntries;
00115
00116
#ifdef DEBUG
00117
printf(
"done\n");
00118
#endif
00119
}
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136 Hashtable
hashNew(
int capacity,
00137
double loadFactor,
00138 IntFunction *hashFunction,
00139 IntFunction *keyEqualFunction)
00140 {
00141 Hashtable ht;
00142
int i;
00143
00144 ht = (Hashtable)memMalloc(
sizeof(
HashtableStruct));
00145 ht->count = 0;
00146
if(capacity < 3) {
00147 capacity = 3;
00148 }
00149 ht->capacity =
primeNext(capacity, PRIME_TESTS);
00150 ht->threshold = (
int)(ht->capacity * loadFactor);
00151 ht->loadFactor = loadFactor;
00152 ht->keyEqualFunction = keyEqualFunction;
00153 ht->hashFunction = hashFunction;
00154 ht->entries =
00155 (HashtableEntry *)memMalloc(
sizeof(
HashtableEntryStruct)*ht->capacity);
00156
for (i = 0; i < ht->capacity; i++)
00157 ht->entries[i] = NULL;
00158
00159
return(ht);
00160 }
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172 Pointer
hashSet(Hashtable ht,
00173 Pointer key,
00174 Pointer value)
00175 {
00176 HashtableEntry entry;
00177
int index;
00178 Pointer p;
00179
00180
if (ht == NULL || key == NULL || value == NULL) {
00181 fprintf(stderr,
"ERROR: hashSet: arguments must not be NULL\n");
00182 abort();
00183 }
00184
00185 index = (((*ht->hashFunction)(key)) & 0x7fffffff) % ht->capacity;
00186
for (entry = ht->entries[index]; entry != NULL; entry = entry->next) {
00187
if ((*ht->keyEqualFunction)(entry->key, key)) {
00188 p = entry->value;
00189 entry->key = key;
00190 entry->value = value;
00191
return(p);
00192 }
00193 }
00194
00195
if (ht->count >= ht->threshold) {
00196
00197
00198
00199
00200
00201
rehashHashtable(ht);
00202
return(
hashSet(ht, key, value));
00203 }
00204
00205 entry = (HashtableEntry)memMalloc(
sizeof(
HashtableEntryStruct));
00206 entry->key = key;
00207 entry->value = value;
00208 entry->next = ht->entries[index];
00209 ht->entries[index] = entry;
00210 ht->count++;
00211
return(NULL);
00212 }
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222 Pointer
hashGet(Hashtable ht,
00223 Pointer key)
00224 {
00225 HashtableEntry entry;
00226
int index;
00227
00228
if (ht == NULL || key == NULL) {
00229 fprintf(stderr,
"ERROR: hashGet: arguments must not be NULL\n");
00230 abort();
00231 }
00232
00233 index = (((*ht->hashFunction)(key)) & 0x7fffffff) % ht->capacity;
00234
for (entry = ht->entries[index]; entry != NULL; entry = entry->next) {
00235
if ((*ht->keyEqualFunction)(entry->key, key)) {
00236
return(entry->value);
00237 }
00238 }
00239
00240
return(NULL);
00241 }
00242
00243
00244
00245
00246
00247
00248
00249
00250 Pointer *
hashGetPointerToValue(Hashtable ht, Pointer key)
00251 {
00252 HashtableEntry entry;
00253
int index;
00254
00255
if (ht == NULL || key == NULL) {
00256 fprintf(stderr,
"ERROR: hashGet: arguments must not be NULL\n");
00257 abort();
00258 }
00259
00260 index = (((*ht->hashFunction)(key)) & 0x7fffffff) % ht->capacity;
00261
for (entry = ht->entries[index]; entry != NULL; entry = entry->next) {
00262
if ((*ht->keyEqualFunction)(entry->key, key)) {
00263
return(&entry->value);
00264 }
00265 }
00266
00267
return(NULL);
00268 }
00269
00270
00271
00272
00273
00274
00275
00276
00277 Pointer
hashRemove(Hashtable ht, Pointer key)
00278 {
00279 HashtableEntry entry, prev;
00280
int index;
00281 Pointer value;
00282
00283
if (ht == NULL || key == NULL) {
00284 fprintf(stderr,
"ERROR: hashRemove: arguments must not be NULL\n");
00285 abort();
00286 }
00287
00288 index = (((*ht->hashFunction)(key)) & 0x7fffffff) % ht->capacity;
00289
for (entry = ht->entries[index], prev = NULL;
00290 entry != NULL;
00291 prev = entry, entry = entry->next) {
00292
if ((*ht->keyEqualFunction)(entry->key, key)) {
00293
if (prev != NULL) {
00294 prev->next = entry->next;
00295 }
else {
00296 ht->entries[index] = entry->next;
00297 }
00298 ht->count--;
00299 value = entry->value;
00300 memFree(entry);
00301
return (value);
00302 }
00303 }
00304
return(NULL);
00305 }
00306
00307
00308
00309
00310
00311
00312
00313 int hashSize(Hashtable ht)
00314 {
00315
if (ht == NULL) {
00316 fprintf(stderr,
"ERROR: hashSize: argument must not be NULL\n");
00317 abort();
00318 }
00319
00320
return(ht->count);
00321 }
00322
00323
00324
00325
00326
00327
00328
00329 Boolean
hashIsEmpty(Hashtable ht)
00330 {
00331
if (ht == NULL) {
00332 fprintf(stderr,
"ERROR: hashIsEmpty: argument must not be NULL\n");
00333 abort();
00334 }
00335
00336
return(ht->count == 0 ? TRUE : FALSE);
00337 }
00338
00339
00340
00341
00342
00343
00344
00345
00346 Boolean
hashContainsKey(Hashtable ht, Pointer key)
00347 {
00348 HashtableEntry entry;
00349
int index;
00350
00351
if (ht == NULL || key == NULL) {
00352 fprintf(stderr,
"ERROR: hashConstainsKey: arguments must not be NULL\n");
00353 abort();
00354 }
00355
00356 index = (((*ht->hashFunction)(key)) & 0x7fffffff) % ht->capacity;
00357
for (entry = ht->entries[index]; entry != NULL; entry = entry->next)
00358
if ((*ht->keyEqualFunction)(entry->key, key))
00359
return(TRUE);
00360
00361
return(FALSE);
00362 }
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373 Boolean
hashContainsValue(Hashtable ht, Pointer value)
00374 {
00375 HashtableEntry entry;
00376
int i;
00377
00378
if (ht == NULL || value == NULL) {
00379 fprintf(stderr,
"ERROR: hashConstainsValue: arguments must not be NULL\n");
00380 abort();
00381 }
00382
00383
for (i = 0; i < ht->count; i++)
00384
for (entry = ht->entries[i]; entry != NULL; entry = entry->next)
00385
if (value == entry->value)
00386
return(TRUE);
00387
00388
return(FALSE);
00389 }
00390
00391
00392
00393
00394
00395
00396 void hashDelete(Hashtable ht)
00397 {
00398 HashtableEntry entry, next;
00399
int i;
00400
00401
for (i = 0; i < ht->capacity; i++) {
00402
for (entry = ht->entries[i]; entry != NULL; entry = next) {
00403 next = entry->next;
00404 memFree(entry);
00405 }
00406 }
00407 memFree(ht->entries);
00408 memFree(ht);
00409 }
00410
00411
00412
00413
00414
00415
00416
00417 void hashForEach(Hashtable ht, VoidFunction *f)
00418 {
00419 HashtableEntry entry;
00420
int i;
00421
00422
for (i = 0; i < ht->capacity; i++) {
00423
for (entry = ht->entries[i]; entry != NULL; entry = entry->next) {
00424 (*f)(entry->key, entry->value);
00425 }
00426 }
00427 }
00428
00429
00430
00431
00432
00433
00434
00435 void hashForEachWithData(Hashtable ht, VoidFunction *f, Pointer clientData)
00436 {
00437 HashtableEntry entry;
00438
int i;
00439
00440
for (i = 0; i < ht->capacity; i++) {
00441
for (entry = ht->entries[i]; entry != NULL; entry = entry->next) {
00442 (*f)(entry->key, entry->value, clientData);
00443 }
00444 }
00445 }
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455 void hashForEachFree(Hashtable ht, VoidFunction *f)
00456 {
00457 HashtableEntry entry, next;
00458
int i;
00459
00460
for (i = 0; i < ht->capacity; i++) {
00461
for (entry = ht->entries[i]; entry != NULL; entry = next) {
00462 next = entry->next;
00463 (*f)(entry->key, entry->value);
00464 memFree(entry);
00465 }
00466 }
00467 memFree(ht->entries);
00468 memFree(ht);
00469 }
00470
00471
00472
00473
00474
00475 void hashForEachFreeValue(Hashtable ht, VoidFunction *f)
00476 {
00477 HashtableEntry entry, next;
00478
int i;
00479
00480
for (i = 0; i < ht->capacity; i++) {
00481
for (entry = ht->entries[i]; entry != NULL; entry = next) {
00482 next = entry->next;
00483 (*f)(entry->value);
00484 memFree(entry);
00485 }
00486 }
00487 memFree(ht->entries);
00488 memFree(ht);
00489 }
00490
00491
00492
00493
00494
00495
00496
00497
00498 List
hashListOfKeys(Hashtable ht)
00499 {
00500
int i;
00501 List l = NULL;
00502 HashtableEntry entry;
00503
00504
for (i = 0; i < ht->capacity; i++) {
00505
for (entry = ht->entries[i]; entry != NULL; entry = entry->next) {
00506 l =
listPrependElement(l, entry->key);
00507 }
00508 }
00509
00510
return(l);
00511 }
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528 HashIterator
hashIteratorNew(Hashtable ht)
00529 {
00530 HashIterator hi;
00531
00532
00533 hi = (HashIterator)memMalloc(
sizeof(
HashIteratorStruct));
00534 hi->hashtable = ht;
00535 hi->index = -1;
00536 hi->entry = NULL;
00537
while (!hi->entry && ++hi->index < ht->capacity) {
00538 hi->entry=ht->entries[hi->index];
00539 }
00540
00541
return(hi);
00542 }
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552 Pointer
hashIteratorNextKey(HashIterator hi)
00553 {
00554 HashtableEntry current=hi->entry;
00555 Hashtable ht=hi->hashtable;
00556
00557
if (!current) {
00558
return(NULL);
00559 }
00560
00561 hi->entry = hi->entry->next;
00562
while (!hi->entry && ++hi->index < ht->capacity) {
00563 hi->entry=ht->entries[hi->index];
00564 }
00565
00566
return(current->key);
00567 }
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577 Pointer
hashIteratorNextValue(HashIterator hi)
00578 {
00579 HashtableEntry current;
00580 Hashtable ht = hi->hashtable;
00581
00582
if (NULL == (current = hi->entry)) {
00583
return(NULL);
00584 }
00585
00586
if (NULL == (hi->entry = hi->entry->next)) {
00587
while (++hi->index < ht->capacity) {
00588
00589
if (NULL != (hi->entry = ht->entries[hi->index])) {
00590
return(current->value);
00591 }
00592 }
00593 }
00594
00595
return(current->value);
00596 }
00597
00598
00599
00600
00601
00602
00603 void hashIteratorDelete(HashIterator hi)
00604 {
00605
00606 memFree(hi);
00607 }
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620 int hashStringHashFunction(
char *s)
00621 {
00622
register int len = strlen(s);
00623
register int value;
00624
00625
#if 1
00626
00627 value = len;
00628
while(len)
00629 value = (value << 5) ^ (value >> 27) ^ s[--len];
00630
00631
#else
00632
value = 1;
00633
while(len)
00634 value *= s[--len];
00635
00636
#endif
00637
00638
00639
return (value);
00640 }
00641
00642
00643
00644
00645
00646
00647
00648
00649 int hashStringEqualFunction(
char *s,
char *t)
00650 {
00651
return(strcmp(s, t) == 0);
00652 }
00653
00654
00655