size_t _index;
};
typedef struct map_dynarr_find *map_find_t;
-#define map_findfree(f) (free(*(f)))
+#define map_findfree(f) (free(*(f)), *(f) = 0)
#else
/* all complexity is in terms of n = strlen(key) and s = size of the character set */
struct trie_node {
char key[1];
};
typedef struct trie_find *map_find_t;
-#define map_findfree(f) (free(*(f)))
+#define map_findfree(f) (free(*(f)), *(f) = 0)
#endif
/* A map abstract data type with following properties:
* Trie complexity: O(ns)
* Dynarr complexity: O(n) */
void map_free(map_t *root);
+/* Traversal functions.
+ * Return 1 on success, 0 on end, -1 on allocation failure.
+ *
+ * Some ground rules:
+ * - map_find_t should be zero-initialized
+ * - map_findfirst and map_findfree are idempotent
+ * - when map_findfirst or map_findnext return 0 or -1, they automatically call
+ * map_findfree
+ *
+ * Non-modifying traversal:
+ * map_find_t f = {0};
+ * if (map_findfirst(&f, &map) == 1)
+ * do {
+ * value_type *v = f->value;
+ * // use f->key and v here
+ * if (gotta_break) {
+ * map_findfree(&f); // call this when breaking!
+ * break;
+ * }
+ * } while(map_findnext(&f) == 1);
+ *
+ * Emptying traversal:
+ * while (map_findfirst(&f, &map) == 1) {
+ * value_type *v = f->value;
+ * // use f->key and v here
+ * map_unset(&map, f->key, 0);
+ * }
+ * map_findfree(&f);
+ *
+ * FIXME: yep, we're silently failing on allocation errors
+ */
NODISCARD int map_findfirst(map_find_t *pf, map_t *root);
NODISCARD int map_findnext(map_find_t *pf);
#endif