1 /*=============================================================================
2 Copyright (c) 2011 Eric Niebler
4 Distributed under the Boost Software License, Version 1.0. (See accompanying
5 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 ==============================================================================*/
7 #if !defined(BOOST_FUSION_SEGMENTED_FOLD_UNTIL_IMPL_HPP_INCLUDED)
8 #define BOOST_FUSION_SEGMENTED_FOLD_UNTIL_IMPL_HPP_INCLUDED
10 #include <boost/mpl/bool.hpp>
11 #include <boost/mpl/eval_if.hpp>
12 #include <boost/mpl/identity.hpp>
13 #include <boost/utility/result_of.hpp>
14 #include <boost/type_traits/add_const.hpp>
15 #include <boost/type_traits/remove_reference.hpp>
17 #include <boost/fusion/support/void.hpp>
18 #include <boost/fusion/container/list/cons_fwd.hpp>
19 #include <boost/fusion/sequence/intrinsic_fwd.hpp>
20 #include <boost/fusion/iterator/equal_to.hpp>
21 #include <boost/fusion/iterator/deref.hpp>
22 #include <boost/fusion/iterator/next.hpp>
23 #include <boost/fusion/support/is_segmented.hpp>
24 #include <boost/fusion/sequence/intrinsic/segments.hpp>
26 // fun(seq, state, context)
27 // seq: a non-segmented range
28 // state: the state of the fold so far
29 // context: the path to the current range
31 // returns: (state', fcontinue)
33 namespace boost { namespace fusion
35 template <typename First, typename Last>
36 struct iterator_range;
38 template <typename Context>
39 struct segmented_iterator;
43 template <typename Cur, typename Context>
44 struct make_segmented_iterator
49 , typename result_of::end<
50 typename remove_reference<
52 typename result_of::deref<
53 typename Context::car_type::begin_type
62 segmented_iterator<cons<range_type, Context> >
67 template <typename Cur, typename Context>
68 typename result_of::make_segmented_iterator<Cur, Context>::type
69 make_segmented_iterator(Cur const& cur, Context const& context)
71 typedef result_of::make_segmented_iterator<Cur, Context> impl_type;
72 typedef typename impl_type::type type;
73 typedef typename impl_type::range_type range_type;
74 return type(cons<range_type, Context>(range_type(cur, fusion::end(*context.car.first)), context));
87 struct segmented_fold_until_iterate_skip_empty;
95 , bool IsDone = result_of::equal_to<Begin, End>::type::value
97 struct segmented_fold_until_iterate;
104 , bool IsSegmented = traits::is_segmented<Sequence>::type::value
106 struct segmented_fold_until_impl;
108 template <typename Segments, typename State, typename Context, typename Fun>
109 struct segmented_fold_until_on_segments;
111 //auto push_context(cur, end, context)
113 // return push_back(context, segment_sequence(iterator_range(cur, end)));
116 template <typename Cur, typename End, typename Context>
119 typedef iterator_range<Cur, End> range_type;
120 typedef cons<range_type, Context> type;
122 static type call(Cur const& cur, End const& end, Context const& context)
124 return cons<range_type, Context>(range_type(cur, end), context);
128 //auto make_segmented_iterator(cur, end, context)
130 // return segmented_iterator(push_context(cur, end, context));
133 //auto segmented_fold_until_impl(seq, state, context, fun)
135 // if (is_segmented(seq))
137 // segmented_fold_until_on_segments(segments(seq), state, context, fun);
141 // return fun(seq, state, context);
152 struct segmented_fold_until_impl
155 segmented_fold_until_on_segments<
156 typename remove_reference<
158 typename result_of::segments<Sequence>::type
167 typedef typename impl::type type;
168 typedef typename impl::continue_type continue_type;
170 static type call(Sequence& seq, State const& state, Context const& context, Fun const& fun)
172 return impl::call(fusion::segments(seq), state, context, fun);
182 struct segmented_fold_until_impl<Sequence, State, Context, Fun, false>
185 typename Fun::template apply<Sequence, State, Context>
188 typedef typename apply_type::type type;
189 typedef typename apply_type::continue_type continue_type;
191 static type call(Sequence& seq, State const& state, Context const& context, Fun const& fun)
193 return apply_type::call(seq, state, context, fun);
197 //auto segmented_fold_until_on_segments(segs, state, context, fun)
199 // auto cur = begin(segs), end = end(segs);
200 // for (; cur != end; ++cur)
204 // auto context` = push_context(cur, end, context);
205 // state = segmented_fold_until_impl(*cur, state, context`, fun);
206 // if (!second(state))
211 template <typename Apply>
214 typedef typename Apply::continue_type type;
217 template <typename Begin, typename End, typename State, typename Context, typename Fun, bool IsEmpty>
218 struct segmented_fold_until_iterate_skip_empty
220 // begin != end and !empty(*begin)
222 push_context<Begin, End, Context>
226 typename push_context_impl::type
230 segmented_fold_until_impl<
231 typename remove_reference<
233 typename result_of::deref<Begin>::type
243 typename fold_recurse_impl::type
247 segmented_fold_until_iterate<
248 typename result_of::next<Begin>::type
257 typename mpl::eval_if<
258 typename fold_recurse_impl::continue_type
259 , next_iteration_impl
260 , mpl::identity<next_state_type>
265 typename mpl::eval_if<
266 typename fold_recurse_impl::continue_type
267 , continue_wrap<next_iteration_impl>
268 , mpl::identity<mpl::false_>
272 static type call(Begin const& beg, End const& end, State const& state
273 , Context const& context, Fun const& fun)
275 return call(beg, end, state, context, fun, typename fold_recurse_impl::continue_type());
278 static type call(Begin const& beg, End const& end, State const& state
279 , Context const& context, Fun const& fun, mpl::true_) // continue
281 return next_iteration_impl::call(
284 , fold_recurse_impl::call(
287 , push_context_impl::call(beg, end, context)
293 static type call(Begin const& beg, End const& end, State const& state
294 , Context const& context, Fun const& fun, mpl::false_) // break
296 return fold_recurse_impl::call(
299 , push_context_impl::call(beg, end, context)
304 template <typename Begin, typename End, typename State, typename Context, typename Fun>
305 struct segmented_fold_until_iterate_skip_empty<Begin, End, State, Context, Fun, true>
308 segmented_fold_until_iterate<
309 typename result_of::next<Begin>::type
317 typedef typename impl::type type;
318 typedef typename impl::continue_type continue_type;
320 static type call(Begin const& beg, End const& end, State const& state
321 , Context const& context, Fun const& fun)
323 return impl::call(fusion::next(beg), end, state, context, fun);
327 template <typename Begin, typename End, typename State, typename Context, typename Fun, bool IsDone>
328 struct segmented_fold_until_iterate
331 typename result_of::empty<
332 typename remove_reference<
333 typename result_of::deref<Begin>::type
339 segmented_fold_until_iterate_skip_empty<Begin, End, State, Context, Fun, empty_type::value>
342 typedef typename impl::type type;
343 typedef typename impl::continue_type continue_type;
345 static type call(Begin const& beg, End const& end, State const& state
346 , Context const& context, Fun const& fun)
348 return impl::call(beg, end, state, context, fun);
352 template <typename Begin, typename End, typename State, typename Context, typename Fun>
353 struct segmented_fold_until_iterate<Begin, End, State, Context, Fun, true>
356 typedef mpl::true_ continue_type;
358 static type call(Begin const&, End const&, State const& state
359 , Context const&, Fun const&)
365 template <typename Segments, typename State, typename Context, typename Fun>
366 struct segmented_fold_until_on_segments
369 segmented_fold_until_iterate<
370 typename result_of::begin<Segments>::type
371 , typename result_of::end<Segments>::type
378 typedef typename impl::type type;
379 typedef typename impl::continue_type continue_type;
381 static type call(Segments& segs, State const& state, Context const& context, Fun const& fun)
383 return impl::call(fusion::begin(segs), fusion::end(segs), state, context, fun);