diff options
| author | Albert Cervin <albert@acervin.com> | 2023-02-25 21:37:48 +0100 |
|---|---|---|
| committer | Albert Cervin <albert@acervin.com> | 2023-02-25 21:38:59 +0100 |
| commit | 40db61eb7a2019ced97f09a9687139f35749f4e0 (patch) | |
| tree | 9291e44eb82721732d04146b5042545e1b9e91f9 /src/hashmap.h | |
| parent | 44fd8cde61e3e89e5f83c98900a403e922073727 (diff) | |
| download | dged-40db61eb7a2019ced97f09a9687139f35749f4e0.tar.gz dged-40db61eb7a2019ced97f09a9687139f35749f4e0.tar.xz dged-40db61eb7a2019ced97f09a9687139f35749f4e0.zip | |
Introduce vec and hashmap
Convenience macros for a hashmap and a growable vector.
Diffstat (limited to 'src/hashmap.h')
| -rw-r--r-- | src/hashmap.h | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/src/hashmap.h b/src/hashmap.h new file mode 100644 index 0000000..405c193 --- /dev/null +++ b/src/hashmap.h @@ -0,0 +1,86 @@ +#ifndef _HASHMAP_H +#define _HASHMAP_H + +#include "vec.h" +#include <stdint.h> + +#define HASHMAP_ENTRY_TYPE(name, entry) \ + struct name { \ + uint32_t key; \ + entry value; \ + } + +#define HASHMAP(entry) \ + struct { \ + VEC(entry) entries; \ + uint32_t (*hash_fn)(const char *); \ + } + +#define HASHMAP_INIT(map, initial_capacity, hasher) \ + VEC_INIT(&(map)->entries, initial_capacity) \ + (map)->hash_fn = hasher; + +#define HASHMAP_DESTROY(map) VEC_DESTROY(&(map)->entries) + +#define HASHMAP_INSERT(map, type, k, v, hash_var) \ + uint32_t key = (map)->hash_fn(k); \ + bool duplicate = false; \ + VEC_FOR_EACH(&(map)->entries, type *pair) { \ + if (pair->key == key) { \ + duplicate = true; \ + break; \ + } \ + } \ + if (!duplicate) { \ + VEC_PUSH(&(map)->entries, ((type){.key = key, .value = v})); \ + } \ + hash_var = key; + +#define HASHMAP_APPEND(map, type, k, var) \ + uint32_t key = (map)->hash_fn(k); \ + bool duplicate = false; \ + VEC_FOR_EACH(&(map)->entries, type *pair) { \ + if (pair->key == key) { \ + duplicate = true; \ + break; \ + } \ + } \ + type *v = NULL; \ + if (!duplicate) { \ + VEC_APPEND(&(map)->entries, v); \ + v->key = key; \ + } \ + var = v; + +#define HASHMAP_GET(map, type, k, var) \ + HASHMAP_GET_BY_HASH(map, type, (map)->hash_fn(k), var) + +#define HASHMAP_GET_BY_HASH(map, type, h, var) \ + type *res = NULL; \ + uint32_t needle = h; \ + VEC_FOR_EACH(&(map)->entries, type *pair) { \ + if (needle == pair->key) { \ + res = pair; \ + break; \ + } \ + } \ + var = res != NULL ? &(res->value) : NULL; + +#define HASHMAP_CONTAINS_KEY(map, key) \ + uint32_t needle = (map)->hash_fn(key); \ + bool exists = false; \ + VEC_FOR_EACH((map)->entries, struct pair *pair) { \ + if (needle == pair->key) { \ + exists = true; \ + break; \ + } \ + } \ + exists + +#define HASHMAP_FOR_EACH(map, var) VEC_FOR_EACH_INDEXED(&(map)->entries, var, i) + +#define HASHMAP_SIZE(map) VEC_SIZE(&(map)->entries) +#define HASHMAP_CAPACITY(map) VEC_CAPACITY(&(map)->entries) +#define HASHMAP_EMPTY(map) HASHMAP_SIZE == 0 + +#endif |
