X-Git-Url: http://git.ozlabs.org/?a=blobdiff_plain;f=ccan%2Ftcon%2Ftcon.h;fp=ccan%2Ftcon%2Ftcon.h;h=5b38c7193406fa1ccae181dbfde21849ace70601;hb=5c451bbbed80e3bcb1f6be4301026ece01ab1309;hp=0000000000000000000000000000000000000000;hpb=37965b33eeb202773dc70c4546d0b050b8e717b5;p=ccan diff --git a/ccan/tcon/tcon.h b/ccan/tcon/tcon.h new file mode 100644 index 00000000..5b38c719 --- /dev/null +++ b/ccan/tcon/tcon.h @@ -0,0 +1,81 @@ +/* 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_to_raw() will compare + * expressions with one of these "type canaries" to cause warnings if + * the container is misused. + * + * A type of "void *" will allow tcon_to_raw() 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_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). + */ +#if HAVE_TYPEOF +#define tcon_cast(x, canary, expr) ((__typeof__((x)->_tcon[0].canary))(expr)) +#else +#define tcon_cast(x, canary, expr) ((void *)(expr)) +#endif + +#endif /* CCAN_TCON_H */