/*============================================================================= 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_HPP_INCLUDED) #define BOOST_FUSION_SEGMENTED_FOLD_UNTIL_HPP_INCLUDED #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // fun(rng, state, context) // rng: 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 struct segmented_iterator; namespace result_of { template 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 > type; }; } template typename result_of::make_segmented_iterator::type make_segmented_iterator(Cur const& cur, Context const& context) { typedef result_of::make_segmented_iterator impl_type; typedef typename impl_type::type type; typedef typename impl_type::range_type range_type; return type(fusion::make_cons(range_type(cur, fusion::end(*context.car.first)), context)); } typedef mpl::true_ continue_; typedef mpl::false_ break_; template struct result { typedef Value value_type; typedef Continue continue_type; result(Value const& val) : value(val) {} value_type value; }; template struct result { typedef void_ value_type; typedef Continue continue_type; result(void_ const&) {} value_type value; }; template result make_result_continue(Value const& val) { return result(val); } template result make_result_break(Value const& val) { return result(val); } namespace detail { template< typename Begin, typename End, typename State, typename Context, typename Fun, bool IsEmpty = result_of::empty< typename result_of::value_of::type >::type::value> struct segmented_fold_until_iterate_skip_empty; template< typename Begin, typename End, typename State, typename Context, typename Fun, bool IsDone = result_of::equal_to::type::value> struct segmented_fold_until_iterate; template< typename Range, typename State, typename Context, typename Fun, bool IsSegmented = traits::is_segmented::type::value> struct segmented_fold_until_impl; template struct segmented_fold_until_on_segments; //auto push_context(cur, end, context) //{ // return push_back(context, segment_sequence(iterator_range(cur, end))); //} template struct push_context { typedef iterator_range range_type; typedef cons type; static type call(Cur const& cur, End const& end, Context const& context) { return fusion::make_cons(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(rng, state, context, fun) //{ // if (is_segmented(rng)) // { // segmented_fold_until_on_segments(segments(rng), state, context, fun); // } // else // { // return fun(rng, state, context); // } //} template< typename Range, 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::type >::type >::type, State, Context, Fun > impl; typedef typename impl::type type; static type call(Range& rng, State const& state, Context const& context, Fun const& fun) { return impl::call(fusion::segments(rng), state, context, fun); } }; template< typename Range, typename State, typename Context, typename Fun> struct segmented_fold_until_impl { typedef typename boost::result_of::type>::type, Context const& )>::type type; static type call(Range& rng, State const& state, Context const& context, Fun const& fun) { return fun(rng, state.value, context); } }; //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 struct segmented_fold_until_iterate_skip_empty { // begin != end and !empty(*begin) typedef push_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::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::type, End, next_state_type, Context, Fun > next_iteration_impl; typedef typename mpl::eval_if< typename next_state_type::continue_type, next_iteration_impl, mpl::identity >::type type; 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 next_state_type::continue_type()); } 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); } 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 struct segmented_fold_until_iterate_skip_empty { typedef segmented_fold_until_iterate< typename result_of::next::type, End, State, Context, Fun > impl; typedef typename impl::type type; 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 struct segmented_fold_until_iterate { typedef segmented_fold_until_iterate_skip_empty impl; typedef typename impl::type type; 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 struct segmented_fold_until_iterate { typedef State type; static type call(Begin const&, End const&, State const& state, Context const&, Fun const&) { return state; } }; template struct segmented_fold_until_on_segments { typedef segmented_fold_until_iterate< typename result_of::begin::type, typename result_of::end::type, State, Context, Fun > impl; typedef typename impl::type type; 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); } }; } //auto segmented_fold_until(rng, state, fun) //{ // return first(segmented_fold_until_impl(rng, state, nil, fun)); //} namespace result_of { template struct segmented_fold_until { typedef detail::segmented_fold_until_impl< Range, result, fusion::nil, Fun > impl; typedef typename impl::type::value_type type; }; } template typename result_of::segmented_fold_until::type segmented_fold_until(Range& rng, State const& state, Fun const& fun) { typedef typename result_of::segmented_fold_until::impl impl; return impl::call(rng, state, fusion::nil(), fun).value; } template typename result_of::segmented_fold_until::type segmented_fold_until(Range const& rng, State const& state, Fun const& fun) { typedef typename result_of::segmented_fold_until::impl impl; return impl::call(rng, state, fusion::nil(), fun).value; } }} #endif