]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/spirit/home/karma/numeric/uint.hpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / boost / spirit / home / karma / numeric / uint.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_UINT_FEB_23_2007_0840PM)
7 #define BOOST_SPIRIT_KARMA_UINT_FEB_23_2007_0840PM
8
9 #if defined(_MSC_VER)
10 #pragma once
11 #endif
12
13 #include <boost/limits.hpp>
14 #include <boost/config.hpp>
15 #include <boost/mpl/bool.hpp>
16 #include <boost/utility/enable_if.hpp>
17
18 #include <boost/spirit/home/support/common_terminals.hpp>
19 #include <boost/spirit/home/support/string_traits.hpp>
20 #include <boost/spirit/home/support/numeric_traits.hpp>
21 #include <boost/spirit/home/support/info.hpp>
22 #include <boost/spirit/home/support/char_class.hpp>
23 #include <boost/spirit/home/support/container.hpp>
24 #include <boost/spirit/home/support/detail/get_encoding.hpp>
25 #include <boost/spirit/home/support/detail/is_spirit_tag.hpp>
26 #include <boost/spirit/home/karma/meta_compiler.hpp>
27 #include <boost/spirit/home/karma/delimit_out.hpp>
28 #include <boost/spirit/home/karma/auxiliary/lazy.hpp>
29 #include <boost/spirit/home/karma/detail/get_casetag.hpp>
30 #include <boost/spirit/home/karma/detail/extract_from.hpp>
31 #include <boost/spirit/home/karma/detail/enable_lit.hpp>
32 #include <boost/spirit/home/karma/domain.hpp>
33 #include <boost/spirit/home/karma/numeric/detail/numeric_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 tag
41 {
42 template <typename T, unsigned Radix>
43 struct uint_generator
44 {
45 BOOST_SPIRIT_IS_TAG()
46 };
47 }
48
49 namespace karma
50 {
51 ///////////////////////////////////////////////////////////////////////
52 // This one is the class that the user can instantiate directly in
53 // order to create a customized int generator
54 template <typename T = unsigned int, unsigned Radix = 10>
55 struct uint_generator
56 : spirit::terminal<tag::uint_generator<T, Radix> >
57 {};
58 }
59
60 ///////////////////////////////////////////////////////////////////////////
61 // Enablers
62 ///////////////////////////////////////////////////////////////////////////
63 template <>
64 struct use_terminal<karma::domain, tag::ushort_> // enables ushort_
65 : mpl::true_ {};
66
67 template <>
68 struct use_terminal<karma::domain, tag::uint_> // enables uint_
69 : mpl::true_ {};
70
71 template <>
72 struct use_terminal<karma::domain, tag::ulong_> // enables ulong_
73 : mpl::true_ {};
74
75 template <>
76 struct use_terminal<karma::domain, tag::bin> // enables bin
77 : mpl::true_ {};
78
79 template <>
80 struct use_terminal<karma::domain, tag::oct> // enables oct
81 : mpl::true_ {};
82
83 template <>
84 struct use_terminal<karma::domain, tag::hex> // enables hex
85 : mpl::true_ {};
86
87 #ifdef BOOST_HAS_LONG_LONG
88 template <>
89 struct use_terminal<karma::domain, tag::ulong_long> // enables ulong_long
90 : mpl::true_ {};
91 #endif
92
93 ///////////////////////////////////////////////////////////////////////////
94 #if !defined(BOOST_NO_INTRINSIC_WCHAR_T)
95 template <> // enables lit(unsigned short(0))
96 struct use_terminal<karma::domain, unsigned short>
97 : mpl::true_ {};
98 #endif
99
100 template <> // enables lit(0U)
101 struct use_terminal<karma::domain, unsigned int>
102 : mpl::true_ {};
103
104 template <> // enables lit(0UL)
105 struct use_terminal<karma::domain, unsigned long>
106 : mpl::true_ {};
107
108 #ifdef BOOST_HAS_LONG_LONG
109 template <> // enables lit(0ULL)
110 struct use_terminal<karma::domain, boost::ulong_long_type>
111 : mpl::true_ {};
112 #endif
113
114 ///////////////////////////////////////////////////////////////////////////
115 template <typename A0>
116 struct use_terminal<karma::domain // enables ushort_(...)
117 , terminal_ex<tag::ushort_, fusion::vector1<A0> >
118 > : mpl::true_ {};
119
120 template <typename A0>
121 struct use_terminal<karma::domain // enables uint_(...)
122 , terminal_ex<tag::uint_, fusion::vector1<A0> >
123 > : mpl::true_ {};
124
125 template <typename A0>
126 struct use_terminal<karma::domain // enables ulong_(...)
127 , terminal_ex<tag::ulong_, fusion::vector1<A0> >
128 > : mpl::true_ {};
129
130 template <typename A0>
131 struct use_terminal<karma::domain // enables bin(...)
132 , terminal_ex<tag::bin, fusion::vector1<A0> >
133 > : mpl::true_ {};
134
135 template <typename A0>
136 struct use_terminal<karma::domain // enables oct(...)
137 , terminal_ex<tag::oct, fusion::vector1<A0> >
138 > : mpl::true_ {};
139
140 template <typename A0>
141 struct use_terminal<karma::domain // enables hex(...)
142 , terminal_ex<tag::hex, fusion::vector1<A0> >
143 > : mpl::true_ {};
144
145 #ifdef BOOST_HAS_LONG_LONG
146 template <typename A0>
147 struct use_terminal<karma::domain // enables ulong_long(...)
148 , terminal_ex<tag::ulong_long, fusion::vector1<A0> >
149 > : mpl::true_ {};
150 #endif
151
152 ///////////////////////////////////////////////////////////////////////////
153 template <> // enables *lazy* ushort_(...)
154 struct use_lazy_terminal<karma::domain, tag::ushort_, 1>
155 : mpl::true_ {};
156
157 template <> // enables *lazy* uint_(...)
158 struct use_lazy_terminal<karma::domain, tag::uint_, 1>
159 : mpl::true_ {};
160
161 template <> // enables *lazy* ulong_(...)
162 struct use_lazy_terminal<karma::domain, tag::ulong_, 1>
163 : mpl::true_ {};
164
165 template <> // enables *lazy* bin(...)
166 struct use_lazy_terminal<karma::domain, tag::bin, 1>
167 : mpl::true_ {};
168
169 template <> // enables *lazy* oct(...)
170 struct use_lazy_terminal<karma::domain, tag::oct, 1>
171 : mpl::true_ {};
172
173 template <> // enables *lazy* hex(...)
174 struct use_lazy_terminal<karma::domain, tag::hex, 1>
175 : mpl::true_ {};
176
177 #ifdef BOOST_HAS_LONG_LONG
178 template <> // enables *lazy* ulong_long(...)
179 struct use_lazy_terminal<karma::domain, tag::ulong_long, 1>
180 : mpl::true_ {};
181 #endif
182
183 ///////////////////////////////////////////////////////////////////////////
184 // enables any custom uint_generator
185 template <typename T, unsigned Radix>
186 struct use_terminal<karma::domain, tag::uint_generator<T, Radix> >
187 : mpl::true_ {};
188
189 // enables any custom uint_generator(...)
190 template <typename T, unsigned Radix, typename A0>
191 struct use_terminal<karma::domain
192 , terminal_ex<tag::uint_generator<T, Radix>, fusion::vector1<A0> >
193 > : mpl::true_ {};
194
195 // enables *lazy* custom uint_generator
196 template <typename T, unsigned Radix>
197 struct use_lazy_terminal<
198 karma::domain
199 , tag::uint_generator<T, Radix>
200 , 1 // arity
201 > : mpl::true_ {};
202
203 // enables lit(uint)
204 template <typename A0>
205 struct use_terminal<karma::domain
206 , terminal_ex<tag::lit, fusion::vector1<A0> >
207 , typename enable_if<traits::is_uint<A0> >::type>
208 : mpl::true_ {};
209 }}
210
211 ///////////////////////////////////////////////////////////////////////////////
212 namespace boost { namespace spirit { namespace karma
213 {
214 #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
215 using spirit::ushort_;
216 using spirit::uint_;
217 using spirit::ulong_;
218 #ifdef BOOST_HAS_LONG_LONG
219 using spirit::ulong_long;
220 #endif
221 using spirit::bin;
222 using spirit::oct;
223 using spirit::hex;
224
225 using spirit::lit; // lit(1U) is equivalent to 1U
226 #endif
227
228 using spirit::ushort_type;
229 using spirit::uint_type;
230 using spirit::ulong_type;
231 #ifdef BOOST_HAS_LONG_LONG
232 using spirit::ulong_long_type;
233 #endif
234 using spirit::bin_type;
235 using spirit::oct_type;
236 using spirit::hex_type;
237
238 using spirit::lit_type;
239
240 ///////////////////////////////////////////////////////////////////////////
241 // This specialization is used for unsigned int generators not having a
242 // direct initializer: uint_, ulong_ etc. These generators must be used in
243 // conjunction with an Attribute.
244 ///////////////////////////////////////////////////////////////////////////
245 template <typename T, typename CharEncoding, typename Tag, unsigned Radix>
246 struct any_uint_generator
247 : primitive_generator<any_uint_generator<T, CharEncoding, Tag, Radix> >
248 {
249 template <typename Context, typename Unused>
250 struct attribute
251 {
252 typedef T type;
253 };
254
255 // check template Attribute 'Radix' for validity
256 BOOST_SPIRIT_ASSERT_MSG(
257 Radix >= 2 && Radix <= 36, not_supported_radix, ());
258
259 BOOST_SPIRIT_ASSERT_MSG(
260 // the following is a workaround for STLPort, where the simpler
261 // `!std::numeric_limits<T>::is_signed` wouldn't compile
262 mpl::not_<mpl::bool_<std::numeric_limits<T>::is_signed> >::value,
263 signed_unsigned_mismatch, ());
264
265 // int has a Attribute attached
266 template <typename OutputIterator, typename Context, typename Delimiter
267 , typename Attribute>
268 static bool
269 generate(OutputIterator& sink, Context& context, Delimiter const& d
270 , Attribute const& attr)
271 {
272 if (!traits::has_optional_value(attr))
273 return false; // fail if it's an uninitialized optional
274
275 return uint_inserter<Radix, CharEncoding, Tag>::
276 call(sink, traits::extract_from<T>(attr, context)) &&
277 delimit_out(sink, d); // always do post-delimiting
278 }
279
280 // this int has no Attribute attached, it needs to have been
281 // initialized from a direct literal
282 template <typename OutputIterator, typename Context, typename Delimiter>
283 static bool
284 generate(OutputIterator&, Context&, Delimiter const&, unused_type)
285 {
286 // It is not possible (doesn't make sense) to use numeric generators
287 // without providing any attribute, as the generator doesn't 'know'
288 // what to output. The following assertion fires if this situation
289 // is detected in your code.
290 BOOST_SPIRIT_ASSERT_FAIL(OutputIterator, uint_not_usable_without_attribute, ());
291 return false;
292 }
293
294 template <typename Context>
295 static info what(Context const& /*context*/)
296 {
297 return info("unsigned-integer");
298 }
299 };
300
301 ///////////////////////////////////////////////////////////////////////////
302 // This specialization is used for unsigned int generators having a direct
303 // initializer: uint_(10), ulong_(20) etc.
304 ///////////////////////////////////////////////////////////////////////////
305 template <
306 typename T, typename CharEncoding, typename Tag, unsigned Radix
307 , bool no_attribute>
308 struct literal_uint_generator
309 : primitive_generator<literal_uint_generator<T, CharEncoding, Tag, Radix
310 , no_attribute> >
311 {
312 template <typename Context, typename Unused = unused_type>
313 struct attribute
314 : mpl::if_c<no_attribute, unused_type, T>
315 {};
316
317 literal_uint_generator(typename add_const<T>::type n)
318 : n_(n) {}
319
320 // check template Attribute 'Radix' for validity
321 BOOST_SPIRIT_ASSERT_MSG(
322 Radix >= 2 && Radix <= 36, not_supported_radix, ());
323
324 BOOST_SPIRIT_ASSERT_MSG(
325 // the following is a workaround for STLPort, where the simpler
326 // `!std::numeric_limits<T>::is_signed wouldn't` compile
327 mpl::not_<mpl::bool_<std::numeric_limits<T>::is_signed> >::value,
328 signed_unsigned_mismatch, ());
329
330 // A uint(1U) which additionally has an associated attribute emits
331 // its immediate literal only if it matches the attribute, otherwise
332 // it fails.
333 template <typename OutputIterator, typename Context, typename Delimiter
334 , typename Attribute>
335 bool generate(OutputIterator& sink, Context& context
336 , Delimiter const& d, Attribute const& attr) const
337 {
338 typedef typename attribute<Context>::type attribute_type;
339 if (!traits::has_optional_value(attr) ||
340 n_ != traits::extract_from<attribute_type>(attr, context))
341 {
342 return false;
343 }
344 return uint_inserter<Radix, CharEncoding, Tag>::call(sink, n_) &&
345 delimit_out(sink, d); // always do post-delimiting
346 }
347
348 // A uint(1U) without any associated attribute just emits its
349 // immediate literal
350 template <typename OutputIterator, typename Context, typename Delimiter>
351 bool generate(OutputIterator& sink, Context&, Delimiter const& d
352 , unused_type) const
353 {
354 return uint_inserter<Radix, CharEncoding, Tag>::call(sink, n_) &&
355 delimit_out(sink, d); // always do post-delimiting
356 }
357
358 template <typename Context>
359 static info what(Context const& /*context*/)
360 {
361 return info("unsigned-integer");
362 }
363
364 T n_;
365 };
366
367 ///////////////////////////////////////////////////////////////////////////
368 // Generator generators: make_xxx function (objects)
369 ///////////////////////////////////////////////////////////////////////////
370 namespace detail
371 {
372 template <typename T, typename Modifiers, unsigned Radix = 10>
373 struct make_uint
374 {
375 static bool const lower =
376 has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
377 static bool const upper =
378 has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
379
380 typedef any_uint_generator<
381 T
382 , typename spirit::detail::get_encoding_with_case<
383 Modifiers, unused_type, lower || upper>::type
384 , typename detail::get_casetag<Modifiers, lower || upper>::type
385 , Radix
386 > result_type;
387
388 result_type operator()(unused_type, unused_type) const
389 {
390 return result_type();
391 }
392 };
393 }
394
395 ///////////////////////////////////////////////////////////////////////////
396 template <typename Modifiers>
397 struct make_primitive<tag::ushort_, Modifiers>
398 : detail::make_uint<unsigned short, Modifiers> {};
399
400 template <typename Modifiers>
401 struct make_primitive<tag::uint_, Modifiers>
402 : detail::make_uint<unsigned int, Modifiers> {};
403
404 template <typename Modifiers>
405 struct make_primitive<tag::ulong_, Modifiers>
406 : detail::make_uint<unsigned long, Modifiers> {};
407
408 template <typename Modifiers>
409 struct make_primitive<tag::bin, Modifiers>
410 : detail::make_uint<unsigned, Modifiers, 2> {};
411
412 template <typename Modifiers>
413 struct make_primitive<tag::oct, Modifiers>
414 : detail::make_uint<unsigned, Modifiers, 8> {};
415
416 template <typename Modifiers>
417 struct make_primitive<tag::hex, Modifiers>
418 : detail::make_uint<unsigned, Modifiers, 16> {};
419
420 #ifdef BOOST_HAS_LONG_LONG
421 template <typename Modifiers>
422 struct make_primitive<tag::ulong_long, Modifiers>
423 : detail::make_uint<boost::ulong_long_type, Modifiers> {};
424 #endif
425
426 template <typename T, unsigned Radix, typename Modifiers>
427 struct make_primitive<tag::uint_generator<T, Radix>, Modifiers>
428 : detail::make_uint<typename remove_const<T>::type, Modifiers, Radix> {};
429
430 ///////////////////////////////////////////////////////////////////////////
431 namespace detail
432 {
433 template <typename T, typename Modifiers, unsigned Radix = 10>
434 struct make_uint_direct
435 {
436 static bool const lower =
437 has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
438 static bool const upper =
439 has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
440
441 typedef literal_uint_generator<
442 T
443 , typename spirit::detail::get_encoding_with_case<
444 Modifiers, unused_type, lower || upper>::type
445 , typename detail::get_casetag<Modifiers, lower || upper>::type
446 , Radix, false
447 > result_type;
448
449 template <typename Terminal>
450 result_type operator()(Terminal const& term, unused_type) const
451 {
452 return result_type(fusion::at_c<0>(term.args));
453 }
454 };
455 }
456
457 template <typename Modifiers, typename A0>
458 struct make_primitive<
459 terminal_ex<tag::ushort_, fusion::vector1<A0> >, Modifiers>
460 : detail::make_uint_direct<unsigned short, Modifiers> {};
461
462 template <typename Modifiers, typename A0>
463 struct make_primitive<
464 terminal_ex<tag::uint_, fusion::vector1<A0> >, Modifiers>
465 : detail::make_uint_direct<unsigned int, Modifiers> {};
466
467 template <typename Modifiers, typename A0>
468 struct make_primitive<
469 terminal_ex<tag::ulong_, fusion::vector1<A0> >, Modifiers>
470 : detail::make_uint_direct<unsigned long, Modifiers> {};
471
472 template <typename Modifiers, typename A0>
473 struct make_primitive<
474 terminal_ex<tag::bin, fusion::vector1<A0> >, Modifiers>
475 : detail::make_uint_direct<unsigned, Modifiers, 2> {};
476
477 template <typename Modifiers, typename A0>
478 struct make_primitive<
479 terminal_ex<tag::oct, fusion::vector1<A0> >, Modifiers>
480 : detail::make_uint_direct<unsigned, Modifiers, 8> {};
481
482 template <typename Modifiers, typename A0>
483 struct make_primitive<
484 terminal_ex<tag::hex, fusion::vector1<A0> >, Modifiers>
485 : detail::make_uint_direct<unsigned, Modifiers, 16> {};
486
487 #ifdef BOOST_HAS_LONG_LONG
488 template <typename Modifiers, typename A0>
489 struct make_primitive<
490 terminal_ex<tag::ulong_long, fusion::vector1<A0> >, Modifiers>
491 : detail::make_uint_direct<boost::ulong_long_type, Modifiers> {};
492 #endif
493
494 template <typename T, unsigned Radix, typename A0, typename Modifiers>
495 struct make_primitive<
496 terminal_ex<tag::uint_generator<T, Radix>, fusion::vector1<A0> >
497 , Modifiers>
498 : detail::make_uint_direct<typename remove_const<T>::type, Modifiers, Radix>
499 {};
500
501 ///////////////////////////////////////////////////////////////////////////
502 namespace detail
503 {
504 template <typename T, typename Modifiers>
505 struct basic_uint_literal
506 {
507 static bool const lower =
508 has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
509 static bool const upper =
510 has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
511
512 typedef literal_uint_generator<
513 T
514 , typename spirit::detail::get_encoding_with_case<
515 Modifiers, unused_type, lower || upper>::type
516 , typename detail::get_casetag<Modifiers, lower || upper>::type
517 , 10, true
518 > result_type;
519
520 template <typename T_>
521 result_type operator()(T_ i, unused_type) const
522 {
523 return result_type(i);
524 }
525 };
526 }
527
528 #if !defined(BOOST_NO_INTRINSIC_WCHAR_T)
529 template <typename Modifiers>
530 struct make_primitive<unsigned short, Modifiers>
531 : detail::basic_uint_literal<unsigned short, Modifiers> {};
532 #endif
533
534 template <typename Modifiers>
535 struct make_primitive<unsigned int, Modifiers>
536 : detail::basic_uint_literal<unsigned int, Modifiers> {};
537
538 template <typename Modifiers>
539 struct make_primitive<unsigned long, Modifiers>
540 : detail::basic_uint_literal<unsigned long, Modifiers> {};
541
542 #ifdef BOOST_HAS_LONG_LONG
543 template <typename Modifiers>
544 struct make_primitive<boost::ulong_long_type, Modifiers>
545 : detail::basic_uint_literal<boost::ulong_long_type, Modifiers> {};
546 #endif
547
548 // lit(uint)
549 template <typename Modifiers, typename A0>
550 struct make_primitive<
551 terminal_ex<tag::lit, fusion::vector1<A0> >
552 , Modifiers
553 , typename enable_if<traits::is_uint<A0> >::type>
554 {
555 static bool const lower =
556 has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
557 static bool const upper =
558 has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
559
560 typedef literal_uint_generator<
561 typename remove_const<A0>::type
562 , typename spirit::detail::get_encoding_with_case<
563 Modifiers, unused_type, lower || upper>::type
564 , typename detail::get_casetag<Modifiers, lower || upper>::type
565 , 10, true
566 > result_type;
567
568 template <typename Terminal>
569 result_type operator()(Terminal const& term, unused_type) const
570 {
571 return result_type(fusion::at_c<0>(term.args));
572 }
573 };
574 }}}
575
576 #endif