Back to home page

EIC code displayed by LXR

 
 

    


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

0001 //  Copyright (c) 2001-2012 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_INT_FEB_23_2007_0840PM)
0007 #define BOOST_SPIRIT_KARMA_INT_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 ///////////////////////////////////////////////////////////////////////////////
0039 namespace boost { namespace spirit
0040 {
0041     namespace tag
0042     {
0043         template <typename T, unsigned Radix, bool force_sign>
0044         struct int_generator
0045         {
0046             BOOST_SPIRIT_IS_TAG()
0047         };
0048     }
0049 
0050     namespace karma
0051     {
0052         ///////////////////////////////////////////////////////////////////////
0053         // This one is the class that the user can instantiate directly in
0054         // order to create a customized int generator
0055         template <typename T = int, unsigned Radix = 10, bool force_sign = false>
0056         struct int_generator
0057           : spirit::terminal<tag::int_generator<T, Radix, force_sign> >
0058         {};
0059     }
0060 
0061     ///////////////////////////////////////////////////////////////////////////
0062     // Enablers
0063     ///////////////////////////////////////////////////////////////////////////
0064     template <>
0065     struct use_terminal<karma::domain, tag::short_>    // enables short_
0066       : mpl::true_ {};
0067 
0068     template <>
0069     struct use_terminal<karma::domain, tag::int_>      // enables int_
0070       : mpl::true_ {};
0071 
0072     template <>
0073     struct use_terminal<karma::domain, tag::long_>     // enables long_
0074       : mpl::true_ {};
0075 
0076 #ifdef BOOST_HAS_LONG_LONG
0077     template <>
0078     struct use_terminal<karma::domain, tag::long_long> // enables long_long
0079       : mpl::true_ {};
0080 #endif
0081 
0082     ///////////////////////////////////////////////////////////////////////////
0083     template <>
0084     struct use_terminal<karma::domain, short>    // enables lit(short(0))
0085       : mpl::true_ {};
0086 
0087     template <>
0088     struct use_terminal<karma::domain, int>      // enables lit(0)
0089       : mpl::true_ {};
0090 
0091     template <>
0092     struct use_terminal<karma::domain, long>     // enables lit(0L)
0093       : mpl::true_ {};
0094 
0095 #ifdef BOOST_HAS_LONG_LONG
0096     template <>
0097     struct use_terminal<karma::domain, boost::long_long_type> // enables lit(0LL)
0098       : mpl::true_ {};
0099 #endif
0100 
0101     ///////////////////////////////////////////////////////////////////////////
0102     template <typename A0>
0103     struct use_terminal<karma::domain         // enables short_(...)
0104       , terminal_ex<tag::short_, fusion::vector1<A0> >
0105     > : mpl::true_ {};
0106 
0107     template <typename A0>
0108     struct use_terminal<karma::domain         // enables int_(...)
0109       , terminal_ex<tag::int_, fusion::vector1<A0> >
0110     > : mpl::true_ {};
0111 
0112     template <typename A0>
0113     struct use_terminal<karma::domain         // enables long_(...)
0114       , terminal_ex<tag::long_, fusion::vector1<A0> >
0115     > : mpl::true_ {};
0116 
0117 #ifdef BOOST_HAS_LONG_LONG
0118     template <typename A0>
0119     struct use_terminal<karma::domain         // enables long_long(...)
0120       , terminal_ex<tag::long_long, fusion::vector1<A0> >
0121     > : mpl::true_ {};
0122 #endif
0123 
0124     ///////////////////////////////////////////////////////////////////////////
0125     template <>                               // enables *lazy* short_(...)
0126     struct use_lazy_terminal<karma::domain, tag::short_, 1>
0127       : mpl::true_ {};
0128 
0129     template <>                               // enables *lazy* int_(...)
0130     struct use_lazy_terminal<karma::domain, tag::int_, 1>
0131       : mpl::true_ {};
0132 
0133     template <>                               // enables *lazy* long_(...)
0134     struct use_lazy_terminal<karma::domain, tag::long_, 1>
0135       : mpl::true_ {};
0136 
0137 #ifdef BOOST_HAS_LONG_LONG
0138     template <>                               // enables *lazy* long_long(...)
0139     struct use_lazy_terminal<karma::domain, tag::long_long, 1>
0140       : mpl::true_ {};
0141 #endif
0142 
0143     ///////////////////////////////////////////////////////////////////////////
0144     // enables any custom int_generator
0145     template <typename T, unsigned Radix, bool force_sign>
0146     struct use_terminal<karma::domain, tag::int_generator<T, Radix, force_sign> >
0147       : mpl::true_ {};
0148 
0149     // enables any custom int_generator(...)
0150     template <typename T, unsigned Radix, bool force_sign, typename A0>
0151     struct use_terminal<karma::domain
0152       , terminal_ex<tag::int_generator<T, Radix, force_sign>
0153                   , fusion::vector1<A0> >
0154     > : mpl::true_ {};
0155 
0156     // enables *lazy* custom int_generator
0157     template <typename T, unsigned Radix, bool force_sign>
0158     struct use_lazy_terminal<
0159         karma::domain
0160       , tag::int_generator<T, Radix, force_sign>
0161       , 1 // arity
0162     > : mpl::true_ {};
0163 
0164     // enables lit(int)
0165     template <typename A0>
0166     struct use_terminal<karma::domain
0167           , terminal_ex<tag::lit, fusion::vector1<A0> >
0168           , typename enable_if<traits::is_int<A0> >::type>
0169       : mpl::true_ {};
0170 }}
0171 
0172 ///////////////////////////////////////////////////////////////////////////////
0173 namespace boost { namespace spirit { namespace karma
0174 {
0175 #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
0176     using spirit::short_;
0177     using spirit::int_;
0178     using spirit::long_;
0179 #ifdef BOOST_HAS_LONG_LONG
0180     using spirit::long_long;
0181 #endif
0182     using spirit::lit;    // lit(1) is equivalent to 1
0183 #endif
0184 
0185     using spirit::short_type;
0186     using spirit::int_type;
0187     using spirit::long_type;
0188 #ifdef BOOST_HAS_LONG_LONG
0189     using spirit::long_long_type;
0190 #endif
0191 
0192     using spirit::lit_type;
0193 
0194     ///////////////////////////////////////////////////////////////////////////
0195     //  This specialization is used for int generators not having a direct
0196     //  initializer: int_, long_ etc. These generators must be used in
0197     //  conjunction with an Attribute.
0198     ///////////////////////////////////////////////////////////////////////////
0199     template <
0200         typename T, typename CharEncoding, typename Tag, unsigned Radix
0201       , bool force_sign>
0202     struct any_int_generator
0203       : primitive_generator<any_int_generator<T, CharEncoding, Tag, Radix
0204           , force_sign> >
0205     {
0206     private:
0207         template <typename OutputIterator, typename Attribute>
0208         static bool insert_int(OutputIterator& sink, Attribute const& attr)
0209         {
0210             return sign_inserter::call(sink, traits::test_zero(attr)
0211                       , traits::test_negative(attr), force_sign) &&
0212                    int_inserter<Radix, CharEncoding, Tag>::call(sink
0213                       , traits::get_absolute_value(attr));
0214         }
0215 
0216     public:
0217         template <typename Context, typename Unused>
0218         struct attribute
0219         {
0220             typedef T type;
0221         };
0222 
0223         // check template Attribute 'Radix' for validity
0224         BOOST_SPIRIT_ASSERT_MSG(
0225             Radix == 2 || Radix == 8 || Radix == 10 || Radix == 16,
0226             not_supported_radix, ());
0227 
0228         BOOST_SPIRIT_ASSERT_MSG(std::numeric_limits<T>::is_signed,
0229             signed_unsigned_mismatch, ());
0230 
0231         // int has a Attribute attached
0232         template <typename OutputIterator, typename Context, typename Delimiter
0233           , typename Attribute>
0234         static bool
0235         generate(OutputIterator& sink, Context& context, Delimiter const& d
0236           , Attribute const& attr)
0237         {
0238             if (!traits::has_optional_value(attr))
0239                 return false;       // fail if it's an uninitialized optional
0240 
0241             return insert_int(sink, traits::extract_from<T>(attr, context)) &&
0242                    delimit_out(sink, d);      // always do post-delimiting
0243         }
0244 
0245         // this int has no Attribute attached, it needs to have been
0246         // initialized from a direct literal
0247         template <typename OutputIterator, typename Context, typename Delimiter>
0248         static bool
0249         generate(OutputIterator&, Context&, Delimiter const&, unused_type)
0250         {
0251             // It is not possible (doesn't make sense) to use numeric generators
0252             // without providing any attribute, as the generator doesn't 'know'
0253             // what to output. The following assertion fires if this situation
0254             // is detected in your code.
0255             BOOST_SPIRIT_ASSERT_FAIL(OutputIterator, int_not_usable_without_attribute, ());
0256             return false;
0257         }
0258 
0259         template <typename Context>
0260         static info what(Context const& /*context*/)
0261         {
0262             return info("integer");
0263         }
0264     };
0265 
0266     ///////////////////////////////////////////////////////////////////////////
0267     //  This specialization is used for int generators having a direct
0268     //  initializer: int_(10), long_(20) etc.
0269     ///////////////////////////////////////////////////////////////////////////
0270     template <
0271         typename T, typename CharEncoding, typename Tag, unsigned Radix
0272       , bool force_sign, bool no_attribute>
0273     struct literal_int_generator
0274       : primitive_generator<literal_int_generator<T, CharEncoding, Tag, Radix
0275           , force_sign, no_attribute> >
0276     {
0277     private:
0278         template <typename OutputIterator, typename Attribute>
0279         static bool insert_int(OutputIterator& sink, Attribute const& attr)
0280         {
0281             return sign_inserter::call(sink, traits::test_zero(attr)
0282                       , traits::test_negative(attr), force_sign) &&
0283                    int_inserter<Radix, CharEncoding, Tag>::call(sink
0284                       , traits::get_absolute_value(attr));
0285         }
0286 
0287     public:
0288         template <typename Context, typename Unused = unused_type>
0289         struct attribute
0290           : mpl::if_c<no_attribute, unused_type, T>
0291         {};
0292 
0293         literal_int_generator(typename add_const<T>::type n)
0294           : n_(n) {}
0295 
0296         // check template Attribute 'Radix' for validity
0297         BOOST_SPIRIT_ASSERT_MSG(
0298             Radix == 2 || Radix == 8 || Radix == 10 || Radix == 16,
0299             not_supported_radix, ());
0300 
0301         BOOST_SPIRIT_ASSERT_MSG(std::numeric_limits<T>::is_signed,
0302             signed_unsigned_mismatch, ());
0303 
0304         // A int_(1) which additionally has an associated attribute emits
0305         // its immediate literal only if it matches the attribute, otherwise
0306         // it fails.
0307         template <typename OutputIterator, typename Context, typename Delimiter
0308           , typename Attribute>
0309         bool generate(OutputIterator& sink, Context& context
0310           , Delimiter const& d, Attribute const& attr) const
0311         {
0312             typedef typename attribute<Context>::type attribute_type;
0313             if (!traits::has_optional_value(attr) ||
0314                 n_ != traits::extract_from<attribute_type>(attr, context))
0315             {
0316                 return false;
0317             }
0318             return insert_int(sink, n_) && delimit_out(sink, d);
0319         }
0320 
0321         // A int_(1) without any associated attribute just emits its
0322         // immediate literal
0323         template <typename OutputIterator, typename Context, typename Delimiter>
0324         bool generate(OutputIterator& sink, Context&, Delimiter const& d
0325           , unused_type) const
0326         {
0327             return insert_int(sink, n_) && delimit_out(sink, d);
0328         }
0329 
0330         template <typename Context>
0331         static info what(Context const& /*context*/)
0332         {
0333             return info("integer");
0334         }
0335 
0336         T n_;
0337     };
0338 
0339     ///////////////////////////////////////////////////////////////////////////
0340     // Generator generators: make_xxx function (objects)
0341     ///////////////////////////////////////////////////////////////////////////
0342     namespace detail
0343     {
0344         template <typename T, typename Modifiers, unsigned Radix = 10
0345           , bool force_sign = false>
0346         struct make_int
0347         {
0348             static bool const lower =
0349                 has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
0350             static bool const upper =
0351                 has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
0352 
0353             typedef any_int_generator<
0354                 T
0355               , typename spirit::detail::get_encoding_with_case<
0356                     Modifiers, unused_type, lower || upper>::type
0357               , typename detail::get_casetag<Modifiers, lower || upper>::type
0358               , Radix
0359               , force_sign
0360             > result_type;
0361 
0362             result_type operator()(unused_type, unused_type) const
0363             {
0364                 return result_type();
0365             }
0366         };
0367     }
0368 
0369     ///////////////////////////////////////////////////////////////////////////
0370     template <typename Modifiers>
0371     struct make_primitive<tag::short_, Modifiers>
0372       : detail::make_int<short, Modifiers> {};
0373 
0374     template <typename Modifiers>
0375     struct make_primitive<tag::int_, Modifiers>
0376       : detail::make_int<int, Modifiers> {};
0377 
0378     template <typename Modifiers>
0379     struct make_primitive<tag::long_, Modifiers>
0380       : detail::make_int<long, Modifiers> {};
0381 
0382 #ifdef BOOST_HAS_LONG_LONG
0383     template <typename Modifiers>
0384     struct make_primitive<tag::long_long, Modifiers>
0385       : detail::make_int<boost::long_long_type, Modifiers> {};
0386 #endif
0387 
0388     template <typename T, unsigned Radix, bool force_sign, typename Modifiers>
0389     struct make_primitive<tag::int_generator<T, Radix, force_sign>, Modifiers>
0390       : detail::make_int<typename remove_const<T>::type
0391           , Modifiers, Radix, force_sign> {};
0392 
0393     ///////////////////////////////////////////////////////////////////////////
0394     namespace detail
0395     {
0396         template <typename T, typename Modifiers, unsigned Radix = 10
0397           , bool force_sign = false>
0398         struct make_int_direct
0399         {
0400             static bool const lower =
0401                 has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
0402             static bool const upper =
0403                 has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
0404 
0405             typedef literal_int_generator<
0406                 T
0407               , typename spirit::detail::get_encoding_with_case<
0408                     Modifiers, unused_type, lower || upper>::type
0409               , typename detail::get_casetag<Modifiers, lower || upper>::type
0410               , Radix, force_sign, false
0411             > result_type;
0412 
0413             template <typename Terminal>
0414             result_type operator()(Terminal const& term, unused_type) const
0415             {
0416                 return result_type(fusion::at_c<0>(term.args));
0417             }
0418         };
0419     }
0420 
0421     ///////////////////////////////////////////////////////////////////////////
0422     template <typename Modifiers, typename A0>
0423     struct make_primitive<
0424         terminal_ex<tag::short_, fusion::vector1<A0> >, Modifiers>
0425       : detail::make_int_direct<short, Modifiers> {};
0426 
0427     template <typename Modifiers, typename A0>
0428     struct make_primitive<
0429         terminal_ex<tag::int_, fusion::vector1<A0> >, Modifiers>
0430       : detail::make_int_direct<int, Modifiers> {};
0431 
0432     template <typename Modifiers, typename A0>
0433     struct make_primitive<
0434         terminal_ex<tag::long_, fusion::vector1<A0> >, Modifiers>
0435       : detail::make_int_direct<long, Modifiers> {};
0436 
0437 #ifdef BOOST_HAS_LONG_LONG
0438     template <typename Modifiers, typename A0>
0439     struct make_primitive<
0440         terminal_ex<tag::long_long, fusion::vector1<A0> >, Modifiers>
0441       : detail::make_int_direct<boost::long_long_type, Modifiers> {};
0442 #endif
0443 
0444     template <typename T, unsigned Radix, bool force_sign, typename A0
0445       , typename Modifiers>
0446     struct make_primitive<
0447         terminal_ex<tag::int_generator<T, Radix, force_sign>
0448           , fusion::vector1<A0> >, Modifiers>
0449       : detail::make_int_direct<typename remove_const<T>::type
0450           , Modifiers, Radix, force_sign> {};
0451 
0452     ///////////////////////////////////////////////////////////////////////////
0453     namespace detail
0454     {
0455         template <typename T, typename Modifiers>
0456         struct basic_int_literal
0457         {
0458             static bool const lower =
0459                 has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
0460             static bool const upper =
0461                 has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
0462 
0463             typedef literal_int_generator<
0464                 T
0465               , typename spirit::detail::get_encoding_with_case<
0466                     Modifiers, unused_type, lower || upper>::type
0467               , typename detail::get_casetag<Modifiers, lower || upper>::type
0468               , 10, false, true
0469             > result_type;
0470 
0471             template <typename T_>
0472             result_type operator()(T_ i, unused_type) const
0473             {
0474                 return result_type(i);
0475             }
0476         };
0477     }
0478 
0479     template <typename Modifiers>
0480     struct make_primitive<short, Modifiers>
0481       : detail::basic_int_literal<short, Modifiers> {};
0482 
0483     template <typename Modifiers>
0484     struct make_primitive<int, Modifiers>
0485       : detail::basic_int_literal<int, Modifiers> {};
0486 
0487     template <typename Modifiers>
0488     struct make_primitive<long, Modifiers>
0489       : detail::basic_int_literal<long, Modifiers> {};
0490 
0491 #ifdef BOOST_HAS_LONG_LONG
0492     template <typename Modifiers>
0493     struct make_primitive<boost::long_long_type, Modifiers>
0494       : detail::basic_int_literal<boost::long_long_type, Modifiers> {};
0495 #endif
0496 
0497     // lit(int)
0498     template <typename Modifiers, typename A0>
0499     struct make_primitive<
0500             terminal_ex<tag::lit, fusion::vector1<A0> >
0501           , Modifiers
0502           , typename enable_if<traits::is_int<A0> >::type>
0503     {
0504         static bool const lower =
0505             has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
0506         static bool const upper =
0507             has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
0508 
0509         typedef literal_int_generator<
0510             typename remove_const<A0>::type
0511           , typename spirit::detail::get_encoding_with_case<
0512                 Modifiers, unused_type, lower || upper>::type
0513           , typename detail::get_casetag<Modifiers, lower || upper>::type
0514           , 10, false, true
0515         > result_type;
0516 
0517         template <typename Terminal>
0518         result_type operator()(Terminal const& term, unused_type) const
0519         {
0520             return result_type(fusion::at_c<0>(term.args));
0521         }
0522     };
0523 }}}
0524 
0525 #endif