Resync
[CMakeLuaTailorHgBridge.git] / CMakeLua / Utilities / cmcurl-7.19.0 / lib / hash.c
blob07790523491e37f8fb2a9e6338112a3c412197d6
1 /***************************************************************************
2 * _ _ ____ _
3 * Project ___| | | | _ \| |
4 * / __| | | | |_) | |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
10 * This software is licensed as described in the file COPYING, which
11 * you should have received as part of this distribution. The terms
12 * are also available at http://curl.haxx.se/docs/copyright.html.
14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15 * copies of the Software, and permit persons to whom the Software is
16 * furnished to do so, under the terms of the COPYING file.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
21 * $Id: hash.c,v 1.1.1.1 2008-09-23 16:32:05 hoffman Exp $
22 ***************************************************************************/
24 #include "setup.h"
26 #include <string.h>
27 #include <stdlib.h>
29 #include "hash.h"
30 #include "llist.h"
31 #include "memory.h"
33 /* this must be the last include file */
34 #include "memdebug.h"
36 static void
37 hash_element_dtor(void *user, void *element)
39 struct curl_hash *h = (struct curl_hash *) user;
40 struct curl_hash_element *e = (struct curl_hash_element *) element;
42 if(e->key)
43 free(e->key);
45 h->dtor(e->ptr);
47 free(e);
50 /* return 1 on error, 0 is fine */
51 int
52 Curl_hash_init(struct curl_hash *h,
53 int slots,
54 hash_function hfunc,
55 comp_function comparator,
56 curl_hash_dtor dtor)
58 int i;
60 if(!slots || !hfunc || !comparator ||!dtor) {
61 return 1; /* failure */
64 h->hash_func = hfunc;
65 h->comp_func = comparator;
66 h->dtor = dtor;
67 h->size = 0;
68 h->slots = slots;
70 h->table = (struct curl_llist **) malloc(slots * sizeof(struct curl_llist *));
71 if(h->table) {
72 for (i = 0; i < slots; ++i) {
73 h->table[i] = Curl_llist_alloc((curl_llist_dtor) hash_element_dtor);
74 if(!h->table[i]) {
75 while(i--)
76 Curl_llist_destroy(h->table[i], NULL);
77 free(h->table);
78 return 1; /* failure */
81 return 0; /* fine */
83 else
84 return 1; /* failure */
87 struct curl_hash *
88 Curl_hash_alloc(int slots,
89 hash_function hfunc,
90 comp_function comparator,
91 curl_hash_dtor dtor)
93 struct curl_hash *h;
95 if(!slots || !hfunc || !comparator ||!dtor) {
96 return NULL; /* failure */
99 h = (struct curl_hash *) malloc(sizeof(struct curl_hash));
100 if(h) {
101 if(Curl_hash_init(h, slots, hfunc, comparator, dtor)) {
102 /* failure */
103 free(h);
104 h = NULL;
108 return h;
113 static struct curl_hash_element *
114 mk_hash_element(const void *key, size_t key_len, const void *p)
116 struct curl_hash_element *he =
117 (struct curl_hash_element *) malloc(sizeof(struct curl_hash_element));
119 if(he) {
120 void *dupkey = malloc(key_len);
121 if(dupkey) {
122 /* copy the key */
123 memcpy(dupkey, key, key_len);
125 he->key = dupkey;
126 he->key_len = key_len;
127 he->ptr = (void *) p;
129 else {
130 /* failed to duplicate the key, free memory and fail */
131 free(he);
132 he = NULL;
135 return he;
138 #define FETCH_LIST(x,y,z) x->table[x->hash_func(y, z, x->slots)]
140 /* Return the data in the hash. If there already was a match in the hash,
141 that data is returned. */
142 void *
143 Curl_hash_add(struct curl_hash *h, void *key, size_t key_len, void *p)
145 struct curl_hash_element *he;
146 struct curl_llist_element *le;
147 struct curl_llist *l = FETCH_LIST (h, key, key_len);
149 for (le = l->head; le; le = le->next) {
150 he = (struct curl_hash_element *) le->ptr;
151 if(h->comp_func(he->key, he->key_len, key, key_len)) {
152 h->dtor(p); /* remove the NEW entry */
153 return he->ptr; /* return the EXISTING entry */
157 he = mk_hash_element(key, key_len, p);
158 if(he) {
159 if(Curl_llist_insert_next(l, l->tail, he)) {
160 ++h->size;
161 return p; /* return the new entry */
164 * Couldn't insert it, destroy the 'he' element and the key again. We
165 * don't call hash_element_dtor() since that would also call the
166 * "destructor" for the actual data 'p'. When we fail, we shall not touch
167 * that data.
169 free(he->key);
170 free(he);
173 return NULL; /* failure */
176 /* remove the identified hash entry, returns non-zero on failure */
177 int Curl_hash_delete(struct curl_hash *h, void *key, size_t key_len)
179 struct curl_llist_element *le;
180 struct curl_hash_element *he;
181 struct curl_llist *l = FETCH_LIST(h, key, key_len);
183 for (le = l->head; le; le = le->next) {
184 he = le->ptr;
185 if(h->comp_func(he->key, he->key_len, key, key_len)) {
186 Curl_llist_remove(l, le, (void *) h);
187 return 0;
190 return 1;
193 void *
194 Curl_hash_pick(struct curl_hash *h, void *key, size_t key_len)
196 struct curl_llist_element *le;
197 struct curl_hash_element *he;
198 struct curl_llist *l = FETCH_LIST(h, key, key_len);
200 for (le = l->head; le; le = le->next) {
201 he = le->ptr;
202 if(h->comp_func(he->key, he->key_len, key, key_len)) {
203 return he->ptr;
207 return NULL;
210 #if defined(CURLDEBUG) && defined(AGGRESIVE_TEST)
211 void
212 Curl_hash_apply(curl_hash *h, void *user,
213 void (*cb)(void *user, void *ptr))
215 struct curl_llist_element *le;
216 int i;
218 for (i = 0; i < h->slots; ++i) {
219 for (le = (h->table[i])->head;
221 le = le->next) {
222 curl_hash_element *el = le->ptr;
223 cb(user, el->ptr);
227 #endif
229 void
230 Curl_hash_clean(struct curl_hash *h)
232 int i;
234 for (i = 0; i < h->slots; ++i) {
235 Curl_llist_destroy(h->table[i], (void *) h);
238 free(h->table);
241 void
242 Curl_hash_clean_with_criterium(struct curl_hash *h, void *user,
243 int (*comp)(void *, void *))
245 struct curl_llist_element *le;
246 struct curl_llist_element *lnext;
247 struct curl_llist *list;
248 int i;
250 for (i = 0; i < h->slots; ++i) {
251 list = h->table[i];
252 le = list->head; /* get first list entry */
253 while(le) {
254 struct curl_hash_element *he = le->ptr;
255 lnext = le->next;
256 /* ask the callback function if we shall remove this entry or not */
257 if(comp(user, he->ptr)) {
258 Curl_llist_remove(list, le, (void *) h);
259 --h->size; /* one less entry in the hash now */
261 le = lnext;
266 void
267 Curl_hash_destroy(struct curl_hash *h)
269 if(!h)
270 return;
272 Curl_hash_clean(h);
273 free(h);
276 size_t Curl_hash_str(void* key, size_t key_length, size_t slots_num)
278 const char* key_str = (const char *) key;
279 const char *end = key_str + key_length;
280 unsigned long h = 5381;
282 while(key_str < end) {
283 h += h << 5;
284 h ^= (unsigned long) *key_str++;
287 return (h % slots_num);
290 size_t Curl_str_key_compare(void*k1, size_t key1_len, void*k2, size_t key2_len)
292 char *key1 = (char *)k1;
293 char *key2 = (char *)k2;
295 if(key1_len == key2_len &&
296 *key1 == *key2 &&
297 memcmp(key1, key2, key1_len) == 0) {
298 return 1;
301 return 0;
304 #if 0 /* useful function for debugging hashes and their contents */
305 void Curl_hash_print(struct curl_hash *h,
306 void (*func)(void *))
308 int i;
309 struct curl_llist_element *le;
310 struct curl_llist *list;
311 struct curl_hash_element *he;
312 if(!h)
313 return;
315 fprintf(stderr, "=Hash dump=\n");
317 for (i = 0; i < h->slots; i++) {
318 list = h->table[i];
319 le = list->head; /* get first list entry */
320 if(le) {
321 fprintf(stderr, "index %d:", i);
322 while(le) {
323 he = le->ptr;
324 if(func)
325 func(he->ptr);
326 else
327 fprintf(stderr, " [%p]", he->ptr);
328 le = le->next;
330 fprintf(stderr, "\n");
334 #endif