Github User Fetcher 1.0.0
C Application with Server and GUI
Loading...
Searching...
No Matches
op.h
Go to the documentation of this file.
1/*
2 * The MIT License (MIT)
3 *
4 * Copyright © 2017 Franklin "Snaipe" Mathieu <http://snai.pe/>
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24#ifndef CRITERION_INTERNAL_ASSERT_OP_H_
25#define CRITERION_INTERNAL_ASSERT_OP_H_
26
27#define CRI_AS_GETTYPE(...) CRI_ASSERT_TYPE_TAG(CR_VA_HEAD(__VA_ARGS__))
28
29/* Comparison specifiers */
30
31#define CRI_MKNODE_DEF (CRI_MKNODE_STR, CRI_MKNODE_STR_ARR)
32
33#define CRI_ASSERT_TEST_SPECIFIER_eq(...) ,
34#define CRI_ASSERT_SPECIFIER_eq(...) \
35 CRI_ASSERT_SPECIFIER_OP(CRI_BINOP_T_EQ, CRI_BINOP_EQ, eq, ( \
36 (TAGGED, CRI_AS_GETTYPE(__VA_ARGS__), cri_actual, "actual", CRI_MKNODE_DEF), \
37 (TAGGED, CRI_AS_GETTYPE(__VA_ARGS__), cri_expected, "expected", CRI_MKNODE_DEF) \
38 ), __VA_ARGS__)
39
40#define CRI_ASSERT_TEST_SPECIFIER_ne(...) ,
41#define CRI_ASSERT_SPECIFIER_ne(...) \
42 CRI_ASSERT_SPECIFIER_OP(CRI_BINOP_T_NE, CRI_BINOP_NE, ne, ( \
43 (TAGGED, CRI_AS_GETTYPE(__VA_ARGS__), cri_actual, "actual", CRI_MKNODE_DEF), \
44 (TAGGED, CRI_AS_GETTYPE(__VA_ARGS__), cri_unexpected, "unexpected", CRI_MKNODE_DEF) \
45 ), __VA_ARGS__)
46
47#define CRI_ASSERT_TEST_SPECIFIER_lt(...) ,
48#define CRI_ASSERT_SPECIFIER_lt(...) \
49 CRI_ASSERT_SPECIFIER_OP(CRI_BINOP_T_LT, CRI_BINOP_LT, lt, ( \
50 (TAGGED, CRI_AS_GETTYPE(__VA_ARGS__), cri_actual, "actual", CRI_MKNODE_DEF), \
51 (TAGGED, CRI_AS_GETTYPE(__VA_ARGS__), cri_reference, "reference", CRI_MKNODE_DEF) \
52 ), __VA_ARGS__)
53
54#define CRI_ASSERT_TEST_SPECIFIER_le(...) ,
55#define CRI_ASSERT_SPECIFIER_le(...) \
56 CRI_ASSERT_SPECIFIER_OP(CRI_BINOP_T_LE, CRI_BINOP_LE, le, ( \
57 (TAGGED, CRI_AS_GETTYPE(__VA_ARGS__), cri_actual, "actual", CRI_MKNODE_DEF), \
58 (TAGGED, CRI_AS_GETTYPE(__VA_ARGS__), cri_reference, "reference", CRI_MKNODE_DEF) \
59 ), __VA_ARGS__)
60
61#define CRI_ASSERT_TEST_SPECIFIER_gt(...) ,
62#define CRI_ASSERT_SPECIFIER_gt(...) \
63 CRI_ASSERT_SPECIFIER_OP(CRI_BINOP_T_GT, CRI_BINOP_GT, gt, ( \
64 (TAGGED, CRI_AS_GETTYPE(__VA_ARGS__), cri_actual, "actual", CRI_MKNODE_DEF), \
65 (TAGGED, CRI_AS_GETTYPE(__VA_ARGS__), cri_reference, "reference", CRI_MKNODE_DEF) \
66 ), __VA_ARGS__)
67
68#define CRI_ASSERT_TEST_SPECIFIER_ge(...) ,
69#define CRI_ASSERT_SPECIFIER_ge(...) \
70 CRI_ASSERT_SPECIFIER_OP(CRI_BINOP_T_GE, CRI_BINOP_GE, ge, ( \
71 (TAGGED, CRI_AS_GETTYPE(__VA_ARGS__), cri_actual, "actual", CRI_MKNODE_DEF), \
72 (TAGGED, CRI_AS_GETTYPE(__VA_ARGS__), cri_reference, "reference", CRI_MKNODE_DEF) \
73 ), __VA_ARGS__)
74
75/* Other specifiers */
76
77#define CRI_ASSERT_TEST_SPECIFIER_zero(...) ,
78#define CRI_ASSERT_SPECIFIER_zero(...) \
79 CRI_ASSERT_SPECIFIER_OP(CRI_UNOP_T_ZERO, CRI_UNOP_ZERO, zero, ( \
80 (TAGGED, CRI_AS_GETTYPE(__VA_ARGS__), cri_value, "value", CRI_MKNODE_DEF) \
81 ), __VA_ARGS__)
82
83/* Generic operator operator helper */
84
85#define CRI_ASSERT_SPECIFIER_OP(OpTag, OpTagless, OpName, Params, ...) \
86 CRI_ASSERT_SPECIFIER_OPN(Params, (__VA_ARGS__))( \
87 OpTag, OpTagless, OpName, Params, (__VA_ARGS__) \
88 )
89
90#define CRI_ASSERT_SPECIFIER_OPN__(Macro, Len) Macro ## Len
91
92#define CRI_ASSERT_SPECIFIER_OPN_(Len) \
93 CRI_ASSERT_SPECIFIER_OPN__(CRI_ASSERT_SPECIFIER_OP, Len)
94
95#define CRI_ASSERT_SPECIFIER_OPN(Params, Va) \
96 CRI_ASSERT_SPECIFIER_OPN_(CRI_ASSERT_SPEC_OPLEN(Params, Va))
97
98#define CRI_ASSERT_SPECIFIER_OP0(OpTag, OpTagless, OpName, Params, Va) \
99 CRI_ASSERT_SPECIFIER_OPTAGLESS CR_EXPAND((OpTagless, OpName \
100 CRI_ASSERT_MKLIST(CRI_ASSERT_IT_MERGEVALS, Params, Va) \
101 ))
102
103#define CRI_ASSERT_IT_MERGEVALS(Def, Val) , CR_EXPAND((CR_EAT Def, Val))
104
105#define CRI_ASSERT_SPECIFIER_OP1(OpTag, OpTagless, OpName, Params, Va) \
106 CRI_ASSERT_CHECK_TAG(CR_EXPAND(CR_VA_HEAD Va), ( \
107 CR_EXPAND((OpTag, OpName, CR_EXPAND(CR_VA_HEAD Va) \
108 CRI_ASSERT_MKLIST(CRI_ASSERT_IT_MERGEVALS, Params, \
109 CR_EXPAND((CR_VA_TAIL Va))) \
110 )) \
111 ) \
112 )
113
114#define CRI_ASSERT_CHECK_TAG(Tag, Content) \
115 CR_EXPAND(CRI_ASSERT_CHECK_TAG_(Tag, Content))
116
117#define CRI_ASSERT_CHECK_TAG_(Tag, Content) \
118 CRI_IF_DEFINED(CRI_ASSERT_TEST_TAG_ ## Tag, \
119 CRI_ASSERT_CHECK_TAG_CONTENT, (Content), \
120 CRI_ASSERT_CHECK_TAG_UNKNOWN, (Tag) \
121 )
122
123#define CRI_ASSERT_CHECK_TAG_CONTENT(Content) \
124 CRI_DEFER1(CRI_ASSERT_SPECIFIER_OPTAG) CR_EAT Content
125
126#define CRI_ASSERT_CHECK_TAG_UNKNOWN(Tag) (0 CR_COMPILE_ERROR(Unknown tag #Tag.))
127
128/* Binary operator helpers */
129
130#define CRI_BINOP(Op, Actual, Ref) Actual Op Ref
131#define CRI_BINOP_EQ(Actual, Ref) CRI_BINOP(==, Actual, Ref)
132#define CRI_BINOP_NE(Actual, Ref) CRI_BINOP(!=, Actual, Ref)
133#define CRI_BINOP_LE(Actual, Ref) CRI_BINOP(<=, Actual, Ref)
134#define CRI_BINOP_LT(Actual, Ref) CRI_BINOP(<, Actual, Ref)
135#define CRI_BINOP_GE(Actual, Ref) CRI_BINOP(>=, Actual, Ref)
136#define CRI_BINOP_GT(Actual, Ref) CRI_BINOP(>, Actual, Ref)
137
138#ifdef __cplusplus
139
140# include "op.hxx"
141
142# define CRI_BINOP_T_EQ(Tag, Actual, Ref) CRI_BINOP_EQ(Actual, Ref)
143# define CRI_BINOP_T_NE(Tag, Actual, Ref) CRI_BINOP_NE(Actual, Ref)
144# define CRI_BINOP_T_LE(Tag, Actual, Ref) CRI_BINOP_LE(Actual, Ref)
145# define CRI_BINOP_T_LT(Tag, Actual, Ref) CRI_BINOP_LT(Actual, Ref)
146# define CRI_BINOP_T_GE(Tag, Actual, Ref) CRI_BINOP_GE(Actual, Ref)
147# define CRI_BINOP_T_GT(Tag, Actual, Ref) CRI_BINOP_GT(Actual, Ref)
148
149# define CRI_UNOP_ZERO(X) ::criterion::internal::operators::zero(X)
150# define CRI_UNOP_T_ZERO(Tag, X) ::criterion::internal::operators::zero(X)
151
152#else /* !__cplusplus */
153
154# define CRI_BINOP_EQ_TAG(Tag, Op, Actual, Ref) (Op (CRI_USER_TAG_ID(eq, Tag)(&(Actual), &(Ref))))
155# define CRI_BINOP_LT_TAG(Tag, Op, Actual, Ref) (Op (CRI_USER_TAG_ID(lt, Tag)(&(Actual), &(Ref))))
156
157# define CRI_BINOP_T_EQ(Tag, Actual, Ref) (CRI_BINOP_EQ_TAG(Tag, , Actual, Ref))
158# define CRI_BINOP_T_NE(Tag, Actual, Ref) (CRI_BINOP_EQ_TAG(Tag, !, Actual, Ref))
159# define CRI_BINOP_T_LE(Tag, Actual, Ref) (CRI_BINOP_LT_TAG(Tag, , Actual, Ref) || CRI_BINOP_EQ_TAG(Tag, , Actual, Ref))
160# define CRI_BINOP_T_LT(Tag, Actual, Ref) (CRI_BINOP_LT_TAG(Tag, , Actual, Ref))
161# define CRI_BINOP_T_GE(Tag, Actual, Ref) (CRI_BINOP_LT_TAG(Tag, !, Actual, Ref))
162# define CRI_BINOP_T_GT(Tag, Actual, Ref) (CRI_BINOP_LT_TAG(Tag, !, Actual, Ref) && CRI_BINOP_EQ_TAG(Tag, !, Actual, Ref))
163
164# define CRI_UNOP_ZERO(X) !(X)
165# define CRI_UNOP_T_ZERO(Tag, X) CRI_USER_TAG_ID(zero, Tag)(&(X))
166
167#endif /* !__cplusplus */
168
169/* These macros are here to extract a specific entry from the operator
170 parameter n-tuple. So, for instance, to get the VAR (2nd) parameter,
171 you'd do CRI_ASSERT_OPGET(VAR, (tuple)) */
172
173#define CRI_ASSERT_OPGET___(What, Kind) What ## Kind
174#define CRI_ASSERT_OPGET__(What, Kind) CRI_ASSERT_OPGET___(What, Kind)
175#define CRI_ASSERT_OPGET_(What, Kind) CRI_ASSERT_OPGET__(What, Kind)
176#define CRI_ASSERT_OPGET(What, Var) \
177 CRI_ASSERT_OPGET_(CRI_ASSERT_OP_ ## What ## _, CRI_ASSERT_OPKIND Var) \
178 CR_EXPAND(CRI_ASSERT_OPKIND_STRIP Var)
179
180#define CRI_ASSERT_OP_VAR_TAGGED(Type, Var, Name, MkNode, Val) Var
181#define CRI_ASSERT_OP_VAR_SINGLE(Type, Var, Name, MkNode, Val) Var
182
183#define CRI_ASSERT_OP_VAL_TAGGED(Type, Var, Name, MkNode, Val) Val
184#define CRI_ASSERT_OP_VAL_SINGLE(Type, Var, Name, MkNode, Val) Val
185
186#define CRI_ASSERT_OP_NAME_TAGGED(Type, Var, Name, MkNode, Val) Name
187#define CRI_ASSERT_OP_NAME_SINGLE(Type, Var, Name, MkNode, Val) Name
188
189#define CRI_ASSERT_OP_SUBSCRIPT_TAGGED(Type, Var, Name, MkNode, Val) Var[cri_i]
190#define CRI_ASSERT_OP_SUBSCRIPT_SINGLE(Type, Var, Name, MkNode, Val) Var
191
192#define CRI_ASSERT_OP_MKNODE_FIRST(First, Second) First
193#define CRI_ASSERT_OP_MKNODE_SECOND(First, Second) Second
194
195#define CRI_ASSERT_OP_MKNODE_TAGGED(Type, Var, Name, MkNode, Val) \
196 CRI_ASSERT_OP_MKNODE_FIRST MkNode
197#define CRI_ASSERT_OP_MKNODE_SINGLE(Type, Var, Name, MkNode, Val) \
198 CRI_ASSERT_OP_MKNODE_FIRST MkNode
199
200#define CRI_ASSERT_OP_MKNODE_ARR_TAGGED(Type, Var, Name, MkNode, Val) \
201 CRI_ASSERT_OP_MKNODE_SECOND MkNode
202#define CRI_ASSERT_OP_MKNODE_ARR_SINGLE(Type, Var, Name, MkNode, Val) \
203 CRI_ASSERT_OP_MKNODE_FIRST MkNode
204
205#define CRI_ASSERT_OP_TYPE_TAGGED(Type, Var, Name, MkNode, Val) Type
206#define CRI_ASSERT_OP_TYPE_SINGLE(Type, Var, Name, MkNode, Val) Type
207
208#define CRI_ASSERT_OP_ARRTYPE_TAGGED(Type, Var, Name, MkNode, Val) Type *
209#define CRI_ASSERT_OP_ARRTYPE_SINGLE(Type, Var, Name, MkNode, Val) Type
210
211#define CRI_ASSERT_OPKIND(Kind, Type, Var, Name, MkNode, Val) Kind
212#define CRI_ASSERT_OPKIND_STRIP(Kind, Type, Var, Name, MkNode, Val) (Type, Var, Name, MkNode, Val)
213
214#define CRI_ASSERT_IT_VAR(T, Var) \
215 CR_CHECKERROR(CRI_ASSERT_OPGET(T, Var)) \
216 CRI_ASSERT_OPGET(VAR, Var) = CRI_VALUE_ESCAPE( \
217 decltype (CRI_ASSERT_OPGET(VAR, Var)), CRI_ASSERT_OPGET(VAL, Var) \
218 );
219
220#define CRI_ASSERT_IT_VAR_AUTO(_, Var) \
221 CRI_AUTOTYPE CRI_ASSERT_OPGET(VAR, Var) = CRI_VALUE_ESCAPE( \
222 decltype (CRI_ASSERT_OPGET(VAL, Var)), CRI_ASSERT_OPGET(VAL, Var) \
223 );
224
225/* MSVC doesn't like obstructions, but it isn't necessary for their preprocessor
226 * implementation */
227#ifdef _MSC_VER
228# define CRI_ASSERT_IT_MKNODE(Tag, Var) \
229 CRI_ASSERT_OPGET(MKNODE, Var)( \
230 Tag, CRI_ASSERT_OPGET(VAR, Var), CRI_ASSERT_OPGET(NAME, Var) \
231 );
232# define CRI_ASSERT_IT_MKNODE_ARR(Tag, Var) \
233 CRI_ASSERT_OPGET(MKNODE_ARR, Var)( \
234 Tag, CRI_ASSERT_OPGET(VAR, Var), CRI_ASSERT_OPGET(NAME, Var) \
235 );
236# define CRI_ASSERT_IT_MKNODE_SUBSCRIPT(Tag, Var) \
237 CRI_ASSERT_OPGET(MKNODE, Var)( \
238 Tag, CRI_ASSERT_OPGET(VAR, Var)[cri_i], CRI_ASSERT_OPGET(NAME, Var) \
239 );
240#else
241# define CRI_ASSERT_IT_MKNODE(Tag, Var) \
242 CRI_OBSTRUCT_N(CRI_ASSERT_OPGET(MKNODE, Var))( \
243 Tag, CRI_ASSERT_OPGET(VAR, Var), CRI_ASSERT_OPGET(NAME, Var) \
244 );
245# define CRI_ASSERT_IT_MKNODE_ARR(Tag, Var) \
246 CRI_OBSTRUCT_N(CRI_ASSERT_OPGET(MKNODE_ARR, Var))( \
247 Tag, CRI_ASSERT_OPGET(VAR, Var), CRI_ASSERT_OPGET(NAME, Var) \
248 );
249# define CRI_ASSERT_IT_MKNODE_SUBSCRIPT(Tag, Var) \
250 CRI_OBSTRUCT_N(CRI_ASSERT_OPGET(MKNODE, Var))( \
251 Tag, CRI_ASSERT_OPGET(VAR, Var)[cri_i], CRI_ASSERT_OPGET(NAME, Var) \
252 );
253#endif
254
255#define CRI_ASSERT_IT_MKNODE_AUTO(Tag, Var) \
256 CRI_MKNODE_UNPRINTABLE(, CRI_ASSERT_OPGET(VAR, Var), CRI_ASSERT_OPGET(NAME, Var));
257
258#define CRI_ASSERT_IT_UNPACK(_, Var) , CRI_ASSERT_OPGET(VAR, Var)
259#define CRI_ASSERT_IT_VUNPACK(_, Var) , CRI_ASSERT_OPGET(VAL, Var)
260#define CRI_ASSERT_IT_SUNPACK(_, Var) , CRI_ASSERT_OPGET(SUBSCRIPT, Var)
261
262#define CRI_ASSERT_OP_APPLY(Op, ...) Op CR_EXPAND((__VA_ARGS__))
263
264#define CRI_ASSERT_MKLIST_1(Macro, L1, L2) Macro(CR_VA_HEAD L1, CR_VA_HEAD L2)
265#define CRI_ASSERT_MKLIST_2(Macro, L1, L2) Macro(CR_VA_HEAD L1, CR_VA_HEAD L2) CRI_ASSERT_MKLIST_1(Macro, (CR_VA_TAIL L1), (CR_VA_TAIL L2))
266#define CRI_ASSERT_MKLIST_3(Macro, L1, L2) Macro(CR_VA_HEAD L1, CR_VA_HEAD L2) CRI_ASSERT_MKLIST_2(Macro, (CR_VA_TAIL L1), (CR_VA_TAIL L2))
267#define CRI_ASSERT_MKLIST_4(Macro, L1, L2) Macro(CR_VA_HEAD L1, CR_VA_HEAD L2) CRI_ASSERT_MKLIST_3(Macro, (CR_VA_TAIL L1), (CR_VA_TAIL L2))
268
269#define CRI_ASSERT_MKLIST__(Macro, n, L1, L2) CRI_ASSERT_MKLIST_ ## n(Macro, L1, L2)
270#define CRI_ASSERT_MKLIST_(Macro, n, L1, L2) CRI_ASSERT_MKLIST__(Macro, n, L1, L2)
271#define CRI_ASSERT_MKLIST(Macro, L1, L2) CRI_ASSERT_MKLIST_(Macro, CRITERION_ARG_LENGTH L1, L1, L2)
272
273#define CRI_MKNODE_STR(Tag, Var, Name) \
274 do { \
275 char *cri_str = CRI_USER_TOSTR(Tag, Var); \
276 cri_tmpn.params[cri_paramidx].name = Name; \
277 cri_tmpn.params[cri_paramidx].type = CRI_ASSERT_RT_STR; \
278 cri_tmpn.params[cri_paramidx].data = cri_str; \
279 cri_paramidx++; \
280 } while (0)
281
282#define CRI_MKNODE_STR_ARR(Tag, Var, Name) \
283 do { \
284 char *cri_str = NULL; \
285 CRI_USER_TOSTR_ARR(cri_str, Var, Tag); \
286 cri_tmpn.params[cri_paramidx].name = Name; \
287 cri_tmpn.params[cri_paramidx].type = CRI_ASSERT_RT_STR; \
288 cri_tmpn.params[cri_paramidx].data = cri_str; \
289 cri_paramidx++; \
290 } while (0)
291
292#define CRI_MKNODE_UNPRINTABLE(_, Var, Name) \
293 do { \
294 char *cri_str = CRI_ASSERT_UNPRINTABLE(Var); \
295 cri_tmpn.params[cri_paramidx].name = Name; \
296 cri_tmpn.params[cri_paramidx].type = CRI_ASSERT_RT_STR; \
297 cri_tmpn.params[cri_paramidx].data = cri_str; \
298 cri_paramidx++; \
299 } while (0)
300
301/* The OPTAGLESS macro handling is here for tagless operator specifiers.
302 As the underlying implementation must have some kind of type system,
303 this only works when an autotype concept is available */
304#ifdef CRI_CAPS_AUTOTYPE
305# define CRI_ASSERT_SPECIFIER_OPTAGLESS(Op, Name, ...) \
306 1; do { \
307 CRI_ASSERT_NAMESPACES; \
308 CRITERION_APPLY(CRI_ASSERT_IT_VAR_AUTO, , __VA_ARGS__) \
309 cri_cond_un = CRI_ASSERT_OP_APPLY CR_EXPAND( \
310 (Op CRITERION_APPLY(CRI_ASSERT_IT_UNPACK, , __VA_ARGS__)) \
311 ); \
312 if (cri_cond_un != cri_cond_expect) { \
313 cri_assert_node_init(&cri_tmpn); \
314 cri_tmpn.repr = #Name "(" CR_STR CR_EXPAND( \
315 (CRITERION_APPLY(CRI_ASSERT_IT_VUNPACK, , __VA_ARGS__)) \
316 ) ")"; \
317 size_t cri_paramidx = 0; \
318 CRITERION_APPLY(CRI_ASSERT_IT_MKNODE_AUTO, , __VA_ARGS__) \
319 cri_tmpn.pass = !!cri_cond_un; \
320 cri_prevnode = cri_assert_node_add(cri_node, &cri_tmpn); \
321 } \
322 } while (0)
323#else
324# define CRI_ASSERT_SPECIFIER_OPTAGLESS(Op, Name, ...) \
325 1; CR_COMPILE_ERROR(Name without a tag parameter is unsupported on this compiler.)
326#endif
327
328/* The OPTAG macro handling is here for tagged operator specifiers.
329 The handling comes in two flavors: one for scalar tags, and one
330 for array tags. */
331
332#define CRI_ASSERT_SPECIFIER_OPTAG(Op, Name, Tag, ...) \
333 CRI_IF_DEFINED_NODEFER(CR_EXPAND(CRI_ASSERT_TEST_TAGC_ ## Tag()), \
334 CRI_ASSERT_SPECIFIER_OPTAG_SCALAR, , \
335 CRI_ASSERT_SPECIFIER_OPTAG_ARRAY, \
336 )(Op, Name, Tag, __VA_ARGS__)
337
338#define CRI_ASSERT_SPECIFIER_OPTAG_SCALAR(Op, Name, Tag, ...) \
339 1; do { \
340 CRI_ASSERT_NAMESPACES; \
341 CRITERION_APPLY(CRI_ASSERT_IT_VAR, TYPE, __VA_ARGS__) \
342 cri_cond_un = CRI_ASSERT_OP_APPLY(Op, Tag \
343 CRITERION_APPLY(CRI_ASSERT_IT_UNPACK,, __VA_ARGS__)); \
344 if (cri_cond_un != cri_cond_expect) { \
345 cri_assert_node_init(&cri_tmpn); \
346 cri_tmpn.repr = #Name "(" #Tag CR_STR CR_EXPAND( \
347 (CRITERION_APPLY(CRI_ASSERT_IT_VUNPACK,, __VA_ARGS__)) \
348 ) ")"; \
349 size_t cri_paramidx = 0; \
350 CRITERION_APPLY(CRI_ASSERT_IT_MKNODE, Tag, __VA_ARGS__) \
351 cri_tmpn.pass = !!cri_cond_un; \
352 cri_prevnode = cri_assert_node_add(cri_node, &cri_tmpn); \
353 } \
354 } while (0)
355
356#define CRI_ASSERT_SPECIFIER_OPTAG_ARRAY(Op, Name, Tag, ...) \
357 1; do { \
358 CRI_ASSERT_NAMESPACES; \
359 CRITERION_APPLY(CRI_ASSERT_IT_VAR, ARRTYPE, __VA_ARGS__) \
360 size_t cri_size = CRI_ASSERT_TYPE_TAG_ARRLEN(Tag); \
361 cri_assert_node_init(&cri_tmpn); \
362 const char *cri_repr = #Name "(" #Tag CR_STR CR_EXPAND( \
363 (CRITERION_APPLY(CRI_ASSERT_IT_VUNPACK, , __VA_ARGS__)) \
364 ) ")"; \
365 cri_tmpn.repr = cri_repr; \
366 cri_tmpn.pass = 1; \
367 size_t cri_paramidx = 0; \
368 CRITERION_APPLY(CRI_ASSERT_IT_MKNODE_ARR, Tag, __VA_ARGS__) \
369 struct cri_assert_node *cri_tmp = cri_assert_node_add(cri_node, &cri_tmpn); \
370 struct cri_assert_node *cri_node = cri_tmp; \
371 for (size_t cri_i = 0; cri_i < cri_size; ++cri_i) { \
372 cri_assert_node_init(&cri_tmpn); \
373 cr_asprintf((char **) &cri_tmpn.repr, "%s [%" CRI_PRIuSIZE "]", \
374 cri_repr, cri_i); \
375 cri_tmpn.dynrepr = 1; \
376 cri_paramidx = 0; \
377 CRITERION_APPLY(CRI_ASSERT_IT_MKNODE_SUBSCRIPT, Tag, __VA_ARGS__) \
378 cri_tmpn.pass = !!(CRI_ASSERT_OP_APPLY(Op, \
379 Tag CRITERION_APPLY(CRI_ASSERT_IT_SUNPACK, , __VA_ARGS__))); \
380 cri_prevnode = cri_assert_node_add(cri_node, &cri_tmpn); \
381 cri_node->pass = cri_node->pass && cri_tmpn.pass; \
382 } \
383 cri_cond_un = cri_node->pass; \
384 } while (0)
385
386#define CRI_ASSERT_SPECIFIER_OP_HELPER(Op, N, ...) \
387 CR_DEFER(CR_CONCAT)(CRI_ASSERT_SPECIFIER_ ## Op, N)(__VA_ARGS__)
388
389#define CRI_ASSERT_SPEC_OPLEN_1(...) \
390 CR_EXPAND(CR_VA_TAIL_SELECT64(__VA_ARGS__, \
391 1, 1, 1, 1, \
392 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
393 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
394 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
395 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
396 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
397 1, 1, 1, 1, 1, 1, 1, 1, 0, 0))
398
399#define CRI_ASSERT_SPEC_OPLEN_2(...) \
400 CR_EXPAND(CR_VA_TAIL_SELECT64(__VA_ARGS__, \
401 1, 1, 1, 1, \
402 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
403 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
404 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
405 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
406 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
407 1, 1, 1, 1, 1, 1, 1, 0, 0, 0))
408
409#define CRI_ASSERT_SPEC_OPLEN_3(...) \
410 CR_EXPAND(CR_VA_TAIL_SELECT64(__VA_ARGS__, \
411 1, 1, 1, 1, \
412 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
413 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
414 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
415 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
416 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
417 1, 1, 1, 1, 1, 1, 0, 0, 0, 0))
418
419#define CRI_ASSERT_SPEC_OPLEN__(N, Va) \
420 CR_EXPAND(CRI_ASSERT_SPEC_OPLEN_ ## N Va)
421#define CRI_ASSERT_SPEC_OPLEN_(N, Va) \
422 CRI_ASSERT_SPEC_OPLEN__(N, Va)
423#define CRI_ASSERT_SPEC_OPLEN(Params, Va) \
424 CRI_ASSERT_SPEC_OPLEN_(CRITERION_ARG_LENGTH Params, Va)
425
426#endif /* !CRITERION_INTERNAL_ASSERT_OP_H_ */