diff options
author | Vlad Voicu <vladv@rosedu.org> | 2012-03-02 10:01:11 (GMT) |
---|---|---|
committer | Kevin Smith <git@kismith.co.uk> | 2012-03-09 15:04:05 (GMT) |
commit | 1c8cd160b79b6bbcec72042bdb104ba530508a93 (patch) | |
tree | cff302b81e74c557fbc9e30fd43144d981b613d0 /3rdParty/Boost/src/boost/spirit/home/support/attributes.hpp | |
parent | 2944711aefec9a9dd66052440bc4f921910dd780 (diff) | |
download | swift-contrib-1c8cd160b79b6bbcec72042bdb104ba530508a93.zip swift-contrib-1c8cd160b79b6bbcec72042bdb104ba530508a93.tar.bz2 |
Added spirit to bundled boost
Diffstat (limited to '3rdParty/Boost/src/boost/spirit/home/support/attributes.hpp')
-rw-r--r-- | 3rdParty/Boost/src/boost/spirit/home/support/attributes.hpp | 1141 |
1 files changed, 1141 insertions, 0 deletions
diff --git a/3rdParty/Boost/src/boost/spirit/home/support/attributes.hpp b/3rdParty/Boost/src/boost/spirit/home/support/attributes.hpp new file mode 100644 index 0000000..fc8cd33 --- /dev/null +++ b/3rdParty/Boost/src/boost/spirit/home/support/attributes.hpp @@ -0,0 +1,1141 @@ +/*============================================================================= + Copyright (c) 2001-2011 Joel de Guzman + 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_ATTRIBUTES_JANUARY_29_2007_0954AM) +#define BOOST_SPIRIT_ATTRIBUTES_JANUARY_29_2007_0954AM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/spirit/home/support/unused.hpp> +#include <boost/spirit/home/support/has_semantic_action.hpp> +#include <boost/spirit/home/support/attributes_fwd.hpp> +#include <boost/spirit/home/support/container.hpp> +#include <boost/spirit/home/support/detail/hold_any.hpp> +#include <boost/spirit/home/support/detail/as_variant.hpp> +#include <boost/optional/optional.hpp> +#include <boost/fusion/include/transform.hpp> +#include <boost/fusion/include/filter_if.hpp> +#include <boost/fusion/include/as_vector.hpp> +#include <boost/fusion/include/push_front.hpp> +#include <boost/fusion/include/pop_front.hpp> +#include <boost/fusion/include/is_sequence.hpp> +#include <boost/fusion/include/for_each.hpp> +#include <boost/fusion/include/is_view.hpp> +#include <boost/foreach.hpp> +#include <boost/utility/value_init.hpp> +#include <boost/type_traits/is_same.hpp> +#include <boost/type_traits/is_convertible.hpp> +#include <boost/mpl/eval_if.hpp> +#include <boost/mpl/end.hpp> +#include <boost/mpl/find_if.hpp> +#include <boost/mpl/identity.hpp> +#include <boost/mpl/deref.hpp> +#include <boost/mpl/distance.hpp> +#include <boost/mpl/or.hpp> +#include <boost/mpl/has_xxx.hpp> +#include <boost/proto/proto_fwd.hpp> +#include <boost/utility/enable_if.hpp> +#include <boost/variant.hpp> +#include <boost/range/iterator_range.hpp> +#include <vector> +#include <utility> + +/////////////////////////////////////////////////////////////////////////////// +namespace boost { namespace spirit { namespace traits +{ + /////////////////////////////////////////////////////////////////////////// + // This file deals with attribute related functions and meta-functions + // including generalized attribute transformation utilities for Spirit + // components. + /////////////////////////////////////////////////////////////////////////// + + template <typename T, typename Enable/* = void*/> + struct is_proxy : mpl::false_ {}; + + template <typename T> + struct is_proxy<T, + typename enable_if< + mpl::and_< + fusion::traits::is_sequence<T>, + fusion::traits::is_view<T> + > + >::type> + : mpl::true_ {}; + + template <typename T, typename Domain, typename Enable/* = void*/> + struct not_is_variant + : mpl::true_ + {}; + + template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Domain> + struct not_is_variant<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Domain> + : mpl::false_ + {}; + + template <typename T, typename Domain> + struct not_is_variant<boost::optional<T>, Domain> + : not_is_variant<T, Domain> + {}; + + // we treat every type as if it where the variant (as this meta function is + // invoked for variant types only) + template <typename T> + struct variant_type + : mpl::identity<T> + {}; + + template <typename T> + struct variant_type<boost::optional<T> > + : variant_type<T> + {}; + + /////////////////////////////////////////////////////////////////////////// + // The compute_compatible_component_variant + /////////////////////////////////////////////////////////////////////////// + namespace detail + { + // A component is compatible to a given Attribute type if the + // Attribute is the same as the expected type of the component or if + // it is convertible to the expected type. + template <typename Expected, typename Attribute> + struct attribute_is_compatible + : is_convertible<Attribute, Expected> + {}; + + template <typename Expected, typename Attribute> + struct attribute_is_compatible<Expected, boost::optional<Attribute> > + : is_convertible<Attribute, Expected> + {}; + + template <typename Container> + struct is_hold_any_container + : is_same<hold_any, typename traits::container_value<Container>::type> + {}; + } + + template <typename Attribute, typename Expected + , typename IsNotVariant = mpl::false_, typename Enable = void> + struct compute_compatible_component_variant + : mpl::or_< + traits::detail::attribute_is_compatible<Expected, Attribute> + , is_same<hold_any, Expected> + , mpl::eval_if< + is_container<Expected> + , traits::detail::is_hold_any_container<Expected> + , mpl::false_> > + {}; + + namespace detail + { + BOOST_MPL_HAS_XXX_TRAIT_DEF(types) + } + + template <typename Variant, typename Expected> + struct compute_compatible_component_variant<Variant, Expected, mpl::false_ + , typename enable_if<detail::has_types<Variant> >::type> + { + typedef typename traits::variant_type<Variant>::type variant_type; + typedef typename variant_type::types types; + typedef typename mpl::end<types>::type end; + + typedef typename + mpl::find_if<types, is_same<Expected, mpl::_1> >::type + iter; + + typedef typename mpl::distance< + typename mpl::begin<types>::type, iter + >::type distance; + + // true_ if the attribute matches one of the types in the variant + typedef typename mpl::not_<is_same<iter, end> >::type type; + enum { value = type::value }; + + // return the type in the variant the attribute is compatible with + typedef typename + mpl::eval_if<type, mpl::deref<iter>, mpl::identity<unused_type> >::type + compatible_type; + + // return whether the given type is compatible with the Expected type + static bool is_compatible(int which) + { + return which == distance::value; + } + }; + + template <typename Expected, typename Attribute, typename Domain> + struct compute_compatible_component + : compute_compatible_component_variant<Attribute, Expected + , typename spirit::traits::not_is_variant<Attribute, Domain>::type> {}; + + template <typename Expected, typename Domain> + struct compute_compatible_component<Expected, unused_type, Domain> + : mpl::false_ {}; + + template <typename Attribute, typename Domain> + struct compute_compatible_component<unused_type, Attribute, Domain> + : mpl::false_ {}; + + template <typename Domain> + struct compute_compatible_component<unused_type, unused_type, Domain> + : mpl::false_ {}; + + /////////////////////////////////////////////////////////////////////////// + // return the type currently stored in the given variant + template <BOOST_VARIANT_ENUM_PARAMS(typename T)> + struct variant_which<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> > + { + static int call(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& v) + { + return v.which(); + } + }; + + template <typename T> + int which(T const& v) + { + return variant_which<T>::call(v); + } + + /////////////////////////////////////////////////////////////////////////// + template <typename T, typename Domain, typename Enable/* = void*/> + struct not_is_optional + : mpl::true_ + {}; + + template <typename T, typename Domain> + struct not_is_optional<boost::optional<T>, Domain> + : mpl::false_ + {}; + + /////////////////////////////////////////////////////////////////////////// + // attribute_of + // + // Get the component's attribute + /////////////////////////////////////////////////////////////////////////// + template <typename Component + , typename Context = unused_type, typename Iterator = unused_type> + struct attribute_of + { + typedef typename Component::template + attribute<Context, Iterator>::type type; + }; + + /////////////////////////////////////////////////////////////////////////// + // attribute_not_unused + // + // An mpl meta-function class that determines whether a component's + // attribute is not unused. + /////////////////////////////////////////////////////////////////////////// + template <typename Context, typename Iterator = unused_type> + struct attribute_not_unused + { + template <typename Component> + struct apply + : not_is_unused<typename + attribute_of<Component, Context, Iterator>::type> + {}; + }; + + /////////////////////////////////////////////////////////////////////////// + // Retrieve the attribute type to use from the given type + // + // This is needed to extract the correct attribute type from proxy classes + // as utilized in FUSION_ADAPT_ADT et. al. + /////////////////////////////////////////////////////////////////////////// + template <typename Attribute, typename Enable/* = void*/> + struct attribute_type : mpl::identity<Attribute> {}; + + + /////////////////////////////////////////////////////////////////////////// + // Retrieve the size of a fusion sequence (compile time) + /////////////////////////////////////////////////////////////////////////// + template <typename T> + struct sequence_size + : fusion::result_of::size<T> + {}; + + template <> + struct sequence_size<unused_type> + : mpl::int_<0> + {}; + + /////////////////////////////////////////////////////////////////////////// + // Retrieve the size of an attribute (runtime) + /////////////////////////////////////////////////////////////////////////// + template <typename Attribute, typename Enable/* = void*/> + struct attribute_size + { + typedef std::size_t type; + + static type call(Attribute const&) + { + return 1; + } + }; + + template <typename Attribute> + struct attribute_size<Attribute + , typename enable_if< + mpl::and_< + fusion::traits::is_sequence<Attribute> + , mpl::not_<traits::is_container<Attribute> > + > + >::type + > { + typedef typename fusion::result_of::size<Attribute>::value_type type; + + static type call(Attribute const& attr) + { + return fusion::size(attr); + } + }; + + template <typename Attribute> + struct attribute_size<Attribute + , typename enable_if< + mpl::and_< + traits::is_container<Attribute> + , mpl::not_<traits::is_iterator_range<Attribute> > + > + >::type + > { + typedef typename Attribute::size_type type; + + static type call(Attribute const& attr) + { + return attr.size(); + } + }; + + template <typename Iterator> + struct attribute_size<iterator_range<Iterator> > + { + typedef typename boost::detail::iterator_traits<Iterator>:: + difference_type type; + + static type call(iterator_range<Iterator> const& r) + { + return boost::detail::distance(r.begin(), r.end()); + } + }; + + template <> + struct attribute_size<unused_type> + { + typedef std::size_t type; + + static type call(unused_type) + { + return 0; + } + }; + + template <typename Attribute> + typename attribute_size<Attribute>::type + size(Attribute const& attr) + { + return attribute_size<Attribute>::call(attr); + } + + /////////////////////////////////////////////////////////////////////////// + // pass_attribute + // + // Determines how we pass attributes to semantic actions. This + // may be specialized. By default, all attributes are wrapped in + // a fusion sequence, because the attribute has to be treated as being + // a single value in any case (even if it actually already is a fusion + // sequence in its own). + /////////////////////////////////////////////////////////////////////////// + template <typename Component, typename Attribute, typename Enable/* = void*/> + struct pass_attribute + { + typedef fusion::vector1<Attribute&> type; + }; + + /////////////////////////////////////////////////////////////////////////// + // Subclass a pass_attribute specialization from this to wrap + // the attribute in a tuple only IFF it is not already a fusion tuple. + /////////////////////////////////////////////////////////////////////////// + template <typename Attribute, typename Force = mpl::false_> + struct wrap_if_not_tuple + : mpl::if_< + fusion::traits::is_sequence<Attribute> + , Attribute&, fusion::vector1<Attribute&> > + {}; + + template <typename Attribute> + struct wrap_if_not_tuple<Attribute, mpl::true_> + { + typedef fusion::vector1<Attribute&> type; + }; + + template <> + struct wrap_if_not_tuple<unused_type, mpl::false_> + { + typedef unused_type type; + }; + + template <> + struct wrap_if_not_tuple<unused_type const, mpl::false_> + { + typedef unused_type type; + }; + + /////////////////////////////////////////////////////////////////////////// + // build_optional + // + // Build a boost::optional from T. Return unused_type if T is unused_type. + /////////////////////////////////////////////////////////////////////////// + template <typename T> + struct build_optional + { + typedef optional<T> type; + }; + + template <> + struct build_optional<unused_type> + { + typedef unused_type type; + }; + + /////////////////////////////////////////////////////////////////////////// + // build_std_vector + // + // Build a std::vector from T. Return unused_type if T is unused_type. + /////////////////////////////////////////////////////////////////////////// + template <typename T> + struct build_std_vector + { + typedef std::vector<T> type; + }; + + template <> + struct build_std_vector<unused_type> + { + typedef unused_type type; + }; + + /////////////////////////////////////////////////////////////////////////// + // filter_unused_attributes + // + // Remove unused_types from a sequence + /////////////////////////////////////////////////////////////////////////// + + // Compute the list of all *used* attributes of sub-components + // (filter all unused attributes from the list) + template <typename Sequence> + struct filter_unused_attributes + : fusion::result_of::filter_if<Sequence, not_is_unused<mpl::_> > + {}; + + /////////////////////////////////////////////////////////////////////////// + // sequence_attribute_transform + // + // This transform is invoked for every attribute in a sequence allowing + // to modify the attribute type exposed by a component to the enclosing + // sequence component. By default no transformation is performed. + /////////////////////////////////////////////////////////////////////////// + template <typename Attribute, typename Domain> + struct sequence_attribute_transform + : mpl::identity<Attribute> + {}; + + /////////////////////////////////////////////////////////////////////////// + // permutation_attribute_transform + // + // This transform is invoked for every attribute in a sequence allowing + // to modify the attribute type exposed by a component to the enclosing + // permutation component. By default a build_optional transformation is + // performed. + /////////////////////////////////////////////////////////////////////////// + template <typename Attribute, typename Domain> + struct permutation_attribute_transform + : traits::build_optional<Attribute> + {}; + + /////////////////////////////////////////////////////////////////////////// + // sequential_or_attribute_transform + // + // This transform is invoked for every attribute in a sequential_or allowing + // to modify the attribute type exposed by a component to the enclosing + // sequential_or component. By default a build_optional transformation is + // performed. + /////////////////////////////////////////////////////////////////////////// + template <typename Attribute, typename Domain> + struct sequential_or_attribute_transform + : traits::build_optional<Attribute> + {}; + + /////////////////////////////////////////////////////////////////////////// + // build_fusion_vector + // + // Build a fusion vector from a fusion sequence. All unused attributes + // are filtered out. If the result is empty after the removal of unused + // types, return unused_type. If the input sequence is an unused_type, + // also return unused_type. + /////////////////////////////////////////////////////////////////////////// + template <typename Sequence> + struct build_fusion_vector + { + // Remove all unused attributes + typedef typename + filter_unused_attributes<Sequence>::type + filtered_attributes; + + // Build a fusion vector from a fusion sequence (Sequence), + // But *only if* the sequence is not empty. i.e. if the + // sequence is empty, our result will be unused_type. + + typedef typename + mpl::eval_if< + fusion::result_of::empty<filtered_attributes> + , mpl::identity<unused_type> + , fusion::result_of::as_vector<filtered_attributes> + >::type + type; + }; + + template <> + struct build_fusion_vector<unused_type> + { + typedef unused_type type; + }; + + /////////////////////////////////////////////////////////////////////////// + // build_attribute_sequence + // + // Build a fusion sequence attribute sequence from a sequence of + // components. Transform<T>::type is called on each element. + /////////////////////////////////////////////////////////////////////////// + template <typename Sequence, typename Context + , template <typename T, typename D> class Transform + , typename Iterator = unused_type, typename Domain = unused_type> + struct build_attribute_sequence + { + struct element_attribute + { + template <typename T> + struct result; + + template <typename F, typename Element> + struct result<F(Element)> + { + typedef typename + Transform< + typename attribute_of<Element, Context, Iterator>::type + , Domain + >::type + type; + }; + + // never called, but needed for decltype-based result_of (C++0x) + template <typename Element> + typename result<element_attribute(Element)>::type + operator()(Element&) const; + }; + + // Compute the list of attributes of all sub-components + typedef typename + fusion::result_of::transform<Sequence, element_attribute>::type + type; + }; + + /////////////////////////////////////////////////////////////////////////// + // has_no_unused + // + // Test if there are no unused attributes in Sequence + /////////////////////////////////////////////////////////////////////////// + template <typename Sequence> + struct has_no_unused + : is_same< + typename mpl::find_if<Sequence, is_same<mpl::_, unused_type> >::type + , typename mpl::end<Sequence>::type> + {}; + + namespace detail + { + template <typename Sequence, bool no_unused + , int size = mpl::size<Sequence>::value> + struct build_collapsed_variant; + + // N element case, no unused + template <typename Sequence, int size> + struct build_collapsed_variant<Sequence, true, size> + : spirit::detail::as_variant<Sequence> {}; + + // N element case with unused + template <typename Sequence, int size> + struct build_collapsed_variant<Sequence, false, size> + { + typedef optional< + typename spirit::detail::as_variant< + typename fusion::result_of::pop_front<Sequence>::type + >::type + > type; + }; + + // 1 element case, no unused + template <typename Sequence> + struct build_collapsed_variant<Sequence, true, 1> + : mpl::front<Sequence> {}; + + // 1 element case, with unused + template <typename Sequence> + struct build_collapsed_variant<Sequence, false, 1> + : mpl::front<Sequence> {}; + + // 2 element case, no unused + template <typename Sequence> + struct build_collapsed_variant<Sequence, true, 2> + : spirit::detail::as_variant<Sequence> {}; + + // 2 element case, with unused + template <typename Sequence> + struct build_collapsed_variant<Sequence, false, 2> + { + typedef optional< + typename mpl::deref< + typename mpl::next< + typename mpl::begin<Sequence>::type + >::type + >::type + > + type; + }; + } + + /////////////////////////////////////////////////////////////////////////// + // alternative_attribute_transform + // + // This transform is invoked for every attribute in an alternative allowing + // to modify the attribute type exposed by a component to the enclosing + // alternative component. By default no transformation is performed. + /////////////////////////////////////////////////////////////////////////// + template <typename Attribute, typename Domain> + struct alternative_attribute_transform + : mpl::identity<Attribute> + {}; + + /////////////////////////////////////////////////////////////////////////// + // build_variant + // + // Build a boost::variant from a fusion sequence. build_variant makes sure + // that 1) all attributes in the variant are unique 2) puts the unused + // attribute, if there is any, to the front and 3) collapses single element + // variants, variant<T> to T. + /////////////////////////////////////////////////////////////////////////// + template <typename Sequence> + struct build_variant + { + // Remove all unused attributes. + typedef typename + filter_unused_attributes<Sequence>::type + filtered_attributes; + + typedef has_no_unused<Sequence> no_unused; + + // If the original attribute list does not contain any unused + // attributes, it is used, otherwise a single unused_type is + // pushed to the front of the list. This is to make sure that if + // there is an unused_type in the list, it is the first one. + typedef typename + mpl::eval_if< + no_unused, + mpl::identity<Sequence>, + fusion::result_of::push_front<filtered_attributes, unused_type> + >::type + attribute_sequence; + + // Make sure each of the types occur only once in the type list + typedef typename + mpl::fold< + attribute_sequence, mpl::vector<>, + mpl::if_< + mpl::contains<mpl::_1, mpl::_2>, + mpl::_1, mpl::push_back<mpl::_1, mpl::_2> + > + >::type + no_duplicates; + + // If there is only one type in the list of types we strip off the + // variant. IOTW, collapse single element variants, variant<T> to T. + // Take note that this also collapses variant<unused_type, T> to T. + typedef typename + traits::detail::build_collapsed_variant< + no_duplicates, no_unused::value>::type + type; + }; + + /////////////////////////////////////////////////////////////////////////// + // transform_attribute + // + // Sometimes the user needs to transform the attribute types for certain + // attributes. This template can be used as a customization point, where + // the user is able specify specific transformation rules for any attribute + // type. + /////////////////////////////////////////////////////////////////////////// + template <typename Exposed, typename Transformed, typename Domain + , typename Enable/* = void*/> + struct transform_attribute; + + /////////////////////////////////////////////////////////////////////////// + template <typename Domain, typename Transformed, typename Exposed> + typename spirit::result_of::pre_transform<Exposed, Transformed, Domain>::type + pre_transform(Exposed& attr BOOST_PROTO_DISABLE_IF_IS_CONST(Exposed)) + { + return transform_attribute<Exposed, Transformed, Domain>::pre(attr); + } + + template <typename Domain, typename Transformed, typename Exposed> + typename spirit::result_of::pre_transform<Exposed const, Transformed, Domain>::type + pre_transform(Exposed const& attr) + { + return transform_attribute<Exposed const, Transformed, Domain>::pre(attr); + } + + /////////////////////////////////////////////////////////////////////////// + // make_attribute + // + // All parsers and generators have specific attribute types. + // Spirit parsers and generators are passed an attribute; these are either + // references to the expected type, or an unused_type -- to flag that we do + // not care about the attribute. For semantic actions, however, we need to + // have a real value to pass to the semantic action. If the client did not + // provide one, we will have to synthesize the value. This class takes care + // of that. + /////////////////////////////////////////////////////////////////////////// + template <typename Attribute, typename ActualAttribute> + struct make_attribute + { + typedef typename remove_const<Attribute>::type attribute_type; + typedef typename + mpl::if_< + is_same<typename remove_const<ActualAttribute>::type, unused_type> + , attribute_type + , ActualAttribute&>::type + type; + + typedef typename + mpl::if_< + is_same<typename remove_const<ActualAttribute>::type, unused_type> + , attribute_type + , ActualAttribute>::type + value_type; + + static Attribute call(unused_type) + { + // synthesize the attribute/parameter + return boost::get(value_initialized<attribute_type>()); + } + + template <typename T> + static T& call(T& value) + { + return value; // just pass the one provided + } + }; + + template <typename Attribute, typename ActualAttribute> + struct make_attribute<Attribute&, ActualAttribute> + : make_attribute<Attribute, ActualAttribute> + {}; + + template <typename Attribute, typename ActualAttribute> + struct make_attribute<Attribute const&, ActualAttribute> + : make_attribute<Attribute const, ActualAttribute> + {}; + + template <typename ActualAttribute> + struct make_attribute<unused_type, ActualAttribute> + { + typedef unused_type type; + typedef unused_type value_type; + static unused_type call(unused_type) + { + return unused; + } + }; + + /////////////////////////////////////////////////////////////////////////// + // swap_impl + // + // Swap (with proper handling of unused_types) + /////////////////////////////////////////////////////////////////////////// + template <typename A, typename B> + void swap_impl(A& a, B& b) + { + A temp = a; + a = b; + b = temp; + } + + template <typename T> + void swap_impl(T& a, T& b) + { + using namespace std; + swap(a, b); + } + + template <typename A> + void swap_impl(A& a, unused_type) + { + } + + template <typename A> + void swap_impl(unused_type, A& a) + { + } + + inline void swap_impl(unused_type, unused_type) + { + } + + /////////////////////////////////////////////////////////////////////////// + // Strips single element fusion vectors into its 'naked' + // form: vector<T> --> T + /////////////////////////////////////////////////////////////////////////// + template <typename T> + struct strip_single_element_vector + { + typedef T type; + }; + + template <typename T> + struct strip_single_element_vector<fusion::vector1<T> > + { + typedef T type; + }; + + template <typename T> + struct strip_single_element_vector<fusion::vector<T> > + { + typedef T type; + }; + + /////////////////////////////////////////////////////////////////////////// + // meta function to return whether the argument is a one element fusion + // sequence + /////////////////////////////////////////////////////////////////////////// + template <typename T + , bool IsFusionSeq = fusion::traits::is_sequence<T>::value + , bool IsProtoExpr = proto::is_expr<T>::value> + struct one_element_sequence + : mpl::false_ + {}; + + template <typename T> + struct one_element_sequence<T, true, false> + : mpl::bool_<mpl::size<T>::value == 1> + {}; + + /////////////////////////////////////////////////////////////////////////// + // clear + // + // Clear data efficiently + /////////////////////////////////////////////////////////////////////////// + template <typename T> + void clear(T& val); + + namespace detail + { + // this is used by the variant and fusion sequence dispatch + struct clear_visitor : static_visitor<> + { + template <typename T> + void operator()(T& val) const + { + spirit::traits::clear(val); + } + }; + + // default + template <typename T> + void clear_impl2(T& val, mpl::false_) + { + val = T(); + } + + // for fusion sequences + template <typename T> + void clear_impl2(T& val, mpl::true_) + { + fusion::for_each(val, clear_visitor()); + } + + // dispatch default or fusion sequence + template <typename T> + void clear_impl(T& val, mpl::false_) + { + clear_impl2(val, fusion::traits::is_sequence<T>()); + } + + // STL containers + template <typename T> + void clear_impl(T& val, mpl::true_) + { + val.clear(); + } + } + + template <typename T, typename Enable/* = void*/> + struct clear_value + { + static void call(T& val) + { + detail::clear_impl(val, typename is_container<T>::type()); + } + }; + + // optionals + template <typename T> + struct clear_value<optional<T> > + { + static void call(optional<T>& val) + { + if (val) + val = none_t(); // leave optional uninitialized + } + }; + + // variants + template <BOOST_VARIANT_ENUM_PARAMS(typename T)> + struct clear_value<variant<BOOST_VARIANT_ENUM_PARAMS(T)> > + { + static void call(variant<BOOST_VARIANT_ENUM_PARAMS(T)>& val) + { + apply_visitor(detail::clear_visitor(), val); + } + }; + + // iterator range + template <typename T> + struct clear_value<iterator_range<T> > + { + static void call(iterator_range<T>& val) + { + val = iterator_range<T>(val.end(), val.end()); + } + }; + + // main dispatch + template <typename T> + void clear(T& val) + { + clear_value<T>::call(val); + } + + // for unused + inline void clear(unused_type) + { + } + + /////////////////////////////////////////////////////////////////////////// + namespace detail + { + template <typename Out> + struct print_fusion_sequence + { + print_fusion_sequence(Out& out) + : out(out), is_first(true) {} + + typedef void result_type; + + template <typename T> + void operator()(T const& val) const + { + if (is_first) + is_first = false; + else + out << ", "; + spirit::traits::print_attribute(out, val); + } + + Out& out; + mutable bool is_first; + }; + + // print elements in a variant + template <typename Out> + struct print_visitor : static_visitor<> + { + print_visitor(Out& out) : out(out) {} + + template <typename T> + void operator()(T const& val) const + { + spirit::traits::print_attribute(out, val); + } + + Out& out; + }; + } + + template <typename Out, typename T, typename Enable> + struct print_attribute_debug + { + // for plain data types + template <typename T_> + static void call_impl3(Out& out, T_ const& val, mpl::false_) + { + out << val; + } + + // for fusion data types + template <typename T_> + static void call_impl3(Out& out, T_ const& val, mpl::true_) + { + out << '['; + fusion::for_each(val, detail::print_fusion_sequence<Out>(out)); + out << ']'; + } + + // non-stl container + template <typename T_> + static void call_impl2(Out& out, T_ const& val, mpl::false_) + { + call_impl3(out, val, fusion::traits::is_sequence<T_>()); + } + + // stl container + template <typename T_> + static void call_impl2(Out& out, T_ const& val, mpl::true_) + { + out << '['; + if (!traits::is_empty(val)) + { + bool first = true; + typename container_iterator<T_ const>::type iend = traits::end(val); + for (typename container_iterator<T_ const>::type i = traits::begin(val); + !traits::compare(i, iend); traits::next(i)) + { + if (!first) + out << ", "; + first = false; + spirit::traits::print_attribute(out, traits::deref(i)); + } + } + out << ']'; + } + + // for variant types + template <typename T_> + static void call_impl(Out& out, T_ const& val, mpl::false_) + { + apply_visitor(detail::print_visitor<Out>(out), val); + } + + // for non-variant types + template <typename T_> + static void call_impl(Out& out, T_ const& val, mpl::true_) + { + call_impl2(out, val, is_container<T_>()); + } + + // main entry point + static void call(Out& out, T const& val) + { + call_impl(out, val, not_is_variant<T>()); + } + }; + + template <typename Out, typename T> + struct print_attribute_debug<Out, boost::optional<T> > + { + static void call(Out& out, boost::optional<T> const& val) + { + if (val) + spirit::traits::print_attribute(out, *val); + else + out << "[empty]"; + } + }; + + /////////////////////////////////////////////////////////////////////////// + template <typename Out, typename T> + inline void print_attribute(Out& out, T const& val) + { + print_attribute_debug<Out, T>::call(out, val); + } + + template <typename Out> + inline void print_attribute(Out& out, unused_type) + { + } + + /////////////////////////////////////////////////////////////////////////// + // generate debug output for lookahead token (character) stream + namespace detail + { + struct token_printer_debug_for_chars + { + template<typename Out, typename Char> + static void print(Out& o, Char c) + { + using namespace std; // allow for ADL to find the proper iscntrl + + if (c == static_cast<Char>('\a')) + o << "\\a"; + else if (c == static_cast<Char>('\b')) + o << "\\b"; + else if (c == static_cast<Char>('\f')) + o << "\\f"; + else if (c == static_cast<Char>('\n')) + o << "\\n"; + else if (c == static_cast<Char>('\r')) + o << "\\r"; + else if (c == static_cast<Char>('\t')) + o << "\\t"; + else if (c == static_cast<Char>('\v')) + o << "\\v"; + else if (c < 127 && iscntrl(c)) + o << "\\" << std::oct << static_cast<int>(c); + else + o << static_cast<char>(c); + } + }; + + // for token types where the comparison with char constants wouldn't work + struct token_printer_debug + { + template<typename Out, typename T> + static void print(Out& o, T const& val) + { + o << val; + } + }; + } + + template <typename T, typename Enable> + struct token_printer_debug + : mpl::if_< + mpl::and_< + is_convertible<T, char>, is_convertible<char, T> > + , detail::token_printer_debug_for_chars + , detail::token_printer_debug>::type + {}; + + template <typename Out, typename T> + inline void print_token(Out& out, T const& val) + { + // allow to customize the token printer routine + token_printer_debug<T>::print(out, val); + } +}}} + +/////////////////////////////////////////////////////////////////////////////// +namespace boost { namespace spirit { namespace result_of +{ + template <typename Exposed, typename Transformed, typename Domain> + struct pre_transform + : traits::transform_attribute<Exposed, Transformed, Domain> + {}; +}}} + + +#endif |