summaryrefslogtreecommitdiff
path: root/lib/ccan/tcon/tcon.h
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ccan/tcon/tcon.h')
-rw-r--r--lib/ccan/tcon/tcon.h115
1 files changed, 115 insertions, 0 deletions
diff --git a/lib/ccan/tcon/tcon.h b/lib/ccan/tcon/tcon.h
new file mode 100644
index 0000000000..93c3ea6b9f
--- /dev/null
+++ b/lib/ccan/tcon/tcon.h
@@ -0,0 +1,115 @@
+/* Placed into the public domain */
+#ifndef CCAN_TCON_H
+#define CCAN_TCON_H
+#include "config.h"
+
+/**
+ * TCON - declare a _tcon type containing canary variables.
+ * @decls: the semi-colon separated list of type canaries.
+ *
+ * This declares a _tcon member for a structure. It should be the
+ * last element in your structure; with sufficient compiler support it
+ * will not use any actual storage. tcon_check() will compare
+ * expressions with one of these "type canaries" to cause warnings if
+ * the container is misused.
+ *
+ * A type of "void *" will allow tcon_check() to pass on any (pointer) type.
+ *
+ * Example:
+ * // Simply typesafe linked list.
+ * struct list_head {
+ * struct list_head *prev, *next;
+ * };
+ *
+ * struct string_list {
+ * struct list_head raw;
+ * TCON(char *canary);
+ * };
+ *
+ * // More complex: mapping from one type to another.
+ * struct map {
+ * void *contents;
+ * };
+ *
+ * struct int_to_string_map {
+ * struct map raw;
+ * TCON(char *charp_canary; int int_canary);
+ * };
+ */
+#if HAVE_FLEXIBLE_ARRAY_MEMBER
+#define TCON(decls) struct { decls; } _tcon[]
+#else
+#define TCON(decls) struct { decls; } _tcon[1]
+#endif
+
+/**
+ * tcon_check - typecheck a typed container
+ * @x: the structure containing the TCON.
+ * @canary: which canary to check against.
+ * @expr: the expression whose type must match the TCON (not evaluated)
+ *
+ * This macro is used to check that the expression is the type
+ * expected for this structure (note the "useless" sizeof() argument
+ * which contains this comparison with the type canary).
+ *
+ * It evaluates to @x so you can chain it.
+ *
+ * Example:
+ * #define tlist_add(h, n, member) \
+ * list_add(&tcon_check((h), canary, (n))->raw, &(n)->member)
+ */
+#define tcon_check(x, canary, expr) \
+ (sizeof((x)->_tcon[0].canary == (expr)) ? (x) : (x))
+
+/**
+ * tcon_check_ptr - typecheck a typed container
+ * @x: the structure containing the TCON.
+ * @canary: which canary to check against.
+ * @expr: the expression whose type must match &TCON (not evaluated)
+ *
+ * This macro is used to check that the expression is a pointer to the type
+ * expected for this structure (note the "useless" sizeof() argument
+ * which contains this comparison with the type canary), or NULL.
+ *
+ * It evaluates to @x so you can chain it.
+ */
+#define tcon_check_ptr(x, canary, expr) \
+ (sizeof(&(x)->_tcon[0].canary == (expr)) ? (x) : (x))
+
+
+/**
+ * tcon_type - the type within a container (or void *)
+ * @x: the structure containing the TCON.
+ * @canary: which canary to check against.
+ */
+#if HAVE_TYPEOF
+#define tcon_type(x, canary) __typeof__((x)->_tcon[0].canary)
+#else
+#define tcon_type(x, canary) void *
+#endif
+
+/**
+ * tcon_ptr_type - pointer to the type within a container (or void *)
+ * @x: the structure containing the TCON.
+ * @canary: which canary to check against.
+ */
+#if HAVE_TYPEOF
+#define tcon_ptr_type(x, canary) __typeof__(&(x)->_tcon[0].canary)
+#else
+#define tcon_ptr_type(x, canary) void *
+#endif
+
+/**
+ * tcon_cast - cast to a canary type for this container (or void *)
+ * @x: a structure containing the TCON.
+ * @canary: which canary to cast to.
+ * @expr: the value to cast
+ *
+ * This is used to cast to the correct type for this container. If the
+ * platform doesn't HAVE_TYPEOF, then it casts to void * (which will
+ * cause a warning if the user doesn't expect a pointer type).
+ */
+#define tcon_cast(x, canary, expr) ((tcon_type((x), canary))(expr))
+#define tcon_cast_ptr(x, canary, expr) ((tcon_ptr_type((x), canary))(expr))
+
+#endif /* CCAN_TCON_H */