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
00084
00085
00086
00087
00088
00089
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
00104
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
00125
00126
00127
00128
00129
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
00145
00146
00147
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
00164
00165
00166
00167
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 }