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 
12 namespace 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     {
multi_pass_uniqueboost::spirit::iterator_policies::multi_pass_unique40         multi_pass_unique() {}
multi_pass_uniqueboost::spirit::iterator_policies::multi_pass_unique41         multi_pass_unique(T& x) : Input(x) {}
multi_pass_uniqueboost::spirit::iterator_policies::multi_pass_unique42         multi_pass_unique(T const& x) : Input(x) {}
43 
44         template <typename MultiPass>
destroyboost::spirit::iterator_policies::multi_pass_unique45         static void destroy(MultiPass& mp)
46         {
47             Ownership::destroy(mp);
48             Checking::destroy(mp);
49             Input::destroy(mp);
50             Storage::destroy(mp);
51         }
52 
swapboost::spirit::iterator_policies::multi_pass_unique53         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>
clear_queueboost::spirit::iterator_policies::multi_pass_unique62         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     {
multi_pass_uniqueboost::spirit::iterator_policies::multi_pass_unique76         multi_pass_unique() {}
multi_pass_uniqueboost::spirit::iterator_policies::multi_pass_unique77         multi_pass_unique(T const&) {}
78 
79         template <typename MultiPass>
destroyboost::spirit::iterator_policies::multi_pass_unique80         static void destroy(MultiPass& mp)
81         {
82             Ownership::destroy(mp);
83             Checking::destroy(mp);
84             Input::destroy(mp);
85             Storage::destroy(mp);
86         }
87 
swapboost::spirit::iterator_policies::multi_pass_unique88         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>
clear_queueboost::spirit::iterator_policies::multi_pass_unique96         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>
advance_inputboost::spirit::iterator_policies::multi_pass_unique104         inline static void advance_input(MultiPass& mp)
105             { Input::advance_input(mp); }
106 
107         template <typename MultiPass>
get_inputboost::spirit::iterator_policies::multi_pass_unique108         inline static typename MultiPass::reference get_input(MultiPass& mp)
109             { return Input::get_input(mp); }
110 
111         template <typename MultiPass>
input_at_eofboost::spirit::iterator_policies::multi_pass_unique112         inline static bool input_at_eof(MultiPass const& mp)
113             { return Input::input_at_eof(mp); }
114 
115         template <typename MultiPass, typename TokenType>
input_is_validboost::spirit::iterator_policies::multi_pass_unique116         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     {
multi_pass_uniqueboost::spirit::iterator_policies::multi_pass_unique127         multi_pass_unique() {}
multi_pass_uniqueboost::spirit::iterator_policies::multi_pass_unique128         multi_pass_unique(T& x) : Input(x) {}
multi_pass_uniqueboost::spirit::iterator_policies::multi_pass_unique129         multi_pass_unique(T const& x) : Input(x) {}
130 
131         template <typename MultiPass>
destroyboost::spirit::iterator_policies::multi_pass_unique132         static void destroy(MultiPass& mp)
133         {
134             Ownership::destroy(mp);
135             Input::destroy(mp);
136             Storage::destroy(mp);
137         }
138 
swapboost::spirit::iterator_policies::multi_pass_unique139         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>
clear_queueboost::spirit::iterator_policies::multi_pass_unique147         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>
docheckboost::spirit::iterator_policies::multi_pass_unique155         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     {
multi_pass_uniqueboost::spirit::iterator_policies::multi_pass_unique166         multi_pass_unique() {}
multi_pass_uniqueboost::spirit::iterator_policies::multi_pass_unique167         multi_pass_unique(T const&) {}
168 
169         template <typename MultiPass>
destroyboost::spirit::iterator_policies::multi_pass_unique170         static void destroy(MultiPass& mp)
171         {
172             Ownership::destroy(mp);
173             Input::destroy(mp);
174             Storage::destroy(mp);
175         }
176 
swapboost::spirit::iterator_policies::multi_pass_unique177         void swap(multi_pass_unique& x)
178         {
179             this->Ownership::swap(x);
180             this->Storage::swap(x);
181         }
182 
183         template <typename MultiPass>
clear_queueboost::spirit::iterator_policies::multi_pass_unique184         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>
advance_inputboost::spirit::iterator_policies::multi_pass_unique192         inline static void advance_input(MultiPass& mp)
193             { Input::advance_input(mp); }
194 
195         template <typename MultiPass>
get_inputboost::spirit::iterator_policies::multi_pass_unique196         inline static typename MultiPass::reference get_input(MultiPass& mp)
197             { return Input::get_input(mp); }
198 
199         template <typename MultiPass>
input_at_eofboost::spirit::iterator_policies::multi_pass_unique200         inline static bool input_at_eof(MultiPass const& mp)
201             { return Input::input_at_eof(mp); }
202 
203         template <typename MultiPass, typename TokenType>
input_is_validboost::spirit::iterator_policies::multi_pass_unique204         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>
docheckboost::spirit::iterator_policies::multi_pass_unique209         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     {
multi_pass_uniqueboost::spirit::iterator_policies::multi_pass_unique220         multi_pass_unique() {}
multi_pass_uniqueboost::spirit::iterator_policies::multi_pass_unique221         multi_pass_unique(T& x) : Input(x) {}
multi_pass_uniqueboost::spirit::iterator_policies::multi_pass_unique222         multi_pass_unique(T const& x) : Input(x) {}
223 
224         template <typename MultiPass>
destroyboost::spirit::iterator_policies::multi_pass_unique225         static void destroy(MultiPass& mp)
226         {
227             Checking::destroy(mp);
228             Input::destroy(mp);
229             Storage::destroy(mp);
230         }
231 
swapboost::spirit::iterator_policies::multi_pass_unique232         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>
clear_queueboost::spirit::iterator_policies::multi_pass_unique240         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>
cloneboost::spirit::iterator_policies::multi_pass_unique248         inline static void clone(MultiPass& mp)
249             { Ownership::clone(mp); }
250 
251         template <typename MultiPass>
releaseboost::spirit::iterator_policies::multi_pass_unique252         inline static bool release(MultiPass& mp)
253             { return Ownership::release(mp); }
254 
255         template <typename MultiPass>
is_uniqueboost::spirit::iterator_policies::multi_pass_unique256         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     {
multi_pass_uniqueboost::spirit::iterator_policies::multi_pass_unique267         multi_pass_unique() {}
multi_pass_uniqueboost::spirit::iterator_policies::multi_pass_unique268         multi_pass_unique(T const&) {}
269 
270         template <typename MultiPass>
destroyboost::spirit::iterator_policies::multi_pass_unique271         static void destroy(MultiPass& mp)
272         {
273             Checking::destroy(mp);
274             Input::destroy(mp);
275             Storage::destroy(mp);
276         }
277 
swapboost::spirit::iterator_policies::multi_pass_unique278         void swap(multi_pass_unique& x)
279         {
280             this->Checking::swap(x);
281             this->Storage::swap(x);
282         }
283 
284         template <typename MultiPass>
clear_queueboost::spirit::iterator_policies::multi_pass_unique285         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>
advance_inputboost::spirit::iterator_policies::multi_pass_unique293         inline static void advance_input(MultiPass& mp)
294             { Input::advance_input(mp); }
295 
296         template <typename MultiPass>
get_inputboost::spirit::iterator_policies::multi_pass_unique297         inline static typename MultiPass::reference get_input(MultiPass& mp)
298             { return Input::get_input(mp); }
299 
300         template <typename MultiPass>
input_at_eofboost::spirit::iterator_policies::multi_pass_unique301         inline static bool input_at_eof(MultiPass const& mp)
302             { return Input::input_at_eof(mp); }
303 
304         template <typename MultiPass, typename TokenType>
input_is_validboost::spirit::iterator_policies::multi_pass_unique305         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>
cloneboost::spirit::iterator_policies::multi_pass_unique310         inline static void clone(MultiPass& mp)
311             { Ownership::clone(mp); }
312 
313         template <typename MultiPass>
releaseboost::spirit::iterator_policies::multi_pass_unique314         inline static bool release(MultiPass& mp)
315             { return Ownership::release(mp); }
316 
317         template <typename MultiPass>
is_uniqueboost::spirit::iterator_policies::multi_pass_unique318         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     {
multi_pass_uniqueboost::spirit::iterator_policies::multi_pass_unique329         multi_pass_unique() {}
multi_pass_uniqueboost::spirit::iterator_policies::multi_pass_unique330         multi_pass_unique(T& x) : Input(x) {}
multi_pass_uniqueboost::spirit::iterator_policies::multi_pass_unique331         multi_pass_unique(T const& x) : Input(x) {}
332 
333         template <typename MultiPass>
destroyboost::spirit::iterator_policies::multi_pass_unique334         static void destroy(MultiPass& mp)
335         {
336             Input::destroy(mp);
337             Storage::destroy(mp);
338         }
339 
swapboost::spirit::iterator_policies::multi_pass_unique340         void swap(multi_pass_unique& x)
341         {
342             this->Input::swap(x);
343             this->Storage::swap(x);
344         }
345 
346         template <typename MultiPass>
clear_queueboost::spirit::iterator_policies::multi_pass_unique347         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>
docheckboost::spirit::iterator_policies::multi_pass_unique355         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>
cloneboost::spirit::iterator_policies::multi_pass_unique360         inline static void clone(MultiPass& mp)
361             { Ownership::clone(mp); }
362 
363         template <typename MultiPass>
releaseboost::spirit::iterator_policies::multi_pass_unique364         inline static bool release(MultiPass& mp)
365             { return Ownership::release(mp); }
366 
367         template <typename MultiPass>
is_uniqueboost::spirit::iterator_policies::multi_pass_unique368         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     {
multi_pass_uniqueboost::spirit::iterator_policies::multi_pass_unique379         multi_pass_unique() {}
multi_pass_uniqueboost::spirit::iterator_policies::multi_pass_unique380         multi_pass_unique(T const&) {}
381 
382         template <typename MultiPass>
destroyboost::spirit::iterator_policies::multi_pass_unique383         static void destroy(MultiPass& mp)
384         {
385             Input::destroy(mp);
386             Storage::destroy(mp);
387         }
388 
swapboost::spirit::iterator_policies::multi_pass_unique389         void swap(multi_pass_unique& x)
390         {
391             this->Storage::swap(x);
392         }
393 
394         template <typename MultiPass>
clear_queueboost::spirit::iterator_policies::multi_pass_unique395         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>
advance_inputboost::spirit::iterator_policies::multi_pass_unique403         inline static void advance_input(MultiPass& mp)
404             { Input::advance_input(mp); }
405 
406         template <typename MultiPass>
get_inputboost::spirit::iterator_policies::multi_pass_unique407         inline static typename MultiPass::reference get_input(MultiPass& mp)
408             { return Input::get_input(mp); }
409 
410         template <typename MultiPass>
input_at_eofboost::spirit::iterator_policies::multi_pass_unique411         inline static bool input_at_eof(MultiPass const& mp)
412             { return Input::input_at_eof(mp); }
413 
414         template <typename MultiPass, typename TokenType>
input_is_validboost::spirit::iterator_policies::multi_pass_unique415         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>
docheckboost::spirit::iterator_policies::multi_pass_unique420         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>
cloneboost::spirit::iterator_policies::multi_pass_unique425         inline static void clone(MultiPass& mp)
426             { Ownership::clone(mp); }
427 
428         template <typename MultiPass>
releaseboost::spirit::iterator_policies::multi_pass_unique429         inline static bool release(MultiPass& mp)
430             { return Ownership::release(mp); }
431 
432         template <typename MultiPass>
is_uniqueboost::spirit::iterator_policies::multi_pass_unique433         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     {
multi_pass_sharedboost::spirit::iterator_policies::multi_pass_shared445         explicit multi_pass_shared(T& input) : Input(input) {}
multi_pass_sharedboost::spirit::iterator_policies::multi_pass_shared446         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 
uniqueboost::spirit::iterator_policies::default_policy::unique480             unique() {}
uniqueboost::spirit::iterator_policies::default_policy::unique481             explicit unique(T& input) : unique_base_type(input) {}
uniqueboost::spirit::iterator_policies::default_policy::unique482             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 
sharedboost::spirit::iterator_policies::default_policy::shared504             explicit shared(T& input)
505               : shared_base_type(input), inhibit_clear_queue_(false) {}
sharedboost::spirit::iterator_policies::default_policy::shared506             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