/*============================================================================= | |
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/spirit/home/phoenix/core/actor.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. | |
/////////////////////////////////////////////////////////////////////////// | |
template <typename Attribute, typename Iterator, typename Enable> | |
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 <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 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<reference_wrapper<Attribute>, T> | |
{ | |
static void | |
call(T const& val, reference_wrapper<Attribute> attr) | |
{ | |
assign_to(val.get(), attr); | |
} | |
}; | |
template <typename Attribute> | |
struct assign_to_attribute_from_value<optional<Attribute>, unused_type> | |
{ | |
static void | |
call(unused_type, optional<Attribute> const&) | |
{ | |
} | |
}; | |
/////////////////////////////////////////////////////////////////////////// | |
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) | |
template <typename T_> | |
static void call(T_ const& val, Attribute& attr, mpl::true_, 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)) | |
push_back(attr, traits::deref(i)); | |
} | |
// 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) | |
push_back(attr, *i); | |
} | |
template <typename T_, typename Pred> | |
static void call(T_ const& val, Attribute& attr, Pred, mpl::true_) | |
{ | |
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)); | |
} | |
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, typename T> | |
struct assign_to_container_from_value<reference_wrapper<Attribute>, T> | |
{ | |
static void | |
call(T const& val, reference_wrapper<Attribute> attr) | |
{ | |
assign_to(val.get(), attr); | |
} | |
}; | |
template <typename Attribute> | |
struct assign_to_container_from_value<optional<Attribute>, unused_type> | |
{ | |
static void | |
call(unused_type, optional<Attribute> const&) | |
{ | |
} | |
}; | |
/////////////////////////////////////////////////////////////////////////// | |
namespace detail | |
{ | |
// overload for non-container attributes | |
template <typename T, typename Attribute, typename P1, typename P2> | |
inline void | |
assign_to(T const& val, Attribute& attr, P1, P2) | |
{ | |
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_, 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 traits::is_container<Attribute>::type is_container; | |
typedef typename mpl::and_< | |
traits::not_is_variant<Attribute> | |
, traits::not_is_optional<Attribute> | |
>::type is_not_wrapped_container; | |
detail::assign_to(val, attr, is_container(), is_not_wrapped_container()); | |
} | |
template <typename T> | |
inline void | |
assign_to(T const&, unused_type) | |
{ | |
} | |
}}} | |
#endif |