Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals   Examples  

chtbl.c

Go to the documentation of this file.
00001 /*! \file chtbl.c
00002     Hash table implementation
00003  */
00004 
00005 #include <stdlib.h>
00006 #include <string.h>
00007 #include "list.h"
00008 #include "chtbl.h"
00009 
00010 
00011 
00012 /*! \brief Initialize the hash table. This function must be called first.
00013     \param htab Pointer to a hash table data structure.
00014     \param conteneurs Number of linked list in the hash table.
00015     \param h Pointer to the function used to hash the input key.
00016     \param corresp Pointer to the function used to compare user's defined data. This function is specific to the type of data stored into
00017                    the hash table. This function must return if the user defined data are identical, 0 otherwise.
00018     \param detruire Pointer to the function used to free all allocated memory for the user's defined data. This function is specific to the
00019                     type of data stored into the hash table.
00020     \return Upon successful completion the function returns 0, otherwise the function returns 1.
00021  */
00022 
00023 int chtbl_init(
00024                 CHTbl *htab,
00025                 int   conteneurs, 
00026                 int   (*h)(const void *cle), 
00027                 int   (*corresp)(const void *cle1, const void *cle2), 
00028                 void  (*detruire)(void *donnee)
00029               )
00030 {
00031   int  i;
00032 
00033   /* ------------------------------------------------------------------------- */
00034   /* Allocate linked lists for hash table                                      */
00035   /* ------------------------------------------------------------------------- */
00036 
00037   if ((htab->table = (List *)malloc(conteneurs * sizeof(List))) == NULL) { return -1; }
00038 
00039   /* ------------------------------------------------------------------------- */
00040   /* Initialize the linked lists                                               */
00041   /* ------------------------------------------------------------------------- */
00042 
00043   htab->conteneurs = conteneurs;
00044   for (i = 0; i < htab->conteneurs; i++) { list_init(&htab->table[i], detruire, corresp); }
00045 
00046   /* ------------------------------------------------------------------------- */
00047   /* Initialize the hash table                                                 */
00048   /* ------------------------------------------------------------------------- */
00049 
00050   htab->h = h;
00051   htab->corresp = corresp;
00052   htab->detruire = detruire;
00053   htab->taille = 0;
00054 
00055   return 0;
00056 }
00057 
00058 /*! \example test_hash_table.c
00059     This test program shows how to use the hash table's API.
00060  */
00061 
00062 /*! \brief Free all memory allocated for the hash table.
00063     \param htab Pointer to the hash table data structure to destroy.
00064  */
00065 
00066 void chtbl_destroy(CHTbl *htab)
00067 {
00068   int                i;
00069  
00070   /* ------------------------------------------------------------------------- */
00071   /* Delete all linked list                                                    */
00072   /* ------------------------------------------------------------------------- */
00073 
00074   for (i = 0; i < htab->conteneurs; i++) { list_destroy(&htab->table[i]); }
00075 
00076   /* ------------------------------------------------------------------------- */
00077   /* Free all memory used by the hash table data structure                     */
00078   /* ------------------------------------------------------------------------- */
00079 
00080   free(htab->table);
00081 
00082   /* ------------------------------------------------------------------------- */
00083   /* Clean up the structure (just to look better)                              */
00084   /* ------------------------------------------------------------------------- */
00085 
00086   memset(htab, 0, sizeof(CHTbl));
00087 
00088   return;
00089 }
00090 
00091 /*! \example test_hash_table.c
00092     This test program shows how to use the hash table's API.
00093  */
00094 
00095 /*! \brief Insert data into the hash table.
00096     \param htab Pointer to the hash table data structure.
00097     \param donnee Pointer to the user defined data to insert.
00098     \return The function may return one of the following value:
00099             <UL>
00100               <li>0: The data was not in the hash table and it has been successfuly inserted.
00101               <li>1: The data already was in the hash table (this is not an error).
00102               <li>-1: An error occured (this means that the program is running out of memory).
00103             </UL>
00104     \warning Data are <B>NOT</B> copied into the hash table. The hash table only contains pointers to user's data. Therefore you should
00105              not free the memory allocated fot the data yourself.
00106  */
00107 
00108 int chtbl_insert(CHTbl *htab, const void *donnee)
00109 {
00110   void *temp;
00111   int   conteneur, retval;
00112 
00113   /* ------------------------------------------------------------------------- */
00114   /* Make sure that the data is not already into the hash table                */
00115   /* ------------------------------------------------------------------------- */
00116 
00117   temp = (void *)donnee;
00118   if (chtbl_lookup(htab, &temp) == 0) { return 1; }
00119 
00120   /* ------------------------------------------------------------------------- */
00121   /* Hash the input key                                                        */
00122   /* ------------------------------------------------------------------------- */
00123 
00124   conteneur = htab->h(donnee) % htab->conteneurs;
00125 
00126   /* ------------------------------------------------------------------------- */
00127   /* Insert data into the hash table                                           */
00128   /* ------------------------------------------------------------------------- */
00129 
00130   if ((retval = list_ins_next(&htab->table[conteneur], NULL, donnee)) == 0)
00131   { htab->taille++; }
00132 
00133   return retval;
00134 }
00135 
00136 /*! \example test_hash_table.c
00137     This test program shows how to use the hash table's API.
00138  */
00139 
00140 /*! \brief Remove a record from the hash table.
00141     \param htab Pointer to a hash table data structure.
00142     \param donnee Pointer to a data structure pointer that will point to the data of the element that have been removed. Keep in mind that
00143                   the user data is <B>NOT</B> freed by the function chtbl_remove(). You must free it yourself.
00144     \return Upon successful completion the function returns 0, otherwise the function returns -1. Please note that the return value -1
00145             is not really an error. It really means that the data was not found in the hash table.
00146     \warning You must keep in mind that the data section of the removed element is <B>NOT</B> freed by the function. A pointer to the
00147              data section is returned (via <i>donnee</i>). This allows you to free it yourself.
00148  */
00149 
00150 int chtbl_remove(CHTbl *htab, void **donnee)
00151 {
00152   ListElmt           *element, *prec;
00153   int                conteneur;
00154 
00155   /* ------------------------------------------------------------------------- */
00156   /* Hash the input key                                                        */
00157   /* ------------------------------------------------------------------------- */
00158 
00159   conteneur = htab->h(*donnee) % htab->conteneurs;
00160 
00161   /* ------------------------------------------------------------------------- */
00162   /* Search the linked list for the data                                       */
00163   /* ------------------------------------------------------------------------- */
00164 
00165   element = list_find (&htab->table[conteneur], NULL, *donnee, &prec); 
00166   if (element != NULL)
00167   {
00168     /* ----------------------------------------------------------------------- */
00169     /* Data found, remove it                                                   */
00170     /* Note that 'prec' could be NULL, but that's OK.                          */
00171     /* ----------------------------------------------------------------------- */
00172 
00173     if (list_rem_next(&htab->table[conteneur], prec, donnee) == 0)
00174     {
00175       htab->taille--;
00176       return 0;
00177     }
00178   }
00179 
00180   /* ------------------------------------------------------------------------- */
00181   /* The data was not found                                                    */
00182   /* ------------------------------------------------------------------------- */
00183 
00184   return -1;
00185 
00186 }
00187 
00188 /*! \example test_hash_table.c
00189     This test program shows how to use the hash table's API.
00190  */
00191 
00192 /*! \brief Searh the hash table for a given data.
00193     \param htab Pointer to a hash table structure.
00194     \param donnee Pointer to a user defined data. This pointer will be used:
00195                   <UL>
00196                      <li>To specify the data to search for.
00197                      <li>To point to the element's data (that has been found).
00198                   </UL>
00199     \return If the element was in the hash table, that the function returns 0 and <i>donnee</i> points to the element's data. Otherwise, 
00200             the function return -1.
00201  */
00202 
00203 int chtbl_lookup(const CHTbl *htab, void **donnee)
00204 {
00205   ListElmt           *element;
00206   int                conteneur;
00207  
00208   /* ------------------------------------------------------------------------- */
00209   /* Hash the input key                                                        */
00210   /* ------------------------------------------------------------------------- */
00211 
00212   conteneur = htab->h(*donnee) % htab->conteneurs;
00213 
00214   /* ------------------------------------------------------------------------- */
00215   /* Search for the jey in the linked list                                     */
00216   /* ------------------------------------------------------------------------- */
00217 
00218   for (element = list_head(&htab->table[conteneur]); element != NULL; element = list_next(element))
00219   {
00220     if (htab->corresp(*donnee, list_data(element)))
00221     {
00222       /* --------------------------------------------------------------------- */
00223       /* The record has been found                                             */
00224       /* Assign 'donnee' to the element's data.                                */
00225       /* --------------------------------------------------------------------- */
00226 
00227       *donnee = list_data(element);
00228       return 0;
00229     }
00230   }
00231 
00232   /* ------------------------------------------------------------------------- */
00233   /* The data was not found                                                    */
00234   /* ------------------------------------------------------------------------- */
00235 
00236   return -1;
00237 }
00238 
00239 /*! \example test_hash_table.c
00240     This test program shows how to use the hash table's API.
00241  */
00242 
00243 /*! \brief Cover the entire hash table in search for an given element.
00244     \param htab Pointer to a hash table structure.
00245     \param donnee Pointer to a user defined data. This pointer will be used:
00246                   <UL>
00247                      <li>To specify the data to search for.
00248                      <li>To point to the element's data (that has been found).
00249                   </UL>
00250     \return If the element was in the hash table, that the function returns 0 and <i>donnee</i> points to the element's data. Otherwise, the function return -1.
00251     \warning This function lookup compare each element in the hash table with a given element (<i>donnee</i>).
00252              It may take long ... do not use it if you don't have to!
00253  */
00254 
00255 int chtbl_find (const CHTbl *htab, void **donnee)
00256 {
00257   int       ht;
00258   List      *linked_list;
00259   ListElmt  *element;
00260 
00261   /* ------------------------------------------------------------------------- */
00262   /* For each linked list, look for the data                                   */
00263   /* ------------------------------------------------------------------------- */
00264 
00265   for (ht=0; ht<htab->conteneurs; ht++)
00266   {
00267     linked_list = &(htab->table[ht]);
00268     element     = list_head (linked_list);
00269 
00270     while (element != NULL)
00271     {
00272       if (htab->corresp(list_data(element), *donnee))
00273       {
00274         *donnee = list_data(element);
00275         return 0;
00276       }
00277       element = list_next(element);
00278     }
00279   }
00280 
00281   return -1;
00282 }
00283 
00284 /*! \example test_hash_table.c
00285     This test program shows how to use the hash table's API.
00286  */
00287 
00288 /*! \brief Returns the next element of a given linked list.
00289     \param htab Pointer to a hash table structure.
00290     \param rewind Flag used to set the hash pointer to the first element of the hash. The value of this
00291                   parameter can be:
00292                   <UL>
00293                      <LI>REWIND_HASH: Set the hash pointer to the first element of the hash. 
00294                      <LI>CURRENT_HASH: Set the hash pointer to the current element in the hash. 
00295                   </UL>
00296     \return The function returns a pointer to the current element in the hash, or NULL if the current element
00297             is the last one.
00298     \warning Each time you call the function, it returns the next element in the hash (until the last one where
00299              the function returns NULL).
00300              <UL>
00301                 <LI>When you <B>start walking</B> through a hash table, you <B>must</B> set the parameter
00302                     <I>rewind</I> to the value REWIND_HASH !. If you don't do that, the baheviour of the function
00303                     is unpredictable. You may generate a segmentation fault.
00304                 <LI>Do <B>NOT</B> modify (add or remove elements) the hash while you are walking
00305                     through it! If you don't do that, the baheviour of the function is unpredictable.
00306                     You may generate a segmentation fault.
00307              </UL>
00308  */
00309 
00310 void* chtbl_next (CHTbl *htab, int rewind)
00311 {
00312   List      *linked_list;
00313   ListElmt  *element;
00314 
00315   /* ------------------------------------------------------------------------- */
00316   /* Set the hash pointer to the first element if necessary                    */
00317   /* ------------------------------------------------------------------------- */
00318 
00319   if (rewind == REWIND_HASH)
00320   {
00321     linked_list = &(htab->table[0]);
00322     (htab->pointer).current_list    = 0;
00323     (htab->pointer).current_element = list_head(linked_list);
00324   }
00325   else
00326   {
00327     linked_list = &(htab->table[(htab->pointer).current_list]);
00328   } 
00329 
00330   /* ------------------------------------------------------------------------- */
00331   /* Find the next element                                                     */
00332   /* ------------------------------------------------------------------------- */
00333 
00334   while ((htab->pointer).current_element == NULL)
00335   {
00336     /* ----------------------------------------------------------------------- */
00337     /* Go to the next linked list                                              */
00338     /* ----------------------------------------------------------------------- */
00339 
00340     (htab->pointer).current_list += 1;
00341     if ((htab->pointer).current_list >= htab->conteneurs) { return NULL; }
00342 
00343     linked_list = &(htab->table[(htab->pointer).current_list]);
00344     (htab->pointer).current_element = list_head(linked_list);
00345   }
00346 
00347   element = (htab->pointer).current_element;
00348 
00349   (htab->pointer).current_element = list_next(element);
00350 
00351   return list_data(element);
00352 }
00353 
00354 /*! \example test_hash_table.c
00355     This test program shows how to use the hash table's API.
00356  */
00357 
00358 

Generated on Thu Apr 3 16:23:42 2003 for Common_C_libraries by doxygen1.3-rc1