* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2013, 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
*
***************************************************************************/
-#include "setup.h"
-
-#include <string.h>
-#include <stdlib.h>
+#include "curl_setup.h"
#include "hash.h"
#include "llist.h"
struct curl_hash *h = (struct curl_hash *) user;
struct curl_hash_element *e = (struct curl_hash_element *) element;
- if(e->key)
- free(e->key);
+ Curl_safefree(e->key);
- if(e->ptr)
+ if(e->ptr) {
h->dtor(e->ptr);
+ e->ptr = NULL;
+ }
+
+ e->key_len = 0;
free(e);
}
h->table = malloc(slots * sizeof(struct curl_llist *));
if(h->table) {
- for (i = 0; i < slots; ++i) {
+ for(i = 0; i < slots; ++i) {
h->table[i] = Curl_llist_alloc((curl_llist_dtor) hash_element_dtor);
if(!h->table[i]) {
- while(i--)
+ while(i--) {
Curl_llist_destroy(h->table[i], NULL);
+ h->table[i] = NULL;
+ }
free(h->table);
+ h->table = NULL;
+ h->slots = 0;
return 1; /* failure */
}
}
return 0; /* fine */
}
- else
+ else {
+ h->slots = 0;
return 1; /* failure */
+ }
}
struct curl_hash *
#define FETCH_LIST(x,y,z) x->table[x->hash_func(y, z, x->slots)]
/* Insert the data in the hash. If there already was a match in the hash,
- that data is replaced. */
+ * that data is replaced.
+ *
+ * @unittest: 1305
+ */
void *
Curl_hash_add(struct curl_hash *h, void *key, size_t key_len, void *p)
{
struct curl_llist_element *le;
struct curl_llist *l = FETCH_LIST (h, key, key_len);
- for (le = l->head; le; le = le->next) {
+ for(le = l->head; le; le = le->next) {
he = (struct curl_hash_element *) le->ptr;
if(h->comp_func(he->key, he->key_len, key, key_len)) {
Curl_llist_remove(l, le, (void *)h);
struct curl_hash_element *he;
struct curl_llist *l = FETCH_LIST(h, key, key_len);
- for (le = l->head; le; le = le->next) {
+ for(le = l->head; le; le = le->next) {
he = le->ptr;
if(h->comp_func(he->key, he->key_len, key, key_len)) {
Curl_llist_remove(l, le, (void *) h);
+ --h->size;
return 0;
}
}
{
struct curl_llist_element *le;
struct curl_hash_element *he;
- struct curl_llist *l = FETCH_LIST(h, key, key_len);
+ struct curl_llist *l;
- for (le = l->head; le; le = le->next) {
- he = le->ptr;
- if(h->comp_func(he->key, he->key_len, key, key_len)) {
- return he->ptr;
+ if(h) {
+ l = FETCH_LIST(h, key, key_len);
+ for(le = l->head; le; le = le->next) {
+ he = le->ptr;
+ if(h->comp_func(he->key, he->key_len, key, key_len)) {
+ return he->ptr;
+ }
}
}
struct curl_llist_element *le;
int i;
- for (i = 0; i < h->slots; ++i) {
- for (le = (h->table[i])->head;
- le;
- le = le->next) {
+ for(i = 0; i < h->slots; ++i) {
+ for(le = (h->table[i])->head;
+ le;
+ le = le->next) {
curl_hash_element *el = le->ptr;
cb(user, el->ptr);
}
{
int i;
- for (i = 0; i < h->slots; ++i) {
+ for(i = 0; i < h->slots; ++i) {
Curl_llist_destroy(h->table[i], (void *) h);
h->table[i] = NULL;
}
- free(h->table);
+ Curl_safefree(h->table);
+ h->size = 0;
+ h->slots = 0;
}
void
struct curl_llist *list;
int i;
- for (i = 0; i < h->slots; ++i) {
+ if(!h)
+ return;
+
+ for(i = 0; i < h->slots; ++i) {
list = h->table[i];
le = list->head; /* get first list entry */
while(le) {
return 0;
}
+void Curl_hash_start_iterate(struct curl_hash *hash,
+ struct curl_hash_iterator *iter)
+{
+ iter->hash = hash;
+ iter->slot_index = 0;
+ iter->current_element = NULL;
+}
+
+struct curl_hash_element *
+Curl_hash_next_element(struct curl_hash_iterator *iter)
+{
+ int i;
+ struct curl_hash *h = iter->hash;
+
+ /* Get the next element in the current list, if any */
+ if(iter->current_element)
+ iter->current_element = iter->current_element->next;
+
+ /* If we have reached the end of the list, find the next one */
+ if(!iter->current_element) {
+ for(i = iter->slot_index;i < h->slots;i++) {
+ if(h->table[i]->head) {
+ iter->current_element = h->table[i]->head;
+ iter->slot_index = i+1;
+ break;
+ }
+ }
+ }
+
+ if(iter->current_element) {
+ struct curl_hash_element *he = iter->current_element->ptr;
+ return he;
+ }
+ else {
+ iter->current_element = NULL;
+ return NULL;
+ }
+}
+
#if 0 /* useful function for debugging hashes and their contents */
void Curl_hash_print(struct curl_hash *h,
void (*func)(void *))
{
- int i;
- struct curl_llist_element *le;
- struct curl_llist *list;
- struct curl_hash_element *he;
+ struct curl_hash_iterator iter;
+ struct curl_hash_element *he;
+ int last_index = -1;
+
if(!h)
return;
fprintf(stderr, "=Hash dump=\n");
- for (i = 0; i < h->slots; i++) {
- list = h->table[i];
- le = list->head; /* get first list entry */
- if(le) {
- fprintf(stderr, "index %d:", i);
- while(le) {
- he = le->ptr;
- if(func)
- func(he->ptr);
- else
- fprintf(stderr, " [%p]", he->ptr);
- le = le->next;
+ Curl_hash_start_iterate(h, &iter);
+
+ he = Curl_hash_next_element(&iter);
+ while(he) {
+ if(iter.slot_index != last_index) {
+ fprintf(stderr, "index %d:", iter.slot_index);
+ if(last_index >= 0) {
+ fprintf(stderr, "\n");
}
- fprintf(stderr, "\n");
+ last_index = iter.slot_index;
}
+
+ if(func)
+ func(he->ptr);
+ else
+ fprintf(stderr, " [%p]", (void *)he->ptr);
+
+ he = Curl_hash_next_element(&iter);
}
+ fprintf(stderr, "\n");
}
#endif