00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "setup.h"
00025
00026 #include <string.h>
00027 #include <stdlib.h>
00028
00029 #include "hash.h"
00030 #include "llist.h"
00031 #include "memory.h"
00032
00033
00034 #include "memdebug.h"
00035
00036 static void
00037 hash_element_dtor(void *user, void *element)
00038 {
00039 struct curl_hash *h = (struct curl_hash *) user;
00040 struct curl_hash_element *e = (struct curl_hash_element *) element;
00041
00042 if (e->key)
00043 free(e->key);
00044
00045 h->dtor(e->ptr);
00046
00047 free(e);
00048 }
00049
00050
00051 int
00052 Curl_hash_init(struct curl_hash *h,
00053 int slots,
00054 hash_function hfunc,
00055 comp_function comparator,
00056 curl_hash_dtor dtor)
00057 {
00058 int i;
00059
00060 if (!slots || !hfunc || !comparator ||!dtor) {
00061 return 1;
00062 }
00063
00064 h->hash_func = hfunc;
00065 h->comp_func = comparator;
00066 h->dtor = dtor;
00067 h->size = 0;
00068 h->slots = slots;
00069
00070 h->table = (struct curl_llist **) malloc(slots * sizeof(struct curl_llist *));
00071 if(h->table) {
00072 for (i = 0; i < slots; ++i) {
00073 h->table[i] = Curl_llist_alloc((curl_llist_dtor) hash_element_dtor);
00074 if(!h->table[i]) {
00075 while(i--)
00076 Curl_llist_destroy(h->table[i], NULL);
00077 free(h->table);
00078 return 1;
00079 }
00080 }
00081 return 0;
00082 }
00083 else
00084 return 1;
00085 }
00086
00087 struct curl_hash *
00088 Curl_hash_alloc(int slots,
00089 hash_function hfunc,
00090 comp_function comparator,
00091 curl_hash_dtor dtor)
00092 {
00093 struct curl_hash *h;
00094
00095 if (!slots || !hfunc || !comparator ||!dtor) {
00096 return NULL;
00097 }
00098
00099 h = (struct curl_hash *) malloc(sizeof(struct curl_hash));
00100 if (h) {
00101 if(Curl_hash_init(h, slots, hfunc, comparator, dtor)) {
00102
00103 free(h);
00104 h = NULL;
00105 }
00106 }
00107
00108 return h;
00109 }
00110
00111
00112
00113 static struct curl_hash_element *
00114 mk_hash_element(void *key, size_t key_len, const void *p)
00115 {
00116 struct curl_hash_element *he =
00117 (struct curl_hash_element *) malloc(sizeof(struct curl_hash_element));
00118
00119 if(he) {
00120 void *dup = malloc(key_len);
00121 if(dup) {
00122
00123 memcpy(dup, key, key_len);
00124
00125 he->key = dup;
00126 he->key_len = key_len;
00127 he->ptr = (void *) p;
00128 }
00129 else {
00130
00131 free(he);
00132 he = NULL;
00133 }
00134 }
00135 return he;
00136 }
00137
00138 #define FETCH_LIST(x,y,z) x->table[x->hash_func(y, z, x->slots)]
00139
00140
00141
00142 void *
00143 Curl_hash_add(struct curl_hash *h, void *key, size_t key_len, void *p)
00144 {
00145 struct curl_hash_element *he;
00146 struct curl_llist_element *le;
00147 struct curl_llist *l = FETCH_LIST (h, key, key_len);
00148
00149 for (le = l->head; le; le = le->next) {
00150 he = (struct curl_hash_element *) le->ptr;
00151 if (h->comp_func(he->key, he->key_len, key, key_len)) {
00152 h->dtor(p);
00153 return he->ptr;
00154 }
00155 }
00156
00157 he = mk_hash_element(key, key_len, p);
00158 if (he) {
00159 if(Curl_llist_insert_next(l, l->tail, he)) {
00160 ++h->size;
00161 return p;
00162 }
00163
00164
00165
00166
00167
00168
00169 free(he->key);
00170 free(he);
00171 }
00172
00173 return NULL;
00174 }
00175
00176
00177 int Curl_hash_delete(struct curl_hash *h, void *key, size_t key_len)
00178 {
00179 struct curl_llist_element *le;
00180 struct curl_hash_element *he;
00181 struct curl_llist *l = FETCH_LIST(h, key, key_len);
00182
00183 for (le = l->head; le; le = le->next) {
00184 he = le->ptr;
00185 if (h->comp_func(he->key, he->key_len, key, key_len)) {
00186 Curl_llist_remove(l, le, (void *) h);
00187 return 0;
00188 }
00189 }
00190 return 1;
00191 }
00192
00193 void *
00194 Curl_hash_pick(struct curl_hash *h, void *key, size_t key_len)
00195 {
00196 struct curl_llist_element *le;
00197 struct curl_hash_element *he;
00198 struct curl_llist *l = FETCH_LIST(h, key, key_len);
00199
00200 for (le = l->head; le; le = le->next) {
00201 he = le->ptr;
00202 if (h->comp_func(he->key, he->key_len, key, key_len)) {
00203 return he->ptr;
00204 }
00205 }
00206
00207 return NULL;
00208 }
00209
00210 #if defined(CURLDEBUG) && defined(AGGRESIVE_TEST)
00211 void
00212 Curl_hash_apply(curl_hash *h, void *user,
00213 void (*cb)(void *user, void *ptr))
00214 {
00215 struct curl_llist_element *le;
00216 int i;
00217
00218 for (i = 0; i < h->slots; ++i) {
00219 for (le = (h->table[i])->head;
00220 le;
00221 le = le->next) {
00222 curl_hash_element *el = le->ptr;
00223 cb(user, el->ptr);
00224 }
00225 }
00226 }
00227 #endif
00228
00229 void
00230 Curl_hash_clean(struct curl_hash *h)
00231 {
00232 int i;
00233
00234 for (i = 0; i < h->slots; ++i) {
00235 Curl_llist_destroy(h->table[i], (void *) h);
00236 }
00237
00238 free(h->table);
00239 }
00240
00241 void
00242 Curl_hash_clean_with_criterium(struct curl_hash *h, void *user,
00243 int (*comp)(void *, void *))
00244 {
00245 struct curl_llist_element *le;
00246 struct curl_llist_element *lnext;
00247 struct curl_llist *list;
00248 int i;
00249
00250 for (i = 0; i < h->slots; ++i) {
00251 list = h->table[i];
00252 le = list->head;
00253 while(le) {
00254 struct curl_hash_element *he = le->ptr;
00255 lnext = le->next;
00256
00257 if (comp(user, he->ptr)) {
00258 Curl_llist_remove(list, le, (void *) h);
00259 --h->size;
00260 }
00261 le = lnext;
00262 }
00263 }
00264 }
00265
00266 void
00267 Curl_hash_destroy(struct curl_hash *h)
00268 {
00269 if (!h)
00270 return;
00271
00272 Curl_hash_clean(h);
00273 free(h);
00274 }
00275
00276 size_t Curl_hash_str(void* key, size_t key_length, size_t slots_num)
00277 {
00278 char* key_str = (char *) key;
00279 char *end = (char *) key_str + key_length;
00280 unsigned long h = 5381;
00281
00282 while (key_str < end) {
00283 h += h << 5;
00284 h ^= (unsigned long) *key_str++;
00285 }
00286
00287 return (h % slots_num);
00288 }
00289
00290 size_t Curl_str_key_compare(void*k1, size_t key1_len, void*k2, size_t key2_len)
00291 {
00292 char *key1 = (char *)k1;
00293 char *key2 = (char *)k2;
00294
00295 if (key1_len == key2_len &&
00296 *key1 == *key2 &&
00297 memcmp(key1, key2, key1_len) == 0) {
00298 return 1;
00299 }
00300
00301 return 0;
00302 }
00303
00304 #if 0
00305 void Curl_hash_print(struct curl_hash *h,
00306 void (*func)(void *))
00307 {
00308 int i;
00309 struct curl_llist_element *le;
00310 struct curl_llist *list;
00311 struct curl_hash_element *he;
00312 if (!h)
00313 return;
00314
00315 fprintf(stderr, "=Hash dump=\n");
00316
00317 for (i = 0; i < h->slots; i++) {
00318 list = h->table[i];
00319 le = list->head;
00320 if(le) {
00321 fprintf(stderr, "index %d:", i);
00322 while(le) {
00323 he = le->ptr;
00324 if(func)
00325 func(he->ptr);
00326 else
00327 fprintf(stderr, " [%p]", he->ptr);
00328 le = le->next;
00329 }
00330 fprintf(stderr, "\n");
00331 }
00332 }
00333 }
00334 #endif