7 #define DEFAULT_CAPACITY 64
29 _hm_free_pair(void *x, void *aux)
34 h->key_dtor(p->k, h->dtor_aux);
36 h->val_dtor(p->v, h->dtor_aux);
41 hm_new(size_t capacity, hashfn *hash,
42 comparator *cmp, void *cmp_aux)
47 capacity = DEFAULT_CAPACITY;
48 hashmap *h = malloc(sizeof *h);
53 .buckets = malloc(capacity * sizeof *h->buckets),
62 for (i = 0; i < capacity; i++)
63 h->buckets[i] = NULL; /* in case allocation fails part-way */
64 for (i = 0; i < capacity; i++)
66 if (!(h->buckets[i] = l_new()))
68 l_dtor(h->buckets[i], _hm_free_pair, h);
79 hm_dtor(hashmap *h, dtor *key_dtor, dtor *val_dtor, void *dtor_aux)
83 h->key_dtor = key_dtor;
84 h->val_dtor = val_dtor;
85 h->dtor_aux = dtor_aux;
95 for (size_t i = 0; i < h->capacity; i++)
96 l_free(h->buckets[i]);
103 hm_length(const hashmap *h)
108 for (n = i = 0; i < h->capacity; i++)
109 n += l_length(h->buckets[i]);
114 hm_is_empty(const hashmap *h)
116 return hm_length(h) == 0;
119 /* kinda weird assumption: p is struct pair*, k is type of p->k */
121 _hm_cmp(const void *p, const void *k, void *aux)
123 assert(p); assert(k); assert(aux);
125 return h->cmp(((const struct pair *)p)->k, k, h->cmp_aux);
129 hm_at(const hashmap *h, const void *key)
133 list *bucket = h->buckets[h->hash(key) % h->capacity];
134 list_item *li = l_find(bucket, key, _hm_cmp, (void*)h);
137 return ((struct pair*)li->data)->v;
141 hm_insert(hashmap *h, void *key, void *val)
145 list *bucket = h->buckets[h->hash(key) % h->capacity];
146 list_item *li = l_find(bucket, key, _hm_cmp, h);
149 struct pair *p = (struct pair*)li->data;
150 if (p->v != val && h->val_dtor)
151 h->val_dtor(p->v, h->dtor_aux);
157 struct pair *p = malloc(sizeof *p);
160 *p = (struct pair){.k = key, .v = val};
167 hm_remove(hashmap *h, void *key)
171 list *bucket = h->buckets[h->hash(key) % h->capacity];
172 list_item *li = l_find(bucket, key, _hm_cmp, h);
175 _hm_free_pair(li->data, h);
176 l_remove(bucket, li);
185 for (size_t i = 0; i < h->capacity; i++)
186 l_clear(h->buckets[i]);