diff --git a/src/hsearch.c b/src/hsearch.c index 0cc4aca..70d757a 100644 --- a/src/hsearch.c +++ b/src/hsearch.c @@ -107,14 +107,14 @@ static int resize(struct htab *htab, size_t nel) return 1; } -static struct elem *lookup(struct htab *htab, const char *key, size_t hash) +static struct elem *lookup(struct htab *htab, const char *key, size_t hash, size_t dead) { size_t i, j; struct elem *e; for (i=hash,j=1; ; i+=j++) { e = htab->elems + (i & htab->mask); - if (!e->item.key || + if ((!e->item.key && (!e->hash || e->hash == dead)) || (e->hash==hash && STRCMP(e->item.key, key)==0)) break; } @@ -138,36 +138,46 @@ void htab_destroy(struct htab *htab) free(htab); } -static htab_entry *htab_find_item(struct htab *htab, const char* key) +static struct elem *htab_find_elem(struct htab *htab, const char* key) { size_t hash = keyhash(key, htab->seed); - struct elem *e = lookup(htab, key, hash); + struct elem *e = lookup(htab, key, hash, 0); if (e->item.key) { - return &e->item; + return e; } return 0; } htab_value* htab_find(struct htab *htab, const char* key) { - htab_entry *i = htab_find_item(htab, key); - if(i) return &i->data; - return 0; + struct elem *e = htab_find_elem(htab, key); + if(!e) return 0; + return &e->item.data; +} + +htab_value* htab_find2(struct htab *htab, const char* key, char **saved_key) +{ + struct elem *e = htab_find_elem(htab, key); + if(!e) return 0; + *saved_key = e->item.key; + return &e->item.data; } int htab_delete(struct htab *htab, const char* key) { - htab_entry *i = htab_find_item(htab, key); - if(!i) return 0; - i->key = 0; + struct elem *e = htab_find_elem(htab, key); + if(!e) return 0; + e->item.key = 0; + e->hash = 0xdeadc0de; + --htab->used; return 1; } int htab_insert(struct htab *htab, char* key, htab_value value) { size_t hash = keyhash(key, htab->seed); - struct elem *e = lookup(htab, key, hash); + struct elem *e = lookup(htab, key, hash, 0xdeadc0de); if(e->item.key) { /* it's not allowed to overwrite existing data */ return 0; diff --git a/src/hsearch.h b/src/hsearch.h index ec81cc3..7e9d770 100644 --- a/src/hsearch.h +++ b/src/hsearch.h @@ -14,6 +14,8 @@ typedef union htab_value { struct htab * htab_create(size_t); void htab_destroy(struct htab *); htab_value* htab_find(struct htab *, const char* key); +/* same as htab_find, but can retrieve the saved key (for freeing) */ +htab_value* htab_find2(struct htab *htab, const char* key, char **saved_key); int htab_insert(struct htab *, char*, htab_value); int htab_delete(struct htab *htab, const char* key); size_t htab_next(struct htab *, size_t iterator, char** key, htab_value **v); diff --git a/src/orderedmap.c b/src/orderedmap.c index 4902be0..1818e27 100644 --- a/src/orderedmap.c +++ b/src/orderedmap.c @@ -81,14 +81,19 @@ char* orderedmap_find(struct orderedmap *o, const char *key) { int orderedmap_remove(struct orderedmap *o, const char *key) { size_t i; char *lk; - htab_value *lv, *v = htab_find(o->map, key); + char *sk; + char **sv; + htab_value *lv, *v = htab_find2(o->map, key, &sk); if(!v) return 0; - htab_delete(o->map, key); + sv = sblist_get(o->values, v->n); + free(*sv); sblist_delete(o->values, v->n); i = 0; while((i = htab_next(o->map, i, &lk, &lv))) { if(lv->n > v->n) lv->n--; } + htab_delete(o->map, key); + free(sk); return 1; }