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   return dest;
00084 }
00085 
00086 /** The default hash function.
00087  * This function can be used as the \c hash parameter
00088  * to \c make_hash_table().
00089  *
00090  * @param key The key to be hashed.
00091  * @returns The hash for the key.
00092  */
00093 unsigned int hashtable_default_hash(const char *key) {
00094   unsigned int hash = 0;
00095   unsigned char *p = (unsigned char*) key;
00096 
00097   while(*p) {
00098     hash = (hash * 33) + ((unsigned int) *p);
00099     p++;
00100   }
00101         
00102   return hash;
00103 }
00104 
00105 /** Free all the memory used by a hash table.
00106  * @param table The hash table to be deallocated.
00107  */
00108 void free_hashtable(struct hashtable *table) {
00109   unsigned int i;
00110   struct hashtable_entry *entry;
00111   struct hashtable_entry *next;
00112 
00113   for(i = 0; i < table->nbuckets; i++) {
00114     entry = table->bucket[i];
00115     while(entry) {
00116       next = entry->next;
00117       free(entry);
00118       entry = next;
00119     }
00120   }
00121 
00122   free(table->bucket);
00123   free(table);
00124 }
00125 
00126 /** Call a function for each entry in a hash table.
00127  * @param table The hash table whose entries to iterate over.
00128  * @param func The function to call for each entry.
00129                The function receives two argument:
00130                1. The key of the entry.
00131                2. The value of the entry.
00132  */
00133 void hashtable_iter(const struct hashtable *table,
00134                     void (*func) (char *key, void *value))
00135 {
00136   unsigned int i;
00137   struct hashtable_entry *entry;
00138 
00139   for(i = 0; i < table->nbuckets; i++) {
00140     for(entry = table->bucket[i]; entry; entry = entry->next) {
00141       func(entry->key, entry->value);
00142     }
00143   }
00144 }
00145 
00146 /** Look up the value bound to a key.
00147  * @param table The hash table in which to look up the key.
00148  * @param key The key to look up.
00149  * @return The value belonging to the key if found, NULL if not found.
00150  */
00151 void *hashtable_lookup(const struct hashtable *table,
00152                        const char *key)
00153 {
00154   unsigned int n = compute_hash(table, key);
00155   struct hashtable_entry *entry = table->bucket[n];
00156 
00157   while(entry) {
00158     if(!strcmp(key, entry->key)) break;
00159     entry = entry->next;
00160   }
00161 
00162   return entry ? entry->value : NULL;
00163 }
00164 
00165 /** Create a hash table.
00166  * @param hash The hash function to use with this hash table.
00167                The function has to map NUL-terminated strings to unsigned ints.
00168  * @param nbuckets The number of buckets in the hash table.
00169  * @return The new hash table on success, NULL on failure.
00170  */ 
00171 struct hashtable *make_hashtable(unsigned int (*hash) (const char*),
00172                                  unsigned int nbuckets)
00173 {
00174   struct hashtable *table = NEW(struct hashtable);
00175 
00176   if(table) {
00177     table->bucket = NEWARRAY(struct hashtable_entry*,
00178                              nbuckets);
00179     if(!table->bucket) {
00180       free(table);
00181       return NULL;
00182     }
00183     table->hash = hash;
00184     table->nbuckets = nbuckets;
00185   }
00186 
00187   return table;
00188 }
 All Data Structures Files Functions Variables Defines
Generated on Sun Jul 11 13:37:58 2010 for hashtable by  doxygen 1.6.3