--- /dev/null
+#ifndef MAP_H_
+#define MAP_H_
+#include <stddef.h>
+#if defined(__has_c_attribute)
+# if __has_c_attribute(nodiscard)
+# define NODISCARD [[nodiscard]]
+# else
+# define NODISCARD
+# endif
+#else
+# define NODISCARD
+#endif
+
+#ifdef USE_MAP_DYNARR
+/* all complexity is in terms of n = number of elements */
+struct map_dynarr_value {
+ char *key;
+ void *value;
+};
+struct map_dynarr {
+ struct map_dynarr_value *ptr;
+ size_t len, cap;
+};
+typedef struct map_dynarr map_t;
+struct trie_find {
+ char *key;
+ struct { void *value; } *n, _n;
+ map_t *_root;
+ int _cap;
+};
+#else
+/* all complexity is in terms of n = strlen(key) and s = size of the character set */
+struct trie_node {
+ unsigned char key;
+ unsigned char len;
+ unsigned char cap;
+ void *value;
+ struct trie_node *parent;
+ struct trie_node *data[1];
+};
+typedef struct trie_node *map_t;
+struct trie_find {
+ struct trie_node *n;
+ size_t len;
+ size_t cap;
+ char key[1];
+};
+#endif
+
+/* A map abstract data type with following properties:
+ * - keys are lexicographically-sorted unique NUL-terminated strings
+ * - values are non-NULL pointers
+ * - a NULL value is synonymous with absence of a key
+ * - keys are owned by the map, values are not.
+ * - traversal can fail with memory allocation errors (sadly)
+ * - the map can't be modified during traversal
+ *
+ * A map is created by allocating and zero-initializing an object of type
+ * map_t. All map functions take a pointer to map_t.
+ */
+
+/* Return the associated value for a given key.
+ * Trie complexity: O(n log s)
+ * Dynarr complexity: O(log n) */
+void *map_get(map_t *root, const char *key);
+/* Associate a new value with a given key.
+ * Returns 0 on success, -1 on allocation error.
+ * If oldvalue is not NULL, it receives the old value of key.
+ * Trie complexity: O(ns)
+ * Dynarr complexity: O(n) */
+NODISCARD int map_set(map_t *root, const char *key, const void *value, void **oldvalue);
+/* Remove a key.
+ * Same as associating a key to NULL. No allocation failures. */
+#define map_unset(root, key, oldvalue) ((void)map_set((root), (key), 0, (oldvalue)))
+/* Removes all keys from the map and frees any associated memory.
+ * The map_t is reset to zero-initialized state and can be used again.
+ * Trie complexity: O(ns)
+ * Dynarr complexity: O(n) */
+void map_free(map_t *root);
+NODISCARD int trie_findfirst(struct trie_find **pf, map_t *root);
+NODISCARD int trie_findnext(struct trie_find **pf);
+#endif
+++ /dev/null
-#ifndef MAP_DYNARR_H_
-#define MAP_DYNARR_H_
-#include <stddef.h>
-#if defined(__has_c_attribute)
-# if __has_c_attribute(nodiscard)
-# define NODISCARD [[nodiscard]]
-# else
-# define NODISCARD
-# endif
-#else
-# define NODISCARD
-#endif
-struct map_dynarr_value {
- char *key;
- void *value;
-};
-struct map_dynarr {
- struct map_dynarr_value *ptr;
- size_t len, cap;
-};
-typedef struct map_dynarr map_t;
-void *map_get(map_t *root, const char *key);
-NODISCARD int map_set(map_t *root, const char *key, const void *value, void **oldvalue);
-#define map_unset(root, key, oldvalue) ((void)map_set((root), (key), 0, (oldvalue)))
-void map_free(map_t *root);
-struct trie_find {
- char *key;
- struct { void *value; } *n, _n;
- map_t *_root;
- int _cap;
-};
-NODISCARD int trie_findfirst(struct trie_find **pf, map_t *root);
-NODISCARD int trie_findnext(struct trie_find **pf);
-#endif
+++ /dev/null
-#ifndef TRIE_H_
-#define TRIE_H_
-#include <stddef.h>
-#ifdef __cplusplus
-extern "C" {
-#endif
-#if defined(__has_c_attribute)
-# if __has_c_attribute(nodiscard)
-# define NODISCARD [[nodiscard]]
-# else
-# define NODISCARD
-# endif
-#else
-# define NODISCARD
-#endif
-// all complexity is in terms of n = strlen(key) and s = size of the character set
-struct trie_node {
- unsigned char key;
- unsigned char len;
- unsigned char cap;
- void *value;
- struct trie_node *parent;
- struct trie_node *data[1];
-};
-typedef struct trie_node *map_t;
-// get value from trie O(n log s)
-void *map_get(map_t *root, const char *key);
-// set value in trie O(ns)
-NODISCARD int map_set(map_t *root, const char *key, const void *value, void **oldvalue);
-#define map_unset(root, key, oldvalue) ((void)map_set((root), (key), 0, (oldvalue)))
-// free a trie
-void map_free(map_t *root);
-struct trie_find {
- struct trie_node *n;
- size_t len;
- size_t cap;
- char key[1];
-};
-NODISCARD int trie_findfirst(struct trie_find **pf, map_t *root);
-NODISCARD int trie_findnext(struct trie_find **pf);
-#ifdef __cplusplus
-}
-#endif
-#endif