1 /* CC0 (Public domain) - see LICENSE file for details */
9 * TCON - declare a _tcon type containing canary variables.
10 * @decls: the semi-colon separated list of type canaries.
12 * This declares a _tcon member for a structure. It should be the
13 * last element in your structure; with sufficient compiler support it
14 * will not use any actual storage. tcon_check() will compare
15 * expressions with one of these "type canaries" to cause warnings if
16 * the container is misused.
18 * A type of "void *" will allow tcon_check() to pass on any (pointer) type.
21 * // Simply typesafe linked list.
23 * struct list_head *prev, *next;
26 * struct string_list {
27 * struct list_head raw;
31 * // More complex: mapping from one type to another.
36 * struct int_to_string_map {
38 * TCON(char *charp_canary; int int_canary);
41 #if HAVE_FLEXIBLE_ARRAY_MEMBER
42 #define TCON(decls) struct { decls; } _tcon[]
44 #define TCON(decls) struct { decls; } _tcon[1]
48 * TCON_WRAP - declare a wrapper type containing a base type and type canaries
49 * @basetype: the base type to wrap
50 * @decls: the semi-colon separated list of type canaries.
52 * This expands to a new type which includes the given base type, and
53 * also type canaries, similar to those created with TCON.
55 * The embedded base type value can be accessed using tcon_unwrap().
57 * Differences from using TCON()
58 * - The wrapper type will take either the size of the base type, or
59 * the size of a single pointer, whichever is greater (regardless of
61 * - A TCON_WRAP type may be included in another structure, and need
62 * not be the last element.
64 * A type of "void *" will allow tcon_check() to pass on any (pointer) type.
67 * // Simply typesafe linked list.
69 * struct list_head *prev, *next;
72 * typedef TCON_WRAP(struct list_head, char *canary) string_list_t;
74 * // More complex: mapping from one type to another.
79 * typedef TCON_WRAP(struct map, char *charp_canary; int int_canary)
80 * int_to_string_map_t;
82 #define TCON_WRAP(basetype, decls) \
91 * TCON_WRAP_INIT - an initializer for a variable declared with TCON_WRAP
92 * @...: Initializer for the base type (treated as variadic so commas
95 * Converts converts an initializer suitable for a base type into one
96 * suitable for that type wrapped with TCON_WRAP.
99 * TCON_WRAP(int, char *canary) canaried_int = TCON_WRAP_INIT(17);
101 #define TCON_WRAP_INIT(...) \
102 { ._base = __VA_ARGS__, }
105 * tcon_unwrap - Access the base type of a TCON_WRAP
106 * @ptr: pointer to an object declared with TCON_WRAP
108 * tcon_unwrap() returns a pointer to the base type of the TCON_WRAP()
109 * object pointer to by @ptr.
112 * TCON_WRAP(int, char *canary) canaried_int;
114 * *tcon_unwrap(&canaried_int) = 17;
116 #define tcon_unwrap(ptr) (&((ptr)->_base))
119 * tcon_check - typecheck a typed container
120 * @x: the structure containing the TCON.
121 * @canary: which canary to check against.
122 * @expr: the expression whose type must match the TCON (not evaluated)
124 * This macro is used to check that the expression is the type
125 * expected for this structure (note the "useless" sizeof() argument
126 * which contains this comparison with the type canary).
128 * It evaluates to @x so you can chain it.
131 * #define tlist_add(h, n, member) \
132 * list_add(&tcon_check((h), canary, (n))->raw, &(n)->member)
134 #define tcon_check(x, canary, expr) \
135 (sizeof((x)->_tcon[0].canary == (expr)) ? (x) : (x))
138 * tcon_check_ptr - typecheck a typed container
139 * @x: the structure containing the TCON.
140 * @canary: which canary to check against.
141 * @expr: the expression whose type must match &TCON (not evaluated)
143 * This macro is used to check that the expression is a pointer to the type
144 * expected for this structure (note the "useless" sizeof() argument
145 * which contains this comparison with the type canary), or NULL.
147 * It evaluates to @x so you can chain it.
149 #define tcon_check_ptr(x, canary, expr) \
150 (sizeof((expr) ? (expr) : &(x)->_tcon[0].canary) ? (x) : (x))
153 * tcon_type - the type within a container (or void *)
154 * @x: the structure containing the TCON.
155 * @canary: which canary to check against.
158 #define tcon_type(x, canary) __typeof__((x)->_tcon[0].canary)
160 #define tcon_type(x, canary) void *
164 * tcon_sizeof - the size of type within a container
165 * @x: the structure containing the TCON.
166 * @canary: which canary to check against.
168 #define tcon_sizeof(x, canary) sizeof((x)->_tcon[0].canary)
171 * TCON_VALUE - encode an integer value in a type canary
172 * @canary: name of the value canary
173 * @val: positive integer compile time constant value
175 * This macro can be included inside the declarations in a TCON() or
176 * TCON_WRAP(), constructing a special "type" canary which encodes the
177 * integer value @val (which must be a compile time constant, and a
178 * positive integer in the range of size_t).
180 #define TCON_VALUE(canary, val) char _value_##canary[val]
183 * tcon_value - retrieve the value of a TCON_VALUE canary
184 * @x: the structure containing the TCON
185 * @canary: name of the value canary
187 * This macros expands to the value previously encoded into a TCON
188 * using TCON_VALUE().
190 #define tcon_value(x, canary) tcon_sizeof(x, _value_##canary)
193 * tcon_ptr_type - pointer to the type within a container (or void *)
194 * @x: the structure containing the TCON.
195 * @canary: which canary to check against.
198 #define tcon_ptr_type(x, canary) __typeof__(&(x)->_tcon[0].canary)
200 #define tcon_ptr_type(x, canary) void *
204 * tcon_cast - cast to a canary type for this container (or void *)
205 * @x: a structure containing the TCON.
206 * @canary: which canary to cast to.
207 * @expr: the value to cast
209 * This is used to cast to the correct type for this container. If the
210 * platform doesn't HAVE_TYPEOF, then it casts to void * (which will
211 * cause a warning if the user doesn't expect a pointer type).
213 #define tcon_cast(x, canary, expr) ((tcon_type((x), canary))(expr))
214 #define tcon_cast_ptr(x, canary, expr) ((tcon_ptr_type((x), canary))(expr))
217 * TCON_CONTAINER - encode information on a specific member of a
218 * containing structure into a "type" canary
219 * @canary: name of the container canary
220 * @container: type of the container structure
221 * @member: name of the member
223 * Used in the declarations in TCON() or TCON_WRAP(), encode a
224 * "container canary". This encodes the type of @container, the type
225 * of @member within it (with sufficient compiler support) and the
226 * offset of @member within @container.
229 #define TCON_CONTAINER(canary, container, member) \
230 container _container_##canary; \
231 typeof(((container *)0)->member) _member_##canary; \
232 TCON_VALUE(_offset_##canary, offsetof(container, member))
234 #define TCON_CONTAINER(canary, container, member) \
235 container _container_##canary; \
236 TCON_VALUE(_offset_##canary, offsetof(container, member))
240 * tcon_container_check
241 * tcon_container_check_ptr
242 * tcon_container_type
243 * tcon_container_ptr_type
244 * tcon_container_sizeof
245 * tcon_container_cast
246 * tcon_container_cast_ptr
247 * @x: the structure containing the TCON.
248 * @canary: which container canary to check against.
250 * As tcon_check / tcon_check_ptr / tcon_type / tcon_ptr_type /
251 * tcon_sizeof / tcon_cast / tcon_cast_ptr, but use the type of the
252 * "container" type declared with TCON_CONTAINER, instead of a simple
255 #define tcon_container_check(x, canary, expr) \
256 tcon_check(x, _container_##canary, expr)
257 #define tcon_container_check_ptr(x, canary, expr) \
258 tcon_check_ptr(x, _container_##canary, expr)
259 #define tcon_container_type(x, canary) \
260 tcon_type(x, _container_##canary)
261 #define tcon_container_ptr_type(x, canary) \
262 tcon_ptr_type(x, _container_##canary)
263 #define tcon_container_sizeof(x, canary) \
264 tcon_sizeof(x, _container_##canary)
265 #define tcon_container_cast(x, canary, expr) \
266 tcon_cast(x, _container_##canary, expr)
267 #define tcon_container_cast_ptr(x, canary, expr) \
268 tcon_cast_ptr(x, _container_##canary, expr)
272 * tcon_member_check_ptr
274 * tcon_member_ptr_type
277 * tcon_member_cast_ptr
278 * @x: the structure containing the TCON.
279 * @canary: which container canary to check against.
281 * As tcon_check / tcon_check_ptr / tcon_type / tcon_ptr_type /
282 * tcon_sizeof / tcon_cast / tcon_cast_ptr, but use the type of the
283 * "member" type declared with TCON_CONTAINER, instead of a simple
286 #define tcon_member_check(x, canary, expr) \
287 tcon_check(x, _member_##canary, expr)
288 #define tcon_member_check_ptr(x, canary, expr) \
289 tcon_check_ptr(x, _member_##canary, expr)
290 #define tcon_member_type(x, canary) \
291 tcon_type(x, _member_##canary)
292 #define tcon_member_ptr_type(x, canary) \
293 tcon_ptr_type(x, _member_##canary)
294 #define tcon_member_sizeof(x, canary) \
295 tcon_sizeof(x, _member_##canary)
296 #define tcon_member_cast(x, canary, expr) \
297 tcon_cast(x, _member_##canary, expr)
298 #define tcon_member_cast_ptr(x, canary, expr) \
299 tcon_cast_ptr(x, _member_##canary, expr)
302 * tcon_offset - the offset of a member within a container, as
303 * declared with TCON_CONTAINER
304 * @x: the structure containing the TCON.
305 * @canary: which container canary to check against.
307 #define tcon_offset(x, canary) \
308 tcon_value((x), _offset_##canary)
311 * tcon_container_of - get pointer to enclosing structure based on a
313 * @x: the structure containing the TCON
314 * @canary: the name of the container canary
315 * @member_ptr: pointer to a member of the container
317 * @member_ptr must be a pointer to the member of a container
318 * structure previously recorded in @canary with TCON_CONTAINER.
320 * tcon_container_of() evaluates to a pointer to the container
321 * structure. With sufficient compiler support, the pointer will be
322 * correctly typed, and the type of @member_ptr will be verified.
323 * Note that const is discarded; a const @member_ptr still yields a
324 * non-const container (unless @canary is const).
326 * Returns NULL if @member_ptr is NULL.
328 #define tcon_container_of(x, canary, member_ptr) \
329 tcon_container_cast_ptr( \
330 tcon_member_check_ptr((x), canary, (member_ptr)), \
331 canary, tcon_container_of_((member_ptr), \
332 tcon_offset((x), canary)))
334 static inline void *tcon_container_of_(const void *member_ptr, size_t offset)
336 return member_ptr ? (char *)member_ptr - offset : NULL;
341 * tcon_member_of - get pointer to enclosed member structure based on a
343 * @x: the structure containing the TCON
344 * @canary: the name of the container canary
345 * @container_ptr: pointer to a container
347 * @container_ptr must be a pointer to a container structure
348 * previously recorded in @canary with TCON_CONTAINER.
350 * tcon_member_of() evaluates to a pointer to the member of the
351 * container recorded in @canary. With sufficient compiler support,
352 * the pointer will be correctly typed, and the type of @container_ptr
355 * Returns NULL if @container_ptr is NULL.
357 #define tcon_member_of(x, canary, container_ptr) \
358 tcon_member_cast_ptr( \
359 tcon_container_check_ptr((x), canary, (container_ptr)), \
360 canary, tcon_member_of_((container_ptr), \
361 tcon_offset((x), canary)))
362 static inline void *tcon_member_of_(void *container_ptr, size_t offset)
364 return container_ptr ? (char *)container_ptr + offset : NULL;
368 #endif /* CCAN_TCON_H */