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) _1 |
18 | |
19 | // Evaluates to the number of arguments after expansion. |
20 | // |
21 | // #define PAIR x, y |
22 | // |
23 | // GMOCK_PP_NARG() => 1 |
24 | // GMOCK_PP_NARG(x) => 1 |
25 | // GMOCK_PP_NARG(x, y) => 2 |
26 | // GMOCK_PP_NARG(PAIR) => 2 |
27 | // |
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. Otherwise |
34 | // 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. Requires |
43 | // 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`. Otherwise |
52 | // 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 one |
56 | // argument. |
57 | // |
58 | // Implementation details: |
59 | // |
60 | // There is one case when it generates a compile error: if the argument is macro |
61 | // that cannot be called with one argument. |
62 | // |
63 | // #define M(a, b) // it doesn't matter what it expands to |
64 | // |
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 0 |
75 | // * __VA_ARGS__ is empty, or has unparen'd commas, or is enclosed in |
76 | // 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, c |
92 | // GMOCK_PP_GENERIC_IF(0, (a, b, c), (d, e, f)) => d, e, f |
93 | // |
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' as |
98 | // 0. |
99 | // |
100 | // #define PAIR x, y |
101 | // |
102 | // GMOCK_PP_NARG0() => 0 |
103 | // GMOCK_PP_NARG0(x) => 1 |
104 | // GMOCK_PP_NARG0(x, y) => 2 |
105 | // GMOCK_PP_NARG0(PAIR) => 2 |
106 | // |
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 one |
109 | // 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 15 |
139 | #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 this |
150 | // file or we will break your code. |
151 | #define GMOCK_PP_INTENRAL_EMPTY_TUPLE (, , , , , , , , , , , , , , , ) |
152 | #define GMOCK_PP_INTERNAL_CAT(_1, _2) _1##_2 |
153 | #define GMOCK_PP_INTERNAL_STRINGIZE(...) #__VA_ARGS__ |
154 | #define GMOCK_PP_INTERNAL_CAT_5(_1, _2, _3, _4, _5) _1##_2##_3##_4##_5 |
155 | #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) _Then |
160 | #define GMOCK_PP_INTERNAL_IF_0(_Then, _Else) _Else |
161 | |
162 | // Because of MSVC treating a token with a comma in it as a single token when |
163 | // passed to another macro, we need to force it to evaluate it as multiple |
164 | // tokens. We do that by using a "IDENTITY(MACRO PARENTHESIZED_ARGS)" macro. We |
165 | // define one per possible macro that relies on this behavior. Note "_Args" must |
166 | // 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 | _16 |
171 | #define GMOCK_PP_INTERNAL_16TH(_Args) \ |
172 | GMOCK_PP_IDENTITY(GMOCK_PP_INTERNAL_INTERNAL_16TH _Args) |
173 | #define GMOCK_PP_INTERNAL_INTERNAL_HEAD(_1, ...) _1 |
174 | #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 1 |
186 | #define GMOCK_PP_INTERNAL_INC_1 2 |
187 | #define GMOCK_PP_INTERNAL_INC_2 3 |
188 | #define GMOCK_PP_INTERNAL_INC_3 4 |
189 | #define GMOCK_PP_INTERNAL_INC_4 5 |
190 | #define GMOCK_PP_INTERNAL_INC_5 6 |
191 | #define GMOCK_PP_INTERNAL_INC_6 7 |
192 | #define GMOCK_PP_INTERNAL_INC_7 8 |
193 | #define GMOCK_PP_INTERNAL_INC_8 9 |
194 | #define GMOCK_PP_INTERNAL_INC_9 10 |
195 | #define GMOCK_PP_INTERNAL_INC_10 11 |
196 | #define GMOCK_PP_INTERNAL_INC_11 12 |
197 | #define GMOCK_PP_INTERNAL_INC_12 13 |
198 | #define GMOCK_PP_INTERNAL_INC_13 14 |
199 | #define GMOCK_PP_INTERNAL_INC_14 15 |
200 | #define GMOCK_PP_INTERNAL_INC_15 16 |
201 | #define GMOCK_PP_INTERNAL_COMMA_IF_0 |
202 | #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 | |