Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-19 09:47:38

0001 //  Copyright (c) 2001-2011 Hartmut Kaiser
0002 //
0003 //  Distributed under the Boost Software License, Version 1.0. (See accompanying
0004 //  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0005 
0006 #if !defined(BOOST_SPIRIT_KARMA_UINT_FEB_23_2007_0840PM)
0007 #define BOOST_SPIRIT_KARMA_UINT_FEB_23_2007_0840PM
0008 
0009 #if defined(_MSC_VER)
0010 #pragma once
0011 #endif
0012 
0013 #include <boost/limits.hpp>
0014 #include <boost/config.hpp>
0015 #include <boost/mpl/bool.hpp>
0016 #include <boost/utility/enable_if.hpp>
0017 
0018 #include <boost/spirit/home/support/common_terminals.hpp>
0019 #include <boost/spirit/home/support/string_traits.hpp>
0020 #include <boost/spirit/home/support/numeric_traits.hpp>
0021 #include <boost/spirit/home/support/info.hpp>
0022 #include <boost/spirit/home/support/char_class.hpp>
0023 #include <boost/spirit/home/support/container.hpp>
0024 #include <boost/spirit/home/support/detail/get_encoding.hpp>
0025 #include <boost/spirit/home/support/detail/is_spirit_tag.hpp>
0026 #include <boost/spirit/home/karma/meta_compiler.hpp>
0027 #include <boost/spirit/home/karma/delimit_out.hpp>
0028 #include <boost/spirit/home/karma/auxiliary/lazy.hpp>
0029 #include <boost/spirit/home/karma/detail/get_casetag.hpp>
0030 #include <boost/spirit/home/karma/detail/extract_from.hpp>
0031 #include <boost/spirit/home/karma/detail/enable_lit.hpp>
0032 #include <boost/spirit/home/karma/domain.hpp>
0033 #include <boost/spirit/home/karma/numeric/detail/numeric_utils.hpp>
0034 #include <boost/fusion/include/at.hpp>
0035 #include <boost/fusion/include/value_at.hpp>
0036 #include <boost/fusion/include/vector.hpp>
0037 
0038 namespace boost { namespace spirit
0039 {
0040     namespace tag
0041     {
0042         template <typename T, unsigned Radix>
0043         struct uint_generator 
0044         {
0045             BOOST_SPIRIT_IS_TAG()
0046         };
0047     }
0048 
0049     namespace karma
0050     {
0051         ///////////////////////////////////////////////////////////////////////
0052         // This one is the class that the user can instantiate directly in
0053         // order to create a customized int generator
0054         template <typename T = unsigned int, unsigned Radix = 10>
0055         struct uint_generator
0056           : spirit::terminal<tag::uint_generator<T, Radix> >
0057         {};
0058     }
0059 
0060     ///////////////////////////////////////////////////////////////////////////
0061     // Enablers
0062     ///////////////////////////////////////////////////////////////////////////
0063     template <>
0064     struct use_terminal<karma::domain, tag::ushort_>   // enables ushort_
0065       : mpl::true_ {};
0066 
0067     template <>
0068     struct use_terminal<karma::domain, tag::uint_>     // enables uint_
0069       : mpl::true_ {};
0070 
0071     template <>
0072     struct use_terminal<karma::domain, tag::ulong_>    // enables ulong_
0073       : mpl::true_ {};
0074 
0075     template <>
0076     struct use_terminal<karma::domain, tag::bin>       // enables bin
0077       : mpl::true_ {};
0078 
0079     template <>
0080     struct use_terminal<karma::domain, tag::oct>       // enables oct
0081       : mpl::true_ {};
0082 
0083     template <>
0084     struct use_terminal<karma::domain, tag::hex>       // enables hex
0085       : mpl::true_ {};
0086 
0087 #ifdef BOOST_HAS_LONG_LONG
0088     template <>
0089     struct use_terminal<karma::domain, tag::ulong_long> // enables ulong_long
0090       : mpl::true_ {};
0091 #endif
0092 
0093     ///////////////////////////////////////////////////////////////////////////
0094 #if !defined(BOOST_NO_INTRINSIC_WCHAR_T)
0095     template <>           // enables lit(unsigned short(0))
0096     struct use_terminal<karma::domain, unsigned short>
0097       : mpl::true_ {};
0098 #endif
0099 
0100     template <>           // enables lit(0U)
0101     struct use_terminal<karma::domain, unsigned int>
0102       : mpl::true_ {};
0103 
0104     template <>           // enables lit(0UL)
0105     struct use_terminal<karma::domain, unsigned long>
0106       : mpl::true_ {};
0107 
0108 #ifdef BOOST_HAS_LONG_LONG
0109     template <>           // enables lit(0ULL)
0110     struct use_terminal<karma::domain, boost::ulong_long_type>
0111       : mpl::true_ {};
0112 #endif
0113 
0114     ///////////////////////////////////////////////////////////////////////////
0115     template <typename A0>
0116     struct use_terminal<karma::domain         // enables ushort_(...)
0117       , terminal_ex<tag::ushort_, fusion::vector1<A0> >
0118     > : mpl::true_ {};
0119 
0120     template <typename A0>
0121     struct use_terminal<karma::domain         // enables uint_(...)
0122       , terminal_ex<tag::uint_, fusion::vector1<A0> >
0123     > : mpl::true_ {};
0124 
0125     template <typename A0>
0126     struct use_terminal<karma::domain         // enables ulong_(...)
0127       , terminal_ex<tag::ulong_, fusion::vector1<A0> >
0128     > : mpl::true_ {};
0129 
0130     template <typename A0>
0131     struct use_terminal<karma::domain         // enables bin(...)
0132       , terminal_ex<tag::bin, fusion::vector1<A0> >
0133     > : mpl::true_ {};
0134 
0135     template <typename A0>
0136     struct use_terminal<karma::domain         // enables oct(...)
0137       , terminal_ex<tag::oct, fusion::vector1<A0> >
0138     > : mpl::true_ {};
0139 
0140     template <typename A0>
0141     struct use_terminal<karma::domain         // enables hex(...)
0142       , terminal_ex<tag::hex, fusion::vector1<A0> >
0143     > : mpl::true_ {};
0144 
0145 #ifdef BOOST_HAS_LONG_LONG
0146     template <typename A0>
0147     struct use_terminal<karma::domain         // enables ulong_long(...)
0148       , terminal_ex<tag::ulong_long, fusion::vector1<A0> >
0149     > : mpl::true_ {};
0150 #endif
0151 
0152     ///////////////////////////////////////////////////////////////////////////
0153     template <>                               // enables *lazy* ushort_(...)
0154     struct use_lazy_terminal<karma::domain, tag::ushort_, 1>
0155       : mpl::true_ {};
0156 
0157     template <>                               // enables *lazy* uint_(...)
0158     struct use_lazy_terminal<karma::domain, tag::uint_, 1>
0159       : mpl::true_ {};
0160 
0161     template <>                               // enables *lazy* ulong_(...)
0162     struct use_lazy_terminal<karma::domain, tag::ulong_, 1>
0163       : mpl::true_ {};
0164 
0165     template <>                               // enables *lazy* bin(...)
0166     struct use_lazy_terminal<karma::domain, tag::bin, 1>
0167       : mpl::true_ {};
0168 
0169     template <>                               // enables *lazy* oct(...)
0170     struct use_lazy_terminal<karma::domain, tag::oct, 1>
0171       : mpl::true_ {};
0172 
0173     template <>                               // enables *lazy* hex(...)
0174     struct use_lazy_terminal<karma::domain, tag::hex, 1>
0175       : mpl::true_ {};
0176 
0177 #ifdef BOOST_HAS_LONG_LONG
0178     template <>                               // enables *lazy* ulong_long(...)
0179     struct use_lazy_terminal<karma::domain, tag::ulong_long, 1>
0180       : mpl::true_ {};
0181 #endif
0182 
0183     ///////////////////////////////////////////////////////////////////////////
0184     // enables any custom uint_generator
0185     template <typename T, unsigned Radix>
0186     struct use_terminal<karma::domain, tag::uint_generator<T, Radix> >
0187       : mpl::true_ {};
0188 
0189     // enables any custom uint_generator(...)
0190     template <typename T, unsigned Radix, typename A0>
0191     struct use_terminal<karma::domain
0192       , terminal_ex<tag::uint_generator<T, Radix>, fusion::vector1<A0> >
0193     > : mpl::true_ {};
0194 
0195     // enables *lazy* custom uint_generator
0196     template <typename T, unsigned Radix>
0197     struct use_lazy_terminal<
0198         karma::domain
0199       , tag::uint_generator<T, Radix>
0200       , 1 // arity
0201     > : mpl::true_ {};
0202 
0203     // enables lit(uint)
0204     template <typename A0>
0205     struct use_terminal<karma::domain
0206           , terminal_ex<tag::lit, fusion::vector1<A0> >
0207           , typename enable_if<traits::is_uint<A0> >::type>
0208       : mpl::true_ {};
0209 }}
0210 
0211 ///////////////////////////////////////////////////////////////////////////////
0212 namespace boost { namespace spirit { namespace karma
0213 {
0214 #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
0215     using spirit::ushort_;
0216     using spirit::uint_;
0217     using spirit::ulong_;
0218 #ifdef BOOST_HAS_LONG_LONG
0219     using spirit::ulong_long;
0220 #endif
0221     using spirit::bin;
0222     using spirit::oct;
0223     using spirit::hex;
0224 
0225     using spirit::lit;    // lit(1U) is equivalent to 1U
0226 #endif
0227 
0228     using spirit::ushort_type;
0229     using spirit::uint_type;
0230     using spirit::ulong_type;
0231 #ifdef BOOST_HAS_LONG_LONG
0232     using spirit::ulong_long_type;
0233 #endif
0234     using spirit::bin_type;
0235     using spirit::oct_type;
0236     using spirit::hex_type;
0237 
0238     using spirit::lit_type;
0239 
0240     ///////////////////////////////////////////////////////////////////////////
0241     //  This specialization is used for unsigned int generators not having a
0242     //  direct initializer: uint_, ulong_ etc. These generators must be used in
0243     //  conjunction with an Attribute.
0244     ///////////////////////////////////////////////////////////////////////////
0245     template <typename T, typename CharEncoding, typename Tag, unsigned Radix>
0246     struct any_uint_generator
0247       : primitive_generator<any_uint_generator<T, CharEncoding, Tag, Radix> >
0248     {
0249         template <typename Context, typename Unused>
0250         struct attribute
0251         {
0252             typedef T type;
0253         };
0254 
0255         // check template Attribute 'Radix' for validity
0256         BOOST_SPIRIT_ASSERT_MSG(
0257             Radix >= 2 && Radix <= 36, not_supported_radix, ());
0258 
0259         BOOST_SPIRIT_ASSERT_MSG(
0260             // the following is a workaround for STLPort, where the simpler
0261             // `!std::numeric_limits<T>::is_signed` wouldn't compile
0262             mpl::not_<mpl::bool_<std::numeric_limits<T>::is_signed> >::value,
0263             signed_unsigned_mismatch, ());
0264 
0265         // int has a Attribute attached
0266         template <typename OutputIterator, typename Context, typename Delimiter
0267           , typename Attribute>
0268         static bool
0269         generate(OutputIterator& sink, Context& context, Delimiter const& d
0270           , Attribute const& attr)
0271         {
0272             if (!traits::has_optional_value(attr))
0273                 return false;       // fail if it's an uninitialized optional
0274 
0275             return uint_inserter<Radix, CharEncoding, Tag>::
0276                         call(sink, traits::extract_from<T>(attr, context)) &&
0277                    delimit_out(sink, d);      // always do post-delimiting
0278         }
0279 
0280         // this int has no Attribute attached, it needs to have been
0281         // initialized from a direct literal
0282         template <typename OutputIterator, typename Context, typename Delimiter>
0283         static bool
0284         generate(OutputIterator&, Context&, Delimiter const&, unused_type)
0285         {
0286             // It is not possible (doesn't make sense) to use numeric generators
0287             // without providing any attribute, as the generator doesn't 'know'
0288             // what to output. The following assertion fires if this situation
0289             // is detected in your code.
0290             BOOST_SPIRIT_ASSERT_FAIL(OutputIterator, uint_not_usable_without_attribute, ());
0291             return false;
0292         }
0293 
0294         template <typename Context>
0295         static info what(Context const& /*context*/)
0296         {
0297             return info("unsigned-integer");
0298         }
0299     };
0300 
0301     ///////////////////////////////////////////////////////////////////////////
0302     //  This specialization is used for unsigned int generators having a direct
0303     //  initializer: uint_(10), ulong_(20) etc.
0304     ///////////////////////////////////////////////////////////////////////////
0305     template <
0306         typename T, typename CharEncoding, typename Tag, unsigned Radix
0307       , bool no_attribute>
0308     struct literal_uint_generator
0309       : primitive_generator<literal_uint_generator<T, CharEncoding, Tag, Radix
0310           , no_attribute> >
0311     {
0312         template <typename Context, typename Unused = unused_type>
0313         struct attribute
0314           : mpl::if_c<no_attribute, unused_type, T>
0315         {};
0316 
0317         literal_uint_generator(typename add_const<T>::type n)
0318           : n_(n) {}
0319 
0320         // check template Attribute 'Radix' for validity
0321         BOOST_SPIRIT_ASSERT_MSG(
0322             Radix >= 2 && Radix <= 36, not_supported_radix, ());
0323 
0324         BOOST_SPIRIT_ASSERT_MSG(
0325             // the following is a workaround for STLPort, where the simpler
0326             // `!std::numeric_limits<T>::is_signed wouldn't` compile
0327             mpl::not_<mpl::bool_<std::numeric_limits<T>::is_signed> >::value,
0328             signed_unsigned_mismatch, ());
0329 
0330         // A uint(1U) which additionally has an associated attribute emits
0331         // its immediate literal only if it matches the attribute, otherwise
0332         // it fails.
0333         template <typename OutputIterator, typename Context, typename Delimiter
0334           , typename Attribute>
0335         bool generate(OutputIterator& sink, Context& context
0336           , Delimiter const& d, Attribute const& attr) const
0337         {
0338             typedef typename attribute<Context>::type attribute_type;
0339             if (!traits::has_optional_value(attr) ||
0340                 n_ != traits::extract_from<attribute_type>(attr, context))
0341             {
0342                 return false;
0343             }
0344             return uint_inserter<Radix, CharEncoding, Tag>::call(sink, n_) &&
0345                    delimit_out(sink, d);      // always do post-delimiting
0346         }
0347 
0348         // A uint(1U) without any associated attribute just emits its
0349         // immediate literal
0350         template <typename OutputIterator, typename Context, typename Delimiter>
0351         bool generate(OutputIterator& sink, Context&, Delimiter const& d
0352           , unused_type) const
0353         {
0354             return uint_inserter<Radix, CharEncoding, Tag>::call(sink, n_) &&
0355                    delimit_out(sink, d);      // always do post-delimiting
0356         }
0357 
0358         template <typename Context>
0359         static info what(Context const& /*context*/)
0360         {
0361             return info("unsigned-integer");
0362         }
0363 
0364         T n_;
0365     };
0366 
0367     ///////////////////////////////////////////////////////////////////////////
0368     // Generator generators: make_xxx function (objects)
0369     ///////////////////////////////////////////////////////////////////////////
0370     namespace detail
0371     {
0372         template <typename T, typename Modifiers, unsigned Radix = 10>
0373         struct make_uint
0374         {
0375             static bool const lower =
0376                 has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
0377             static bool const upper =
0378                 has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
0379 
0380             typedef any_uint_generator<
0381                 T
0382               , typename spirit::detail::get_encoding_with_case<
0383                     Modifiers, unused_type, lower || upper>::type
0384               , typename detail::get_casetag<Modifiers, lower || upper>::type
0385               , Radix
0386             > result_type;
0387 
0388             result_type operator()(unused_type, unused_type) const
0389             {
0390                 return result_type();
0391             }
0392         };
0393     }
0394 
0395     ///////////////////////////////////////////////////////////////////////////
0396     template <typename Modifiers>
0397     struct make_primitive<tag::ushort_, Modifiers>
0398       : detail::make_uint<unsigned short, Modifiers> {};
0399 
0400     template <typename Modifiers>
0401     struct make_primitive<tag::uint_, Modifiers>
0402       : detail::make_uint<unsigned int, Modifiers> {};
0403 
0404     template <typename Modifiers>
0405     struct make_primitive<tag::ulong_, Modifiers>
0406       : detail::make_uint<unsigned long, Modifiers> {};
0407 
0408     template <typename Modifiers>
0409     struct make_primitive<tag::bin, Modifiers>
0410       : detail::make_uint<unsigned, Modifiers, 2> {};
0411 
0412     template <typename Modifiers>
0413     struct make_primitive<tag::oct, Modifiers>
0414       : detail::make_uint<unsigned, Modifiers, 8> {};
0415 
0416     template <typename Modifiers>
0417     struct make_primitive<tag::hex, Modifiers>
0418       : detail::make_uint<unsigned, Modifiers, 16> {};
0419 
0420 #ifdef BOOST_HAS_LONG_LONG
0421     template <typename Modifiers>
0422     struct make_primitive<tag::ulong_long, Modifiers>
0423       : detail::make_uint<boost::ulong_long_type, Modifiers> {};
0424 #endif
0425 
0426     template <typename T, unsigned Radix, typename Modifiers>
0427     struct make_primitive<tag::uint_generator<T, Radix>, Modifiers>
0428       : detail::make_uint<typename remove_const<T>::type, Modifiers, Radix> {};
0429 
0430     ///////////////////////////////////////////////////////////////////////////
0431     namespace detail
0432     {
0433         template <typename T, typename Modifiers, unsigned Radix = 10>
0434         struct make_uint_direct
0435         {
0436             static bool const lower =
0437                 has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
0438             static bool const upper =
0439                 has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
0440 
0441             typedef literal_uint_generator<
0442                 T
0443               , typename spirit::detail::get_encoding_with_case<
0444                     Modifiers, unused_type, lower || upper>::type
0445               , typename detail::get_casetag<Modifiers, lower || upper>::type
0446               , Radix, false
0447             > result_type;
0448 
0449             template <typename Terminal>
0450             result_type operator()(Terminal const& term, unused_type) const
0451             {
0452                 return result_type(fusion::at_c<0>(term.args));
0453             }
0454         };
0455     }
0456 
0457     template <typename Modifiers, typename A0>
0458     struct make_primitive<
0459         terminal_ex<tag::ushort_, fusion::vector1<A0> >, Modifiers>
0460       : detail::make_uint_direct<unsigned short, Modifiers> {};
0461 
0462     template <typename Modifiers, typename A0>
0463     struct make_primitive<
0464         terminal_ex<tag::uint_, fusion::vector1<A0> >, Modifiers>
0465       : detail::make_uint_direct<unsigned int, Modifiers> {};
0466 
0467     template <typename Modifiers, typename A0>
0468     struct make_primitive<
0469         terminal_ex<tag::ulong_, fusion::vector1<A0> >, Modifiers>
0470       : detail::make_uint_direct<unsigned long, Modifiers> {};
0471 
0472     template <typename Modifiers, typename A0>
0473     struct make_primitive<
0474         terminal_ex<tag::bin, fusion::vector1<A0> >, Modifiers>
0475       : detail::make_uint_direct<unsigned, Modifiers, 2> {};
0476 
0477     template <typename Modifiers, typename A0>
0478     struct make_primitive<
0479         terminal_ex<tag::oct, fusion::vector1<A0> >, Modifiers>
0480       : detail::make_uint_direct<unsigned, Modifiers, 8> {};
0481 
0482     template <typename Modifiers, typename A0>
0483     struct make_primitive<
0484         terminal_ex<tag::hex, fusion::vector1<A0> >, Modifiers>
0485       : detail::make_uint_direct<unsigned, Modifiers, 16> {};
0486 
0487 #ifdef BOOST_HAS_LONG_LONG
0488     template <typename Modifiers, typename A0>
0489     struct make_primitive<
0490         terminal_ex<tag::ulong_long, fusion::vector1<A0> >, Modifiers>
0491       : detail::make_uint_direct<boost::ulong_long_type, Modifiers> {};
0492 #endif
0493 
0494     template <typename T, unsigned Radix, typename A0, typename Modifiers>
0495     struct make_primitive<
0496         terminal_ex<tag::uint_generator<T, Radix>, fusion::vector1<A0> >
0497           , Modifiers>
0498       : detail::make_uint_direct<typename remove_const<T>::type, Modifiers, Radix>
0499     {};
0500 
0501     ///////////////////////////////////////////////////////////////////////////
0502     namespace detail
0503     {
0504         template <typename T, typename Modifiers>
0505         struct basic_uint_literal
0506         {
0507             static bool const lower =
0508                 has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
0509             static bool const upper =
0510                 has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
0511 
0512             typedef literal_uint_generator<
0513                 T
0514               , typename spirit::detail::get_encoding_with_case<
0515                     Modifiers, unused_type, lower || upper>::type
0516               , typename detail::get_casetag<Modifiers, lower || upper>::type
0517               , 10, true
0518             > result_type;
0519 
0520             template <typename T_>
0521             result_type operator()(T_ i, unused_type) const
0522             {
0523                 return result_type(i);
0524             }
0525         };
0526     }
0527 
0528 #if !defined(BOOST_NO_INTRINSIC_WCHAR_T)
0529     template <typename Modifiers>
0530     struct make_primitive<unsigned short, Modifiers>
0531       : detail::basic_uint_literal<unsigned short, Modifiers> {};
0532 #endif
0533 
0534     template <typename Modifiers>
0535     struct make_primitive<unsigned int, Modifiers>
0536       : detail::basic_uint_literal<unsigned int, Modifiers> {};
0537 
0538     template <typename Modifiers>
0539     struct make_primitive<unsigned long, Modifiers>
0540       : detail::basic_uint_literal<unsigned long, Modifiers> {};
0541 
0542 #ifdef BOOST_HAS_LONG_LONG
0543     template <typename Modifiers>
0544     struct make_primitive<boost::ulong_long_type, Modifiers>
0545       : detail::basic_uint_literal<boost::ulong_long_type, Modifiers> {};
0546 #endif
0547 
0548     // lit(uint)
0549     template <typename Modifiers, typename A0>
0550     struct make_primitive<
0551             terminal_ex<tag::lit, fusion::vector1<A0> >
0552           , Modifiers
0553           , typename enable_if<traits::is_uint<A0> >::type>
0554     {
0555         static bool const lower =
0556             has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
0557         static bool const upper =
0558             has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
0559 
0560         typedef literal_uint_generator<
0561             typename remove_const<A0>::type
0562           , typename spirit::detail::get_encoding_with_case<
0563                 Modifiers, unused_type, lower || upper>::type
0564           , typename detail::get_casetag<Modifiers, lower || upper>::type
0565           , 10, true
0566         > result_type;
0567 
0568         template <typename Terminal>
0569         result_type operator()(Terminal const& term, unused_type) const
0570         {
0571             return result_type(fusion::at_c<0>(term.args));
0572         }
0573     };
0574 }}}
0575 
0576 #endif