diff options
Diffstat (limited to 'Source/CTest/Curl/hash.c')
-rw-r--r-- | Source/CTest/Curl/hash.c | 263 |
1 files changed, 111 insertions, 152 deletions
diff --git a/Source/CTest/Curl/hash.c b/Source/CTest/Curl/hash.c index 6d4ce2e..be841b3 100644 --- a/Source/CTest/Curl/hash.c +++ b/Source/CTest/Curl/hash.c @@ -1,16 +1,16 @@ /*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms * are also available at http://curl.haxx.se/docs/copyright.html. - * + * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is * furnished to do so, under the terms of the COPYING file. @@ -28,17 +28,13 @@ #include "hash.h" #include "llist.h" +#include "memory.h" -#ifdef MALLOCDEBUG /* this must be the last include file */ #include "memdebug.h" -#endif - -/* {{{ static unsigned long _hash_str (const char *, size_t) - */ static unsigned long -_hash_str (const char *key, size_t key_length) +hash_str(const char *key, size_t key_length) { char *end = (char *) key + key_length; unsigned long h = 5381; @@ -50,12 +46,9 @@ _hash_str (const char *key, size_t key_length) return h; } -/* }}} */ -/* {{{ static void _hash_element_dtor (void *, void *) - */ -static void -_hash_element_dtor (void *user, void *element) +static void +hash_element_dtor(void *user, void *element) { curl_hash *h = (curl_hash *) user; curl_hash_element *e = (curl_hash_element *) element; @@ -68,49 +61,55 @@ _hash_element_dtor (void *user, void *element) free(e); } -/* }}} */ -/* {{{ void curl_hash_init (curl_hash *, int, curl_hash_dtor) - */ -void -Curl_hash_init (curl_hash *h, int slots, curl_hash_dtor dtor) +/* return 1 on error, 0 is fine */ +int +Curl_hash_init(curl_hash *h, int slots, curl_hash_dtor dtor) { int i; h->dtor = dtor; h->size = 0; - h->slots = slots; + h->slots = slots; h->table = (curl_llist **) malloc(slots * sizeof(curl_llist *)); - for (i = 0; i < slots; ++i) { - h->table[i] = Curl_llist_alloc((curl_llist_dtor) _hash_element_dtor); + if(h->table) { + for (i = 0; i < slots; ++i) { + h->table[i] = Curl_llist_alloc((curl_llist_dtor) hash_element_dtor); + if(!h->table[i]) { + while(i--) + Curl_llist_destroy(h->table[i], NULL); + free(h->table); + return 1; /* failure */ + } + } + return 0; /* fine */ } + else + return 1; /* failure */ } -/* }}} */ -/* {{{ curl_hash *curl_hash_alloc (int, curl_hash_dtor) - */ curl_hash * -Curl_hash_alloc (int slots, curl_hash_dtor dtor) +Curl_hash_alloc(int slots, curl_hash_dtor dtor) { curl_hash *h; h = (curl_hash *) malloc(sizeof(curl_hash)); - if (NULL == h) - return NULL; - - Curl_hash_init(h, slots, dtor); + if (h) { + if(Curl_hash_init(h, slots, dtor)) { + /* failure */ + free(h); + h = NULL; + } + } return h; } -/* }}} */ -/* {{{ static int _hash_key_compare (char *, size_t, char *, size_t) - */ -static int -_hash_key_compare (char *key1, size_t key1_len, char *key2, size_t key2_len) +static int +hash_key_compare(char *key1, size_t key1_len, char *key2, size_t key2_len) { - if (key1_len == key2_len && + if (key1_len == key2_len && *key1 == *key2 && memcmp(key1, key2, key1_len) == 0) { return 1; @@ -118,108 +117,90 @@ _hash_key_compare (char *key1, size_t key1_len, char *key2, size_t key2_len) return 0; } -/* }}} */ -/* {{{ static int _mk_hash_element (curl_hash_element **, char *, size_t, const void *) - */ -static int -_mk_hash_element (curl_hash_element **e, char *key, size_t key_len, const void *p) +static curl_hash_element * +mk_hash_element(char *key, size_t key_len, const void *p) { - *e = (curl_hash_element *) malloc(sizeof(curl_hash_element)); - (*e)->key = strdup(key); - (*e)->key_len = key_len; - (*e)->ptr = (void *) p; - return 0; + curl_hash_element *he = + (curl_hash_element *) malloc(sizeof(curl_hash_element)); + + if(he) { + char *dup = strdup(key); + if(dup) { + he->key = dup; + he->key_len = key_len; + he->ptr = (void *) p; + } + else { + /* failed to duplicate the key, free memory and fail */ + free(he); + he = NULL; + } + } + return he; } -/* }}} */ -#define find_slot(__h, __k, __k_len) (_hash_str(__k, __k_len) % (__h)->slots) +#define find_slot(__h, __k, __k_len) (hash_str(__k, __k_len) % (__h)->slots) -#define FETCH_LIST \ - curl_llist *l = h->table[find_slot(h, key, key_len)] +#define FETCH_LIST(x,y,z) x->table[find_slot(x, y, z)] - -/* {{{ int curl_hash_add (curl_hash *, char *, size_t, const void *) - */ -int -Curl_hash_add (curl_hash *h, char *key, size_t key_len, const void *p) +/* Return the data in the hash. If there already was a match in the hash, + that data is returned. */ +void * +Curl_hash_add(curl_hash *h, char *key, size_t key_len, void *p) { curl_hash_element *he; curl_llist_element *le; - FETCH_LIST; - - for (le = CURL_LLIST_HEAD(l); - le != NULL; - le = CURL_LLIST_NEXT(le)) { - he = (curl_hash_element *) CURL_LLIST_VALP(le); - if (_hash_key_compare(he->key, he->key_len, key, key_len)) { - h->dtor(he->ptr); - he->ptr = (void *) p; - return 1; - } - } - - if (_mk_hash_element(&he, key, key_len, p) != 0) - return 0; + curl_llist *l = FETCH_LIST(h, key, key_len); - if (Curl_llist_insert_next(l, CURL_LLIST_TAIL(l), he)) { - ++h->size; - return 1; + for (le = l->head; le; le = le->next) { + he = (curl_hash_element *) le->ptr; + if (hash_key_compare(he->key, he->key_len, key, key_len)) { + h->dtor(p); /* remove the NEW entry */ + return he->ptr; /* return the EXISTING entry */ + } } - return 0; -} -/* }}} */ - -/* {{{ int curl_hash_delete (curl_hash *, char *, size_t) - */ -int -Curl_hash_delete(curl_hash *h, char *key, size_t key_len) -{ - curl_hash_element *he; - curl_llist_element *le; - FETCH_LIST; - - for (le = CURL_LLIST_HEAD(l); - le != NULL; - le = CURL_LLIST_NEXT(le)) { - he = CURL_LLIST_VALP(le); - if (_hash_key_compare(he->key, he->key_len, key, key_len)) { - Curl_llist_remove(l, le, (void *) h); - --h->size; - return 1; + he = mk_hash_element(key, key_len, p); + if (he) { + if(Curl_llist_insert_next(l, l->tail, he)) { + ++h->size; + return p; /* return the new entry */ } + /* + * Couldn't insert it, destroy the 'he' element and the key again. We + * don't call hash_element_dtor() since that would also call the + * "destructor" for the actual data 'p'. When we fail, we shall not touch + * that data. + */ + free(he->key); + free(he); } - return 0; + return NULL; /* failure */ } -/* }}} */ -/* {{{ int curl_hash_pick (curl_hash *, char *, size_t, void **) - */ void * Curl_hash_pick(curl_hash *h, char *key, size_t key_len) { curl_llist_element *le; curl_hash_element *he; - FETCH_LIST; + curl_llist *l = FETCH_LIST(h, key, key_len); - for (le = CURL_LLIST_HEAD(l); - le != NULL; - le = CURL_LLIST_NEXT(le)) { - he = CURL_LLIST_VALP(le); - if (_hash_key_compare(he->key, he->key_len, key, key_len)) { + for (le = l->head; + le; + le = le->next) { + he = le->ptr; + if (hash_key_compare(he->key, he->key_len, key, key_len)) { return he->ptr; } } return NULL; } -/* }}} */ -/* {{{ void curl_hash_apply (curl_hash *, void *, void (*)(void *, curl_hash_element *)) - */ -void +#if defined(CURLDEBUG) && defined(AGGRESIVE_TEST) +void Curl_hash_apply(curl_hash *h, void *user, void (*cb)(void *user, void *ptr)) { @@ -227,18 +208,16 @@ Curl_hash_apply(curl_hash *h, void *user, int i; for (i = 0; i < h->slots; ++i) { - for (le = CURL_LLIST_HEAD(h->table[i]); - le != NULL; - le = CURL_LLIST_NEXT(le)) { - curl_hash_element *el = CURL_LLIST_VALP(le); + for (le = (h->table[i])->head; + le; + le = le->next) { + curl_hash_element *el = le->ptr; cb(user, el->ptr); } } } -/* }}} */ +#endif -/* {{{ void curl_hash_clean (curl_hash *) - */ void Curl_hash_clean(curl_hash *h) { @@ -250,45 +229,33 @@ Curl_hash_clean(curl_hash *h) free(h->table); } -/* }}} */ -/* {{{ void curl_hash_clean_with_criterium (curl_hash *, void *, - int (*)(void *, void *)) - */ void Curl_hash_clean_with_criterium(curl_hash *h, void *user, int (*comp)(void *, void *)) { curl_llist_element *le; curl_llist_element *lnext; + curl_llist *list; int i; for (i = 0; i < h->slots; ++i) { - le = CURL_LLIST_HEAD(h->table[i]); - while(le != NULL) - if (comp(user, ((curl_hash_element *) CURL_LLIST_VALP(le))->ptr)) { - lnext = CURL_LLIST_NEXT(le); - Curl_llist_remove(h->table[i], le, (void *) h); - --h->size; - le = lnext; + list = h->table[i]; + le = list->head; /* get first list entry */ + while(le) { + curl_hash_element *he = le->ptr; + lnext = le->next; + /* ask the callback function if we shall remove this entry or not */ + if (comp(user, he->ptr)) { + Curl_llist_remove(list, le, (void *) h); + --h->size; /* one less entry in the hash now */ } - else - le = CURL_LLIST_NEXT(le); + le = lnext; + } } } -/* {{{ int curl_hash_count (curl_hash *) - */ -int -Curl_hash_count(curl_hash *h) -{ - return (int)h->size; -} -/* }}} */ - -/* {{{ void curl_hash_destroy (curl_hash *) - */ -void +void Curl_hash_destroy(curl_hash *h) { if (!h) @@ -297,12 +264,4 @@ Curl_hash_destroy(curl_hash *h) Curl_hash_clean(h); free(h); } -/* }}} */ - -/* - * local variables: - * eval: (load-file "../curl-mode.el") - * end: - * vim600: fdm=marker - * vim: et sw=2 ts=2 sts=2 tw=78 - */ + |