21 int nhash_init(
NHash *htbl,
int buckets,
void (*destroy)(
void*data)) {
27 if ((htbl->table = (
List *)malloc(buckets *
sizeof(
List))) == NULL) {
34 htbl->destroy = destroy;
36 htbl->buckets = buckets;
41 for (i = 0; i < htbl->buckets; i++) {
42 list_init(&htbl->table[i], htbl->destroy);
57 void nhash_destroy(
NHash *htbl) {
63 for (i = 0; i < htbl->buckets; i++) {
75 memset(htbl, 0,
sizeof(
NHash));
80 void nhash_vhash(
size_t nk, va_list args, uint32_t *h1, uint32_t *h2) {
81 for (
size_t i = 0; i < nk / 2; ++i) {
82 void* data = va_arg(args,
void*);
83 size_t len = va_arg(args,
size_t);
84 hashlittle2(data, len, h1, h2);
91 NHashEntry* nhash_create_entry(uint64_t key,
const void *val) {
115 nhash_vhash(nk, args, &h1, &h2);
120 uint64_t key = h1 + (((uint64_t)h2)<<32);
125 bucket = key % htbl->buckets;
131 for (element =
list_head(&htbl->table[bucket]); element != NULL;
135 if (entry->key == key) {
152 NHashEntry *retval = nhash_vget(htbl, nk, args);
162 int nhash_vinsert(
NHash *htbl,
const void *val,
size_t nk, va_list args) {
175 nhash_vhash(nk, args, &h1, &h2);
180 uint64_t key = h1 + (((uint64_t)h2)<<32);
185 bucket = key % htbl->buckets;
191 for (element =
list_head(&htbl->table[bucket]); element != NULL;
195 if (entry->key == key) {
207 entry = nhash_create_entry(key, val);
213 if ((retval =
list_ins_next(&htbl->table[bucket], NULL, entry)) == 0) {
215 if (nhash_loadfactor(htbl) > 2) {
227 int nhash_insert(
NHash *htbl,
const void *val,
size_t nk, ...) {
233 int retval = nhash_vinsert(htbl, val, nk, args);
244 void* nhash_vremove(
NHash *htbl,
size_t nk, va_list args) {
258 nhash_vhash(nk, args, &h1, &h2);
263 uint64_t key = h1 + (((uint64_t)h2)<<32);
268 bucket = key % htbl->buckets;
274 for (element =
list_head(&htbl->table[bucket]); element != NULL;
277 if (entry->key == key) {
284 val = (
void*)entry->val;
306 void* nhash_remove(
NHash *htbl,
size_t nk, ...) {
315 data = nhash_vremove(htbl, nk, args);
322 void* nhash_pop(
NHash *htbl) {
326 for (
int i = 0; i < htbl->buckets; i++) {
327 bucket = &htbl->table[i];
329 if (element != NULL) {
331 return (
void*)entry->val;
340 void nhash_grow(
NHash *htbl) {
341 printf(
"nhash_grow %d -> %d (size %d, load factor %.2f)...",
342 htbl->buckets, htbl->buckets * 2, htbl->size,
343 nhash_loadfactor(htbl));
345 size_t old_size = htbl->buckets;
346 List *old_table = htbl->table;
349 htbl->table = calloc(htbl->buckets,
sizeof(
List*));
354 for (
size_t i = 0; i < old_size; i++) {
355 List *bucket = &old_table[i];
359 int bucket_index = entry->key % htbl->buckets;
360 htbl->table[bucket_index] = *bucket;
368 for (
int i = 0; i < htbl->buckets; i++) {
369 if (&htbl->table[i] != NULL) {
370 list_init(&htbl->table[i], htbl->destroy);
int list_ins_next(List *list, ListElmt *element, const void *data)
Inserts an element just after element on list.
Interface for the linked list implementation.
void list_destroy(List *list)
Destroys the linked list specified by list.
#define list_head(list)
evaluates to the element at the head of list.
void list_init(List *list, void(*destroy)(void *data))
Initializes the linked list specified by list.
int list_rem_next(List *list, ListElmt *element, void **data)
Removes the element just after element on list.
#define list_is_empty(list)
determines whether list is empty.
#define list_next(element)
evaluates to the element following element.
#define list_data(element)
evaluates to the data stored on element.
structure for linked lists.
structure for linked list elements.