Back to home page

EIC code displayed by LXR

 
 

    


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

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_EXTRACT_FROM_SEP_30_2009_0732AM)
0007 #define BOOST_SPIRIT_KARMA_EXTRACT_FROM_SEP_30_2009_0732AM
0008 
0009 #if defined(_MSC_VER)
0010 #pragma once
0011 #endif
0012 
0013 #include <boost/spirit/home/support/unused.hpp>
0014 #include <boost/spirit/home/support/attributes_fwd.hpp>
0015 #include <boost/spirit/home/karma/detail/attributes.hpp>
0016 #include <boost/spirit/home/support/container.hpp>
0017 
0018 #include <boost/ref.hpp>
0019 #include <boost/optional.hpp>
0020 
0021 ///////////////////////////////////////////////////////////////////////////////
0022 namespace boost { namespace spirit { namespace traits
0023 {
0024     ///////////////////////////////////////////////////////////////////////////
0025     //  This file contains attribute extraction utilities. The utilities
0026     //  provided also accept spirit's unused_type; all no-ops. Compiler
0027     //  optimization will easily strip these away.
0028     ///////////////////////////////////////////////////////////////////////////
0029 
0030     namespace detail
0031     {
0032         ///////////////////////////////////////////////////////////////////////
0033         // extract first and second element of a fusion sequence
0034         template <typename T>
0035         struct add_const_ref
0036           : add_reference<typename add_const<T>::type>
0037         {};
0038 
0039         template <typename T, int N>
0040         struct value_at_c
0041           : add_const_ref<typename fusion::result_of::value_at_c<T, N>::type>
0042         {};
0043     }
0044 
0045     // This is the default case: the plain attribute values
0046     template <typename Attribute, typename Exposed
0047       , bool IsOneElemSeq = traits::one_element_sequence<Attribute>::value>
0048     struct extract_from_attribute_base
0049     {
0050         typedef Attribute const& type;
0051 
0052         template <typename Context>
0053         static type call(Attribute const& attr, Context&)
0054         {
0055             return attr;
0056         }
0057     };
0058 
0059     // This handles the case where the attribute is a single element fusion
0060     // sequence. We silently extract the only element and treat it as the
0061     // attribute to generate output from.
0062     template <typename Attribute, typename Exposed>
0063     struct extract_from_attribute_base<Attribute, Exposed, true>
0064     {
0065         typedef typename remove_const<
0066             typename remove_reference<
0067                 typename fusion::result_of::at_c<Attribute, 0>::type
0068             >::type
0069         >::type elem_type;
0070 
0071         typedef typename result_of::extract_from<Exposed, elem_type>::type type;
0072 
0073         template <typename Context>
0074         static type call(Attribute const& attr, Context& ctx)
0075         {
0076             return extract_from<Exposed>(fusion::at_c<0>(attr), ctx);
0077         }
0078     };
0079 
0080     template <typename Attribute, typename Exposed, typename Enable/*= void*/>
0081     struct extract_from_attribute
0082       : extract_from_attribute_base<Attribute, Exposed>
0083     {};
0084 
0085     // This handles optional attributes.
0086     template <typename Attribute, typename Exposed>
0087     struct extract_from_attribute<boost::optional<Attribute>, Exposed>
0088     {
0089         typedef Attribute const& type;
0090 
0091         template <typename Context>
0092         static type call(boost::optional<Attribute> const& attr, Context& ctx)
0093         {
0094             return extract_from<Exposed>(boost::get<Attribute>(attr), ctx);
0095         }
0096     };
0097 
0098     template <typename Attribute, typename Exposed>
0099     struct extract_from_attribute<boost::optional<Attribute const>, Exposed>
0100     {
0101         typedef Attribute const& type;
0102 
0103         template <typename Context>
0104         static type call(boost::optional<Attribute const> const& attr, Context& ctx)
0105         {
0106             return extract_from<Exposed>(boost::get<Attribute const>(attr), ctx);
0107         }
0108     };
0109 
0110     // This handles attributes wrapped inside a boost::ref().
0111     template <typename Attribute, typename Exposed>
0112     struct extract_from_attribute<reference_wrapper<Attribute>, Exposed>
0113     {
0114         typedef Attribute const& type;
0115 
0116         template <typename Context>
0117         static type call(reference_wrapper<Attribute> const& attr, Context& ctx)
0118         {
0119             return extract_from<Exposed>(attr.get(), ctx);
0120         }
0121     };
0122 
0123     ///////////////////////////////////////////////////////////////////////////
0124     template <typename Attribute, typename Exposed, typename Enable>
0125     struct extract_from_container
0126     {
0127         typedef typename traits::container_value<Attribute const>::type
0128             value_type;
0129         typedef typename is_convertible<value_type, Exposed>::type
0130             is_convertible_to_value_type;
0131 
0132         typedef typename mpl::if_<
0133            mpl::or_<
0134                 is_same<value_type, Exposed>, is_same<Attribute, Exposed> >
0135           , Exposed const&, Exposed
0136         >::type type;
0137 
0138         // handle case where container value type is convertible to result type
0139         // we simply return the front element of the container
0140         template <typename Context, typename Pred>
0141         static type call(Attribute const& attr, Context&, mpl::true_, Pred)
0142         {
0143             // return first element from container
0144             typedef typename traits::container_iterator<Attribute const>::type
0145                 iterator_type;
0146 
0147             iterator_type it = traits::begin(attr);
0148             type result = *it;
0149             ++it;
0150             return result;
0151         }
0152 
0153         // handle strings
0154         template <typename Iterator>
0155         static void append_to_string(Exposed& result, Iterator begin, Iterator end)
0156         {
0157             for (Iterator i = begin; i != end; ++i)
0158                 push_back(result, *i);
0159         }
0160 
0161         template <typename Context>
0162         static type call(Attribute const& attr, Context&, mpl::false_, mpl::true_)
0163         {
0164             typedef typename char_type_of<Attribute>::type char_type;
0165 
0166             Exposed result;
0167             append_to_string(result, traits::get_begin<char_type>(attr)
0168               , traits::get_end<char_type>(attr));
0169             return result;
0170         }
0171 
0172         // everything else gets just passed through
0173         template <typename Context>
0174         static type call(Attribute const& attr, Context&, mpl::false_, mpl::false_)
0175         {
0176             return type(attr);
0177         }
0178 
0179         template <typename Context>
0180         static type call(Attribute const& attr, Context& ctx)
0181         {
0182             typedef typename mpl::and_<
0183                 traits::is_string<Exposed>, traits::is_string<Attribute>
0184             >::type handle_strings;
0185 
0186             // return first element from container
0187             return call(attr, ctx, is_convertible_to_value_type()
0188               , handle_strings());
0189         }
0190     };
0191 
0192     template <typename Attribute>
0193     struct extract_from_container<Attribute, Attribute>
0194     {
0195         typedef Attribute const& type;
0196 
0197         template <typename Context>
0198         static type call(Attribute const& attr, Context&)
0199         {
0200             return attr;
0201         }
0202     };
0203 
0204     ///////////////////////////////////////////////////////////////////////////
0205     namespace detail
0206     {
0207         // overload for non-container attributes
0208         template <typename Exposed, typename Attribute, typename Context>
0209         inline typename spirit::result_of::extract_from<Exposed, Attribute>::type
0210         extract_from(Attribute const& attr, Context& ctx, mpl::false_)
0211         {
0212             return extract_from_attribute<Attribute, Exposed>::call(attr, ctx);
0213         }
0214 
0215         // overload for containers (but not for variants or optionals
0216         // holding containers)
0217         template <typename Exposed, typename Attribute, typename Context>
0218         inline typename spirit::result_of::extract_from<Exposed, Attribute>::type
0219         extract_from(Attribute const& attr, Context& ctx, mpl::true_)
0220         {
0221             return extract_from_container<Attribute, Exposed>::call(attr, ctx);
0222         }
0223     }
0224 
0225     template <typename Exposed, typename Attribute, typename Context>
0226     inline typename spirit::result_of::extract_from<Exposed, Attribute>::type
0227     extract_from(Attribute const& attr, Context& ctx
0228 #if (defined(__GNUC__) && (__GNUC__ < 4)) || \
0229     (defined(__APPLE__) && defined(__INTEL_COMPILER))
0230       , typename enable_if<traits::not_is_unused<Attribute> >::type*
0231 #endif
0232     )
0233     {
0234         typedef typename mpl::and_<
0235             traits::is_container<Attribute>
0236           , traits::not_is_variant<Attribute>
0237           , traits::not_is_optional<Attribute>
0238         >::type is_not_wrapped_container;
0239 
0240         return detail::extract_from<Exposed>(attr, ctx
0241           , is_not_wrapped_container());
0242     }
0243 
0244     template <typename Exposed, typename Context>
0245     inline unused_type extract_from(unused_type, Context&)
0246     {
0247         return unused;
0248     }
0249 }}}
0250 
0251 ///////////////////////////////////////////////////////////////////////////////
0252 namespace boost { namespace spirit { namespace result_of
0253 {
0254     template <typename Exposed, typename Attribute>
0255     struct extract_from
0256       : mpl::if_<
0257             mpl::and_<
0258                 traits::is_container<Attribute>
0259               , traits::not_is_variant<Attribute>
0260               , traits::not_is_optional<Attribute> >
0261           , traits::extract_from_container<Attribute, Exposed>
0262           , traits::extract_from_attribute<Attribute, Exposed> >::type
0263     {};
0264 
0265     template <typename Exposed>
0266     struct extract_from<Exposed, unused_type>
0267     {
0268         typedef unused_type type;
0269     };
0270 
0271     template <typename Exposed>
0272     struct extract_from<Exposed, unused_type const>
0273     {
0274         typedef unused_type type;
0275     };
0276 }}}
0277 
0278 #endif