diff options
Diffstat (limited to '3rdParty/Boost/src/boost/spirit/home/qi/detail/assign_to.hpp')
-rw-r--r-- | 3rdParty/Boost/src/boost/spirit/home/qi/detail/assign_to.hpp | 392 |
1 files changed, 392 insertions, 0 deletions
diff --git a/3rdParty/Boost/src/boost/spirit/home/qi/detail/assign_to.hpp b/3rdParty/Boost/src/boost/spirit/home/qi/detail/assign_to.hpp new file mode 100644 index 0000000..38142bf --- /dev/null +++ b/3rdParty/Boost/src/boost/spirit/home/qi/detail/assign_to.hpp @@ -0,0 +1,392 @@ +/*============================================================================= + Copyright (c) 2001-2011 Joel de Guzman + Copyright (c) 2001-2011 Hartmut Kaiser + http://spirit.sourceforge.net/ + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +=============================================================================*/ +#if !defined(BOOST_SPIRIT_ASSIGN_TO_APR_16_2006_0812PM) +#define BOOST_SPIRIT_ASSIGN_TO_APR_16_2006_0812PM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/spirit/home/qi/detail/construct.hpp> +#include <boost/spirit/home/support/unused.hpp> +#include <boost/spirit/home/qi/detail/attributes.hpp> +#include <boost/spirit/home/support/container.hpp> +#include <boost/fusion/include/copy.hpp> +#include <boost/ref.hpp> +#include <boost/range/iterator_range.hpp> + +namespace boost { namespace spirit { namespace traits +{ + /////////////////////////////////////////////////////////////////////////// + // This file contains assignment utilities. The utilities provided also + // accept spirit's unused_type; all no-ops. Compiler optimization will + // easily strip these away. + /////////////////////////////////////////////////////////////////////////// + namespace detail + { + template <typename T> + struct is_iter_range : mpl::false_ {}; + + template <typename I> + struct is_iter_range<boost::iterator_range<I> > : mpl::true_ {}; + + template <typename C> + struct is_container_of_ranges + : is_iter_range<typename C::value_type> {}; + } + + template <typename Attribute, typename Iterator, typename Enable> + struct assign_to_attribute_from_iterators + { + // Common case + static void + call(Iterator const& first, Iterator const& last, Attribute& attr, mpl::false_) + { + if (traits::is_empty(attr)) + attr = Attribute(first, last); + else { + for (Iterator i = first; i != last; ++i) + push_back(attr, *i); + } + } + + // If Attribute is a container with value_type==iterator_range<T> just push the + // iterator_range into it + static void + call(Iterator const& first, Iterator const& last, Attribute& attr, mpl::true_) + { + typename Attribute::value_type rng(first, last); + push_back(attr, rng); + } + + static void + call(Iterator const& first, Iterator const& last, Attribute& attr) + { + call(first, last, attr, detail::is_container_of_ranges<Attribute>()); + } + }; + + template <typename Attribute, typename Iterator> + struct assign_to_attribute_from_iterators< + reference_wrapper<Attribute>, Iterator> + { + static void + call(Iterator const& first, Iterator const& last + , reference_wrapper<Attribute> attr) + { + if (traits::is_empty(attr)) + attr = Attribute(first, last); + else { + for (Iterator i = first; i != last; ++i) + push_back(attr, *i); + } + } + }; + + template <typename Attribute, typename Iterator> + struct assign_to_attribute_from_iterators< + boost::optional<Attribute>, Iterator> + { + static void + call(Iterator const& first, Iterator const& last + , boost::optional<Attribute>& attr) + { + Attribute val; + assign_to(first, last, val); + attr = val; + } + }; + + template <typename Iterator> + struct assign_to_attribute_from_iterators< + iterator_range<Iterator>, Iterator> + { + static void + call(Iterator const& first, Iterator const& last + , iterator_range<Iterator>& attr) + { + attr = iterator_range<Iterator>(first, last); + } + }; + + template <typename Iterator, typename Attribute> + inline void + assign_to(Iterator const& first, Iterator const& last, Attribute& attr) + { + assign_to_attribute_from_iterators<Attribute, Iterator>:: + call(first, last, attr); + } + + template <typename Iterator> + inline void + assign_to(Iterator const&, Iterator const&, unused_type) + { + } + + /////////////////////////////////////////////////////////////////////////// + template <typename T, typename Attribute> + void assign_to(T const& val, Attribute& attr); + + template <typename Attribute, typename T, typename Enable> + struct assign_to_attribute_from_value + { + typedef typename traits::one_element_sequence<Attribute>::type + is_one_element_sequence; + + typedef typename mpl::eval_if< + is_one_element_sequence + , fusion::result_of::at_c<Attribute, 0> + , mpl::identity<Attribute&> + >::type type; + + template <typename T_> + static void + call(T_ const& val, Attribute& attr, mpl::false_) + { + attr = static_cast<Attribute>(val); + } + + // This handles the case where the attribute is a single element fusion + // sequence. We silently assign to the only element and treat it as the + // attribute to parse the results into. + template <typename T_> + static void + call(T_ const& val, Attribute& attr, mpl::true_) + { + typedef typename fusion::result_of::value_at_c<Attribute, 0>::type + element_type; + fusion::at_c<0>(attr) = static_cast<element_type>(val); + } + + static void + call(T const& val, Attribute& attr) + { + call(val, attr, is_one_element_sequence()); + } + }; + + template <typename Attribute> + struct assign_to_attribute_from_value<Attribute, Attribute> + { + static void + call(Attribute const& val, Attribute& attr) + { + attr = val; + } + }; + + template <typename Attribute, typename T> + struct assign_to_attribute_from_value<Attribute, reference_wrapper<T> + , typename disable_if<is_same<Attribute, reference_wrapper<T> > >::type> + { + static void + call(reference_wrapper<T> const& val, Attribute& attr) + { + assign_to(val.get(), attr); + } + }; + + template <typename Attribute, typename T> + struct assign_to_attribute_from_value<Attribute, boost::optional<T> + , typename disable_if<is_same<Attribute, boost::optional<T> > >::type> + { + static void + call(boost::optional<T> const& val, Attribute& attr) + { + assign_to(val.get(), attr); + } + }; + + namespace detail + { + template <typename A, typename B> + struct is_same_size_sequence + : mpl::bool_<fusion::result_of::size<A>::value + == fusion::result_of::size<B>::value> + {}; + } + + template <typename Attribute, typename T> + struct assign_to_attribute_from_value<Attribute, T, + mpl::and_< + fusion::traits::is_sequence<Attribute>, + fusion::traits::is_sequence<T>, + detail::is_same_size_sequence<Attribute, T> + > + > + { + static void + call(T const& val, Attribute& attr) + { + fusion::copy(val, attr); + } + }; + + /////////////////////////////////////////////////////////////////////////// + template <typename Attribute, typename T, typename Enable> + struct assign_to_container_from_value + { + // T is not a container and not a string + template <typename T_> + static void call(T_ const& val, Attribute& attr, mpl::false_, mpl::false_) + { + traits::push_back(attr, val); + } + + // T is a container (but not a string), and T is convertible to the + // value_type of the Attribute container + template <typename T_> + static void + append_to_container_not_string(T_ const& val, Attribute& attr, mpl::true_) + { + traits::push_back(attr, val); + } + + // T is a container (but not a string), generic overload + template <typename T_> + static void + append_to_container_not_string(T_ const& val, Attribute& attr, mpl::false_) + { + typedef typename traits::container_iterator<T_ const>::type + iterator_type; + + iterator_type end = traits::end(val); + for (iterator_type i = traits::begin(val); i != end; traits::next(i)) + traits::push_back(attr, traits::deref(i)); + } + + // T is a container (but not a string) + template <typename T_> + static void call(T_ const& val, Attribute& attr, mpl::true_, mpl::false_) + { + typedef typename container_value<Attribute>::type value_type; + typedef typename is_convertible<T, value_type>::type is_value_type; + + append_to_container_not_string(val, attr, is_value_type()); + } + + /////////////////////////////////////////////////////////////////////// + // T is a string + template <typename Iterator> + static void append_to_string(Attribute& attr, Iterator begin, Iterator end) + { + for (Iterator i = begin; i != end; ++i) + traits::push_back(attr, *i); + } + + // T is string, but not convertible to value_type of container + template <typename T_> + static void append_to_container(T_ const& val, Attribute& attr, mpl::false_) + { + typedef typename char_type_of<T_>::type char_type; + + append_to_string(attr, traits::get_begin<char_type>(val) + , traits::get_end<char_type>(val)); + } + + // T is string, and convertible to value_type of container + template <typename T_> + static void append_to_container(T_ const& val, Attribute& attr, mpl::true_) + { + traits::push_back(attr, val); + } + + template <typename T_, typename Pred> + static void call(T_ const& val, Attribute& attr, Pred, mpl::true_) + { + typedef typename container_value<Attribute>::type value_type; + typedef typename is_convertible<T, value_type>::type is_value_type; + + append_to_container(val, attr, is_value_type()); + } + + /////////////////////////////////////////////////////////////////////// + static void call(T const& val, Attribute& attr) + { + typedef typename traits::is_container<T>::type is_container; + typedef typename traits::is_string<T>::type is_string; + + call(val, attr, is_container(), is_string()); + } + }; + + template <typename Attribute> + struct assign_to_container_from_value<Attribute, Attribute> + { + static void + call(Attribute const& val, Attribute& attr) + { + attr = val; + } + }; + + template <typename Attribute, typename T> + struct assign_to_container_from_value<Attribute, boost::optional<T> + , typename disable_if<is_same<Attribute, boost::optional<T> > >::type> + { + static void + call(boost::optional<T> const& val, Attribute& attr) + { + assign_to(val.get(), attr); + } + }; + + template <typename Attribute, typename T> + struct assign_to_container_from_value<Attribute, reference_wrapper<T> + , typename disable_if<is_same<Attribute, reference_wrapper<T> > >::type> + { + static void + call(reference_wrapper<T> const& val, Attribute& attr) + { + assign_to(val.get(), attr); + } + }; + + /////////////////////////////////////////////////////////////////////////// + namespace detail + { + // overload for non-container attributes + template <typename T, typename Attribute> + inline void + assign_to(T const& val, Attribute& attr, mpl::false_) + { + assign_to_attribute_from_value<Attribute, T>::call(val, attr); + } + + // overload for containers (but not for variants or optionals + // holding containers) + template <typename T, typename Attribute> + inline void + assign_to(T const& val, Attribute& attr, mpl::true_) + { + assign_to_container_from_value<Attribute, T>::call(val, attr); + } + } + + template <typename T, typename Attribute> + inline void + assign_to(T const& val, Attribute& attr) + { + typedef typename mpl::and_< + traits::is_container<Attribute> + , traits::not_is_variant<Attribute> + , traits::not_is_optional<Attribute> + >::type is_not_wrapped_container; + + detail::assign_to(val, attr, is_not_wrapped_container()); + } + + template <typename T> + inline void + assign_to(T const&, unused_type) + { + } +}}} + +#endif |