Back to home page

EIC code displayed by LXR

 
 

    


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

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_META_CREATE_NOV_21_2009_0425PM)
0007 #define BOOST_SPIRIT_KARMA_META_CREATE_NOV_21_2009_0425PM
0008 
0009 #if defined(_MSC_VER)
0010 #pragma once
0011 #endif
0012 
0013 #include <boost/spirit/home/karma/domain.hpp>
0014 #include <boost/spirit/home/support/common_terminals.hpp>
0015 #include <boost/spirit/home/support/auto/meta_create.hpp>
0016 
0017 #include <boost/utility/enable_if.hpp>
0018 #include <boost/variant.hpp>
0019 #include <boost/optional.hpp>
0020 #include <boost/config.hpp>
0021 #include <boost/mpl/not.hpp>
0022 #include <boost/mpl/fold.hpp>
0023 #include <boost/mpl/vector.hpp>
0024 #include <boost/mpl/push_back.hpp>
0025 #include <boost/fusion/include/as_vector.hpp>
0026 #include <boost/proto/tags.hpp>
0027 #include <boost/type_traits/is_same.hpp>
0028 
0029 ///////////////////////////////////////////////////////////////////////////////
0030 namespace boost { namespace spirit { namespace karma
0031 {
0032     ///////////////////////////////////////////////////////////////////////////
0033     // compatible STL containers
0034     template <typename Container>
0035     struct meta_create_container
0036     {
0037         typedef make_unary_proto_expr<
0038             typename Container::value_type
0039           , proto::tag::dereference, karma::domain
0040         > make_proto_expr;
0041 
0042         typedef typename make_proto_expr::type type;
0043 
0044         static type call()
0045         {
0046             return make_proto_expr::call();
0047         }
0048     };
0049 
0050     ///////////////////////////////////////////////////////////////////////////
0051     // String types
0052     template <typename String>
0053     struct meta_create_string
0054     {
0055         typedef spirit::standard::string_type type;
0056         static type const call() { return type(); }
0057     };
0058 
0059     template <>
0060     struct meta_create_string<wchar_t*>
0061     {
0062         typedef spirit::standard_wide::string_type type;
0063         static type const call() { return type(); }
0064     };
0065 
0066     template <>
0067     struct meta_create_string<wchar_t const*>
0068     {
0069         typedef spirit::standard_wide::string_type type;
0070         static type const call() { return type(); }
0071     };
0072 
0073     template <int N>
0074     struct meta_create_string<wchar_t[N]>
0075     {
0076         typedef spirit::standard_wide::string_type type;
0077         static type const call() { return type(); }
0078     };
0079 
0080     template <int N>
0081     struct meta_create_string<wchar_t const[N]>
0082     {
0083         typedef spirit::standard_wide::string_type type;
0084         static type const call() { return type(); }
0085     };
0086 
0087     template <int N>
0088     struct meta_create_string<wchar_t(&)[N]>
0089     {
0090         typedef spirit::standard_wide::string_type type;
0091         static type const call() { return type(); }
0092     };
0093 
0094     template <int N>
0095     struct meta_create_string<wchar_t const(&)[N]>
0096     {
0097         typedef spirit::standard_wide::string_type type;
0098         static type const call() { return type(); }
0099     };
0100 
0101     template <typename Traits, typename Allocator>
0102     struct meta_create_string<std::basic_string<wchar_t, Traits, Allocator> >
0103     {
0104         typedef spirit::standard_wide::string_type type;
0105         static type const call() { return type(); }
0106     };
0107 
0108     ///////////////////////////////////////////////////////////////////////////
0109     // Fusion sequences
0110     template <typename Sequence>
0111     struct meta_create_sequence
0112     {
0113         // create a mpl sequence from the given fusion sequence
0114         typedef typename mpl::fold<
0115             typename fusion::result_of::as_vector<Sequence>::type
0116           , mpl::vector<>, mpl::push_back<mpl::_, mpl::_>
0117         >::type sequence_type;
0118 
0119         typedef make_nary_proto_expr<
0120             sequence_type, proto::tag::shift_left, karma::domain
0121         > make_proto_expr;
0122 
0123         typedef typename make_proto_expr::type type;
0124 
0125         static type call()
0126         {
0127             return make_proto_expr::call();
0128         }
0129     };
0130 
0131     ///////////////////////////////////////////////////////////////////////////
0132     // the default is to use the standard streaming operator unless it's a
0133     // STL container or a fusion sequence
0134 
0135     // The default implementation will be chosen if no predefined mapping of
0136     // the data type T to a Karma component is defined.
0137     struct no_auto_mapping_exists {};
0138 
0139     template <typename T, typename Enable = void>
0140     struct meta_create_impl : mpl::identity<no_auto_mapping_exists> {};
0141 
0142     template <typename T>
0143     struct meta_create_impl<T
0144           , typename enable_if<
0145                 mpl::and_<
0146                     traits::is_container<T>
0147                   , mpl::not_<traits::is_string<T> >
0148                   , mpl::not_<fusion::traits::is_sequence<T> >
0149                 > >::type>
0150       : meta_create_container<T> {};
0151 
0152     template <typename T>
0153     struct meta_create_impl<T
0154           , typename enable_if<traits::is_string<T> >::type>
0155       : meta_create_string<T> {};
0156 
0157     template <typename T>
0158     struct meta_create_impl<T, typename enable_if<
0159                 spirit::detail::is_fusion_sequence_but_not_proto_expr<T>
0160             >::type>
0161       : meta_create_sequence<T> {};
0162 
0163     template <typename T, typename Enable = void>
0164     struct meta_create : meta_create_impl<T> {};
0165 
0166     ///////////////////////////////////////////////////////////////////////////
0167     // optional
0168     template <typename T>
0169     struct meta_create<boost::optional<T> >
0170     {
0171         typedef make_unary_proto_expr<
0172             T, proto::tag::negate, karma::domain
0173         > make_proto_expr;
0174 
0175         typedef typename make_proto_expr::type type;
0176 
0177         static type call()
0178         {
0179             return make_proto_expr::call();
0180         }
0181     };
0182 
0183     ///////////////////////////////////////////////////////////////////////////
0184     // alternatives
0185     template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
0186     struct meta_create<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
0187     {
0188         typedef make_nary_proto_expr<
0189             typename boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>::types
0190           , proto::tag::bitwise_or, karma::domain
0191         > make_proto_expr;
0192 
0193         typedef typename make_proto_expr::type type;
0194 
0195         static type call()
0196         {
0197             return make_proto_expr::call();
0198         }
0199     };
0200 
0201     ///////////////////////////////////////////////////////////////////////////
0202     // predefined specializations for primitive components
0203 
0204     // character generator
0205     template <>
0206     struct meta_create<char>
0207     {
0208         typedef spirit::standard::char_type type;
0209         static type const call() { return type(); }
0210     };
0211     template <>
0212     struct meta_create<signed char>
0213     {
0214         typedef spirit::standard::char_type type;
0215         static type const call() { return type(); }
0216     };
0217     template <>
0218     struct meta_create<wchar_t>
0219     {
0220         typedef spirit::standard_wide::char_type type;
0221         static type const call() { return type(); }
0222     };
0223 
0224     template <>
0225     struct meta_create<unsigned char>
0226     {
0227         typedef spirit::standard::char_type type;
0228         static type const call() { return type(); }
0229     };
0230 
0231     // boolean generator
0232     template <>
0233     struct meta_create<bool>
0234     {
0235         typedef spirit::bool_type type;
0236         static type call() { return type(); }
0237     };
0238 
0239     // integral generators
0240     template <>
0241     struct meta_create<int>
0242     {
0243         typedef spirit::int_type type;
0244         static type call() { return type(); }
0245     };
0246     template <>
0247     struct meta_create<short>
0248     {
0249         typedef spirit::short_type type;
0250         static type call() { return type(); }
0251     };
0252     template <>
0253     struct meta_create<long>
0254     {
0255         typedef spirit::long_type type;
0256         static type call() { return type(); }
0257     };
0258     template <>
0259     struct meta_create<unsigned int>
0260     {
0261         typedef spirit::uint_type type;
0262         static type call() { return type(); }
0263     };
0264 #if !defined(BOOST_NO_INTRINSIC_WCHAR_T)
0265     template <>
0266     struct meta_create<unsigned short>
0267     {
0268         typedef spirit::ushort_type type;
0269         static type call() { return type(); }
0270     };
0271 #endif
0272     template <>
0273     struct meta_create<unsigned long>
0274     {
0275         typedef spirit::ulong_type type;
0276         static type call() { return type(); }
0277     };
0278 
0279 #ifdef BOOST_HAS_LONG_LONG
0280     template <>
0281     struct meta_create<boost::long_long_type>
0282     {
0283         typedef spirit::long_long_type type;
0284         static type call() { return type(); }
0285     };
0286     template <>
0287     struct meta_create<boost::ulong_long_type>
0288     {
0289         typedef spirit::ulong_long_type type;
0290         static type call() { return type(); }
0291     };
0292 #endif
0293 
0294     // floating point generators
0295     template <>
0296     struct meta_create<float>
0297     {
0298         typedef spirit::float_type type;
0299         static type call() { return type(); }
0300     };
0301     template <>
0302     struct meta_create<double>
0303     {
0304         typedef spirit::double_type type;
0305         static type call() { return type(); }
0306     };
0307     template <>
0308     struct meta_create<long double>
0309     {
0310         typedef spirit::long_double_type type;
0311         static type call() { return type(); }
0312     };
0313 }}}
0314 
0315 ///////////////////////////////////////////////////////////////////////////////
0316 namespace boost { namespace spirit { namespace traits
0317 {
0318     ///////////////////////////////////////////////////////////////////////////
0319     // main customization point for create_generator
0320     template <typename T, typename Enable = void>
0321     struct create_generator : karma::meta_create<T> {};
0322 
0323     ///////////////////////////////////////////////////////////////////////////
0324     // dispatch this to the karma related specializations
0325     template <typename T>
0326     struct meta_create<karma::domain, T>
0327       : create_generator<typename spirit::detail::remove_const_ref<T>::type> {};
0328 
0329     ///////////////////////////////////////////////////////////////////////////
0330     // Check whether a valid mapping exits for the given data type to a Karma
0331     // component
0332     template <typename T>
0333     struct meta_create_exists<karma::domain, T>
0334       : mpl::not_<is_same<
0335             karma::no_auto_mapping_exists
0336           , typename meta_create<karma::domain, T>::type
0337         > > {};
0338 }}}
0339 
0340 #endif