hashtable.c
Go to the documentation of this file.00001 #include <stdlib.h>
00002 #include <string.h>
00003 #include "hashtable.h"
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #define NEW(T) (T*) malloc(sizeof(T))
00019
00020
00021
00022
00023
00024
00025 #define NEWARRAY(T, N) (T*) calloc((N), sizeof(T))
00026
00027
00028
00029
00030
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
00040
00041
00042
00043
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
00069
00070
00071
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
00087
00088
00089
00090
00091
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
00106
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
00127
00128
00129
00130
00131
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
00147
00148
00149
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
00166
00167
00168
00169
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 }