Mercurial > hg > vamp-build-and-test
diff DEPENDENCIES/generic/include/boost/spirit/home/karma/operator/sequence.hpp @ 16:2665513ce2d3
Add boost headers
author | Chris Cannam |
---|---|
date | Tue, 05 Aug 2014 11:11:38 +0100 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DEPENDENCIES/generic/include/boost/spirit/home/karma/operator/sequence.hpp Tue Aug 05 11:11:38 2014 +0100 @@ -0,0 +1,313 @@ +// Copyright (c) 2001-2011 Hartmut Kaiser +// Copyright (c) 2001-2011 Joel de Guzman +// +// 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(SPIRIT_KARMA_SEQUENCE_FEB_28_2007_0247PM) +#define SPIRIT_KARMA_SEQUENCE_FEB_28_2007_0247PM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/spirit/home/karma/domain.hpp> +#include <boost/spirit/home/karma/generator.hpp> +#include <boost/spirit/home/karma/meta_compiler.hpp> +#include <boost/spirit/home/karma/detail/fail_function.hpp> +#include <boost/spirit/home/karma/detail/pass_container.hpp> +#include <boost/spirit/home/karma/detail/get_stricttag.hpp> +#include <boost/spirit/home/support/info.hpp> +#include <boost/spirit/home/support/detail/what_function.hpp> +#include <boost/spirit/home/karma/detail/attributes.hpp> +#include <boost/spirit/home/karma/detail/indirect_iterator.hpp> +#include <boost/spirit/home/support/algorithm/any_if.hpp> +#include <boost/spirit/home/support/unused.hpp> +#include <boost/spirit/home/support/sequence_base_id.hpp> +#include <boost/spirit/home/support/has_semantic_action.hpp> +#include <boost/spirit/home/support/handles_container.hpp> +#include <boost/spirit/home/support/attributes.hpp> +#include <boost/fusion/include/vector.hpp> +#include <boost/fusion/include/as_vector.hpp> +#include <boost/fusion/include/for_each.hpp> +#include <boost/type_traits/is_same.hpp> +#include <boost/mpl/bitor.hpp> +#include <boost/mpl/int.hpp> +#include <boost/mpl/and.hpp> +#include <boost/mpl/not.hpp> +#include <boost/fusion/include/transform.hpp> +#include <boost/mpl/accumulate.hpp> +#include <boost/config.hpp> + +/////////////////////////////////////////////////////////////////////////////// +namespace boost { namespace spirit +{ + /////////////////////////////////////////////////////////////////////////// + // Enablers + /////////////////////////////////////////////////////////////////////////// + template <> + struct use_operator<karma::domain, proto::tag::shift_left> // enables << + : mpl::true_ {}; + + template <> + struct flatten_tree<karma::domain, proto::tag::shift_left> // flattens << + : mpl::true_ {}; +}} + +/////////////////////////////////////////////////////////////////////////////// +namespace boost { namespace spirit { namespace traits +{ + // specialization for sequences + template <typename Elements> + struct sequence_properties + { + struct element_properties + { + template <typename T> + struct result; + + template <typename F, typename Element> + struct result<F(Element)> + { + typedef properties_of<Element> type; + }; + + // never called, but needed for decltype-based result_of (C++0x) +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + template <typename Element> + typename result<element_properties(Element)>::type + operator()(Element&&) const; +#endif + }; + + typedef typename mpl::accumulate< + typename fusion::result_of::transform< + Elements, element_properties>::type + , mpl::int_<karma::generator_properties::no_properties> + , mpl::bitor_<mpl::_2, mpl::_1> + >::type type; + }; +}}} + +/////////////////////////////////////////////////////////////////////////////// +namespace boost { namespace spirit { namespace karma +{ + template <typename Elements, typename Strict, typename Derived> + struct base_sequence : nary_generator<Derived> + { + typedef typename traits::sequence_properties<Elements>::type properties; + + base_sequence(Elements const& elements) + : elements(elements) {} + + typedef Elements elements_type; + struct sequence_base_id; + + template <typename Context, typename Iterator = unused_type> + struct attribute + { + // Put all the element attributes in a tuple + typedef typename traits::build_attribute_sequence< + Elements, Context, traits::sequence_attribute_transform + , Iterator, karma::domain + >::type all_attributes; + + // Now, build a fusion vector over the attributes. Note + // that build_fusion_vector 1) removes all unused attributes + // and 2) may return unused_type if all elements have + // unused_type(s). + typedef typename + traits::build_fusion_vector<all_attributes>::type + type_; + + // Finally, strip single element vectors into its + // naked form: vector1<T> --> T + typedef typename + traits::strip_single_element_vector<type_>::type + type; + }; + + // standard case. Attribute is a fusion tuple + template < + typename OutputIterator, typename Context, typename Delimiter + , typename Attribute, typename Pred1, typename Pred2> + bool generate_impl(OutputIterator& sink, Context& ctx + , Delimiter const& d, Attribute& attr_, Pred1, Pred2) const + { + typedef detail::fail_function< + OutputIterator, Context, Delimiter> fail_function; + typedef traits::attribute_not_unused<Context> predicate; + + // wrap the attribute in a tuple if it is not a tuple or if the + // attribute of this sequence is a single element tuple + typedef typename attribute<Context>::type_ attr_type_; + typename traits::wrap_if_not_tuple<Attribute + , typename mpl::and_< + traits::one_element_sequence<attr_type_> + , mpl::not_<traits::one_element_sequence<Attribute> > + >::type + >::type attr(attr_); + + // return false if *any* of the generators fail + bool r = spirit::any_if(elements, attr + , fail_function(sink, ctx, d), predicate()); + + typedef typename traits::attribute_size<Attribute>::type size_type; + + // fail generating if sequences have not the same (logical) length + return !r && (!Strict::value || + // This ignores container element count (which is not good), + // but allows valid attributes to succeed. This will lead to + // false positives (failing generators, even if they shouldn't) + // if the embedded component is restricting the number of + // container elements it consumes (i.e. repeat). This solution + // is not optimal but much better than letting _all_ repetitive + // components fail. + Pred1::value || + size_type(traits::sequence_size<attr_type_>::value) == traits::size(attr_)); + } + + // Special case when Attribute is an stl container and the sequence's + // attribute is not a one element sequence + template < + typename OutputIterator, typename Context, typename Delimiter + , typename Attribute> + bool generate_impl(OutputIterator& sink, Context& ctx + , Delimiter const& d, Attribute const& attr_ + , mpl::true_, mpl::false_) const + { + // return false if *any* of the generators fail + typedef detail::fail_function< + OutputIterator, Context, Delimiter> fail_function; + + typedef typename traits::container_iterator< + typename add_const<Attribute>::type + >::type iterator_type; + + typedef + typename traits::make_indirect_iterator<iterator_type>::type + indirect_iterator_type; + typedef detail::pass_container< + fail_function, Attribute, indirect_iterator_type, mpl::true_> + pass_container; + + iterator_type begin = traits::begin(attr_); + iterator_type end = traits::end(attr_); + + pass_container pass(fail_function(sink, ctx, d), + indirect_iterator_type(begin), indirect_iterator_type(end)); + bool r = fusion::any(elements, pass); + + // fail generating if sequences have not the same (logical) length + return !r && (!Strict::value || begin == end); + } + + // main generate function. Dispatches to generate_impl depending + // on the Attribute type. + template < + typename OutputIterator, typename Context, typename Delimiter + , typename Attribute> + bool generate(OutputIterator& sink, Context& ctx, Delimiter const& d + , Attribute const& attr) const + { + typedef typename traits::is_container<Attribute>::type + is_container; + + typedef typename attribute<Context>::type_ attr_type_; + typedef typename traits::one_element_sequence<attr_type_>::type + is_one_element_sequence; + + return generate_impl(sink, ctx, d, attr, is_container() + , is_one_element_sequence()); + } + + template <typename Context> + info what(Context& context) const + { + info result("sequence"); + fusion::for_each(elements, + spirit::detail::what_function<Context>(result, context)); + return result; + } + + Elements elements; + }; + + template <typename Elements> + struct sequence + : base_sequence<Elements, mpl::false_, sequence<Elements> > + { + typedef base_sequence<Elements, mpl::false_, sequence> base_sequence_; + + sequence(Elements const& subject) + : base_sequence_(subject) {} + }; + + template <typename Elements> + struct strict_sequence + : base_sequence<Elements, mpl::true_, strict_sequence<Elements> > + { + typedef base_sequence<Elements, mpl::true_, strict_sequence> + base_sequence_; + + strict_sequence(Elements const& subject) + : base_sequence_(subject) {} + }; + + /////////////////////////////////////////////////////////////////////////// + // Generator generators: make_xxx function (objects) + /////////////////////////////////////////////////////////////////////////// + namespace detail + { + template <typename Elements, bool strict_mode = false> + struct make_sequence + : make_nary_composite<Elements, sequence> + {}; + + template <typename Elements> + struct make_sequence<Elements, true> + : make_nary_composite<Elements, strict_sequence> + {}; + } + + template <typename Elements, typename Modifiers> + struct make_composite<proto::tag::shift_left, Elements, Modifiers> + : detail::make_sequence<Elements, detail::get_stricttag<Modifiers>::value> + {}; + + /////////////////////////////////////////////////////////////////////////// + // Helper template allowing to get the required container type for a rule + // attribute, which is part of a sequence. + template <typename Iterator> + struct make_sequence_iterator_range + { + typedef iterator_range<detail::indirect_iterator<Iterator> > type; + }; +}}} + +namespace boost { namespace spirit { namespace traits +{ + /////////////////////////////////////////////////////////////////////////// + template <typename Elements> + struct has_semantic_action<karma::sequence<Elements> > + : nary_has_semantic_action<Elements> {}; + + template <typename Elements> + struct has_semantic_action<karma::strict_sequence<Elements> > + : nary_has_semantic_action<Elements> {}; + + /////////////////////////////////////////////////////////////////////////// + template <typename Elements, typename Attribute, typename Context + , typename Iterator> + struct handles_container<karma::sequence<Elements>, Attribute, Context + , Iterator> + : mpl::true_ {}; + + template <typename Elements, typename Attribute, typename Context + , typename Iterator> + struct handles_container<karma::strict_sequence<Elements>, Attribute + , Context, Iterator> + : mpl::true_ {}; +}}} + +#endif