280 lines · c
1#ifndef GOOGLEMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_PP_H_2#define GOOGLEMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_PP_H_3 4// Expands and concatenates the arguments. Constructed macros reevaluate.5#define GMOCK_PP_CAT(_1, _2) GMOCK_PP_INTERNAL_CAT(_1, _2)6 7// Expands and stringifies the only argument.8#define GMOCK_PP_STRINGIZE(...) GMOCK_PP_INTERNAL_STRINGIZE(__VA_ARGS__)9 10// Returns empty. Given a variadic number of arguments.11#define GMOCK_PP_EMPTY(...)12 13// Returns a comma. Given a variadic number of arguments.14#define GMOCK_PP_COMMA(...) ,15 16// Returns the only argument.17#define GMOCK_PP_IDENTITY(_1) _118 19// Evaluates to the number of arguments after expansion.20//21// #define PAIR x, y22//23// GMOCK_PP_NARG() => 124// GMOCK_PP_NARG(x) => 125// GMOCK_PP_NARG(x, y) => 226// GMOCK_PP_NARG(PAIR) => 227//28// Requires: the number of arguments after expansion is at most 15.29#define GMOCK_PP_NARG(...) \30 GMOCK_PP_INTERNAL_16TH( \31 (__VA_ARGS__, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0))32 33// Returns 1 if the expansion of arguments has an unprotected comma. Otherwise34// returns 0. Requires no more than 15 unprotected commas.35#define GMOCK_PP_HAS_COMMA(...) \36 GMOCK_PP_INTERNAL_16TH( \37 (__VA_ARGS__, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0))38 39// Returns the first argument.40#define GMOCK_PP_HEAD(...) GMOCK_PP_INTERNAL_HEAD((__VA_ARGS__, unusedArg))41 42// Returns the tail. A variadic list of all arguments minus the first. Requires43// at least one argument.44#define GMOCK_PP_TAIL(...) GMOCK_PP_INTERNAL_TAIL((__VA_ARGS__))45 46// Calls CAT(_Macro, NARG(__VA_ARGS__))(__VA_ARGS__)47#define GMOCK_PP_VARIADIC_CALL(_Macro, ...) \48 GMOCK_PP_IDENTITY( \49 GMOCK_PP_CAT(_Macro, GMOCK_PP_NARG(__VA_ARGS__))(__VA_ARGS__))50 51// If the arguments after expansion have no tokens, evaluates to `1`. Otherwise52// evaluates to `0`.53//54// Requires: * the number of arguments after expansion is at most 15.55// * If the argument is a macro, it must be able to be called with one56// argument.57//58// Implementation details:59//60// There is one case when it generates a compile error: if the argument is macro61// that cannot be called with one argument.62//63// #define M(a, b) // it doesn't matter what it expands to64//65// // Expected: expands to `0`.66// // Actual: compile error.67// GMOCK_PP_IS_EMPTY(M)68//69// There are 4 cases tested:70//71// * __VA_ARGS__ possible expansion has no unparen'd commas. Expected 0.72// * __VA_ARGS__ possible expansion is not enclosed in parenthesis. Expected 0.73// * __VA_ARGS__ possible expansion is not a macro that ()-evaluates to a comma.74// Expected 075// * __VA_ARGS__ is empty, or has unparen'd commas, or is enclosed in76// parenthesis, or is a macro that ()-evaluates to comma. Expected 1.77//78// We trigger detection on '0001', i.e. on empty.79#define GMOCK_PP_IS_EMPTY(...) \80 GMOCK_PP_INTERNAL_IS_EMPTY(GMOCK_PP_HAS_COMMA(__VA_ARGS__), \81 GMOCK_PP_HAS_COMMA(GMOCK_PP_COMMA __VA_ARGS__), \82 GMOCK_PP_HAS_COMMA(__VA_ARGS__()), \83 GMOCK_PP_HAS_COMMA(GMOCK_PP_COMMA __VA_ARGS__()))84 85// Evaluates to _Then if _Cond is 1 and _Else if _Cond is 0.86#define GMOCK_PP_IF(_Cond, _Then, _Else) \87 GMOCK_PP_CAT(GMOCK_PP_INTERNAL_IF_, _Cond)(_Then, _Else)88 89// Similar to GMOCK_PP_IF but takes _Then and _Else in parentheses.90//91// GMOCK_PP_GENERIC_IF(1, (a, b, c), (d, e, f)) => a, b, c92// GMOCK_PP_GENERIC_IF(0, (a, b, c), (d, e, f)) => d, e, f93//94#define GMOCK_PP_GENERIC_IF(_Cond, _Then, _Else) \95 GMOCK_PP_REMOVE_PARENS(GMOCK_PP_IF(_Cond, _Then, _Else))96 97// Evaluates to the number of arguments after expansion. Identifies 'empty' as98// 0.99//100// #define PAIR x, y101//102// GMOCK_PP_NARG0() => 0103// GMOCK_PP_NARG0(x) => 1104// GMOCK_PP_NARG0(x, y) => 2105// GMOCK_PP_NARG0(PAIR) => 2106//107// Requires: * the number of arguments after expansion is at most 15.108// * If the argument is a macro, it must be able to be called with one109// argument.110#define GMOCK_PP_NARG0(...) \111 GMOCK_PP_IF(GMOCK_PP_IS_EMPTY(__VA_ARGS__), 0, GMOCK_PP_NARG(__VA_ARGS__))112 113// Expands to 1 if the first argument starts with something in parentheses,114// otherwise to 0.115#define GMOCK_PP_IS_BEGIN_PARENS(...) \116 GMOCK_PP_HEAD(GMOCK_PP_CAT(GMOCK_PP_INTERNAL_IBP_IS_VARIADIC_R_, \117 GMOCK_PP_INTERNAL_IBP_IS_VARIADIC_C __VA_ARGS__))118 119// Expands to 1 is there is only one argument and it is enclosed in parentheses.120#define GMOCK_PP_IS_ENCLOSED_PARENS(...) \121 GMOCK_PP_IF(GMOCK_PP_IS_BEGIN_PARENS(__VA_ARGS__), \122 GMOCK_PP_IS_EMPTY(GMOCK_PP_EMPTY __VA_ARGS__), 0)123 124// Remove the parens, requires GMOCK_PP_IS_ENCLOSED_PARENS(args) => 1.125#define GMOCK_PP_REMOVE_PARENS(...) GMOCK_PP_INTERNAL_REMOVE_PARENS __VA_ARGS__126 127// Expands to _Macro(0, _Data, e1) _Macro(1, _Data, e2) ... _Macro(K -1, _Data,128// eK) as many of GMOCK_INTERNAL_NARG0 _Tuple.129// Requires: * |_Macro| can be called with 3 arguments.130// * |_Tuple| expansion has no more than 15 elements.131#define GMOCK_PP_FOR_EACH(_Macro, _Data, _Tuple) \132 GMOCK_PP_CAT(GMOCK_PP_INTERNAL_FOR_EACH_IMPL_, GMOCK_PP_NARG0 _Tuple) \133 (0, _Macro, _Data, _Tuple)134 135// Expands to _Macro(0, _Data, ) _Macro(1, _Data, ) ... _Macro(K - 1, _Data, )136// Empty if _K = 0.137// Requires: * |_Macro| can be called with 3 arguments.138// * |_K| literal between 0 and 15139#define GMOCK_PP_REPEAT(_Macro, _Data, _N) \140 GMOCK_PP_CAT(GMOCK_PP_INTERNAL_FOR_EACH_IMPL_, _N) \141 (0, _Macro, _Data, GMOCK_PP_INTENRAL_EMPTY_TUPLE)142 143// Increments the argument, requires the argument to be between 0 and 15.144#define GMOCK_PP_INC(_i) GMOCK_PP_CAT(GMOCK_PP_INTERNAL_INC_, _i)145 146// Returns comma if _i != 0. Requires _i to be between 0 and 15.147#define GMOCK_PP_COMMA_IF(_i) GMOCK_PP_CAT(GMOCK_PP_INTERNAL_COMMA_IF_, _i)148 149// Internal details follow. Do not use any of these symbols outside of this150// file or we will break your code.151#define GMOCK_PP_INTENRAL_EMPTY_TUPLE (, , , , , , , , , , , , , , , )152#define GMOCK_PP_INTERNAL_CAT(_1, _2) _1##_2153#define GMOCK_PP_INTERNAL_STRINGIZE(...) #__VA_ARGS__154#define GMOCK_PP_INTERNAL_CAT_5(_1, _2, _3, _4, _5) _1##_2##_3##_4##_5155#define GMOCK_PP_INTERNAL_IS_EMPTY(_1, _2, _3, _4) \156 GMOCK_PP_HAS_COMMA(GMOCK_PP_INTERNAL_CAT_5(GMOCK_PP_INTERNAL_IS_EMPTY_CASE_, \157 _1, _2, _3, _4))158#define GMOCK_PP_INTERNAL_IS_EMPTY_CASE_0001 ,159#define GMOCK_PP_INTERNAL_IF_1(_Then, _Else) _Then160#define GMOCK_PP_INTERNAL_IF_0(_Then, _Else) _Else161 162// Because of MSVC treating a token with a comma in it as a single token when163// passed to another macro, we need to force it to evaluate it as multiple164// tokens. We do that by using a "IDENTITY(MACRO PARENTHESIZED_ARGS)" macro. We165// define one per possible macro that relies on this behavior. Note "_Args" must166// be parenthesized.167#define GMOCK_PP_INTERNAL_INTERNAL_16TH(_1, _2, _3, _4, _5, _6, _7, _8, _9, \168 _10, _11, _12, _13, _14, _15, _16, \169 ...) \170 _16171#define GMOCK_PP_INTERNAL_16TH(_Args) \172 GMOCK_PP_IDENTITY(GMOCK_PP_INTERNAL_INTERNAL_16TH _Args)173#define GMOCK_PP_INTERNAL_INTERNAL_HEAD(_1, ...) _1174#define GMOCK_PP_INTERNAL_HEAD(_Args) \175 GMOCK_PP_IDENTITY(GMOCK_PP_INTERNAL_INTERNAL_HEAD _Args)176#define GMOCK_PP_INTERNAL_INTERNAL_TAIL(_1, ...) __VA_ARGS__177#define GMOCK_PP_INTERNAL_TAIL(_Args) \178 GMOCK_PP_IDENTITY(GMOCK_PP_INTERNAL_INTERNAL_TAIL _Args)179 180#define GMOCK_PP_INTERNAL_IBP_IS_VARIADIC_C(...) 1 _181#define GMOCK_PP_INTERNAL_IBP_IS_VARIADIC_R_1 1,182#define GMOCK_PP_INTERNAL_IBP_IS_VARIADIC_R_GMOCK_PP_INTERNAL_IBP_IS_VARIADIC_C \183 0,184#define GMOCK_PP_INTERNAL_REMOVE_PARENS(...) __VA_ARGS__185#define GMOCK_PP_INTERNAL_INC_0 1186#define GMOCK_PP_INTERNAL_INC_1 2187#define GMOCK_PP_INTERNAL_INC_2 3188#define GMOCK_PP_INTERNAL_INC_3 4189#define GMOCK_PP_INTERNAL_INC_4 5190#define GMOCK_PP_INTERNAL_INC_5 6191#define GMOCK_PP_INTERNAL_INC_6 7192#define GMOCK_PP_INTERNAL_INC_7 8193#define GMOCK_PP_INTERNAL_INC_8 9194#define GMOCK_PP_INTERNAL_INC_9 10195#define GMOCK_PP_INTERNAL_INC_10 11196#define GMOCK_PP_INTERNAL_INC_11 12197#define GMOCK_PP_INTERNAL_INC_12 13198#define GMOCK_PP_INTERNAL_INC_13 14199#define GMOCK_PP_INTERNAL_INC_14 15200#define GMOCK_PP_INTERNAL_INC_15 16201#define GMOCK_PP_INTERNAL_COMMA_IF_0202#define GMOCK_PP_INTERNAL_COMMA_IF_1 ,203#define GMOCK_PP_INTERNAL_COMMA_IF_2 ,204#define GMOCK_PP_INTERNAL_COMMA_IF_3 ,205#define GMOCK_PP_INTERNAL_COMMA_IF_4 ,206#define GMOCK_PP_INTERNAL_COMMA_IF_5 ,207#define GMOCK_PP_INTERNAL_COMMA_IF_6 ,208#define GMOCK_PP_INTERNAL_COMMA_IF_7 ,209#define GMOCK_PP_INTERNAL_COMMA_IF_8 ,210#define GMOCK_PP_INTERNAL_COMMA_IF_9 ,211#define GMOCK_PP_INTERNAL_COMMA_IF_10 ,212#define GMOCK_PP_INTERNAL_COMMA_IF_11 ,213#define GMOCK_PP_INTERNAL_COMMA_IF_12 ,214#define GMOCK_PP_INTERNAL_COMMA_IF_13 ,215#define GMOCK_PP_INTERNAL_COMMA_IF_14 ,216#define GMOCK_PP_INTERNAL_COMMA_IF_15 ,217#define GMOCK_PP_INTERNAL_CALL_MACRO(_Macro, _i, _Data, _element) \218 _Macro(_i, _Data, _element)219#define GMOCK_PP_INTERNAL_FOR_EACH_IMPL_0(_i, _Macro, _Data, _Tuple)220#define GMOCK_PP_INTERNAL_FOR_EACH_IMPL_1(_i, _Macro, _Data, _Tuple) \221 GMOCK_PP_INTERNAL_CALL_MACRO(_Macro, _i, _Data, GMOCK_PP_HEAD _Tuple)222#define GMOCK_PP_INTERNAL_FOR_EACH_IMPL_2(_i, _Macro, _Data, _Tuple) \223 GMOCK_PP_INTERNAL_CALL_MACRO(_Macro, _i, _Data, GMOCK_PP_HEAD _Tuple) \224 GMOCK_PP_INTERNAL_FOR_EACH_IMPL_1(GMOCK_PP_INC(_i), _Macro, _Data, \225 (GMOCK_PP_TAIL _Tuple))226#define GMOCK_PP_INTERNAL_FOR_EACH_IMPL_3(_i, _Macro, _Data, _Tuple) \227 GMOCK_PP_INTERNAL_CALL_MACRO(_Macro, _i, _Data, GMOCK_PP_HEAD _Tuple) \228 GMOCK_PP_INTERNAL_FOR_EACH_IMPL_2(GMOCK_PP_INC(_i), _Macro, _Data, \229 (GMOCK_PP_TAIL _Tuple))230#define GMOCK_PP_INTERNAL_FOR_EACH_IMPL_4(_i, _Macro, _Data, _Tuple) \231 GMOCK_PP_INTERNAL_CALL_MACRO(_Macro, _i, _Data, GMOCK_PP_HEAD _Tuple) \232 GMOCK_PP_INTERNAL_FOR_EACH_IMPL_3(GMOCK_PP_INC(_i), _Macro, _Data, \233 (GMOCK_PP_TAIL _Tuple))234#define GMOCK_PP_INTERNAL_FOR_EACH_IMPL_5(_i, _Macro, _Data, _Tuple) \235 GMOCK_PP_INTERNAL_CALL_MACRO(_Macro, _i, _Data, GMOCK_PP_HEAD _Tuple) \236 GMOCK_PP_INTERNAL_FOR_EACH_IMPL_4(GMOCK_PP_INC(_i), _Macro, _Data, \237 (GMOCK_PP_TAIL _Tuple))238#define GMOCK_PP_INTERNAL_FOR_EACH_IMPL_6(_i, _Macro, _Data, _Tuple) \239 GMOCK_PP_INTERNAL_CALL_MACRO(_Macro, _i, _Data, GMOCK_PP_HEAD _Tuple) \240 GMOCK_PP_INTERNAL_FOR_EACH_IMPL_5(GMOCK_PP_INC(_i), _Macro, _Data, \241 (GMOCK_PP_TAIL _Tuple))242#define GMOCK_PP_INTERNAL_FOR_EACH_IMPL_7(_i, _Macro, _Data, _Tuple) \243 GMOCK_PP_INTERNAL_CALL_MACRO(_Macro, _i, _Data, GMOCK_PP_HEAD _Tuple) \244 GMOCK_PP_INTERNAL_FOR_EACH_IMPL_6(GMOCK_PP_INC(_i), _Macro, _Data, \245 (GMOCK_PP_TAIL _Tuple))246#define GMOCK_PP_INTERNAL_FOR_EACH_IMPL_8(_i, _Macro, _Data, _Tuple) \247 GMOCK_PP_INTERNAL_CALL_MACRO(_Macro, _i, _Data, GMOCK_PP_HEAD _Tuple) \248 GMOCK_PP_INTERNAL_FOR_EACH_IMPL_7(GMOCK_PP_INC(_i), _Macro, _Data, \249 (GMOCK_PP_TAIL _Tuple))250#define GMOCK_PP_INTERNAL_FOR_EACH_IMPL_9(_i, _Macro, _Data, _Tuple) \251 GMOCK_PP_INTERNAL_CALL_MACRO(_Macro, _i, _Data, GMOCK_PP_HEAD _Tuple) \252 GMOCK_PP_INTERNAL_FOR_EACH_IMPL_8(GMOCK_PP_INC(_i), _Macro, _Data, \253 (GMOCK_PP_TAIL _Tuple))254#define GMOCK_PP_INTERNAL_FOR_EACH_IMPL_10(_i, _Macro, _Data, _Tuple) \255 GMOCK_PP_INTERNAL_CALL_MACRO(_Macro, _i, _Data, GMOCK_PP_HEAD _Tuple) \256 GMOCK_PP_INTERNAL_FOR_EACH_IMPL_9(GMOCK_PP_INC(_i), _Macro, _Data, \257 (GMOCK_PP_TAIL _Tuple))258#define GMOCK_PP_INTERNAL_FOR_EACH_IMPL_11(_i, _Macro, _Data, _Tuple) \259 GMOCK_PP_INTERNAL_CALL_MACRO(_Macro, _i, _Data, GMOCK_PP_HEAD _Tuple) \260 GMOCK_PP_INTERNAL_FOR_EACH_IMPL_10(GMOCK_PP_INC(_i), _Macro, _Data, \261 (GMOCK_PP_TAIL _Tuple))262#define GMOCK_PP_INTERNAL_FOR_EACH_IMPL_12(_i, _Macro, _Data, _Tuple) \263 GMOCK_PP_INTERNAL_CALL_MACRO(_Macro, _i, _Data, GMOCK_PP_HEAD _Tuple) \264 GMOCK_PP_INTERNAL_FOR_EACH_IMPL_11(GMOCK_PP_INC(_i), _Macro, _Data, \265 (GMOCK_PP_TAIL _Tuple))266#define GMOCK_PP_INTERNAL_FOR_EACH_IMPL_13(_i, _Macro, _Data, _Tuple) \267 GMOCK_PP_INTERNAL_CALL_MACRO(_Macro, _i, _Data, GMOCK_PP_HEAD _Tuple) \268 GMOCK_PP_INTERNAL_FOR_EACH_IMPL_12(GMOCK_PP_INC(_i), _Macro, _Data, \269 (GMOCK_PP_TAIL _Tuple))270#define GMOCK_PP_INTERNAL_FOR_EACH_IMPL_14(_i, _Macro, _Data, _Tuple) \271 GMOCK_PP_INTERNAL_CALL_MACRO(_Macro, _i, _Data, GMOCK_PP_HEAD _Tuple) \272 GMOCK_PP_INTERNAL_FOR_EACH_IMPL_13(GMOCK_PP_INC(_i), _Macro, _Data, \273 (GMOCK_PP_TAIL _Tuple))274#define GMOCK_PP_INTERNAL_FOR_EACH_IMPL_15(_i, _Macro, _Data, _Tuple) \275 GMOCK_PP_INTERNAL_CALL_MACRO(_Macro, _i, _Data, GMOCK_PP_HEAD _Tuple) \276 GMOCK_PP_INTERNAL_FOR_EACH_IMPL_14(GMOCK_PP_INC(_i), _Macro, _Data, \277 (GMOCK_PP_TAIL _Tuple))278 279#endif // GOOGLEMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_PP_H_280