| /*============================================================================= |
| Copyright (c) 2011 Eric Niebler |
| |
| 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_FUSION_SEGMENTED_FOLD_UNTIL_IMPL_HPP_INCLUDED) |
| #define BOOST_FUSION_SEGMENTED_FOLD_UNTIL_IMPL_HPP_INCLUDED |
| |
| #include <boost/fusion/support/config.hpp> |
| #include <boost/mpl/bool.hpp> |
| #include <boost/mpl/eval_if.hpp> |
| #include <boost/mpl/identity.hpp> |
| #include <boost/utility/result_of.hpp> |
| #include <boost/type_traits/add_const.hpp> |
| #include <boost/type_traits/remove_reference.hpp> |
| |
| #include <boost/fusion/support/void.hpp> |
| #include <boost/fusion/container/list/cons_fwd.hpp> |
| #include <boost/fusion/sequence/intrinsic_fwd.hpp> |
| #include <boost/fusion/iterator/equal_to.hpp> |
| #include <boost/fusion/iterator/deref.hpp> |
| #include <boost/fusion/iterator/next.hpp> |
| #include <boost/fusion/support/is_segmented.hpp> |
| #include <boost/fusion/sequence/intrinsic/segments.hpp> |
| |
| // fun(seq, state, context) |
| // seq: a non-segmented range |
| // state: the state of the fold so far |
| // context: the path to the current range |
| // |
| // returns: (state', fcontinue) |
| |
| namespace boost { namespace fusion |
| { |
| template <typename First, typename Last> |
| struct iterator_range; |
| |
| template <typename Context> |
| struct segmented_iterator; |
| |
| namespace result_of |
| { |
| template <typename Cur, typename Context> |
| struct make_segmented_iterator |
| { |
| typedef |
| iterator_range< |
| Cur |
| , typename result_of::end< |
| typename remove_reference< |
| typename add_const< |
| typename result_of::deref< |
| typename Context::car_type::begin_type |
| >::type |
| >::type |
| >::type |
| >::type |
| > |
| range_type; |
| |
| typedef |
| segmented_iterator<cons<range_type, Context> > |
| type; |
| }; |
| } |
| |
| template <typename Cur, typename Context> |
| BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED |
| inline typename result_of::make_segmented_iterator<Cur, Context>::type |
| make_segmented_iterator(Cur const& cur, Context const& context) |
| { |
| typedef result_of::make_segmented_iterator<Cur, Context> impl_type; |
| typedef typename impl_type::type type; |
| typedef typename impl_type::range_type range_type; |
| return type(cons<range_type, Context>(range_type(cur, fusion::end(*context.car.first)), context)); |
| } |
| |
| namespace detail |
| { |
| template < |
| typename Begin |
| , typename End |
| , typename State |
| , typename Context |
| , typename Fun |
| , bool IsEmpty |
| > |
| struct segmented_fold_until_iterate_skip_empty; |
| |
| template < |
| typename Begin |
| , typename End |
| , typename State |
| , typename Context |
| , typename Fun |
| , bool IsDone = result_of::equal_to<Begin, End>::type::value |
| > |
| struct segmented_fold_until_iterate; |
| |
| template < |
| typename Sequence |
| , typename State |
| , typename Context |
| , typename Fun |
| , bool IsSegmented = traits::is_segmented<Sequence>::type::value |
| > |
| struct segmented_fold_until_impl; |
| |
| template <typename Segments, typename State, typename Context, typename Fun> |
| struct segmented_fold_until_on_segments; |
| |
| //auto push_context(cur, end, context) |
| //{ |
| // return push_back(context, segment_sequence(iterator_range(cur, end))); |
| //} |
| |
| template <typename Cur, typename End, typename Context> |
| struct push_context |
| { |
| typedef iterator_range<Cur, End> range_type; |
| typedef cons<range_type, Context> type; |
| |
| BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED |
| static type call(Cur const& cur, End const& end, Context const& context) |
| { |
| return cons<range_type, Context>(range_type(cur, end), context); |
| } |
| }; |
| |
| //auto make_segmented_iterator(cur, end, context) |
| //{ |
| // return segmented_iterator(push_context(cur, end, context)); |
| //} |
| // |
| //auto segmented_fold_until_impl(seq, state, context, fun) |
| //{ |
| // if (is_segmented(seq)) |
| // { |
| // segmented_fold_until_on_segments(segments(seq), state, context, fun); |
| // } |
| // else |
| // { |
| // return fun(seq, state, context); |
| // } |
| //} |
| |
| template < |
| typename Sequence |
| , typename State |
| , typename Context |
| , typename Fun |
| , bool IsSegmented |
| > |
| struct segmented_fold_until_impl |
| { |
| typedef |
| segmented_fold_until_on_segments< |
| typename remove_reference< |
| typename add_const< |
| typename result_of::segments<Sequence>::type |
| >::type |
| >::type |
| , State |
| , Context |
| , Fun |
| > |
| impl; |
| |
| typedef typename impl::type type; |
| typedef typename impl::continue_type continue_type; |
| |
| BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED |
| static type call(Sequence& seq, State const& state, Context const& context, Fun const& fun) |
| { |
| return impl::call(fusion::segments(seq), state, context, fun); |
| } |
| }; |
| |
| template < |
| typename Sequence |
| , typename State |
| , typename Context |
| , typename Fun |
| > |
| struct segmented_fold_until_impl<Sequence, State, Context, Fun, false> |
| { |
| typedef |
| typename Fun::template apply<Sequence, State, Context> |
| apply_type; |
| |
| typedef typename apply_type::type type; |
| typedef typename apply_type::continue_type continue_type; |
| |
| BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED |
| static type call(Sequence& seq, State const& state, Context const& context, Fun const& fun) |
| { |
| return apply_type::call(seq, state, context, fun); |
| } |
| }; |
| |
| //auto segmented_fold_until_on_segments(segs, state, context, fun) |
| //{ |
| // auto cur = begin(segs), end = end(segs); |
| // for (; cur != end; ++cur) |
| // { |
| // if (empty(*cur)) |
| // continue; |
| // auto context` = push_context(cur, end, context); |
| // state = segmented_fold_until_impl(*cur, state, context`, fun); |
| // if (!second(state)) |
| // return state; |
| // } |
| //} |
| |
| template <typename Apply> |
| struct continue_wrap |
| { |
| typedef typename Apply::continue_type type; |
| }; |
| |
| template <typename Begin, typename End, typename State, typename Context, typename Fun, bool IsEmpty> |
| struct segmented_fold_until_iterate_skip_empty |
| { |
| // begin != end and !empty(*begin) |
| typedef |
| push_context<Begin, End, Context> |
| push_context_impl; |
| |
| typedef |
| typename push_context_impl::type |
| next_context_type; |
| |
| typedef |
| segmented_fold_until_impl< |
| typename remove_reference< |
| typename add_const< |
| typename result_of::deref<Begin>::type |
| >::type |
| >::type |
| , State |
| , next_context_type |
| , Fun |
| > |
| fold_recurse_impl; |
| |
| typedef |
| typename fold_recurse_impl::type |
| next_state_type; |
| |
| typedef |
| segmented_fold_until_iterate< |
| typename result_of::next<Begin>::type |
| , End |
| , next_state_type |
| , Context |
| , Fun |
| > |
| next_iteration_impl; |
| |
| typedef |
| typename mpl::eval_if< |
| typename fold_recurse_impl::continue_type |
| , next_iteration_impl |
| , mpl::identity<next_state_type> |
| >::type |
| type; |
| |
| typedef |
| typename mpl::eval_if< |
| typename fold_recurse_impl::continue_type |
| , continue_wrap<next_iteration_impl> |
| , mpl::identity<mpl::false_> |
| >::type |
| continue_type; |
| |
| BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED |
| static type call(Begin const& beg, End const& end, State const& state |
| , Context const& context, Fun const& fun) |
| { |
| return call(beg, end, state, context, fun, typename fold_recurse_impl::continue_type()); |
| } |
| |
| BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED |
| static type call(Begin const& beg, End const& end, State const& state |
| , Context const& context, Fun const& fun, mpl::true_) // continue |
| { |
| return next_iteration_impl::call( |
| fusion::next(beg) |
| , end |
| , fold_recurse_impl::call( |
| *beg |
| , state |
| , push_context_impl::call(beg, end, context) |
| , fun) |
| , context |
| , fun); |
| } |
| |
| BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED |
| static type call(Begin const& beg, End const& end, State const& state |
| , Context const& context, Fun const& fun, mpl::false_) // break |
| { |
| return fold_recurse_impl::call( |
| *beg |
| , state |
| , push_context_impl::call(beg, end, context) |
| , fun); |
| } |
| }; |
| |
| template <typename Begin, typename End, typename State, typename Context, typename Fun> |
| struct segmented_fold_until_iterate_skip_empty<Begin, End, State, Context, Fun, true> |
| { |
| typedef |
| segmented_fold_until_iterate< |
| typename result_of::next<Begin>::type |
| , End |
| , State |
| , Context |
| , Fun |
| > |
| impl; |
| |
| typedef typename impl::type type; |
| typedef typename impl::continue_type continue_type; |
| |
| BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED |
| static type call(Begin const& beg, End const& end, State const& state |
| , Context const& context, Fun const& fun) |
| { |
| return impl::call(fusion::next(beg), end, state, context, fun); |
| } |
| }; |
| |
| template <typename Begin, typename End, typename State, typename Context, typename Fun, bool IsDone> |
| struct segmented_fold_until_iterate |
| { |
| typedef |
| typename result_of::empty< |
| typename remove_reference< |
| typename result_of::deref<Begin>::type |
| >::type |
| >::type |
| empty_type; |
| |
| typedef |
| segmented_fold_until_iterate_skip_empty<Begin, End, State, Context, Fun, empty_type::value> |
| impl; |
| |
| typedef typename impl::type type; |
| typedef typename impl::continue_type continue_type; |
| |
| BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED |
| static type call(Begin const& beg, End const& end, State const& state |
| , Context const& context, Fun const& fun) |
| { |
| return impl::call(beg, end, state, context, fun); |
| } |
| }; |
| |
| template <typename Begin, typename End, typename State, typename Context, typename Fun> |
| struct segmented_fold_until_iterate<Begin, End, State, Context, Fun, true> |
| { |
| typedef State type; |
| typedef mpl::true_ continue_type; |
| |
| BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED |
| static type call(Begin const&, End const&, State const& state |
| , Context const&, Fun const&) |
| { |
| return state; |
| } |
| }; |
| |
| template <typename Segments, typename State, typename Context, typename Fun> |
| struct segmented_fold_until_on_segments |
| { |
| typedef |
| segmented_fold_until_iterate< |
| typename result_of::begin<Segments>::type |
| , typename result_of::end<Segments>::type |
| , State |
| , Context |
| , Fun |
| > |
| impl; |
| |
| typedef typename impl::type type; |
| typedef typename impl::continue_type continue_type; |
| |
| BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED |
| static type call(Segments& segs, State const& state, Context const& context, Fun const& fun) |
| { |
| return impl::call(fusion::begin(segs), fusion::end(segs), state, context, fun); |
| } |
| }; |
| } |
| }} |
| |
| #endif |