1// Copyright (c) 2001-2012 Hartmut Kaiser
2//
3// Distributed under the Boost Software License, Version 1.0. (See accompanying
4// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5
6#if !defined(BOOST_SPIRIT_ITERATOR_COMBINE_POLICIES_APR_06_2008_0136PM)
7#define BOOST_SPIRIT_ITERATOR_COMBINE_POLICIES_APR_06_2008_0136PM
8
9#include <boost/config.hpp>
10#include <boost/type_traits/is_empty.hpp>
11
12namespace boost { namespace spirit { namespace iterator_policies
13{
14 ///////////////////////////////////////////////////////////////////////////
15 // The purpose of the multi_pass_unique template is to eliminate
16 // empty policy classes (policies not containing any data items) from the
17 // multiple inheritance chain. This is necessary since some compilers
18 // fail to apply the empty base optimization if multiple inheritance is
19 // involved.
20 // Additionally this can be used to combine separate policies into one
21 // single multi_pass_policy as required by the multi_pass template
22 ///////////////////////////////////////////////////////////////////////////
23
24 ///////////////////////////////////////////////////////////////////////////
25 // select the correct derived classes based on if a policy is empty
26 template <typename T
27 , typename Ownership, typename Checking, typename Input, typename Storage
28 , bool OwnershipIsEmpty = boost::is_empty<Ownership>::value
29 , bool CheckingIsEmpty = boost::is_empty<Checking>::value
30 , bool InputIsEmpty = boost::is_empty<Input>::value>
31 struct multi_pass_unique;
32
33 ///////////////////////////////////////////////////////////////////////////
34 template <typename T, typename Ownership, typename Checking
35 , typename Input, typename Storage>
36 struct multi_pass_unique<T, Ownership, Checking, Input, Storage
37 , false, false, false>
38 : Ownership, Checking, Input, Storage
39 {
40 multi_pass_unique() {}
41 multi_pass_unique(T& x) : Input(x) {}
42 multi_pass_unique(T const& x) : Input(x) {}
43
44 template <typename MultiPass>
45 static void destroy(MultiPass& mp)
46 {
47 Ownership::destroy(mp);
48 Checking::destroy(mp);
49 Input::destroy(mp);
50 Storage::destroy(mp);
51 }
52
53 void swap(multi_pass_unique& x)
54 {
55 this->Ownership::swap(x);
56 this->Checking::swap(x);
57 this->Input::swap(x);
58 this->Storage::swap(x);
59 }
60
61 template <typename MultiPass>
62 inline static void clear_queue(MultiPass& mp)
63 {
64 Checking::clear_queue(mp);
65 Storage::clear_queue(mp);
66 }
67 };
68
69 ///////////////////////////////////////////////////////////////////////////
70 template <typename T, typename Ownership, typename Checking
71 , typename Input, typename Storage>
72 struct multi_pass_unique<T, Ownership, Checking, Input, Storage
73 , false, false, true>
74 : Ownership, Checking, Storage
75 {
76 multi_pass_unique() {}
77 multi_pass_unique(T const&) {}
78
79 template <typename MultiPass>
80 static void destroy(MultiPass& mp)
81 {
82 Ownership::destroy(mp);
83 Checking::destroy(mp);
84 Input::destroy(mp);
85 Storage::destroy(mp);
86 }
87
88 void swap(multi_pass_unique& x)
89 {
90 this->Ownership::swap(x);
91 this->Checking::swap(x);
92 this->Storage::swap(x);
93 }
94
95 template <typename MultiPass>
96 inline static void clear_queue(MultiPass& mp)
97 {
98 Checking::clear_queue(mp);
99 Storage::clear_queue(mp);
100 }
101
102 // implement input policy functions by forwarding to the Input type
103 template <typename MultiPass>
104 inline static void advance_input(MultiPass& mp)
105 { Input::advance_input(mp); }
106
107 template <typename MultiPass>
108 inline static typename MultiPass::reference get_input(MultiPass& mp)
109 { return Input::get_input(mp); }
110
111 template <typename MultiPass>
112 inline static bool input_at_eof(MultiPass const& mp)
113 { return Input::input_at_eof(mp); }
114
115 template <typename MultiPass, typename TokenType>
116 inline static bool input_is_valid(MultiPass& mp, TokenType& curtok)
117 { return Input::input_is_valid(mp, curtok); }
118 };
119
120 ///////////////////////////////////////////////////////////////////////////
121 template <typename T, typename Ownership, typename Checking
122 , typename Input, typename Storage>
123 struct multi_pass_unique<T, Ownership, Checking, Input, Storage
124 , false, true, false>
125 : Ownership, Input, Storage
126 {
127 multi_pass_unique() {}
128 multi_pass_unique(T& x) : Input(x) {}
129 multi_pass_unique(T const& x) : Input(x) {}
130
131 template <typename MultiPass>
132 static void destroy(MultiPass& mp)
133 {
134 Ownership::destroy(mp);
135 Input::destroy(mp);
136 Storage::destroy(mp);
137 }
138
139 void swap(multi_pass_unique& x)
140 {
141 this->Ownership::swap(x);
142 this->Input::swap(x);
143 this->Storage::swap(x);
144 }
145
146 template <typename MultiPass>
147 inline static void clear_queue(MultiPass& mp)
148 {
149 Checking::clear_queue(mp);
150 Storage::clear_queue(mp);
151 }
152
153 // checking policy functions are forwarded to the Checking type
154 template <typename MultiPass>
155 inline static void docheck(MultiPass const& mp)
156 { Checking::docheck(mp); }
157 };
158
159 ///////////////////////////////////////////////////////////////////////////
160 template <typename T, typename Ownership, typename Checking
161 , typename Input, typename Storage>
162 struct multi_pass_unique<T, Ownership, Checking, Input, Storage
163 , false, true, true>
164 : Ownership, Storage
165 {
166 multi_pass_unique() {}
167 multi_pass_unique(T const&) {}
168
169 template <typename MultiPass>
170 static void destroy(MultiPass& mp)
171 {
172 Ownership::destroy(mp);
173 Input::destroy(mp);
174 Storage::destroy(mp);
175 }
176
177 void swap(multi_pass_unique& x)
178 {
179 this->Ownership::swap(x);
180 this->Storage::swap(x);
181 }
182
183 template <typename MultiPass>
184 inline static void clear_queue(MultiPass& mp)
185 {
186 Checking::clear_queue(mp);
187 Storage::clear_queue(mp);
188 }
189
190 // implement input policy functions by forwarding to the Input type
191 template <typename MultiPass>
192 inline static void advance_input(MultiPass& mp)
193 { Input::advance_input(mp); }
194
195 template <typename MultiPass>
196 inline static typename MultiPass::reference get_input(MultiPass& mp)
197 { return Input::get_input(mp); }
198
199 template <typename MultiPass>
200 inline static bool input_at_eof(MultiPass const& mp)
201 { return Input::input_at_eof(mp); }
202
203 template <typename MultiPass, typename TokenType>
204 inline static bool input_is_valid(MultiPass& mp, TokenType& curtok)
205 { return Input::input_is_valid(mp, curtok); }
206
207 // checking policy functions are forwarded to the Checking type
208 template <typename MultiPass>
209 inline static void docheck(MultiPass const& mp)
210 { Checking::docheck(mp); }
211 };
212
213 ///////////////////////////////////////////////////////////////////////////
214 template <typename T, typename Ownership, typename Checking
215 , typename Input, typename Storage>
216 struct multi_pass_unique<T, Ownership, Checking, Input, Storage
217 , true, false, false>
218 : Checking, Input, Storage
219 {
220 multi_pass_unique() {}
221 multi_pass_unique(T& x) : Input(x) {}
222 multi_pass_unique(T const& x) : Input(x) {}
223
224 template <typename MultiPass>
225 static void destroy(MultiPass& mp)
226 {
227 Checking::destroy(mp);
228 Input::destroy(mp);
229 Storage::destroy(mp);
230 }
231
232 void swap(multi_pass_unique& x)
233 {
234 this->Checking::swap(x);
235 this->Input::swap(x);
236 this->Storage::swap(x);
237 }
238
239 template <typename MultiPass>
240 inline static void clear_queue(MultiPass& mp)
241 {
242 Checking::clear_queue(mp);
243 Storage::clear_queue(mp);
244 }
245
246 // ownership policy functions are forwarded to the Ownership type
247 template <typename MultiPass>
248 inline static void clone(MultiPass& mp)
249 { Ownership::clone(mp); }
250
251 template <typename MultiPass>
252 inline static bool release(MultiPass& mp)
253 { return Ownership::release(mp); }
254
255 template <typename MultiPass>
256 inline static bool is_unique(MultiPass const& mp)
257 { return Ownership::is_unique(mp); }
258 };
259
260 ///////////////////////////////////////////////////////////////////////////
261 template <typename T, typename Ownership, typename Checking
262 , typename Input, typename Storage>
263 struct multi_pass_unique<T, Ownership, Checking, Input, Storage
264 , true, false, true>
265 : Checking, Storage
266 {
267 multi_pass_unique() {}
268 multi_pass_unique(T const&) {}
269
270 template <typename MultiPass>
271 static void destroy(MultiPass& mp)
272 {
273 Checking::destroy(mp);
274 Input::destroy(mp);
275 Storage::destroy(mp);
276 }
277
278 void swap(multi_pass_unique& x)
279 {
280 this->Checking::swap(x);
281 this->Storage::swap(x);
282 }
283
284 template <typename MultiPass>
285 inline static void clear_queue(MultiPass& mp)
286 {
287 Checking::clear_queue(mp);
288 Storage::clear_queue(mp);
289 }
290
291 // implement input policy functions by forwarding to the Input type
292 template <typename MultiPass>
293 inline static void advance_input(MultiPass& mp)
294 { Input::advance_input(mp); }
295
296 template <typename MultiPass>
297 inline static typename MultiPass::reference get_input(MultiPass& mp)
298 { return Input::get_input(mp); }
299
300 template <typename MultiPass>
301 inline static bool input_at_eof(MultiPass const& mp)
302 { return Input::input_at_eof(mp); }
303
304 template <typename MultiPass, typename TokenType>
305 inline static bool input_is_valid(MultiPass& mp, TokenType& curtok)
306 { return Input::input_is_valid(mp, curtok); }
307
308 // ownership policy functions are forwarded to the Ownership type
309 template <typename MultiPass>
310 inline static void clone(MultiPass& mp)
311 { Ownership::clone(mp); }
312
313 template <typename MultiPass>
314 inline static bool release(MultiPass& mp)
315 { return Ownership::release(mp); }
316
317 template <typename MultiPass>
318 inline static bool is_unique(MultiPass const& mp)
319 { return Ownership::is_unique(mp); }
320 };
321
322 ///////////////////////////////////////////////////////////////////////////
323 template <typename T, typename Ownership, typename Checking
324 , typename Input, typename Storage>
325 struct multi_pass_unique<T, Ownership, Checking, Input, Storage
326 , true, true, false>
327 : Input, Storage
328 {
329 multi_pass_unique() {}
330 multi_pass_unique(T& x) : Input(x) {}
331 multi_pass_unique(T const& x) : Input(x) {}
332
333 template <typename MultiPass>
334 static void destroy(MultiPass& mp)
335 {
336 Input::destroy(mp);
337 Storage::destroy(mp);
338 }
339
340 void swap(multi_pass_unique& x)
341 {
342 this->Input::swap(x);
343 this->Storage::swap(x);
344 }
345
346 template <typename MultiPass>
347 inline static void clear_queue(MultiPass& mp)
348 {
349 Checking::clear_queue(mp);
350 Storage::clear_queue(mp);
351 }
352
353 // checking policy functions are forwarded to the Checking type
354 template <typename MultiPass>
355 inline static void docheck(MultiPass const& mp)
356 { Checking::docheck(mp); }
357
358 // ownership policy functions are forwarded to the Ownership type
359 template <typename MultiPass>
360 inline static void clone(MultiPass& mp)
361 { Ownership::clone(mp); }
362
363 template <typename MultiPass>
364 inline static bool release(MultiPass& mp)
365 { return Ownership::release(mp); }
366
367 template <typename MultiPass>
368 inline static bool is_unique(MultiPass const& mp)
369 { return Ownership::is_unique(mp); }
370 };
371
372 ///////////////////////////////////////////////////////////////////////////
373 template <typename T, typename Ownership, typename Checking
374 , typename Input, typename Storage>
375 struct multi_pass_unique<T, Ownership, Checking, Input, Storage
376 , true, true, true>
377 : Storage
378 {
379 multi_pass_unique() {}
380 multi_pass_unique(T const&) {}
381
382 template <typename MultiPass>
383 static void destroy(MultiPass& mp)
384 {
385 Input::destroy(mp);
386 Storage::destroy(mp);
387 }
388
389 void swap(multi_pass_unique& x)
390 {
391 this->Storage::swap(x);
392 }
393
394 template <typename MultiPass>
395 inline static void clear_queue(MultiPass& mp)
396 {
397 Checking::clear_queue(mp);
398 Storage::clear_queue(mp);
399 }
400
401 // implement input policy functions by forwarding to the Input type
402 template <typename MultiPass>
403 inline static void advance_input(MultiPass& mp)
404 { Input::advance_input(mp); }
405
406 template <typename MultiPass>
407 inline static typename MultiPass::reference get_input(MultiPass& mp)
408 { return Input::get_input(mp); }
409
410 template <typename MultiPass>
411 inline static bool input_at_eof(MultiPass const& mp)
412 { return Input::input_at_eof(mp); }
413
414 template <typename MultiPass, typename TokenType>
415 inline static bool input_is_valid(MultiPass& mp, TokenType& curtok)
416 { return Input::input_is_valid(mp, curtok); }
417
418 // checking policy functions are forwarded to the Checking type
419 template <typename MultiPass>
420 inline static void docheck(MultiPass const& mp)
421 { Checking::docheck(mp); }
422
423 // ownership policy functions are forwarded to the Ownership type
424 template <typename MultiPass>
425 inline static void clone(MultiPass& mp)
426 { Ownership::clone(mp); }
427
428 template <typename MultiPass>
429 inline static bool release(MultiPass& mp)
430 { return Ownership::release(mp); }
431
432 template <typename MultiPass>
433 inline static bool is_unique(MultiPass const& mp)
434 { return Ownership::is_unique(mp); }
435 };
436
437 ///////////////////////////////////////////////////////////////////////////
438 // the multi_pass_shared structure is used to combine the shared data items
439 // of all policies into one single structure
440 ///////////////////////////////////////////////////////////////////////////
441 template<typename T, typename Ownership, typename Checking, typename Input
442 , typename Storage>
443 struct multi_pass_shared : Ownership, Checking, Input, Storage
444 {
445 explicit multi_pass_shared(T& input) : Input(input) {}
446 explicit multi_pass_shared(T const& input) : Input(input) {}
447 };
448
449 ///////////////////////////////////////////////////////////////////////////
450 // This is a default implementation of a policy class as required by the
451 // multi_pass template, combining 4 separate policies into one. Any other
452 // multi_pass policy class needs to follow the scheme as shown below.
453 template<typename Ownership, typename Checking, typename Input
454 , typename Storage>
455 struct default_policy
456 {
457 typedef Ownership ownership_policy;
458 typedef Checking checking_policy;
459 typedef Input input_policy;
460 typedef Storage storage_policy;
461
462 ///////////////////////////////////////////////////////////////////////
463 template <typename T>
464 struct unique : multi_pass_unique<T
465 , typename Ownership::unique, typename Checking::unique
466 , typename Input::BOOST_NESTED_TEMPLATE unique<T>
467 , typename Storage::BOOST_NESTED_TEMPLATE unique<
468 typename Input::BOOST_NESTED_TEMPLATE unique<T>::value_type> >
469 {
470 typedef typename Ownership::unique ownership_policy;
471 typedef typename Checking::unique checking_policy;
472 typedef typename Input::BOOST_NESTED_TEMPLATE unique<T>
473 input_policy;
474 typedef typename Storage::BOOST_NESTED_TEMPLATE unique<
475 typename input_policy::value_type> storage_policy;
476
477 typedef multi_pass_unique<T, ownership_policy, checking_policy
478 , input_policy, storage_policy> unique_base_type;
479
480 unique() {}
481 explicit unique(T& input) : unique_base_type(input) {}
482 explicit unique(T const& input) : unique_base_type(input) {}
483 };
484
485 ///////////////////////////////////////////////////////////////////////
486 template <typename T>
487 struct shared : multi_pass_shared<T
488 , typename Ownership::shared, typename Checking::shared
489 , typename Input::BOOST_NESTED_TEMPLATE shared<T>
490 , typename Storage::BOOST_NESTED_TEMPLATE shared<
491 typename Input::BOOST_NESTED_TEMPLATE unique<T>::value_type> >
492 {
493 typedef typename Ownership::shared ownership_policy;
494 typedef typename Checking::shared checking_policy;
495 typedef typename Input::BOOST_NESTED_TEMPLATE shared<T>
496 input_policy;
497 typedef typename Storage::BOOST_NESTED_TEMPLATE shared<
498 typename Input::BOOST_NESTED_TEMPLATE unique<T>::value_type>
499 storage_policy;
500
501 typedef multi_pass_shared<T, ownership_policy, checking_policy
502 , input_policy, storage_policy> shared_base_type;
503
504 explicit shared(T& input)
505 : shared_base_type(input), inhibit_clear_queue_(false) {}
506 explicit shared(T const& input)
507 : shared_base_type(input), inhibit_clear_queue_(false) {}
508
509 // This is needed for the correct implementation of expectation
510 // points. Normally expectation points flush any multi_pass
511 // iterator they may act on, but if the corresponding error handler
512 // is of type 'retry' no flushing of the internal buffers should be
513 // executed (even if explicitly requested).
514 bool inhibit_clear_queue_;
515 };
516 };
517
518}}}
519
520#endif
521