7 #define DEFAULT_CAPACITY 64
20 void (*key_dtor)(void *);
21 void (*val_dtor)(void *);
28 hm_new(size_t capacity, hashfn *hash,
29 comparator *cmp, void *aux,
30 void (*key_dtor)(void *),
31 void (*val_dtor)(void *))
36 capacity = DEFAULT_CAPACITY;
37 hashmap *h = malloc(sizeof *h);
42 .buckets = malloc(capacity * sizeof *h->buckets),
53 for (i = 0; i < capacity; i++)
54 h->buckets[i] = NULL; /* in case allocation fails part-way */
55 for (i = 0; i < capacity; i++)
56 if (!(h->buckets[i] = l_new(NULL))) /* XXX: proper dtor */
72 for (size_t i = 0; i < h->capacity; i++)
73 l_free(h->buckets[i]);
80 hm_length(const hashmap *h)
85 for (n = i = 0; i < h->capacity; i++)
86 n += l_length(h->buckets[i]);
91 hm_is_empty(const hashmap *h)
93 return hm_length(h) == 0;
96 /* kinda weird assumption: p is struct pair*, k is type of p->k */
98 _hm_cmp(const void *p, const void *k, void *aux)
100 assert(p); assert(k); assert(aux);
102 return h->cmp(((const struct pair *)p)->k, k, h->cmp_aux);
106 hm_at(const hashmap *h, const void *key)
110 list *bucket = h->buckets[h->hash(key) % h->capacity];
111 list_item *li = l_find(bucket, key, _hm_cmp, (void*)h);
114 return ((struct pair*)li->data)->v;
118 hm_insert(hashmap *h, void *key, void *val)
122 list *bucket = h->buckets[h->hash(key) % h->capacity];
123 list_item *li = l_find(bucket, key, _hm_cmp, h);
126 struct pair *p = (struct pair*)li->data;
127 if (p->v != val && h->val_dtor)
134 struct pair *p = malloc(sizeof *p);
137 *p = (struct pair){.k = key, .v = val};
144 hm_remove(hashmap *h, void *key)
148 list *bucket = h->buckets[h->hash(key) % h->capacity];
149 list_item *li = l_find(bucket, key, _hm_cmp, h);
152 l_remove(bucket, li);
153 /* XXX: free li and pair */
162 for (size_t i = 0; i < h->capacity; i++)
163 l_clear(h->buckets[i]);