]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | |
2 | // (C) Copyright Edward Diener 2011-2015 | |
3 | // Use, modification and distribution are subject to the Boost Software License, | |
4 | // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at | |
5 | // http://www.boost.org/LICENSE_1_0.txt). | |
6 | ||
7 | #if !defined(BOOST_VMD_TEST_DOC_EXAMPLE_SWITCH_HPP) | |
8 | #define BOOST_VMD_TEST_DOC_EXAMPLE_SWITCH_HPP | |
9 | ||
10 | //[ example_switch | |
11 | ||
12 | #include <boost/vmd/detail/setup.hpp> | |
13 | ||
14 | #if BOOST_PP_VARIADICS | |
15 | ||
16 | #include <boost/preprocessor/cat.hpp> | |
17 | #include <boost/preprocessor/arithmetic/inc.hpp> | |
18 | #include <boost/preprocessor/comparison/equal.hpp> | |
19 | #include <boost/preprocessor/control/expr_iif.hpp> | |
20 | #include <boost/preprocessor/control/iif.hpp> | |
21 | #include <boost/preprocessor/control/while.hpp> | |
22 | #include <boost/preprocessor/tuple/elem.hpp> | |
23 | #include <boost/preprocessor/tuple/enum.hpp> | |
24 | #include <boost/preprocessor/facilities/expand.hpp> | |
25 | #include <boost/preprocessor/tuple/replace.hpp> | |
26 | #include <boost/preprocessor/tuple/size.hpp> | |
27 | #include <boost/preprocessor/variadic/to_tuple.hpp> | |
28 | #include <boost/preprocessor/variadic/size.hpp> | |
29 | #include <boost/vmd/equal.hpp> | |
30 | #include <boost/vmd/identity.hpp> | |
31 | #include <boost/vmd/is_empty.hpp> | |
32 | ||
33 | /* | |
34 | ||
35 | State index into state values | |
36 | ||
37 | */ | |
38 | ||
39 | #define BOOST_VMD_SWITCH_STATE_ELEM_INDEX 2 | |
40 | #define BOOST_VMD_SWITCH_STATE_ELEM_DEFAULT 4 | |
41 | #define BOOST_VMD_SWITCH_STATE_ELEM_RESULT 5 | |
42 | ||
43 | /* | |
44 | ||
45 | Retrieve the state value, never changes | |
46 | ||
47 | */ | |
48 | ||
49 | #define BOOST_VMD_SWITCH_STATE_GET_VALUE(state) \ | |
50 | BOOST_PP_TUPLE_ELEM(0,state) \ | |
51 | /**/ | |
52 | ||
53 | /* | |
54 | ||
55 | Retrieve the state tuple of values, never changes | |
56 | ||
57 | */ | |
58 | ||
59 | #define BOOST_VMD_SWITCH_STATE_GET_CHOICES(state) \ | |
60 | BOOST_PP_TUPLE_ELEM(1,state) \ | |
61 | /**/ | |
62 | ||
63 | /* | |
64 | ||
65 | Retrieve the state index | |
66 | ||
67 | */ | |
68 | ||
69 | #define BOOST_VMD_SWITCH_STATE_GET_INDEX(state) \ | |
70 | BOOST_PP_TUPLE_ELEM(2,state) \ | |
71 | /**/ | |
72 | ||
73 | /* | |
74 | ||
75 | Retrieve the state tuple of values size, never changes | |
76 | ||
77 | */ | |
78 | ||
79 | #define BOOST_VMD_SWITCH_STATE_GET_SIZE(state) \ | |
80 | BOOST_PP_TUPLE_ELEM(3,state) \ | |
81 | /**/ | |
82 | ||
83 | /* | |
84 | ||
85 | Retrieve the state default tuple | |
86 | ||
87 | */ | |
88 | ||
89 | #define BOOST_VMD_SWITCH_STATE_GET_DEFAULT(state) \ | |
90 | BOOST_PP_TUPLE_ELEM(4,state) \ | |
91 | /**/ | |
92 | ||
93 | /* | |
94 | ||
95 | Retrieve the state result tuple | |
96 | ||
97 | */ | |
98 | ||
99 | #define BOOST_VMD_SWITCH_STATE_GET_RESULT(state) \ | |
100 | BOOST_PP_TUPLE_ELEM(5,state) \ | |
101 | /**/ | |
102 | ||
103 | /* | |
104 | ||
105 | Retrieve the current value tuple | |
106 | ||
107 | */ | |
108 | ||
109 | #define BOOST_VMD_SWITCH_STATE_GET_CURRENT_CHOICE(state) \ | |
110 | BOOST_PP_TUPLE_ELEM \ | |
111 | ( \ | |
112 | BOOST_VMD_SWITCH_STATE_GET_INDEX(state), \ | |
113 | BOOST_VMD_SWITCH_STATE_GET_CHOICES(state) \ | |
114 | ) \ | |
115 | /**/ | |
116 | ||
117 | /* | |
118 | ||
119 | Expands to the state | |
120 | ||
121 | value = value to compare against | |
122 | tuple = choices as a tuple of values | |
123 | size = size of tuple of values | |
124 | ||
125 | None of these ever change in the WHILE state | |
126 | ||
127 | */ | |
128 | ||
129 | #define BOOST_VMD_SWITCH_STATE_EXPAND(value,tuple,size) \ | |
130 | (value,tuple,0,size,(0,),(,)) \ | |
131 | /**/ | |
132 | ||
133 | /* | |
134 | ||
135 | Expands to the WHILE state | |
136 | ||
137 | The state to our WHILE consists of a tuple of elements: | |
138 | ||
139 | 1: value to compare against | |
140 | 2: tuple of values. Each value is a value/macro pair or if the default just a macro | |
141 | 3: index into the values | |
142 | 4: tuple for default macro. 0 means no default macro, 1 means default macro and then second value is the default macro. | |
143 | 5: tuple of result matched. Emptiness means no result yet specified, 0 means no match, 1 means match and second value is the matching macro. | |
144 | ||
145 | */ | |
146 | ||
147 | #define BOOST_VMD_SWITCH_STATE(value,...) \ | |
148 | BOOST_VMD_SWITCH_STATE_EXPAND \ | |
149 | ( \ | |
150 | value, \ | |
151 | BOOST_PP_VARIADIC_TO_TUPLE(__VA_ARGS__), \ | |
152 | BOOST_PP_VARIADIC_SIZE(__VA_ARGS__) \ | |
153 | ) \ | |
154 | /**/ | |
155 | ||
156 | /* | |
157 | ||
158 | Sets the state upon a successful match. | |
159 | ||
160 | macro = is the matching macro found | |
161 | ||
162 | */ | |
163 | ||
164 | #define BOOST_VMD_SWITCH_OP_SUCCESS(d,state,macro) \ | |
165 | BOOST_PP_TUPLE_REPLACE_D \ | |
166 | ( \ | |
167 | d, \ | |
168 | state, \ | |
169 | BOOST_VMD_SWITCH_STATE_ELEM_RESULT, \ | |
170 | (1,macro) \ | |
171 | ) \ | |
172 | /**/ | |
173 | ||
174 | /* | |
175 | ||
176 | Sets the state upon final failure to find a match. | |
177 | ||
178 | def = default tuple macro, ignored | |
179 | ||
180 | */ | |
181 | ||
182 | #define BOOST_VMD_SWITCH_OP_FAILURE(d,state,def) \ | |
183 | BOOST_PP_TUPLE_REPLACE_D \ | |
184 | ( \ | |
185 | d, \ | |
186 | state, \ | |
187 | BOOST_VMD_SWITCH_STATE_ELEM_RESULT, \ | |
188 | (0,) \ | |
189 | ) \ | |
190 | /**/ | |
191 | ||
192 | /* | |
193 | ||
194 | Increments the state index into the tuple values | |
195 | ||
196 | */ | |
197 | ||
198 | #define BOOST_VMD_SWITCH_OP_UPDATE_INDEX(d,state) \ | |
199 | BOOST_PP_TUPLE_REPLACE_D \ | |
200 | ( \ | |
201 | d, \ | |
202 | state, \ | |
203 | BOOST_VMD_SWITCH_STATE_ELEM_INDEX, \ | |
204 | BOOST_PP_INC(BOOST_VMD_SWITCH_STATE_GET_INDEX(state)) \ | |
205 | ) \ | |
206 | /**/ | |
207 | ||
208 | /* | |
209 | ||
210 | Choose our current value's macro as our successful match | |
211 | ||
212 | tuple = current tuple to test | |
213 | ||
214 | */ | |
215 | ||
216 | #define BOOST_VMD_SWITCH_OP_TEST_CURRENT_VALUE_MATCH(d,state,tuple) \ | |
217 | BOOST_VMD_SWITCH_OP_SUCCESS(d,state,BOOST_PP_TUPLE_ELEM(1,tuple)) \ | |
218 | /**/ | |
219 | ||
220 | /* | |
221 | ||
222 | Update our state index | |
223 | ||
224 | tuple = current tuple to test, ignored | |
225 | ||
226 | */ | |
227 | ||
228 | #define BOOST_VMD_SWITCH_OP_TEST_CURRENT_VALUE_UPDATE_INDEX(d,state,tuple) \ | |
229 | BOOST_VMD_SWITCH_OP_UPDATE_INDEX(d,state) \ | |
230 | /**/ | |
231 | ||
232 | /* | |
233 | ||
234 | Test our current value against our value to compare against | |
235 | ||
236 | tuple = current tuple to test | |
237 | ||
238 | */ | |
239 | ||
240 | #define BOOST_VMD_SWITCH_OP_TEST_CURRENT_VALUE(d,state,tuple) \ | |
241 | BOOST_PP_IIF \ | |
242 | ( \ | |
243 | BOOST_VMD_EQUAL_D \ | |
244 | ( \ | |
245 | d, \ | |
246 | BOOST_VMD_SWITCH_STATE_GET_VALUE(state), \ | |
247 | BOOST_PP_TUPLE_ELEM(0,tuple) \ | |
248 | ), \ | |
249 | BOOST_VMD_SWITCH_OP_TEST_CURRENT_VALUE_MATCH, \ | |
250 | BOOST_VMD_SWITCH_OP_TEST_CURRENT_VALUE_UPDATE_INDEX \ | |
251 | ) \ | |
252 | (d,state,tuple) \ | |
253 | /**/ | |
254 | ||
255 | /* | |
256 | ||
257 | Set our default macro and update the index in our WHILE state | |
258 | ||
259 | tuple = current tuple to test | |
260 | ||
261 | */ | |
262 | ||
263 | #if BOOST_VMD_MSVC | |
264 | ||
265 | #define BOOST_VMD_SWITCH_OP_TEST_CURRENT_CREATE_DEFAULT_NN(number,name) \ | |
266 | (number,name) \ | |
267 | /**/ | |
268 | ||
269 | #define BOOST_VMD_SWITCH_OP_TEST_CURRENT_CREATE_DEFAULT(d,state,tuple) \ | |
270 | BOOST_VMD_SWITCH_OP_UPDATE_INDEX \ | |
271 | ( \ | |
272 | d, \ | |
273 | BOOST_PP_TUPLE_REPLACE_D \ | |
274 | ( \ | |
275 | d, \ | |
276 | state, \ | |
277 | BOOST_VMD_SWITCH_STATE_ELEM_DEFAULT, \ | |
278 | BOOST_VMD_SWITCH_OP_TEST_CURRENT_CREATE_DEFAULT_NN(1,BOOST_PP_TUPLE_ENUM(tuple)) \ | |
279 | ) \ | |
280 | ) \ | |
281 | /**/ | |
282 | ||
283 | #else | |
284 | ||
285 | #define BOOST_VMD_SWITCH_OP_TEST_CURRENT_CREATE_DEFAULT(d,state,tuple) \ | |
286 | BOOST_VMD_SWITCH_OP_UPDATE_INDEX \ | |
287 | ( \ | |
288 | d, \ | |
289 | BOOST_PP_TUPLE_REPLACE_D \ | |
290 | ( \ | |
291 | d, \ | |
292 | state, \ | |
293 | BOOST_VMD_SWITCH_STATE_ELEM_DEFAULT, \ | |
294 | (1,BOOST_PP_TUPLE_ENUM(tuple)) \ | |
295 | ) \ | |
296 | ) \ | |
297 | /**/ | |
298 | ||
299 | #endif | |
300 | ||
301 | /* | |
302 | ||
303 | If our current value is a default macro, just set the default macro, | |
304 | else test our current value. | |
305 | ||
306 | tuple = current tuple to test | |
307 | ||
308 | */ | |
309 | ||
310 | #define BOOST_VMD_SWITCH_OP_TEST_CURRENT_TUPLE(d,state,tuple) \ | |
311 | BOOST_PP_IIF \ | |
312 | ( \ | |
313 | BOOST_PP_EQUAL_D \ | |
314 | ( \ | |
315 | d, \ | |
316 | BOOST_PP_TUPLE_SIZE(tuple), \ | |
317 | 1 \ | |
318 | ), \ | |
319 | BOOST_VMD_SWITCH_OP_TEST_CURRENT_CREATE_DEFAULT, \ | |
320 | BOOST_VMD_SWITCH_OP_TEST_CURRENT_VALUE \ | |
321 | ) \ | |
322 | (d,state,tuple) \ | |
323 | /**/ | |
324 | ||
325 | /* | |
326 | ||
327 | Test the current value in our tuple of values | |
328 | ||
329 | */ | |
330 | ||
331 | #define BOOST_VMD_SWITCH_OP_TEST_CURRENT(d,state) \ | |
332 | BOOST_VMD_SWITCH_OP_TEST_CURRENT_TUPLE \ | |
333 | ( \ | |
334 | d, \ | |
335 | state, \ | |
336 | BOOST_VMD_SWITCH_STATE_GET_CURRENT_CHOICE(state) \ | |
337 | ) \ | |
338 | /**/ | |
339 | ||
340 | /* | |
341 | ||
342 | Choose the default macro as our successful match | |
343 | ||
344 | def = default tuple consisting of just the default macro name | |
345 | ||
346 | */ | |
347 | ||
348 | #define BOOST_VMD_SWITCH_OP_DEFAULT_RET_CHOSEN(d,state,def) \ | |
349 | BOOST_VMD_SWITCH_OP_SUCCESS \ | |
350 | ( \ | |
351 | d, \ | |
352 | state, \ | |
353 | BOOST_PP_TUPLE_ELEM(1,def) \ | |
354 | ) \ | |
355 | /**/ | |
356 | ||
357 | /* | |
358 | ||
359 | If the default macro exists, choose it else indicate no macro was found | |
360 | ||
361 | def = default tuple consisting of just the default macro name | |
362 | ||
363 | */ | |
364 | ||
365 | #define BOOST_VMD_SWITCH_OP_DEFAULT_RET(d,state,def) \ | |
366 | BOOST_PP_IIF \ | |
367 | ( \ | |
368 | BOOST_PP_TUPLE_ELEM(0,def), \ | |
369 | BOOST_VMD_SWITCH_OP_DEFAULT_RET_CHOSEN, \ | |
370 | BOOST_VMD_SWITCH_OP_FAILURE \ | |
371 | ) \ | |
372 | (d,state,def) \ | |
373 | /**/ | |
374 | ||
375 | /* | |
376 | ||
377 | Try to choose the default macro if it exists | |
378 | ||
379 | */ | |
380 | ||
381 | #define BOOST_VMD_SWITCH_OP_DEFAULT(d,state) \ | |
382 | BOOST_VMD_SWITCH_OP_DEFAULT_RET \ | |
383 | ( \ | |
384 | d, \ | |
385 | state, \ | |
386 | BOOST_VMD_SWITCH_STATE_GET_DEFAULT(state) \ | |
387 | ) \ | |
388 | /**/ | |
389 | ||
390 | /* | |
391 | ||
392 | WHILE loop operation | |
393 | ||
394 | Check for the next value match or try to choose the default if all matches have been checked | |
395 | ||
396 | */ | |
397 | ||
398 | #define BOOST_VMD_SWITCH_OP(d,state) \ | |
399 | BOOST_PP_IIF \ | |
400 | ( \ | |
401 | BOOST_PP_EQUAL_D \ | |
402 | ( \ | |
403 | d, \ | |
404 | BOOST_VMD_SWITCH_STATE_GET_INDEX(state), \ | |
405 | BOOST_VMD_SWITCH_STATE_GET_SIZE(state) \ | |
406 | ), \ | |
407 | BOOST_VMD_SWITCH_OP_DEFAULT, \ | |
408 | BOOST_VMD_SWITCH_OP_TEST_CURRENT \ | |
409 | ) \ | |
410 | (d,state) \ | |
411 | /**/ | |
412 | ||
413 | /* | |
414 | ||
415 | WHILE loop predicate | |
416 | ||
417 | Continue the WHILE loop if a result has not yet been specified | |
418 | ||
419 | */ | |
420 | ||
421 | #define BOOST_VMD_SWITCH_PRED(d,state) \ | |
422 | BOOST_VMD_IS_EMPTY \ | |
423 | ( \ | |
424 | BOOST_PP_TUPLE_ELEM \ | |
425 | ( \ | |
426 | 0, \ | |
427 | BOOST_VMD_SWITCH_STATE_GET_RESULT(state) \ | |
428 | ) \ | |
429 | ) \ | |
430 | /**/ | |
431 | ||
432 | /* | |
433 | ||
434 | Invokes the function-like macro | |
435 | ||
436 | macro = function-like macro name | |
437 | tparams = tuple of macro parameters | |
438 | ||
439 | */ | |
440 | ||
441 | #define BOOST_VMD_SWITCH_PROCESS_INVOKE_MACRO(macro,tparams) \ | |
442 | BOOST_PP_EXPAND(macro tparams) \ | |
443 | /**/ | |
444 | ||
445 | /* | |
446 | ||
447 | Processes our WHILE loop result | |
448 | ||
449 | callp = tuple of parameters for the called macro | |
450 | result = tuple. The first tuple element is 0 | |
451 | if no macro has been found or 1 if a macro | |
452 | has been found. If 1 the second element is | |
453 | the name of a function-like macro | |
454 | ||
455 | */ | |
456 | ||
457 | #define BOOST_VMD_SWITCH_PROCESS(callp,result) \ | |
458 | BOOST_PP_EXPR_IIF \ | |
459 | ( \ | |
460 | BOOST_PP_TUPLE_ELEM(0,result), \ | |
461 | BOOST_VMD_SWITCH_PROCESS_INVOKE_MACRO \ | |
462 | ( \ | |
463 | BOOST_PP_TUPLE_ELEM(1,result), \ | |
464 | callp \ | |
465 | ) \ | |
466 | ) \ | |
467 | /**/ | |
468 | ||
469 | /* | |
470 | ||
471 | Use BOOST_VMD_SWITCH_IDENTITY to pass a fixed value instead | |
472 | of a function-like macro as the second element of | |
473 | any tuple of the variadic parameters, or as the default | |
474 | value, to BOOST_VMD_SWITCH. | |
475 | ||
476 | */ | |
477 | ||
478 | #if BOOST_VMD_MSVC | |
479 | #define BOOST_VMD_SWITCH_IDENTITY(item) BOOST_PP_CAT(BOOST_VMD_IDENTITY(item),) | |
480 | #else | |
481 | #define BOOST_VMD_SWITCH_IDENTITY BOOST_VMD_IDENTITY | |
482 | #endif | |
483 | ||
484 | /* | |
485 | ||
486 | Switch macro | |
487 | ||
488 | Parameters are: | |
489 | ||
490 | value = value to compare against. May be any VMD data value. | |
491 | callp = tuple of parameters for the called macro | |
492 | variadic parameters = each parameter must be a tuple. | |
493 | Each tuple consists of a two-element tuple. The first element is | |
494 | a value, which may be any VMD data value, and the second element | |
495 | is the name of a function-like macro to be called if the value | |
496 | is equal to the value to compare against. For a default value | |
497 | the tuple is a single-element tuple which contains the name of | |
498 | a function-like macro to be called if no other value matches. | |
499 | ||
500 | */ | |
501 | ||
502 | #define BOOST_VMD_SWITCH(value,callp,...) \ | |
503 | BOOST_VMD_SWITCH_PROCESS \ | |
504 | ( \ | |
505 | callp, \ | |
506 | BOOST_VMD_SWITCH_STATE_GET_RESULT \ | |
507 | ( \ | |
508 | BOOST_PP_WHILE \ | |
509 | ( \ | |
510 | BOOST_VMD_SWITCH_PRED, \ | |
511 | BOOST_VMD_SWITCH_OP, \ | |
512 | BOOST_VMD_SWITCH_STATE(value,__VA_ARGS__) \ | |
513 | ) \ | |
514 | ) \ | |
515 | ) \ | |
516 | /**/ | |
517 | ||
518 | #endif /* BOOST_PP_VARIADICS */ | |
519 | ||
520 | //] | |
521 | ||
522 | #endif /* BOOST_VMD_TEST_DOC_EXAMPLE_SWITCH_HPP */ |