402 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			402 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| /*=============================================================================
 | |
|     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
 | 
