• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 */
523