00001
00020 #include <stdio.h>
00021 #include <stdlib.h>
00022 #include <string.h>
00023 #include "epDefs.h"
00024 #include "epUtils.h"
00025 #include "epHash.h"
00026
00050 epHash_t *epHash_create(const ulong numOfBuckets,
00051 boolean_t (*keyComparisonFunction)(const void *key1, const void *key2),
00052 uint (*hashFunction)(const void *key),
00053 int (*keyDeallocatorFunction)(void *key),
00054 int (*valueDeallocatorFunction)(void *value))
00055 {
00056 epHash_t *hashTable;
00057 int i;
00058
00059 _DEBUG("epHash_create call");
00060
00061 if(keyComparisonFunction == NULL || hashFunction == NULL)
00062 { }
00063 else if((hashTable =(epHash_t *) malloc(sizeof(epHash_t))) == NULL)
00064 { }
00065 else if((hashTable->bucketArray =
00066 (struct epHashElt_s **) malloc(sizeof(struct epHashElt_s *) *
00067 numOfBuckets)) == NULL)
00068 {
00069
00070 free(hashTable);
00071 hashTable = NULL;
00072 } else {
00073 hashTable->numOfBuckets = numOfBuckets<5? 5: numOfBuckets;
00074 hashTable->numOfElements = 0;
00075
00076
00077 hashTable->lowerRehashThreshold = _DEFAULT_LowerRehashThreshold;
00078 hashTable->upperRehashThreshold = _DEFAULT_UpperRehashThreshold;
00079 hashTable->idealRatio = _DEFAULT_IdealRatio;
00080
00081
00082 hashTable->keyComparisonFunction = keyComparisonFunction;
00083 hashTable->hashFunction = hashFunction;
00084 hashTable->keyDeallocatorFunction = (keyDeallocatorFunction != NULL?
00085 keyDeallocatorFunction:
00086 epUtils_ptrDeallocatorFunction);
00087 hashTable->valueDeallocatorFunction = (valueDeallocatorFunction != NULL?
00088 valueDeallocatorFunction:
00089 epUtils_ptrDeallocatorFunction);
00090
00091
00092 for(i = 0; i < numOfBuckets; i++) {
00093 hashTable->bucketArray[i] = NULL;
00094 }
00095 }
00096
00097 return(hashTable);
00098 }
00099
00109 int epHash_destroy(epHash_t *hashTable)
00110 {
00111 int i;
00112 struct epHashElt_s *curElt,
00113 *nextElt;
00114
00115 _DEBUG("epHash_destroy call");
00116
00117
00118 for(i = 0; i < hashTable->numOfBuckets; i++)
00119 {
00120 curElt = hashTable->bucketArray[i];
00121
00122 while(curElt != NULL)
00123 {
00124 nextElt = curElt->next;
00125
00126 (void) hashTable->keyDeallocatorFunction(curElt->key);
00127 (void) hashTable->valueDeallocatorFunction(curElt->value);
00128 free(curElt);
00129
00130 curElt = nextElt;
00131 }
00132 }
00133
00134
00135 free(hashTable->bucketArray);
00136 free(hashTable);
00137
00138 return(0);
00139 }
00140
00149 uint epHash_size(epHash_t *hashTable)
00150 {
00151 _DEBUG("epHash_size call");
00152 return(hashTable->numOfElements);
00153 }
00154
00164 boolean_t epHash_isEmpty(epHash_t *hashTable)
00165 {
00166 _DEBUG("epHash_isEmpty call");
00167 return(hashTable->numOfElements == 0? _true: _false);
00168 }
00169
00178 uint epHash_getNumOfBuckets(epHash_t *hashTable)
00179 {
00180 _DEBUG("epHash_getNumOfBuckets call");
00181 return(hashTable->numOfBuckets);
00182 }
00183
00201 int epHash_put(epHash_t *hashTable, const void *key, const void *value)
00202 {
00203 int retVal = -1;
00204 struct epHashElt_s *curElt;
00205 uint hashVal;
00206
00207 _DEBUG("epHash_put call");
00208
00209 hashVal = (hashTable->hashFunction(key) % hashTable->numOfBuckets);
00210
00211 00212
00213 curElt = hashTable->bucketArray[hashVal];
00214
00215 while(curElt != NULL &&
00216 !hashTable->keyComparisonFunction(curElt->key, key))
00217 { curElt = curElt->next; }
00218
00219
00220 if(curElt != NULL)
00221 {
00222 _DEBUG("clé déjà présente");
00223
00224 } else if((curElt =
00225 (struct epHashElt_s *) malloc(sizeof(struct epHashElt_s))) ==
00226 NULL) {
00227
00228 } else {
00229 curElt->key = (void *)key;
00230 curElt->value = (void *)value;
00231
00232 00233
00234 curElt->next = hashTable->bucketArray[hashVal];
00235 hashTable->bucketArray[hashVal] = curElt;
00236
00237 hashTable->numOfElements++;
00238
00239
00240 if(HAS_TO_BE_REHASHED(hashTable))
00241 { epHash_rehash(hashTable, 0); }
00242
00243 retVal = 0;
00244 }
00245
00246 return(retVal);
00247 }
00248
00258 void *epHash_get(const epHash_t *hashTable, const void *key)
00259 {
00260 void *value;
00261 struct epHashElt_s *curElt;
00262 uint hashVal;
00263
00264 _DEBUG("epHash_get call");
00265
00266 hashVal = hashTable->hashFunction(key) % hashTable->numOfBuckets;
00267
00268 curElt = hashTable->bucketArray[hashVal];
00269 while(curElt != NULL &&
00270 !hashTable->keyComparisonFunction(curElt->key, key))
00271 { curElt = curElt->next; }
00272
00273 if(curElt == NULL)
00274 {
00275
00276 value = NULL;
00277 }
00278 else
00279 { value = curElt->value; }
00280
00281 return(value);
00282 }
00283
00300 int epHash_remove(epHash_t *hashTable, const void *key)
00301 {
00302 struct epHashElt_s *curElt,
00303 *prevElt;
00304 uint hashVal;
00305
00306 _DEBUG("epHash_remove call");
00307
00308 hashVal = hashTable->hashFunction(key) % hashTable->numOfBuckets;
00309
00310 curElt = hashTable->bucketArray[hashVal];
00311 prevElt = NULL;
00312
00313 while(curElt != NULL &&
00314 !hashTable->keyComparisonFunction(curElt->key, key))
00315 {
00316 prevElt = curElt;
00317 curElt = curElt->next;
00318 }
00319
00320 if(curElt != NULL)
00321 {
00322 hashTable->keyDeallocatorFunction(curElt->key);
00323 hashTable->valueDeallocatorFunction(curElt->value);
00324
00325 if(prevElt == NULL)
00326 { hashTable->bucketArray[hashVal] = curElt->next; }
00327 else
00328 { prevElt->next = curElt->next; }
00329
00330 free(curElt);
00331 hashTable->numOfElements--;
00332 }
00333
00334
00335 if(HAS_TO_BE_REHASHED(hashTable))
00336 { epHash_rehash(hashTable, 0); }
00337
00338 return(0);
00339 }
00340
00351 boolean_t epHash_containsKey(epHash_t *hashTable, const void *key)
00352 {
00353 _DEBUG("epHash_containsKey call");
00354 return(epHash_get(hashTable, key) != NULL? _true: _false);
00355 }
00356
00374 int epHash_rehash(epHash_t *hashTable, uint numOfBuckets)
00375 {
00376 int i;
00377 uint hashVal;
00378 struct epHashElt_s **newBucketArray,
00379 *curElt,
00380 *nextElt;
00381
00382 _DEBUG("epHash_rehash call");
00383
00384 if(numOfBuckets == 0)
00385 { numOfBuckets = calculateIdealNumOfBuckets(hashTable); }
00386 else if(numOfBuckets < 5)
00387 { numOfBuckets = 5; }
00388
00389 if(numOfBuckets != hashTable->numOfBuckets)
00390 {
00391 if((newBucketArray =
00392 (struct epHashElt_s **) malloc(sizeof(struct epHashElt_s *) *
00393 numOfBuckets)) != NULL)
00394 {
00395 for(i = 0; i < numOfBuckets; newBucketArray[i] = NULL, i++);
00396
00397 for(i = 0; i < hashTable->numOfBuckets; i++)
00398 {
00399 curElt = hashTable->bucketArray[i];
00400
00401 while(curElt != NULL)
00402 {
00403 nextElt = curElt->next;
00404 hashVal = hashTable->hashFunction(curElt->key) %
00405 numOfBuckets;
00406
00407 curElt->next = newBucketArray[hashVal];
00408 newBucketArray[hashVal] = curElt;
00409 curElt = nextElt;
00410 }
00411 }
00412
00413 free(hashTable->bucketArray);
00414 hashTable->bucketArray = newBucketArray;
00415 hashTable->numOfBuckets = numOfBuckets;
00416 }
00417 }
00418
00419 return(0);
00420 }
00421
00454 void epHash_setIdealRatio(epHash_t *hashTable, double idealRatio,
00455 double lowerRehashThreshold,
00456 double upperRehashThreshold)
00457 {
00458 _DEBUG("epHash_setIdealRatio call");
00459
00460
00461 hashTable->idealRatio = idealRatio;
00462 hashTable->lowerRehashThreshold = lowerRehashThreshold;
00463
00464 hashTable->upperRehashThreshold = upperRehashThreshold;
00465 }
00466
00480 uint calculateIdealNumOfBuckets(const epHash_t *hashTable)
00481 {
00482 uint idealNumOfBuckets;
00483
00484 _DEBUG("calculateIdealNumOfBuckets call");
00485
00486 idealNumOfBuckets =(uint) (hashTable->numOfElements /
00487 hashTable->idealRatio);
00488
00489 if(idealNumOfBuckets < 5)
00490 { idealNumOfBuckets = 5; }
00491 else
00492 {
00493 idealNumOfBuckets |= 0x01;
00494
00495 while (!epUtils_isProbablePrime(idealNumOfBuckets))
00496 { idealNumOfBuckets += 2; }
00497 }
00498
00499 return(idealNumOfBuckets);
00500 }
00501
00502