typesafe_cb.h (5499B)
1 /* CC0 (Public domain) - see LICENSE file for details */ 2 #ifndef CCAN_TYPESAFE_CB_H 3 #define CCAN_TYPESAFE_CB_H 4 #include "../config.h" 5 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 12 * 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. 17 * 18 * This macro can be used in static initializers. 19 * 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. 25 * 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 *, unsigned long, (e))) 31 */ 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 40 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 48 * 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. 52 * 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))) 60 */ 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)))) 66 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. 73 * 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. 77 * 78 * It is assumed that @arg is of pointer type: usually @arg is passed 79 * or assigned to a void * elsewhere anyway. 80 * 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)) 85 */ 86 #define typesafe_cb(rtype, atype, fn, arg) \ 87 typesafe_cb_cast(rtype (*)(atype), \ 88 rtype (*)(__typeof__(arg)), \ 89 (fn)) 90 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. 97 * 98 * This is a version of typesafe_cb() for callbacks that take other arguments 99 * before the @arg. 100 * 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)) 107 */ 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)) 112 113 /** 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. 119 * 120 * This is a version of typesafe_cb() for callbacks that take other arguments 121 * after the @arg. 122 * 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)) 129 */ 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 */