7 #define DEFAULT_CAPACITY 64
23 _hm_free_pair(void *x, void *aux)
26 struct map_pair *p = x;
28 h->key_dtor(p->k, h->dtor_aux);
30 h->val_dtor(p->v, h->dtor_aux);
35 hm_new(size_t capacity, hashfn *hash,
36 comparator *cmp, void *cmp_aux)
41 capacity = DEFAULT_CAPACITY;
42 hashmap *h = malloc(sizeof *h);
47 .buckets = malloc(capacity * sizeof *h->buckets),
56 for (i = 0; i < capacity; i++)
57 h->buckets[i] = NULL; /* in case allocation fails part-way */
58 for (i = 0; i < capacity; i++)
60 if (!(h->buckets[i] = l_new()))
62 l_dtor(h->buckets[i], _hm_free_pair, h);
73 hm_dtor(hashmap *h, dtor *key_dtor, dtor *val_dtor, void *dtor_aux)
77 h->key_dtor = key_dtor;
78 h->val_dtor = val_dtor;
79 h->dtor_aux = dtor_aux;
89 for (size_t i = 0; i < h->capacity; i++)
90 l_free(h->buckets[i]);
97 hm_length(const hashmap *h)
102 for (n = i = 0; i < h->capacity; i++)
103 n += l_length(h->buckets[i]);
108 hm_is_empty(const hashmap *h)
110 return hm_length(h) == 0;
113 /* kinda weird assumption: p is struct pair*, k is type of p->k */
115 _hm_cmp(const void *p, const void *k, void *aux)
117 assert(p); assert(k); assert(aux);
119 return h->cmp(((const struct map_pair *)p)->k, k, h->cmp_aux);
123 hm_at(const hashmap *h, const void *key)
127 list *bucket = h->buckets[h->hash(key) % h->capacity];
128 list_item *li = l_find(bucket, key, _hm_cmp, (void*)h);
131 return ((struct map_pair*)li->data)->v;
135 hm_insert(hashmap *h, void *key, void *val)
139 list *bucket = h->buckets[h->hash(key) % h->capacity];
140 list_item *li = l_find(bucket, key, _hm_cmp, h);
143 struct map_pair *p = (struct map_pair*)li->data;
144 if (p->v != val && h->val_dtor)
145 h->val_dtor(p->v, h->dtor_aux);
150 struct map_pair *p = malloc(sizeof *p);
153 *p = (struct map_pair){.k = key, .v = val};
160 hm_remove(hashmap *h, void *key)
164 list *bucket = h->buckets[h->hash(key) % h->capacity];
165 list_item *li = l_find(bucket, key, _hm_cmp, h);
168 _hm_free_pair(li->data, h);
169 l_remove(bucket, li);
178 for (size_t i = 0; i < h->capacity; i++)
179 l_clear(h->buckets[i]);
183 hm_iter_begin(hashmap *h, hm_iter *i)
187 *i = (hm_iter){.h = h};
192 hm_iter_next(hm_iter *i)
196 while (!i->offset && i->bucket < i->h->capacity)
197 i->offset = l_first(i->h->buckets[++i->bucket]);
200 struct map_pair *p = i->offset->data;
201 i->offset = i->offset->next;