123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278 |
- // Copyright (c) 2001-2011 Hartmut Kaiser
- //
- // 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_KARMA_EXTRACT_FROM_SEP_30_2009_0732AM)
- #define BOOST_SPIRIT_KARMA_EXTRACT_FROM_SEP_30_2009_0732AM
- #if defined(_MSC_VER)
- #pragma once
- #endif
- #include <boost/spirit/home/support/unused.hpp>
- #include <boost/spirit/home/support/attributes_fwd.hpp>
- #include <boost/spirit/home/karma/detail/attributes.hpp>
- #include <boost/spirit/home/support/container.hpp>
- #include <boost/ref.hpp>
- #include <boost/optional.hpp>
- ///////////////////////////////////////////////////////////////////////////////
- namespace boost { namespace spirit { namespace traits
- {
- ///////////////////////////////////////////////////////////////////////////
- // This file contains attribute extraction utilities. The utilities
- // provided also accept spirit's unused_type; all no-ops. Compiler
- // optimization will easily strip these away.
- ///////////////////////////////////////////////////////////////////////////
- namespace detail
- {
- ///////////////////////////////////////////////////////////////////////
- // extract first and second element of a fusion sequence
- template <typename T>
- struct add_const_ref
- : add_reference<typename add_const<T>::type>
- {};
- template <typename T, int N>
- struct value_at_c
- : add_const_ref<typename fusion::result_of::value_at_c<T, N>::type>
- {};
- }
- // This is the default case: the plain attribute values
- template <typename Attribute, typename Exposed
- , bool IsOneElemSeq = traits::one_element_sequence<Attribute>::value>
- struct extract_from_attribute_base
- {
- typedef Attribute const& type;
- template <typename Context>
- static type call(Attribute const& attr, Context&)
- {
- return attr;
- }
- };
- // This handles the case where the attribute is a single element fusion
- // sequence. We silently extract the only element and treat it as the
- // attribute to generate output from.
- template <typename Attribute, typename Exposed>
- struct extract_from_attribute_base<Attribute, Exposed, true>
- {
- typedef typename remove_const<
- typename remove_reference<
- typename fusion::result_of::at_c<Attribute, 0>::type
- >::type
- >::type elem_type;
- typedef typename result_of::extract_from<Exposed, elem_type>::type type;
- template <typename Context>
- static type call(Attribute const& attr, Context& ctx)
- {
- return extract_from<Exposed>(fusion::at_c<0>(attr), ctx);
- }
- };
- template <typename Attribute, typename Exposed, typename Enable/*= void*/>
- struct extract_from_attribute
- : extract_from_attribute_base<Attribute, Exposed>
- {};
- // This handles optional attributes.
- template <typename Attribute, typename Exposed>
- struct extract_from_attribute<boost::optional<Attribute>, Exposed>
- {
- typedef Attribute const& type;
- template <typename Context>
- static type call(boost::optional<Attribute> const& attr, Context& ctx)
- {
- return extract_from<Exposed>(boost::get<Attribute>(attr), ctx);
- }
- };
- template <typename Attribute, typename Exposed>
- struct extract_from_attribute<boost::optional<Attribute const>, Exposed>
- {
- typedef Attribute const& type;
- template <typename Context>
- static type call(boost::optional<Attribute const> const& attr, Context& ctx)
- {
- return extract_from<Exposed>(boost::get<Attribute const>(attr), ctx);
- }
- };
- // This handles attributes wrapped inside a boost::ref().
- template <typename Attribute, typename Exposed>
- struct extract_from_attribute<reference_wrapper<Attribute>, Exposed>
- {
- typedef Attribute const& type;
- template <typename Context>
- static type call(reference_wrapper<Attribute> const& attr, Context& ctx)
- {
- return extract_from<Exposed>(attr.get(), ctx);
- }
- };
- ///////////////////////////////////////////////////////////////////////////
- template <typename Attribute, typename Exposed, typename Enable>
- struct extract_from_container
- {
- typedef typename traits::container_value<Attribute const>::type
- value_type;
- typedef typename is_convertible<value_type, Exposed>::type
- is_convertible_to_value_type;
- typedef typename mpl::if_<
- mpl::or_<
- is_same<value_type, Exposed>, is_same<Attribute, Exposed> >
- , Exposed const&, Exposed
- >::type type;
- // handle case where container value type is convertible to result type
- // we simply return the front element of the container
- template <typename Context, typename Pred>
- static type call(Attribute const& attr, Context&, mpl::true_, Pred)
- {
- // return first element from container
- typedef typename traits::container_iterator<Attribute const>::type
- iterator_type;
- iterator_type it = traits::begin(attr);
- type result = *it;
- ++it;
- return result;
- }
- // handle strings
- template <typename Iterator>
- static void append_to_string(Exposed& result, Iterator begin, Iterator end)
- {
- for (Iterator i = begin; i != end; ++i)
- push_back(result, *i);
- }
- template <typename Context>
- static type call(Attribute const& attr, Context&, mpl::false_, mpl::true_)
- {
- typedef typename char_type_of<Attribute>::type char_type;
- Exposed result;
- append_to_string(result, traits::get_begin<char_type>(attr)
- , traits::get_end<char_type>(attr));
- return result;
- }
- // everything else gets just passed through
- template <typename Context>
- static type call(Attribute const& attr, Context&, mpl::false_, mpl::false_)
- {
- return type(attr);
- }
- template <typename Context>
- static type call(Attribute const& attr, Context& ctx)
- {
- typedef typename mpl::and_<
- traits::is_string<Exposed>, traits::is_string<Attribute>
- >::type handle_strings;
- // return first element from container
- return call(attr, ctx, is_convertible_to_value_type()
- , handle_strings());
- }
- };
- template <typename Attribute>
- struct extract_from_container<Attribute, Attribute>
- {
- typedef Attribute const& type;
- template <typename Context>
- static type call(Attribute const& attr, Context&)
- {
- return attr;
- }
- };
- ///////////////////////////////////////////////////////////////////////////
- namespace detail
- {
- // overload for non-container attributes
- template <typename Exposed, typename Attribute, typename Context>
- inline typename spirit::result_of::extract_from<Exposed, Attribute>::type
- extract_from(Attribute const& attr, Context& ctx, mpl::false_)
- {
- return extract_from_attribute<Attribute, Exposed>::call(attr, ctx);
- }
- // overload for containers (but not for variants or optionals
- // holding containers)
- template <typename Exposed, typename Attribute, typename Context>
- inline typename spirit::result_of::extract_from<Exposed, Attribute>::type
- extract_from(Attribute const& attr, Context& ctx, mpl::true_)
- {
- return extract_from_container<Attribute, Exposed>::call(attr, ctx);
- }
- }
- template <typename Exposed, typename Attribute, typename Context>
- inline typename spirit::result_of::extract_from<Exposed, Attribute>::type
- extract_from(Attribute const& attr, Context& ctx
- #if (defined(__GNUC__) && (__GNUC__ < 4)) || \
- (defined(__APPLE__) && defined(__INTEL_COMPILER))
- , typename enable_if<traits::not_is_unused<Attribute> >::type*
- #endif
- )
- {
- typedef typename mpl::and_<
- traits::is_container<Attribute>
- , traits::not_is_variant<Attribute>
- , traits::not_is_optional<Attribute>
- >::type is_not_wrapped_container;
- return detail::extract_from<Exposed>(attr, ctx
- , is_not_wrapped_container());
- }
- template <typename Exposed, typename Context>
- inline unused_type extract_from(unused_type, Context&)
- {
- return unused;
- }
- }}}
- ///////////////////////////////////////////////////////////////////////////////
- namespace boost { namespace spirit { namespace result_of
- {
- template <typename Exposed, typename Attribute>
- struct extract_from
- : mpl::if_<
- mpl::and_<
- traits::is_container<Attribute>
- , traits::not_is_variant<Attribute>
- , traits::not_is_optional<Attribute> >
- , traits::extract_from_container<Attribute, Exposed>
- , traits::extract_from_attribute<Attribute, Exposed> >::type
- {};
- template <typename Exposed>
- struct extract_from<Exposed, unused_type>
- {
- typedef unused_type type;
- };
- template <typename Exposed>
- struct extract_from<Exposed, unused_type const>
- {
- typedef unused_type type;
- };
- }}}
- #endif
|