int ht_rm_entry(t_hash *hash, void *key, size_t key_size, void (*destructor)(void*)) { int offset; t_list *list; t_node *node; t_entry *entry; size_t i; entry = NULL; offset = (hash->hash(key, key_size) % hash->size); if (((list = (hash->buckets[offset])) == NULL) || ((node = list->first) == NULL)) return (false); i = 0; while (node != NULL) { entry = node->data; if (entry != NULL) if (ht_key_cmp(key, key_size, entry->key, entry->key_size)) { ht_free_entry(entry, destructor); return (list->rm_node(list, i, NULL)); } i++; node = node->next; } return (false); }
void ht_delete(/*@only@*/ hashtable ht, boolean show_progress) { unsigned int i; if(show_progress) { progress_label("ht_delete"); progress_reset(); } LOCK; for(i=0; i<ht->table_size; i++) { hashentry *he = ht->table[i]; hashentry *prvhe; if(show_progress && (i % 100)==0) progress((float)i / (float)ht->table_size); while(he) { /* remove from the list */ prvhe = he; he=he->next; /* then free the data -- avoiding dodgy free-calls-remove cycles. */ ht_free_entry(ht, prvhe->keyval); free(prvhe); } } UNLOCK; if(show_progress) progress(1.0); free(ht->table); free(ht); }
HT_RETVAL hashtable_remove(hashtable ht, void* key) { HTEntryAndBucket eab = ht_find_entry(ht, key); if (eab.entry) { /* The entry is in the table. */ HTEntry* he = ht->table[eab.nbucket]; assert(he); /* Is it the first entry in the bucket? */ if (he == eab.entry) { ht->table[eab.nbucket] = he->next; ht_free_entry(ht, he); ht->numentries--; return HT_OK; } /* It's not the first. So find its predecessor in the ** chain. */ while (he) { if (he->next == eab.entry) { he->next = eab.entry->next; ht_free_entry(ht, eab.entry); ht->numentries--; return HT_OK; } he = he->next; } /* We can't be here, since the entry was found in the ** table. */ assert(0); return HT_ERR_NOTFOUND; /* soothe compiler warning */ } else return HT_ERR_NOTFOUND; }
void hashtable_free(hashtable ht) { size_t i; for (i = 0; i < ht->numbuckets; ++i) { HTEntry *he, *next; if ((he = ht->table[i]) == NULL) continue; while (he) { next = he->next; ht_free_entry(ht, he); he = next; } } mem_free(ht->table); mem_free(ht); }