wintest: add option to select the dns backend
[Samba/gebeck_regimport.git] / lib / ccan / typesafe_cb / typesafe_cb.h
blob884314975eda5506f6eed3ef941ae7401dd21a3e
1 /* Licensed under LGPLv2.1+ - see LICENSE file for details */
2 #ifndef CCAN_TYPESAFE_CB_H
3 #define CCAN_TYPESAFE_CB_H
4 #include "config.h"
6 #if HAVE_TYPEOF && HAVE_BUILTIN_CHOOSE_EXPR && HAVE_BUILTIN_TYPES_COMPATIBLE_P
7 /**
8 * typesafe_cb_cast - only cast an expression if it matches a given type
9 * @desttype: the type to cast to
10 * @oktype: the type we allow
11 * @expr: the expression to cast
13 * This macro is used to create functions which allow multiple types.
14 * The result of this macro is used somewhere that a @desttype type is
15 * expected: if @expr is exactly of type @oktype, then it will be
16 * cast to @desttype type, otherwise left alone.
18 * This macro can be used in static initializers.
20 * This is merely useful for warnings: if the compiler does not
21 * support the primitives required for typesafe_cb_cast(), it becomes an
22 * unconditional cast, and the @oktype argument is not used. In
23 * particular, this means that @oktype can be a type which uses the
24 * "typeof": it will not be evaluated if typeof is not supported.
26 * Example:
27 * // We can take either an unsigned long or a void *.
28 * void _set_some_value(void *val);
29 * #define set_some_value(e) \
30 * _set_some_value(typesafe_cb_cast(void *, (e), unsigned long))
32 #define typesafe_cb_cast(desttype, oktype, expr) \
33 __builtin_choose_expr( \
34 __builtin_types_compatible_p(__typeof__(0?(expr):(expr)), \
35 oktype), \
36 (desttype)(expr), (expr))
37 #else
38 #define typesafe_cb_cast(desttype, oktype, expr) ((desttype)(expr))
39 #endif
41 /**
42 * typesafe_cb_cast3 - only cast an expression if it matches given types
43 * @desttype: the type to cast to
44 * @ok1: the first type we allow
45 * @ok2: the second type we allow
46 * @ok3: the third type we allow
47 * @expr: the expression to cast
49 * This is a convenient wrapper for multiple typesafe_cb_cast() calls.
50 * You can chain them inside each other (ie. use typesafe_cb_cast()
51 * for expr) if you need more than 3 arguments.
53 * Example:
54 * // We can take either a long, unsigned long, void * or a const void *.
55 * void _set_some_value(void *val);
56 * #define set_some_value(expr) \
57 * _set_some_value(typesafe_cb_cast3(void *,, \
58 * long, unsigned long, const void *,\
59 * (expr)))
61 #define typesafe_cb_cast3(desttype, ok1, ok2, ok3, expr) \
62 typesafe_cb_cast(desttype, ok1, \
63 typesafe_cb_cast(desttype, ok2, \
64 typesafe_cb_cast(desttype, ok3, \
65 (expr))))
67 /**
68 * typesafe_cb - cast a callback function if it matches the arg
69 * @rtype: the return type of the callback function
70 * @atype: the (pointer) type which the callback function expects.
71 * @fn: the callback function to cast
72 * @arg: the (pointer) argument to hand to the callback function.
74 * If a callback function takes a single argument, this macro does
75 * appropriate casts to a function which takes a single atype argument if the
76 * callback provided matches the @arg.
78 * It is assumed that @arg is of pointer type: usually @arg is passed
79 * or assigned to a void * elsewhere anyway.
81 * Example:
82 * void _register_callback(void (*fn)(void *arg), void *arg);
83 * #define register_callback(fn, arg) \
84 * _register_callback(typesafe_cb(void, (fn), void*, (arg)), (arg))
86 #define typesafe_cb(rtype, atype, fn, arg) \
87 typesafe_cb_cast(rtype (*)(atype), \
88 rtype (*)(__typeof__(arg)), \
89 (fn))
91 /**
92 * typesafe_cb_preargs - cast a callback function if it matches the arg
93 * @rtype: the return type of the callback function
94 * @atype: the (pointer) type which the callback function expects.
95 * @fn: the callback function to cast
96 * @arg: the (pointer) argument to hand to the callback function.
98 * This is a version of typesafe_cb() for callbacks that take other arguments
99 * before the @arg.
101 * Example:
102 * void _register_callback(void (*fn)(int, void *arg), void *arg);
103 * #define register_callback(fn, arg) \
104 * _register_callback(typesafe_cb_preargs(void, void *, \
105 * (fn), (arg), int), \
106 * (arg))
108 #define typesafe_cb_preargs(rtype, atype, fn, arg, ...) \
109 typesafe_cb_cast(rtype (*)(__VA_ARGS__, atype), \
110 rtype (*)(__VA_ARGS__, __typeof__(arg)), \
111 (fn))
114 * typesafe_cb_postargs - cast a callback function if it matches the arg
115 * @rtype: the return type of the callback function
116 * @atype: the (pointer) type which the callback function expects.
117 * @fn: the callback function to cast
118 * @arg: the (pointer) argument to hand to the callback function.
120 * This is a version of typesafe_cb() for callbacks that take other arguments
121 * after the @arg.
123 * Example:
124 * void _register_callback(void (*fn)(void *arg, int), void *arg);
125 * #define register_callback(fn, arg) \
126 * _register_callback(typesafe_cb_postargs(void, (fn), void *, \
127 * (arg), int), \
128 * (arg))
130 #define typesafe_cb_postargs(rtype, atype, fn, arg, ...) \
131 typesafe_cb_cast(rtype (*)(atype, __VA_ARGS__), \
132 rtype (*)(__typeof__(arg), __VA_ARGS__), \
133 (fn))
134 #endif /* CCAN_CAST_IF_TYPE_H */