Main Page   Alphabetical List   Compound List   File List   Compound Members   File Members  

epHash.c

Go to the documentation of this file.
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     { /*err_set(errno, SYS_ERROR);*/ } 
00065   else if((hashTable->bucketArray =
00066            (struct epHashElt_s **) malloc(sizeof(struct epHashElt_s *) * 
00067                                           numOfBuckets)) == NULL) 
00068     {
00069       /*err_set(errno, SYS_ERROR); */
00070       free(hashTable);
00071       hashTable = NULL;
00072     } else {
00073       hashTable->numOfBuckets = numOfBuckets<5? 5: numOfBuckets;
00074       hashTable->numOfElements = 0;
00075 
00076       /* par défaut, pas de rehashage automatique décrémentiel */
00077       hashTable->lowerRehashThreshold = _DEFAULT_LowerRehashThreshold;
00078       hashTable->upperRehashThreshold = _DEFAULT_UpperRehashThreshold;
00079       hashTable->idealRatio = _DEFAULT_IdealRatio;
00080 
00081       /* on sait que les 2 1ères fncts ne sont pas nulles(cf 'if')*/
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       /* initialisation de la table de hashage */       
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   /* 1. On supprime tous les couple <clé, valeur> de la table */        
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   /* 2. On libère l'espace mémoire occupé par la table de Hashage */
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;             /* valeur de retour */
00204   struct epHashElt_s *curElt;
00205   uint hashVal;
00206 
00207   _DEBUG("epHash_put call");
00208 
00209   hashVal = (hashTable->hashFunction(key) % hashTable->numOfBuckets);
00210 
00211   /* on vérifie que la clé n'est pas déjà présente dans la table 
00212      de hashage                                                  */
00213   curElt = hashTable->bucketArray[hashVal]; 
00214 
00215   while(curElt != NULL && 
00216         !hashTable->keyComparisonFunction(curElt->key, key))
00217     { curElt = curElt->next; }
00218       
00219   /* on a trouvé la même clé */
00220   if(curElt != NULL)
00221     {
00222       _DEBUG("clé déjà présente");
00223       //err_set(KEY_EXIST, PER_ERROR);                  
00224     } else if((curElt =
00225                (struct epHashElt_s *) malloc(sizeof(struct epHashElt_s))) == 
00226               NULL) {  
00227       //err_set(errno, SYS_ERROR);
00228     } else {
00229       curElt->key = (void *)key;
00230       curElt->value = (void *)value;
00231 
00232       /* le nouvel élément est inséré comme premier élément du bucket 
00233          considéré                                                    */
00234       curElt->next = hashTable->bucketArray[hashVal];
00235       hashTable->bucketArray[hashVal] = curElt;
00236 
00237       hashTable->numOfElements++;
00238 
00239       /* rehashage automatique si autorisé et nécessaire */
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;              /* valeur de retour */
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       //err_set(KEY_NEXIST, PER_ERROR);
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   /* rehashage automatique si autorisé et nécessaire */
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   /* tester tous > à 0 */
00461   hashTable->idealRatio = idealRatio;
00462   hashTable->lowerRehashThreshold = lowerRehashThreshold;
00463   /* tester > à idealRatio */
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; /* make it an odd number */
00494       
00495       while (!epUtils_isProbablePrime(idealNumOfBuckets))
00496         { idealNumOfBuckets += 2; }
00497     }
00498   
00499   return(idealNumOfBuckets);
00500 }
00501 
00502 

Generated at Sun Nov 25 14:05:07 2001 for ExtendedPersonnalLibrary by doxygen1.2.1 written by Dimitri van Heesch, © 1997-2000