#ifndef INCLUDED_METHOD_MACRO_H #define INCLUDED_METHOD_MACRO_H #if __has_attribute(always_inline) # define always_inline inline __attribute__((always_inline)) #else # define always_inline inline #endif #if __has_attribute(unused) # define UNUSED __attribute__((unused)) #else # define UNUSED #endif // clang-format off #define _ELEVENTH(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, ...) a11 #define _COUNT_ARGS(...) _ELEVENTH(__VA_ARGS__, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) #define _GLUE(a, b) a##b #define _GLUE2(a, b) _GLUE(a, b) #define _IGNORE(...) #define _REMOVE_FIRST(a1, ...) __VA_ARGS__ #define _EVAL(...) __VA_ARGS__ // clang-format on // This is needed because C11 doesn't allow empty __VA_ARGS__ #define _GET_1_1(a1) a1 #define _GET_1_2(a1, a2) a1 #define _GET_1_3(a1, a2, a3) a1 #define _GET_1_4(a1, a2, a3, a4) a1 #define _GET_1_5(a1, a2, a3, a4, a5) a1 #define _GET_1_6(a1, a2, a3, a4, a5, a6) a1 #define _GET_2_2(a1, a2) a2 #define _GET_2_3(a1, a2, a3) a2 #define _GET_2_4(a1, a2, a3, a4) a2 #define _GET_2_5(a1, a2, a3, a4, a5) a2 #define _GET_2_6(a1, a2, a3, a4, a5, a6) a2 #define _GET_3_3(a1, a2, a3) a3 #define _GET_3_4(a1, a2, a3, a4) a3 #define _GET_3_5(a1, a2, a3, a4, a5) a3 #define _GET_3_6(a1, a2, a3, a4, a5, a6) a3 #define _GET_4_4(a1, a2, a3, a4) a4 #define _GET_4_5(a1, a2, a3, a4, a5) a4 #define _GET_4_6(a1, a2, a3, a4, a5, a6) a4 #define _GET_5_5(a1, a2, a3, a4, a5) a5 #define _GET_5_6(a1, a2, a3, a4, a5, a6) a5 #define _GET_6_6(a1, a2, a3, a4, a5, a6) a6 #define _GET_NTH(n, args) \ _EVAL(_GLUE2(_GLUE2(_GLUE2(_GET_, n), _), _COUNT_ARGS args) args) #define METHOD_CALLBACK_NAME(name) _##name##__as_callback #define _CB_DECL_ARGS_1 Object * #define _CB_DECL_ARGS_2 Object *, _CB_DECL_ARGS_1 #define _CB_DECL_ARGS_3 Object *, _CB_DECL_ARGS_2 #define _CB_DECL_ARGS_4 Object *, _CB_DECL_ARGS_3 #define _CB_DECL_ARGS_5 Object *, _CB_DECL_ARGS_4 #define _CB_DECL_ARGS_6 Object *, _CB_DECL_ARGS_5 #define _CB_DECL_ARGS_N(count) (_GLUE(_CB_DECL_ARGS_, count)) #define _CB_DECL_ARGS_FOR(...) _CB_DECL_ARGS_N(_COUNT_ARGS(__VA_ARGS__)) #define _GEN_CB_DECL(name, args) \ Object *METHOD_CALLBACK_NAME(name) \ _CB_DECL_ARGS_FOR args #define _ARG_NAME_1(args) _IGNORE _GET_NTH(1, args) #define _ARG_NAME_2(args) _IGNORE _GET_NTH(2, args) #define _ARG_NAME_3(args) _IGNORE _GET_NTH(3, args) #define _ARG_NAME_4(args) _IGNORE _GET_NTH(4, args) #define _ARG_NAME_5(args) _IGNORE _GET_NTH(5, args) #define _ARG_NAME_6(args) _IGNORE _GET_NTH(6, args) #define _ARG_NAME_N(n, args) _EVAL(_GLUE(_ARG_NAME_, n)(args)) #define _VOID_ARG_N(n, args) (void *) _ARG_NAME_N(n, args) #define _CALL_ARGS_1(args) _VOID_ARG_N(1, args) #define _CALL_ARGS_2(args) _CALL_ARGS_1(args), _VOID_ARG_N(2, args) #define _CALL_ARGS_3(args) _CALL_ARGS_2(args), _VOID_ARG_N(3, args) #define _CALL_ARGS_4(args) _CALL_ARGS_3(args), _VOID_ARG_N(4, args) #define _CALL_ARGS_5(args) _CALL_ARGS_4(args), _VOID_ARG_N(5, args) #define _CALL_ARGS_6(args) _CALL_ARGS_5(args), _VOID_ARG_N(6, args) #define _CALL_ARGS_N(n, args) _GLUE(_CALL_ARGS_, n)(args) #define _GEN_REAL_CALL(name, args) \ METHOD_CALLBACK_NAME(name)(_CALL_ARGS_N(_COUNT_ARGS args, args)) #define _UNWRAP_TYPE(arg) _EVAL arg #define _UNWRAP_ARG_N(n, args) _UNWRAP_TYPE(_GET_NTH(n, args)) #define _UNWRAP_ARGS_1(args) _UNWRAP_ARG_N(1, args) #define _UNWRAP_ARGS_2(args) _UNWRAP_ARGS_1(args), _UNWRAP_ARG_N(2, args) #define _UNWRAP_ARGS_3(args) _UNWRAP_ARGS_2(args), _UNWRAP_ARG_N(3, args) #define _UNWRAP_ARGS_4(args) _UNWRAP_ARGS_3(args), _UNWRAP_ARG_N(4, args) #define _UNWRAP_ARGS_5(args) _UNWRAP_ARGS_4(args), _UNWRAP_ARG_N(5, args) #define _UNWRAP_ARGS_6(args) _UNWRAP_ARGS_5(args), _UNWRAP_ARG_N(6, args) #define _UNWRAP_ARGS_N(n, args) _GLUE(_UNWRAP_ARGS_, n)(args) #define _UNWRAP_ARGS(args) _UNWRAP_ARGS_N(_COUNT_ARGS args, args) #define _METHOD_RAW(rtype, ret_stmt, name, args) \ _GEN_CB_DECL(name, args); \ static always_inline rtype name(_UNWRAP_ARGS(args)) { \ ret_stmt _GEN_REAL_CALL(name, args); \ } \ struct __dummy_struct #define METHOD(rtype, name, args) _METHOD_RAW(rtype, return (rtype), name, args) #define VOID_METHOD(name, args) _METHOD_RAW(void, , name, args) #define _CB_DEF_ARGS_1 Object *_internal_arg1 #define _CB_DEF_ARGS_2 _CB_DEF_ARGS_1, Object *_internal_arg2 #define _CB_DEF_ARGS_3 _CB_DEF_ARGS_2, Object *_internal_arg3 #define _CB_DEF_ARGS_4 _CB_DEF_ARGS_3, Object *_internal_arg4 #define _CB_DEF_ARGS_5 _CB_DEF_ARGS_4, Object *_internal_arg5 #define _CB_DEF_ARGS_6 _CB_DEF_ARGS_5, Object *_internal_arg6 #define _CB_DEF_ARGS_N(count) (_GLUE(_CB_DEF_ARGS_, count)) #define _CB_DEF_ARGS_FOR(...) _CB_DEF_ARGS_N(_COUNT_ARGS(__VA_ARGS__)) #define _GEN_CB_DEF(name, args) \ Object *METHOD_CALLBACK_NAME(name) \ _CB_DEF_ARGS_FOR args #define _SET_NTH_ARG(n, args) \ UNUSED _GET_NTH(n, args) = (void *) _internal_arg##n; #define _SET_ARGS_1(args) _SET_NTH_ARG(1, args) #define _SET_ARGS_2(args) _SET_ARGS_1(args) _SET_NTH_ARG(2, args) #define _SET_ARGS_3(args) _SET_ARGS_2(args) _SET_NTH_ARG(3, args) #define _SET_ARGS_4(args) _SET_ARGS_3(args) _SET_NTH_ARG(4, args) #define _SET_ARGS_5(args) _SET_ARGS_4(args) _SET_NTH_ARG(5, args) #define _SET_ARGS_6(args) _SET_ARGS_5(args) _SET_NTH_ARG(6, args) #define _SET_ARGS_N(n, args) _GLUE(_SET_ARGS_, n)(args) #define DEFINE_METHOD(rtype, name, args, body) \ _GEN_CB_DEF(name, args) { \ _SET_ARGS_N(_COUNT_ARGS args, args) \ body \ } #endif