]> git.ozlabs.org Git - ccan/blob - ccan/tcon/tcon.h
ccanlint: ignore "unused" non-ccan dependencies.
[ccan] / ccan / tcon / tcon.h
1 /* CC0 (Public domain) - see LICENSE file for details */
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_check() 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_check() 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  * tcon_check_ptr - typecheck a typed container
66  * @x: the structure containing the TCON.
67  * @canary: which canary to check against.
68  * @expr: the expression whose type must match &TCON (not evaluated)
69  *
70  * This macro is used to check that the expression is a pointer to the type
71  * expected for this structure (note the "useless" sizeof() argument
72  * which contains this comparison with the type canary), or NULL.
73  *
74  * It evaluates to @x so you can chain it.
75  */
76 #define tcon_check_ptr(x, canary, expr)                         \
77         (sizeof(&(x)->_tcon[0].canary == (expr)) ? (x) : (x))
78
79
80 /**
81  * tcon_type - the type within a container (or void *)
82  * @x: the structure containing the TCON.
83  * @canary: which canary to check against.
84  */
85 #if HAVE_TYPEOF
86 #define tcon_type(x, canary) __typeof__((x)->_tcon[0].canary)
87 #else
88 #define tcon_type(x, canary) void *
89 #endif
90
91 /**
92  * tcon_ptr_type - pointer to the type within a container (or void *)
93  * @x: the structure containing the TCON.
94  * @canary: which canary to check against.
95  */
96 #if HAVE_TYPEOF
97 #define tcon_ptr_type(x, canary) __typeof__(&(x)->_tcon[0].canary)
98 #else
99 #define tcon_ptr_type(x, canary) void *
100 #endif
101
102 /**
103  * tcon_cast - cast to a canary type for this container (or void *)
104  * @x: a structure containing the TCON.
105  * @canary: which canary to cast to.
106  * @expr: the value to cast
107  *
108  * This is used to cast to the correct type for this container.  If the
109  * platform doesn't HAVE_TYPEOF, then it casts to void * (which will
110  * cause a warning if the user doesn't expect a pointer type).
111  */
112 #define tcon_cast(x, canary, expr) ((tcon_type((x), canary))(expr))
113 #define tcon_cast_ptr(x, canary, expr) ((tcon_ptr_type((x), canary))(expr))
114
115 #endif /* CCAN_TCON_H */