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