Back to home page

EIC code displayed by LXR

 
 

    


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

0001 /*=============================================================================
0002     Copyright (c) 2001-2011 Joel de Guzman
0003     Copyright (c) 2001-2011 Hartmut Kaiser
0004     http://spirit.sourceforge.net/
0005 
0006     Distributed under the Boost Software License, Version 1.0. (See accompanying
0007     file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0008 =============================================================================*/
0009 #if !defined(BOOST_SPIRIT_ASSIGN_TO_APR_16_2006_0812PM)
0010 #define BOOST_SPIRIT_ASSIGN_TO_APR_16_2006_0812PM
0011 
0012 #if defined(_MSC_VER)
0013 #pragma once
0014 #endif
0015 
0016 #include <boost/spirit/home/qi/detail/construct.hpp>
0017 #include <boost/spirit/home/support/unused.hpp>
0018 #include <boost/spirit/home/qi/detail/attributes.hpp>
0019 #include <boost/spirit/home/support/container.hpp>
0020 #include <boost/fusion/include/copy.hpp>
0021 #include <boost/fusion/adapted/struct/detail/extension.hpp>
0022 #include <boost/ref.hpp>
0023 #include <boost/range/range_fwd.hpp>
0024 
0025 namespace boost { namespace spirit { namespace traits
0026 {
0027     ///////////////////////////////////////////////////////////////////////////
0028     //  This file contains assignment utilities. The utilities provided also
0029     //  accept spirit's unused_type; all no-ops. Compiler optimization will
0030     //  easily strip these away.
0031     ///////////////////////////////////////////////////////////////////////////
0032     namespace detail
0033     {
0034         template <typename T>
0035         struct is_iter_range : mpl::false_ {};
0036 
0037         template <typename I>
0038         struct is_iter_range<boost::iterator_range<I> > : mpl::true_ {};
0039 
0040         template <typename C>
0041         struct is_container_of_ranges
0042           : is_iter_range<typename C::value_type> {};
0043     }
0044 
0045     template <typename Attribute, typename Iterator, typename Enable>
0046     struct assign_to_attribute_from_iterators
0047     {
0048         // Common case
0049         static void
0050         call(Iterator const& first, Iterator const& last, Attribute& attr, mpl::false_)
0051         {
0052             if (traits::is_empty(attr))
0053                 attr = Attribute(first, last);
0054             else {
0055                 for (Iterator i = first; i != last; ++i)
0056                     push_back(attr, *i);
0057             }
0058         }
0059 
0060         // If Attribute is a container with value_type==iterator_range<T> just push the
0061         // iterator_range into it
0062         static void
0063         call(Iterator const& first, Iterator const& last, Attribute& attr, mpl::true_)
0064         {
0065             typename Attribute::value_type rng(first, last);
0066             push_back(attr, rng);
0067         }
0068 
0069         static void
0070         call(Iterator const& first, Iterator const& last, Attribute& attr)
0071         {
0072             call(first, last, attr, detail::is_container_of_ranges<Attribute>());
0073         }
0074     };
0075 
0076     template <typename Attribute, typename Iterator>
0077     struct assign_to_attribute_from_iterators<
0078         reference_wrapper<Attribute>, Iterator>
0079     {
0080         static void
0081         call(Iterator const& first, Iterator const& last
0082           , reference_wrapper<Attribute> attr)
0083         {
0084             if (traits::is_empty(attr))
0085                 attr = Attribute(first, last);
0086             else {
0087                 for (Iterator i = first; i != last; ++i)
0088                     push_back(attr, *i);
0089             }
0090         }
0091     };
0092 
0093     template <typename Attribute, typename Iterator>
0094     struct assign_to_attribute_from_iterators<
0095         boost::optional<Attribute>, Iterator>
0096     {
0097         static void
0098         call(Iterator const& first, Iterator const& last
0099           , boost::optional<Attribute>& attr)
0100         {
0101             Attribute val;
0102             assign_to(first, last, val);
0103             attr = val;
0104         }
0105     };
0106 
0107     template <typename Iterator>
0108     struct assign_to_attribute_from_iterators<
0109         iterator_range<Iterator>, Iterator>
0110     {
0111         static void
0112         call(Iterator const& first, Iterator const& last
0113           , iterator_range<Iterator>& attr)
0114         {
0115             attr = iterator_range<Iterator>(first, last);
0116         }
0117     };
0118 
0119     template <typename Iterator, typename Attribute>
0120     inline void
0121     assign_to(Iterator const& first, Iterator const& last, Attribute& attr)
0122     {
0123         assign_to_attribute_from_iterators<Attribute, Iterator>::
0124             call(first, last, attr);
0125     }
0126 
0127     template <typename Iterator>
0128     inline void
0129     assign_to(Iterator const&, Iterator const&, unused_type)
0130     {
0131     }
0132 
0133     ///////////////////////////////////////////////////////////////////////////
0134     template <typename T, typename Attribute>
0135     void assign_to(T const& val, Attribute& attr);
0136 
0137     template <typename Attribute, typename T, typename Enable>
0138     struct assign_to_attribute_from_value
0139     {
0140         typedef typename traits::one_element_sequence<Attribute>::type
0141             is_one_element_sequence;
0142 
0143         typedef typename mpl::eval_if<
0144             is_one_element_sequence
0145           , fusion::result_of::at_c<Attribute, 0>
0146           , mpl::identity<Attribute&>
0147         >::type type;
0148 
0149         template <typename T_>
0150         static void
0151         call(T_ const& val, Attribute& attr, mpl::false_)
0152         {
0153             attr = static_cast<Attribute>(val);
0154         }
0155 
0156         // This handles the case where the attribute is a single element fusion
0157         // sequence. We silently assign to the only element and treat it as the
0158         // attribute to parse the results into.
0159         template <typename T_>
0160         static void
0161         call(T_ const& val, Attribute& attr, mpl::true_)
0162         {
0163             typedef typename fusion::result_of::value_at_c<Attribute, 0>::type
0164                 element_type;
0165             fusion::at_c<0>(attr) = static_cast<element_type>(val);
0166         }
0167 
0168         static void
0169         call(T const& val, Attribute& attr)
0170         {
0171             call(val, attr, is_one_element_sequence());
0172         }
0173     };
0174 
0175     template <typename Attribute>
0176     struct assign_to_attribute_from_value<Attribute, Attribute>
0177     {
0178         static void
0179         call(Attribute const& val, Attribute& attr)
0180         {
0181             attr = val;
0182         }
0183     };
0184 
0185     template <typename Attribute, typename T>
0186     struct assign_to_attribute_from_value<Attribute, reference_wrapper<T>
0187       , typename disable_if<is_same<Attribute, reference_wrapper<T> > >::type>
0188     {
0189         static void
0190         call(reference_wrapper<T> const& val, Attribute& attr)
0191         {
0192             assign_to(val.get(), attr);
0193         }
0194     };
0195 
0196     template <typename Attribute, typename T>
0197     struct assign_to_attribute_from_value<Attribute, boost::optional<T>
0198       , typename disable_if<is_same<Attribute, boost::optional<T> > >::type>
0199     {
0200         static void
0201         call(boost::optional<T> const& val, Attribute& attr)
0202         {
0203             assign_to(val.get(), attr);
0204         }
0205     };
0206 
0207     template <typename Attribute, int N, bool Const, typename T>
0208     struct assign_to_attribute_from_value<fusion::extension::adt_attribute_proxy<Attribute, N, Const>, T>
0209     {
0210         static void
0211         call(T const& val, typename fusion::extension::adt_attribute_proxy<Attribute, N, Const>& attr)
0212         {
0213             attr = val;
0214         }
0215     };
0216 
0217     namespace detail
0218     {
0219         template <typename A, typename B>
0220         struct is_same_size_sequence
0221           : mpl::bool_<fusion::result_of::size<A>::value
0222                 == fusion::result_of::size<B>::value>
0223         {};
0224     }
0225 
0226     template <typename Attribute, typename T>
0227     struct assign_to_attribute_from_value<Attribute, T,
0228             mpl::and_<
0229                 fusion::traits::is_sequence<Attribute>,
0230                 fusion::traits::is_sequence<T>,
0231                 detail::is_same_size_sequence<Attribute, T>
0232             >
0233         >
0234     {
0235         static void
0236         call(T const& val, Attribute& attr)
0237         {
0238             fusion::copy(val, attr);
0239         }
0240     };
0241 
0242     ///////////////////////////////////////////////////////////////////////////
0243     template <typename Attribute, typename T, typename Enable>
0244     struct assign_to_container_from_value
0245     {
0246         // T is not a container and not a string
0247         template <typename T_>
0248         static void call(T_ const& val, Attribute& attr, mpl::false_, mpl::false_)
0249         {
0250             traits::push_back(attr, val);
0251         }
0252 
0253         // T is a container (but not a string), and T is convertible to the 
0254         // value_type of the Attribute container
0255         template <typename T_>
0256         static void 
0257         append_to_container_not_string(T_ const& val, Attribute& attr, mpl::true_)
0258         {
0259             traits::push_back(attr, val);
0260         }
0261 
0262         // T is a container (but not a string), generic overload
0263         template <typename T_>
0264         static void 
0265         append_to_container_not_string(T_ const& val, Attribute& attr, mpl::false_)
0266         {
0267             typedef typename traits::container_iterator<T_ const>::type
0268                 iterator_type;
0269 
0270             iterator_type end = traits::end(val);
0271             for (iterator_type i = traits::begin(val); i != end; traits::next(i))
0272                 traits::push_back(attr, traits::deref(i));
0273         }
0274 
0275         // T is a container (but not a string)
0276         template <typename T_>
0277         static void call(T_ const& val, Attribute& attr,  mpl::true_, mpl::false_)
0278         {
0279             typedef typename container_value<Attribute>::type value_type;
0280             typedef typename is_convertible<T, value_type>::type is_value_type;
0281 
0282             append_to_container_not_string(val, attr, is_value_type());
0283         }
0284 
0285         ///////////////////////////////////////////////////////////////////////
0286         // T is a string
0287         template <typename Iterator>
0288         static void append_to_string(Attribute& attr, Iterator begin, Iterator end)
0289         {
0290             for (Iterator i = begin; i != end; ++i)
0291                 traits::push_back(attr, *i);
0292         }
0293 
0294         // T is string, but not convertible to value_type of container
0295         template <typename T_>
0296         static void append_to_container(T_ const& val, Attribute& attr, mpl::false_)
0297         {
0298             typedef typename char_type_of<T_>::type char_type;
0299 
0300             append_to_string(attr, traits::get_begin<char_type>(val)
0301               , traits::get_end<char_type>(val));
0302         }
0303 
0304         // T is string, and convertible to value_type of container
0305         template <typename T_>
0306         static void append_to_container(T_ const& val, Attribute& attr, mpl::true_)
0307         {
0308             traits::push_back(attr, val);
0309         }
0310 
0311         template <typename T_, typename Pred>
0312         static void call(T_ const& val, Attribute& attr, Pred, mpl::true_)
0313         {
0314             typedef typename container_value<Attribute>::type value_type;
0315             typedef typename is_convertible<T, value_type>::type is_value_type;
0316 
0317             append_to_container(val, attr, is_value_type());
0318         }
0319 
0320         ///////////////////////////////////////////////////////////////////////
0321         static void call(T const& val, Attribute& attr)
0322         {
0323             typedef typename traits::is_container<T>::type is_container;
0324             typedef typename traits::is_string<T>::type is_string;
0325 
0326             call(val, attr, is_container(), is_string());
0327         }
0328     };
0329 
0330     template <typename Attribute>
0331     struct assign_to_container_from_value<Attribute, Attribute>
0332     {
0333         static void
0334         call(Attribute const& val, Attribute& attr)
0335         {
0336             attr = val;
0337         }
0338     };
0339 
0340     template <typename Attribute, typename T>
0341     struct assign_to_container_from_value<Attribute, boost::optional<T>
0342       , typename disable_if<is_same<Attribute, boost::optional<T> > >::type>
0343     {
0344         static void
0345         call(boost::optional<T> const& val, Attribute& attr)
0346         {
0347             assign_to(val.get(), attr);
0348         }
0349     };
0350 
0351     template <typename Attribute, typename T>
0352     struct assign_to_container_from_value<Attribute, reference_wrapper<T>
0353       , typename disable_if<is_same<Attribute, reference_wrapper<T> > >::type>
0354     {
0355         static void
0356         call(reference_wrapper<T> const& val, Attribute& attr)
0357         {
0358             assign_to(val.get(), attr);
0359         }
0360     };
0361 
0362     ///////////////////////////////////////////////////////////////////////////
0363     namespace detail
0364     {
0365         // overload for non-container attributes
0366         template <typename T, typename Attribute>
0367         inline void
0368         assign_to(T const& val, Attribute& attr, mpl::false_)
0369         {
0370             assign_to_attribute_from_value<Attribute, T>::call(val, attr);
0371         }
0372 
0373         // overload for containers (but not for variants or optionals
0374         // holding containers)
0375         template <typename T, typename Attribute>
0376         inline void
0377         assign_to(T const& val, Attribute& attr, mpl::true_)
0378         {
0379             assign_to_container_from_value<Attribute, T>::call(val, attr);
0380         }
0381     }
0382 
0383     template <typename T, typename Attribute>
0384     inline void
0385     assign_to(T const& val, Attribute& attr)
0386     {
0387         typedef typename mpl::and_<
0388             traits::is_container<Attribute>
0389           , traits::not_is_variant<Attribute>
0390           , traits::not_is_optional<Attribute>
0391         >::type is_not_wrapped_container;
0392 
0393         detail::assign_to(val, attr, is_not_wrapped_container());
0394     }
0395 
0396     template <typename T>
0397     inline void
0398     assign_to(T const&, unused_type)
0399     {
0400     }
0401 }}}
0402 
0403 #endif