hashtable.c

Go to the documentation of this file.
00001 #include <stdlib.h>
00002 #include <string.h>
00003 #include "hashtable.h"
00004 
00005 /** \file
00006  * Hashtable implementation internals.
00007  *
00008  * <em>This file contains the full documentation of all functions, types,
00009  * constants, and variables used in the hashtable implementation, including
00010  * those that are intended only for internal use. For the public interface
00011  * to hash tables, see \ref hashtable.h.</em>
00012  */
00013 
00014 /** Allocate memory for some type.
00015  * @param T The type to allocate memory for.
00016  * @return A pointer to the newly allocated storage.
00017  */
00018 #define NEW(T) (T*) malloc(sizeof(T))
00019 
00020 /** Allocate memory for an array.
00021  * @param T The type of the elements of the array.
00022  * @param N The number of elements in the array.
00023  * @return A pointer to the array.
00024  */
00025 #define NEWARRAY(T, N) (T*) calloc((N), sizeof(T))
00026 
00027 /** Hash a key using a table's hash function.
00028  * @param table The table whose hash function to use.
00029  * @param key The key to hash.
00030  * @return The hash of the key, clipped to the number of buckets in the table.
00031  */
00032 static inline unsigned int compute_hash(const struct hashtable *table,
00033                                         const char *key)
00034 {
00035   unsigned int n = table->hash(key);
00036   return (n < table->nbuckets) ? n : (n % table->nbuckets);
00037 }
00038 
00039 /** Add an entry to a hash table.
00040  * @param table The hash table the entry is to be added to.
00041  * @param key The key for the entry.
00042  * @param value The value for the entry.
00043  * @return Nonzero on success, 0 on failure.
00044  */
00045 int hashtable_add(struct hashtable *table, char *key, void *value)
00046 {
00047   unsigned int n;
00048   struct hashtable_entry *entry = NEW(struct hashtable_entry);
00049   struct hashtable_entry *entries;
00050 
00051   if(entry) {
00052     entry->key = key;
00053     entry->value = value;
00054     entry->next = NULL;
00055     n = compute_hash(table, key);
00056     entries = table->bucket[n];
00057     if(!entries) table->bucket[n] = entry;
00058     else {
00059       while(entries->next) entries = entries->next;
00060       entries->next = entry;
00061     }
00062     return 1;
00063   }
00064 
00065   return 0;
00066 }
00067 
00068 /** Insert all elements from one hash table into another.
00069  * @param dest The hash table to insert elements into.
00070  * @param src The hash table whose elements are to be inserted.
00071  * @return \a dest
00072  */
00073 struct hashtable *copy_hashtable(struct hashtable *dest, struct hashtable *src) {
00074   unsigned int i;
00075   struct hashtable_entry *entry;
00076 
00077   for(i = 0; i < src->nbuckets; i++) {
00078     for(entry = src->bucket[i]; entry; entry = entry->next) {
00079       hashtable_add(dest, entry->key, entry->value);
00080     }
00081   }  
00082 }
00083 
00084 /** The default hash function.
00085  * This function can be used as the \c hash parameter
00086  * to \c make_hash_table().
00087  *
00088  * @param key The key to be hashed.
00089  * @returns The hash for the key.
00090  */
00091 unsigned int hashtable_default_hash(const char *key) {
00092   unsigned int hash = 0;
00093   unsigned char *p = (unsigned char*) key;
00094 
00095   while(*p) {
00096     hash = (hash * 33) + ((unsigned int) *p);
00097     p++;
00098   }
00099         
00100   return hash;
00101 }
00102 
00103 /** Free all the memory used by a hash table.
00104  * @param table The hash table to be deallocated.
00105  */
00106 void free_hashtable(struct hashtable *table) {
00107   unsigned int i;
00108   struct hashtable_entry *entry;
00109   struct hashtable_entry *next;
00110 
00111   for(i = 0; i < table->nbuckets; i++) {
00112     entry = table->bucket[i];
00113     while(entry) {
00114       next = entry->next;
00115       free(entry);
00116       entry = next;
00117     }
00118   }
00119 
00120   free(table->bucket);
00121   free(table);
00122 }
00123 
00124 /** Call a function for each entry in a hash table.
00125  * @param table The hash table whose entries to iterate over.
00126  * @param func The function to call for each entry.
00127                The function receives two argument:
00128                1. The key of the entry.
00129                2. The value of the entry.
00130  */
00131 void hashtable_iter(const struct hashtable *table,
00132                     void (*func) (char *key, void *value))
00133 {
00134   unsigned int i;
00135   struct hashtable_entry *entry;
00136 
00137   for(i = 0; i < table->nbuckets; i++) {
00138     for(entry = table->bucket[i]; entry; entry = entry->next) {
00139       func(entry->key, entry->value);
00140     }
00141   }
00142 }
00143 
00144 /** Look up the value bound to a key.
00145  * @param table The hash table in which to look up the key.
00146  * @param key The key to look up.
00147  * @return The value belonging to the key if found, NULL if not found.
00148  */
00149 void *hashtable_lookup(const struct hashtable *table,
00150                        const char *key)
00151 {
00152   unsigned int n = compute_hash(table, key);
00153   struct hashtable_entry *entry = table->bucket[n];
00154 
00155   while(entry) {
00156     if(!strcmp(key, entry->key)) break;
00157     entry = entry->next;
00158   }
00159 
00160   return entry ? entry->value : NULL;
00161 }
00162 
00163 /** Create a hash table.
00164  * @param hash The hash function to use with this hash table.
00165                The function has to map NUL-terminated strings to unsigned ints.
00166  * @param nbuckets The number of buckets in the hash table.
00167  * @return The new hash table on success, NULL on failure.
00168  */ 
00169 struct hashtable *make_hashtable(unsigned int (*hash) (const char*),
00170                                  unsigned int nbuckets)
00171 {
00172   struct hashtable *table = NEW(struct hashtable);
00173 
00174   if(table) {
00175     table->bucket = NEWARRAY(struct hashtable_entry*,
00176                              nbuckets);
00177     if(!table->bucket) {
00178       free(table);
00179       return NULL;
00180     }
00181     table->hash = hash;
00182     table->nbuckets = nbuckets;
00183   }
00184 
00185   return table;
00186 }

Generated on Mon Jul 30 14:58:22 2007 for hashtable by  doxygen 1.5.1