summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Voss <mail@thomasvoss.com> 2022-12-24 02:43:41 +0100
committerThomas Voss <mail@thomasvoss.com> 2022-12-24 02:52:25 +0100
commit6dc60bf49d2c43c701c6f578711d91e51dacb9cf (patch)
tree8d7fd630b076eca04c365a3081651604d3b74291
parenta5d1c6da7e5617c15dd729a7907fb38cc25c2e1b (diff)
Add the FOREACH and FOREACH_SAFE macros
-rw-r--r--examples/gehashmap.c16
-rw-r--r--src/gehashmap.h32
2 files changed, 48 insertions, 0 deletions
diff --git a/examples/gehashmap.c b/examples/gehashmap.c
index 1ddd391..df91669 100644
--- a/examples/gehashmap.c
+++ b/examples/gehashmap.c
@@ -56,6 +56,7 @@ main(void)
{
int i;
unsigned int u;
+ struct atoimap_entry *entry, *tmp;
atoimap_t *map_a;
itoumap_t *map_b;
@@ -69,6 +70,11 @@ main(void)
atoimap_get(map_a, "THOMAS VOẞ", &i); printf("THOMAS VOẞ -> %d\n", i);
atoimap_get(map_a, "Thomas Voss", &i); printf("Thomas Voss -> %d\n", i);
+ GEHASHMAP_FOREACH_SAFE(entry, tmp, map_a)
+ atoimap_remove(map_a, entry->key);
+ GEHASHMAP_FOREACH(entry, map_a)
+ puts(entry->key);
+
itoumap_set(map_b, -42, +42);
itoumap_set(map_b, -69, +69);
itoumap_set(map_b, -420, +420);
@@ -92,6 +98,16 @@ main(void)
atoimap_free(map_a);
itoumap_free(map_b);
+ atoimap_new(map_a);
+ atoimap_set(map_a, strdup("Thomas Voß"), 5);
+ atoimap_set(map_a, strdup("THOMAS VOẞ"), 6);
+ atoimap_set(map_a, strdup("Thomas Voss"), 7);
+
+ GEHASHMAP_FOREACH(entry, map_a)
+ free(entry->key);
+
+ atoimap_free(map_a);
+
free(map_a);
free(map_b);
}
diff --git a/src/gehashmap.h b/src/gehashmap.h
index 311c2c3..1f24943 100644
--- a/src/gehashmap.h
+++ b/src/gehashmap.h
@@ -11,6 +11,38 @@
#define GEHASHMAP_INITIAL_SIZE 16
#define GEHASHMAP_LOAD_FACTOR 0.75
+/* The GEHASHMAP_FOREACH() macro takes 2 arguments. The first argument “entry”
+ * is a “struct n##_entry *”. This variable will be set to point to the next
+ * hashmap entry each iteration. The second argument “map” is a pointer to the
+ * hashmap to iterate over.
+ *
+ * This macro is unsafe to use when modifying the hashmap inplace (i.e. when
+ * calling n##_remove() in the loop).
+ */
+#define GEHASHMAP_FOREACH(entry, map) \
+ for (size_t _gehashmap_i = 0; \
+ _gehashmap_i < (map)->capacity; \
+ (_gehashmap_i)++) \
+ for ((entry) = (map)->entries[_gehashmap_i]; \
+ (entry) != NULL; \
+ (entry) = (entry)->next)
+
+/* The GEHASHMAP_FOREACH_SAFE() macro is identical to the GEHASHMAP_FOREACH()
+ * macro except it takes an additional “tmp” argument. This argument is of the
+ * same type as “entry” (a “struct n##_entry *”) and shouldn’t be interacted
+ * with by the library user. This macro allows you to modify the hashmap
+ * inplace while iterating.
+ */
+#define GEHASHMAP_FOREACH_SAFE(entry, tmp, map) \
+ for (size_t _gehashmap_i = 0; \
+ _gehashmap_i < (map)->capacity; \
+ (_gehashmap_i)++) \
+ for ((entry) = (map)->entries[_gehashmap_i], \
+ (tmp) = (entry) ? (entry)->next : NULL; \
+ (entry) != NULL; \
+ (entry) = (tmp), \
+ (tmp) = (entry) ? (entry)->next : NULL)
+
#define GEHASHMAP_API(k, v, n) \
struct n##_entry { \
k key; \