/*============================================================================= 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 #include #include #include #include #include #include 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. /////////////////////////////////////////////////////////////////////////// template struct assign_to_attribute_from_iterators { static void call(Iterator const& first, Iterator const& last, Attribute& attr) { if (traits::is_empty(attr)) attr = Attribute(first, last); else { for (Iterator i = first; i != last; ++i) push_back(attr, *i); } } }; template struct assign_to_attribute_from_iterators< reference_wrapper, Iterator> { static void call(Iterator const& first, Iterator const& last , reference_wrapper attr) { if (traits::is_empty(attr)) attr = Attribute(first, last); else { for (Iterator i = first; i != last; ++i) push_back(attr, *i); } } }; template struct assign_to_attribute_from_iterators< iterator_range, Iterator> { static void call(Iterator const& first, Iterator const& last , iterator_range& attr) { attr = iterator_range(first, last); } }; template inline void assign_to(Iterator const& first, Iterator const& last, Attribute& attr) { assign_to_attribute_from_iterators:: call(first, last, attr); } template inline void assign_to(Iterator const&, Iterator const&, unused_type) { } /////////////////////////////////////////////////////////////////////////// template void assign_to(T const& val, Attribute& attr); template struct assign_to_attribute_from_value { typedef typename traits::one_element_sequence::type is_one_element_sequence; typedef typename mpl::eval_if< is_one_element_sequence , fusion::result_of::at_c , mpl::identity >::type type; template static void call(T_ const& val, Attribute& attr, mpl::false_) { attr = static_cast(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 static void call(T_ const& val, Attribute& attr, mpl::true_) { typedef typename fusion::result_of::value_at_c::type element_type; fusion::at_c<0>(attr) = static_cast(val); } static void call(T const& val, Attribute& attr) { call(val, attr, is_one_element_sequence()); } }; template struct assign_to_attribute_from_value { static void call(Attribute const& val, Attribute& attr) { attr = val; } }; template struct assign_to_attribute_from_value, T> { static void call(T const& val, reference_wrapper attr) { assign_to(val.get(), attr); } }; template struct assign_to_attribute_from_value, unused_type> { static void call(unused_type, optional const&) { } }; /////////////////////////////////////////////////////////////////////////// template struct assign_to_container_from_value { // T is not a container and not a string template 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) template static void call(T_ const& val, Attribute& attr, mpl::true_, mpl::false_) { typedef typename traits::container_iterator::type iterator_type; iterator_type end = traits::end(val); for (iterator_type i = traits::begin(val); i != end; traits::next(i)) push_back(attr, traits::deref(i)); } // T is a string template static void append_to_string(Attribute& attr, Iterator begin, Iterator end) { for (Iterator i = begin; i != end; ++i) push_back(attr, *i); } template static void call(T_ const& val, Attribute& attr, Pred, mpl::true_) { typedef typename char_type_of::type char_type; append_to_string(attr, traits::get_begin(val) , traits::get_end(val)); } static void call(T const& val, Attribute& attr) { typedef typename traits::is_container::type is_container; typedef typename traits::is_string::type is_string; call(val, attr, is_container(), is_string()); } }; template struct assign_to_container_from_value, T> { static void call(T const& val, reference_wrapper attr) { assign_to(val.get(), attr); } }; template struct assign_to_container_from_value, unused_type> { static void call(unused_type, optional const&) { } }; /////////////////////////////////////////////////////////////////////////// namespace detail { // overload for non-container attributes template inline void assign_to(T const& val, Attribute& attr, P1, P2) { assign_to_attribute_from_value::call(val, attr); } // overload for containers (but not for variants or optionals // holding containers) template inline void assign_to(T const& val, Attribute& attr, mpl::true_, mpl::true_) { assign_to_container_from_value::call(val, attr); } } template inline void assign_to(T const& val, Attribute& attr) { typedef typename traits::is_container::type is_container; typedef typename mpl::and_< traits::not_is_variant , traits::not_is_optional >::type is_not_wrapped_container; detail::assign_to(val, attr, is_container(), is_not_wrapped_container()); } template inline void assign_to(T const&, unused_type) { } }}} #endif