summaryrefslogtreecommitdiff
path: root/src/hashmap.h
diff options
context:
space:
mode:
authorAlbert Cervin <albert@acervin.com>2023-02-25 21:37:48 +0100
committerAlbert Cervin <albert@acervin.com>2023-02-25 21:38:59 +0100
commit40db61eb7a2019ced97f09a9687139f35749f4e0 (patch)
tree9291e44eb82721732d04146b5042545e1b9e91f9 /src/hashmap.h
parent44fd8cde61e3e89e5f83c98900a403e922073727 (diff)
downloaddged-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.h86
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