]> git.sesse.net Git - casparcg/blob - dependencies/boost/boost/spirit/home/karma/numeric/bool.hpp
Manually merged pull request #222
[casparcg] / dependencies / boost / boost / spirit / home / karma / numeric / bool.hpp
1 //  Copyright (c) 2001-2011 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_KARMA_BOOL_SEP_28_2009_1113AM)
7 #define BOOST_SPIRIT_KARMA_BOOL_SEP_28_2009_1113AM
8
9 #if defined(_MSC_VER)
10 #pragma once
11 #endif
12
13 #include <boost/limits.hpp>
14 #include <boost/mpl/bool.hpp>
15 #include <boost/utility/enable_if.hpp>
16
17 #include <boost/spirit/home/support/common_terminals.hpp>
18 #include <boost/spirit/home/support/string_traits.hpp>
19 #include <boost/spirit/home/support/numeric_traits.hpp>
20 #include <boost/spirit/home/support/info.hpp>
21 #include <boost/spirit/home/support/char_class.hpp>
22 #include <boost/spirit/home/karma/meta_compiler.hpp>
23 #include <boost/spirit/home/karma/delimit_out.hpp>
24 #include <boost/spirit/home/karma/auxiliary/lazy.hpp>
25 #include <boost/spirit/home/karma/detail/get_casetag.hpp>
26 #include <boost/spirit/home/karma/detail/extract_from.hpp>
27 #include <boost/spirit/home/karma/detail/enable_lit.hpp>
28 #include <boost/spirit/home/karma/domain.hpp>
29 #include <boost/spirit/home/karma/numeric/bool_policies.hpp>
30 #include <boost/spirit/home/karma/numeric/detail/bool_utils.hpp>
31
32 ///////////////////////////////////////////////////////////////////////////////
33 namespace boost { namespace spirit
34 {
35     namespace karma
36     {
37         ///////////////////////////////////////////////////////////////////////
38         // forward declaration only
39         template <typename T>
40         struct bool_policies;
41
42         ///////////////////////////////////////////////////////////////////////
43         // This is the class that the user can instantiate directly in
44         // order to create a customized bool generator
45         template <typename T = bool, typename Policies = bool_policies<T> >
46         struct bool_generator
47           : spirit::terminal<tag::stateful_tag<Policies, tag::bool_, T> >
48         {
49             typedef tag::stateful_tag<Policies, tag::bool_, T> tag_type;
50
51             bool_generator() {}
52             bool_generator(Policies const& data)
53               : spirit::terminal<tag_type>(data) {}
54         };
55     }
56
57     ///////////////////////////////////////////////////////////////////////////
58     // Enablers
59     ///////////////////////////////////////////////////////////////////////////
60     template <>
61     struct use_terminal<karma::domain, tag::bool_>    // enables bool_
62       : mpl::true_ {};
63
64     template <>
65     struct use_terminal<karma::domain, tag::true_>    // enables true_
66       : mpl::true_ {};
67
68     template <>
69     struct use_terminal<karma::domain, tag::false_>    // enables false_
70       : mpl::true_ {};
71
72     template <>
73     struct use_terminal<karma::domain, bool>          // enables lit(true)
74       : mpl::true_ {};
75
76     template <typename A0>
77     struct use_terminal<karma::domain                 // enables bool_(...)
78       , terminal_ex<tag::bool_, fusion::vector1<A0> >
79     > : mpl::true_ {};
80
81     template <>                                       // enables *lazy* bool_(...)
82     struct use_lazy_terminal<karma::domain, tag::bool_, 1>
83       : mpl::true_ {};
84
85     ///////////////////////////////////////////////////////////////////////////
86     // enables any custom bool_generator
87     template <typename Policies, typename T>
88     struct use_terminal<karma::domain
89           , tag::stateful_tag<Policies, tag::bool_, T> >
90       : mpl::true_ {};
91
92     // enables any custom bool_generator(...)
93     template <typename Policies, typename T, typename A0>
94     struct use_terminal<karma::domain
95           , terminal_ex<tag::stateful_tag<Policies, tag::bool_, T>
96           , fusion::vector1<A0> > >
97       : mpl::true_ {};
98
99     // enables *lazy* custom bool_generator
100     template <typename Policies, typename T>
101     struct use_lazy_terminal<karma::domain
102           , tag::stateful_tag<Policies, tag::bool_, T>, 1>
103       : mpl::true_ {};
104
105     // enables lit(bool)
106     template <typename A0>
107     struct use_terminal<karma::domain
108           , terminal_ex<tag::lit, fusion::vector1<A0> >
109           , typename enable_if<traits::is_bool<A0> >::type>
110       : mpl::true_ {};
111 }}
112
113 ///////////////////////////////////////////////////////////////////////////////
114 namespace boost { namespace spirit { namespace karma
115 {
116 #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
117     using spirit::bool_;
118     using spirit::true_;
119     using spirit::false_;
120     using spirit::lit;    // lit(true) is equivalent to true
121 #endif
122
123     using spirit::bool_type;
124     using spirit::true_type;
125     using spirit::false_type;
126     using spirit::lit_type;
127
128     ///////////////////////////////////////////////////////////////////////////
129     //  This specialization is used for bool generators not having a direct
130     //  initializer: bool_. These generators must be used in conjunction with
131     //  an Attribute.
132     ///////////////////////////////////////////////////////////////////////////
133     template <typename T, typename CharEncoding, typename Tag, typename Policies>
134     struct any_bool_generator
135       : primitive_generator<any_bool_generator<T, CharEncoding, Tag, Policies> >
136     {
137     public:
138         any_bool_generator(Policies const& p = Policies())
139           : p_(p) {}
140
141         typedef typename Policies::properties properties;
142
143         template <typename Context, typename Unused>
144         struct attribute
145         {
146             typedef T type;
147         };
148
149         // bool_ has a Attribute attached
150         template <typename OutputIterator, typename Context, typename Delimiter
151           , typename Attribute>
152         bool
153         generate(OutputIterator& sink, Context& context, Delimiter const& d
154           , Attribute const& attr) const
155         {
156             if (!traits::has_optional_value(attr))
157                 return false;       // fail if it's an uninitialized optional
158
159             return bool_inserter<T, Policies, CharEncoding, Tag>::call(
160                         sink, traits::extract_from<T>(attr, context), p_) &&
161                    delimit_out(sink, d);      // always do post-delimiting
162         }
163
164         // this bool_ has no Attribute attached, it needs to have been
165         // initialized from a direct literal
166         template <typename OutputIterator, typename Context, typename Delimiter>
167         static bool
168         generate(OutputIterator&, Context&, Delimiter const&, unused_type)
169         {
170             // It is not possible (doesn't make sense) to use boolean generators
171             // without providing any attribute, as the generator doesn't 'know'
172             // what to output. The following assertion fires if this situation
173             // is detected in your code.
174             BOOST_SPIRIT_ASSERT_MSG(false, bool_not_usable_without_attribute, ());
175             return false;
176         }
177
178         template <typename Context>
179         static info what(Context const& /*context*/)
180         {
181             return info("bool");
182         }
183
184         Policies p_;
185     };
186
187     ///////////////////////////////////////////////////////////////////////////
188     //  This specialization is used for bool generators having a direct
189     //  initializer: bool_(true), bool_(0) etc.
190     ///////////////////////////////////////////////////////////////////////////
191     template <typename T, typename CharEncoding, typename Tag
192       , typename Policies, bool no_attribute>
193     struct literal_bool_generator
194       : primitive_generator<literal_bool_generator<T, CharEncoding, Tag
195           , Policies, no_attribute> >
196     {
197     public:
198         typedef typename Policies::properties properties;
199
200         template <typename Context, typename Unused = unused_type>
201         struct attribute
202           : mpl::if_c<no_attribute, unused_type, T>
203         {};
204
205         literal_bool_generator(typename add_const<T>::type n
206               , Policies const& p = Policies())
207           : n_(n), p_(p) {}
208
209         // A bool_() which additionally has an associated attribute emits
210         // its immediate literal only if it matches the attribute, otherwise
211         // it fails.
212         template <typename OutputIterator, typename Context, typename Delimiter
213           , typename Attribute>
214         bool generate(OutputIterator& sink, Context& context
215           , Delimiter const& d, Attribute const& attr) const
216         {
217             typedef typename attribute<Context>::type attribute_type;
218             if (!traits::has_optional_value(attr) ||
219                 bool(n_) != bool(traits::extract_from<attribute_type>(attr, context)))
220             {
221                 return false;
222             }
223             return bool_inserter<T, Policies, CharEncoding, Tag>::
224                       call(sink, n_, p_) && delimit_out(sink, d);
225         }
226
227         // A bool_() without any associated attribute just emits its
228         // immediate literal
229         template <typename OutputIterator, typename Context, typename Delimiter>
230         bool generate(OutputIterator& sink, Context&, Delimiter const& d
231           , unused_type) const
232         {
233             return bool_inserter<T, Policies, CharEncoding, Tag>::
234                       call(sink, n_) && delimit_out(sink, d);
235         }
236
237         template <typename Context>
238         static info what(Context const& /*context*/)
239         {
240             return info("bool");
241         }
242
243         T n_;
244         Policies p_;
245     };
246
247     ///////////////////////////////////////////////////////////////////////////
248     // Generator generators: make_xxx function (objects)
249     ///////////////////////////////////////////////////////////////////////////
250     namespace detail
251     {
252         template <typename Modifiers, typename T = bool
253           , typename Policies = bool_policies<T> >
254         struct make_bool
255         {
256             static bool const lower =
257                 has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
258             static bool const upper =
259                 has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
260
261             typedef any_bool_generator<
262                 T
263               , typename spirit::detail::get_encoding_with_case<
264                     Modifiers, unused_type, lower || upper>::type
265               , typename detail::get_casetag<Modifiers, lower || upper>::type
266               , Policies
267             > result_type;
268
269             template <typename Terminal>
270             result_type operator()(Terminal const& term, unused_type) const
271             {
272                 typedef tag::stateful_tag<Policies, tag::bool_, T> tag_type;
273                 using spirit::detail::get_stateful_data;
274                 return result_type(get_stateful_data<tag_type>::call(term));
275             }
276         };
277
278         template <typename Modifiers, bool b>
279         struct make_bool_literal
280         {
281             static bool const lower =
282                 has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
283             static bool const upper =
284                 has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
285
286             typedef literal_bool_generator<
287                 bool
288               , typename spirit::detail::get_encoding_with_case<
289                     Modifiers, unused_type, lower || upper>::type
290               , typename detail::get_casetag<Modifiers, lower || upper>::type
291               , bool_policies<>, false
292             > result_type;
293
294             result_type operator()(unused_type, unused_type) const
295             {
296                 return result_type(b);
297             }
298         };
299     }
300
301     ///////////////////////////////////////////////////////////////////////////
302     template <typename Modifiers>
303     struct make_primitive<tag::bool_, Modifiers>
304       : detail::make_bool<Modifiers> {};
305
306     template <typename Modifiers>
307     struct make_primitive<tag::true_, Modifiers>
308       : detail::make_bool_literal<Modifiers, true> {};
309
310     template <typename Modifiers>
311     struct make_primitive<tag::false_, Modifiers>
312       : detail::make_bool_literal<Modifiers, false> {};
313
314     template <typename T, typename Policies, typename Modifiers>
315     struct make_primitive<
316             tag::stateful_tag<Policies, tag::bool_, T>, Modifiers>
317       : detail::make_bool<Modifiers
318           , typename remove_const<T>::type, Policies> {};
319
320     ///////////////////////////////////////////////////////////////////////////
321     namespace detail
322     {
323         template <typename Modifiers, typename T = bool
324           , typename Policies = bool_policies<T> >
325         struct make_bool_direct
326         {
327             static bool const lower =
328                 has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
329             static bool const upper =
330                 has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
331
332             typedef literal_bool_generator<
333                 T
334               , typename spirit::detail::get_encoding_with_case<
335                     Modifiers, unused_type, lower || upper>::type
336               , typename detail::get_casetag<Modifiers, lower || upper>::type
337               , Policies, false
338             > result_type;
339
340             template <typename Terminal>
341             result_type operator()(Terminal const& term, unused_type) const
342             {
343                 typedef tag::stateful_tag<Policies, tag::bool_, T> tag_type;
344                 using spirit::detail::get_stateful_data;
345                 return result_type(fusion::at_c<0>(term.args)
346                   , get_stateful_data<tag_type>::call(term.term));
347             }
348         };
349     }
350
351     ///////////////////////////////////////////////////////////////////////////
352     template <typename Modifiers, typename A0>
353     struct make_primitive<
354             terminal_ex<tag::bool_, fusion::vector1<A0> >, Modifiers>
355       : detail::make_bool_direct<Modifiers> {};
356
357     template <typename T, typename Policies, typename A0, typename Modifiers>
358     struct make_primitive<
359         terminal_ex<tag::stateful_tag<Policies, tag::bool_, T>
360           , fusion::vector1<A0> >
361           , Modifiers>
362       : detail::make_bool_direct<Modifiers
363           , typename remove_const<T>::type, Policies> {};
364
365     ///////////////////////////////////////////////////////////////////////////
366     namespace detail
367     {
368         template <typename Modifiers>
369         struct basic_bool_literal
370         {
371             static bool const lower =
372                 has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
373             static bool const upper =
374                 has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
375
376             typedef literal_bool_generator<
377                 bool
378               , typename spirit::detail::get_encoding_with_case<
379                     Modifiers, unused_type, lower || upper>::type
380               , typename detail::get_casetag<Modifiers, lower || upper>::type
381               , bool_policies<>, true
382             > result_type;
383
384             template <typename T_>
385             result_type operator()(T_ i, unused_type) const
386             {
387                 return result_type(i);
388             }
389         };
390     }
391
392     template <typename Modifiers>
393     struct make_primitive<bool, Modifiers>
394       : detail::basic_bool_literal<Modifiers> {};
395
396     template <typename Modifiers, typename A0>
397     struct make_primitive<
398             terminal_ex<tag::lit, fusion::vector1<A0> >
399           , Modifiers
400           , typename enable_if<traits::is_bool<A0> >::type>
401       : detail::basic_bool_literal<Modifiers>
402     {
403         static bool const lower =
404             has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
405         static bool const upper =
406             has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
407
408         typedef literal_bool_generator<
409             bool
410           , typename spirit::detail::get_encoding_with_case<
411                 Modifiers, unused_type, lower || upper>::type
412           , typename detail::get_casetag<Modifiers, lower || upper>::type
413           , bool_policies<>, true
414         > result_type;
415
416         template <typename Terminal>
417         result_type operator()(Terminal const& term, unused_type) const
418         {
419             return result_type(fusion::at_c<0>(term.args));
420         }
421     };
422 }}}
423
424 #endif