]> git.ozlabs.org Git - ccan/blob - ccan/tcon/tcon.h
tcon: routines for creating typesafe generic containers
[ccan] / ccan / tcon / tcon.h
1 /* Placed into the public domain */
2 #ifndef CCAN_TCON_H
3 #define CCAN_TCON_H
4 #include "config.h"
5
6 /**
7  * TCON - declare a _tcon type containing canary variables.
8  * @decls: the semi-colon separated list of type canaries.
9  *
10  * This declares a _tcon member for a structure.  It should be the
11  * last element in your structure; with sufficient compiler support it
12  * will not use any actual storage.  tcon_to_raw() will compare
13  * expressions with one of these "type canaries" to cause warnings if
14  * the container is misused.
15  *
16  * A type of "void *" will allow tcon_to_raw() to pass on any (pointer) type.
17  *
18  * Example:
19  *      // Simply typesafe linked list.
20  *      struct list_head {
21  *              struct list_head *prev, *next;
22  *      };
23  *
24  *      struct string_list {
25  *              struct list_head raw;
26  *              TCON(char *canary);
27  *      };
28  *
29  *      // More complex: mapping from one type to another.
30  *      struct map {
31  *              void *contents;
32  *      };
33  *
34  *      struct int_to_string_map {
35  *              struct map raw;
36  *              TCON(char *charp_canary; int int_canary);
37  *      };
38  */
39 #if HAVE_FLEXIBLE_ARRAY_MEMBER
40 #define TCON(decls) struct { decls; } _tcon[]
41 #else
42 #define TCON(decls) struct { decls; } _tcon[1]
43 #endif
44
45 /**
46  * tcon_check - typecheck a typed container
47  * @x: the structure containing the TCON.
48  * @canary: which canary to check against.
49  * @expr: the expression whose type must match the TCON (not evaluated)
50  *
51  * This macro is used to check that the expression is the type
52  * expected for this structure (note the "useless" sizeof() argument
53  * which contains this comparison with the type canary).
54  *
55  * It evaluates to @x so you can chain it.
56  *
57  * Example:
58  *      #define tlist_add(h, n, member) \
59  *              list_add(&tcon_check((h), canary, (n))->raw, &(n)->member)
60  */
61 #define tcon_check(x, canary, expr)                             \
62         (sizeof((x)->_tcon[0].canary == (expr)) ? (x) : (x))
63
64
65 /**
66  * tcon_cast - cast to a canary type for this container (or void *)
67  * @x: a structure containing the TCON.
68  * @canary: which canary to cast to.
69  * @expr: the value to cast
70  *
71  * This is used to cast to the correct type for this container.  If the
72  * platform doesn't HAVE_TYPEOF, then it casts to void * (which will
73  * cause a warning if the user doesn't expect a pointer type).
74  */
75 #if HAVE_TYPEOF
76 #define tcon_cast(x, canary, expr) ((__typeof__((x)->_tcon[0].canary))(expr))
77 #else
78 #define tcon_cast(x, canary, expr) ((void *)(expr))
79 #endif
80
81 #endif /* CCAN_TCON_H */