]> Dogcows Code - chaz/rasterize/blobdiff - map.h
add support for 3d scenes, depth testing, lighting
[chaz/rasterize] / map.h
diff --git a/map.h b/map.h
new file mode 100644 (file)
index 0000000..9b408b0
--- /dev/null
+++ b/map.h
@@ -0,0 +1,120 @@
+
+/*
+ * CS5600 University of Utah
+ * Charles McGarvey
+ * mcgarvey@eng.utah.edu
+ */
+
+#ifndef _MAP_H_
+#define _MAP_H_
+
+#include "rbtree.h"
+
+
+/*
+ * An associative array backed by a red-black tree.
+ */
+typedef rbtree_t map_t;
+
+
+/*
+ * These macros generate the code that can be used for type-safe interaction
+ * with the red-black tree.  The interface is like an associative array.
+ * There are different macros for generating the declarations and definitions
+ * separately or together, depending on which module(s) you want the static
+ * code to be.  To create a map, you need to specify at least the type of the
+ * key and the type of the value.  You may also need to specify a namespace
+ * and a comparison statement (especially if the key isn't a primitive number
+ * type).
+ */
+
+
+#define DECLARE_MAP_TYPE(K, V) DECLARE_MAP_TYPE(K##_t, V##_t, K##_##V)
+#define DECLARE_MAP_TYPE2(K, V, N) \
+int map_##N##_search_fn(rbtree_node_t** np, void* data); \
+typedef struct map_##N##_data \
+{ \
+    const K key; \
+    V   val; \
+} map_##N##_data_t; \
+INLINE_MAYBE map_t* map_##N##_alloc() \
+{ \
+    return rbtree_alloc(sizeof(map_##N##_data_t), map_##N##_search_fn); \
+} \
+INLINE_MAYBE map_##N##_data_t* \
+map_##N##_insert(map_t* m, K k, V v) \
+{ \
+    map_##N##_data_t d = {k, v}; \
+    rbtree_node_t* n = rbtree_insert(m, &d); \
+    if (!n) return NULL; \
+    return (map_##N##_data_t*)RBTREE_NODE_DATA(n); \
+} \
+INLINE_MAYBE V* \
+map_##N##_delete(map_t* m, K k) \
+{ \
+    rbtree_node_t* n = rbtree_delete(m, &k); \
+    if (!n) return NULL; \
+    map_##N##_data_t* dp = (map_##N##_data_t*)RBTREE_NODE_DATA(n); \
+    return &(dp->val); \
+} \
+INLINE_MAYBE V* \
+map_##N##_search(map_t* m, K k) \
+{ \
+    rbtree_node_t* n = rbtree_search(m, &k); \
+    if (!n) return NULL; \
+    map_##N##_data_t* dp = (map_##N##_data_t*)RBTREE_NODE_DATA(n); \
+    return &(dp->val); \
+} \
+typedef void (*map_##N##_call_fn_t)(const K* k, V* v); \
+INLINE_MAYBE void \
+map_##N##_call_recurse(rbtree_node_t* n, map_##N##_call_fn_t fn) \
+{ \
+    if (n == rbtree_sentinel) return; \
+    map_##N##_call_recurse(n->left, fn); \
+    map_##N##_data_t* d = RBTREE_NODE_DATA(n); \
+    fn(&d->key, &d->val); \
+    map_##N##_call_recurse(n->right, fn); \
+} \
+INLINE_MAYBE void \
+map_##N##_call(const map_t* t, map_##N##_call_fn_t fn) \
+{ \
+    map_##N##_call_recurse(t->root, fn); \
+}
+
+
+#define DEFINE_MAP_TYPE(K, V) DEFINE_MAP_TYPE2(K##_t, V##_t, K##_##V)
+#define DEFINE_MAP_TYPE2(K, V, N) DEFINE_MAP_TYPE3(K, V, N, *a - *b)
+#define DEFINE_MAP_TYPE3(K, V, N, C) \
+int map_##N##_search_fn(rbtree_node_t** np, void* data) \
+{ \
+    K* a = (K*)data; \
+    rbtree_node_t* n = *np; \
+    int c = -1; \
+    while (n != rbtree_sentinel) \
+    { \
+        K* b = (K*)RBTREE_NODE_DATA(n); \
+        *np = n; \
+        c = (C); \
+        if (c == 0) break; \
+        else if (c < 0) n = n->left; \
+        else n = n->right; \
+    } \
+    return c; \
+}
+
+
+#define DECLARE_AND_DEFINE_MAP_TYPE(K, V) \
+    DECLARE_MAP_TYPE(K, V) \
+    DEFINE_MAP_TYPE(K, V)
+
+#define DECLARE_AND_DEFINE_MAP_TYPE2(K, V, N) \
+    DECLARE_MAP_TYPE2(K, V, N) \
+    DEFINE_MAP_TYPE2(K, V, N)
+
+#define DECLARE_AND_DEFINE_MAP_TYPE3(K, V, N, C) \
+    DECLARE_MAP_TYPE2(K, V, N) \
+    DEFINE_MAP_TYPE3(K, V, N, C)
+
+
+#endif // _MAP_H_
+
This page took 0.018691 seconds and 4 git commands to generate.