1 | /*============================================================================= |
2 | Copyright (c) 2011 Eric Niebler |
3 | |
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 |
9 | |
10 | #include <boost/fusion/support/config.hpp> |
11 | #include <boost/mpl/bool.hpp> |
12 | #include <boost/mpl/eval_if.hpp> |
13 | #include <boost/mpl/identity.hpp> |
14 | #include <boost/utility/result_of.hpp> |
15 | #include <boost/type_traits/add_const.hpp> |
16 | #include <boost/type_traits/remove_reference.hpp> |
17 | |
18 | #include <boost/fusion/support/void.hpp> |
19 | #include <boost/fusion/container/list/cons_fwd.hpp> |
20 | #include <boost/fusion/sequence/intrinsic_fwd.hpp> |
21 | #include <boost/fusion/iterator/equal_to.hpp> |
22 | #include <boost/fusion/iterator/deref.hpp> |
23 | #include <boost/fusion/iterator/next.hpp> |
24 | #include <boost/fusion/support/is_segmented.hpp> |
25 | #include <boost/fusion/sequence/intrinsic/segments.hpp> |
26 | |
27 | // fun(seq, state, context) |
28 | // seq: a non-segmented range |
29 | // state: the state of the fold so far |
30 | // context: the path to the current range |
31 | // |
32 | // returns: (state', fcontinue) |
33 | |
34 | namespace boost { namespace fusion |
35 | { |
36 | template <typename First, typename Last> |
37 | struct iterator_range; |
38 | |
39 | template <typename Context> |
40 | struct segmented_iterator; |
41 | |
42 | namespace result_of |
43 | { |
44 | template <typename Cur, typename Context> |
45 | struct make_segmented_iterator |
46 | { |
47 | typedef |
48 | iterator_range< |
49 | Cur |
50 | , typename result_of::end< |
51 | typename remove_reference< |
52 | typename add_const< |
53 | typename result_of::deref< |
54 | typename Context::car_type::begin_type |
55 | >::type |
56 | >::type |
57 | >::type |
58 | >::type |
59 | > |
60 | range_type; |
61 | |
62 | typedef |
63 | segmented_iterator<cons<range_type, Context> > |
64 | type; |
65 | }; |
66 | } |
67 | |
68 | template <typename Cur, typename Context> |
69 | BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED |
70 | inline typename result_of::make_segmented_iterator<Cur, Context>::type |
71 | make_segmented_iterator(Cur const& cur, Context const& context) |
72 | { |
73 | typedef result_of::make_segmented_iterator<Cur, Context> impl_type; |
74 | typedef typename impl_type::type type; |
75 | typedef typename impl_type::range_type range_type; |
76 | return type(cons<range_type, Context>(range_type(cur, fusion::end(*context.car.first)), context)); |
77 | } |
78 | |
79 | namespace detail |
80 | { |
81 | template < |
82 | typename Begin |
83 | , typename End |
84 | , typename State |
85 | , typename Context |
86 | , typename Fun |
87 | , bool IsEmpty |
88 | > |
89 | struct segmented_fold_until_iterate_skip_empty; |
90 | |
91 | template < |
92 | typename Begin |
93 | , typename End |
94 | , typename State |
95 | , typename Context |
96 | , typename Fun |
97 | , bool IsDone = result_of::equal_to<Begin, End>::type::value |
98 | > |
99 | struct segmented_fold_until_iterate; |
100 | |
101 | template < |
102 | typename Sequence |
103 | , typename State |
104 | , typename Context |
105 | , typename Fun |
106 | , bool IsSegmented = traits::is_segmented<Sequence>::type::value |
107 | > |
108 | struct segmented_fold_until_impl; |
109 | |
110 | template <typename Segments, typename State, typename Context, typename Fun> |
111 | struct segmented_fold_until_on_segments; |
112 | |
113 | //auto push_context(cur, end, context) |
114 | //{ |
115 | // return push_back(context, segment_sequence(iterator_range(cur, end))); |
116 | //} |
117 | |
118 | template <typename Cur, typename End, typename Context> |
119 | struct push_context |
120 | { |
121 | typedef iterator_range<Cur, End> range_type; |
122 | typedef cons<range_type, Context> type; |
123 | |
124 | BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED |
125 | static type call(Cur const& cur, End const& end, Context const& context) |
126 | { |
127 | return cons<range_type, Context>(range_type(cur, end), context); |
128 | } |
129 | }; |
130 | |
131 | //auto make_segmented_iterator(cur, end, context) |
132 | //{ |
133 | // return segmented_iterator(push_context(cur, end, context)); |
134 | //} |
135 | // |
136 | //auto segmented_fold_until_impl(seq, state, context, fun) |
137 | //{ |
138 | // if (is_segmented(seq)) |
139 | // { |
140 | // segmented_fold_until_on_segments(segments(seq), state, context, fun); |
141 | // } |
142 | // else |
143 | // { |
144 | // return fun(seq, state, context); |
145 | // } |
146 | //} |
147 | |
148 | template < |
149 | typename Sequence |
150 | , typename State |
151 | , typename Context |
152 | , typename Fun |
153 | , bool IsSegmented |
154 | > |
155 | struct segmented_fold_until_impl |
156 | { |
157 | typedef |
158 | segmented_fold_until_on_segments< |
159 | typename remove_reference< |
160 | typename add_const< |
161 | typename result_of::segments<Sequence>::type |
162 | >::type |
163 | >::type |
164 | , State |
165 | , Context |
166 | , Fun |
167 | > |
168 | impl; |
169 | |
170 | typedef typename impl::type type; |
171 | typedef typename impl::continue_type continue_type; |
172 | |
173 | BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED |
174 | static type call(Sequence& seq, State const& state, Context const& context, Fun const& fun) |
175 | { |
176 | return impl::call(fusion::segments(seq), state, context, fun); |
177 | } |
178 | }; |
179 | |
180 | template < |
181 | typename Sequence |
182 | , typename State |
183 | , typename Context |
184 | , typename Fun |
185 | > |
186 | struct segmented_fold_until_impl<Sequence, State, Context, Fun, false> |
187 | { |
188 | typedef |
189 | typename Fun::template apply<Sequence, State, Context> |
190 | apply_type; |
191 | |
192 | typedef typename apply_type::type type; |
193 | typedef typename apply_type::continue_type continue_type; |
194 | |
195 | BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED |
196 | static type call(Sequence& seq, State const& state, Context const& context, Fun const& fun) |
197 | { |
198 | return apply_type::call(seq, state, context, fun); |
199 | } |
200 | }; |
201 | |
202 | //auto segmented_fold_until_on_segments(segs, state, context, fun) |
203 | //{ |
204 | // auto cur = begin(segs), end = end(segs); |
205 | // for (; cur != end; ++cur) |
206 | // { |
207 | // if (empty(*cur)) |
208 | // continue; |
209 | // auto context` = push_context(cur, end, context); |
210 | // state = segmented_fold_until_impl(*cur, state, context`, fun); |
211 | // if (!second(state)) |
212 | // return state; |
213 | // } |
214 | //} |
215 | |
216 | template <typename Apply> |
217 | struct continue_wrap |
218 | { |
219 | typedef typename Apply::continue_type type; |
220 | }; |
221 | |
222 | template <typename Begin, typename End, typename State, typename Context, typename Fun, bool IsEmpty> |
223 | struct segmented_fold_until_iterate_skip_empty |
224 | { |
225 | // begin != end and !empty(*begin) |
226 | typedef |
227 | push_context<Begin, End, Context> |
228 | push_context_impl; |
229 | |
230 | typedef |
231 | typename push_context_impl::type |
232 | next_context_type; |
233 | |
234 | typedef |
235 | segmented_fold_until_impl< |
236 | typename remove_reference< |
237 | typename add_const< |
238 | typename result_of::deref<Begin>::type |
239 | >::type |
240 | >::type |
241 | , State |
242 | , next_context_type |
243 | , Fun |
244 | > |
245 | fold_recurse_impl; |
246 | |
247 | typedef |
248 | typename fold_recurse_impl::type |
249 | next_state_type; |
250 | |
251 | typedef |
252 | segmented_fold_until_iterate< |
253 | typename result_of::next<Begin>::type |
254 | , End |
255 | , next_state_type |
256 | , Context |
257 | , Fun |
258 | > |
259 | next_iteration_impl; |
260 | |
261 | typedef |
262 | typename mpl::eval_if< |
263 | typename fold_recurse_impl::continue_type |
264 | , next_iteration_impl |
265 | , mpl::identity<next_state_type> |
266 | >::type |
267 | type; |
268 | |
269 | typedef |
270 | typename mpl::eval_if< |
271 | typename fold_recurse_impl::continue_type |
272 | , continue_wrap<next_iteration_impl> |
273 | , mpl::identity<mpl::false_> |
274 | >::type |
275 | continue_type; |
276 | |
277 | BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED |
278 | static type call(Begin const& beg, End const& end, State const& state |
279 | , Context const& context, Fun const& fun) |
280 | { |
281 | return call(beg, end, state, context, fun, typename fold_recurse_impl::continue_type()); |
282 | } |
283 | |
284 | BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED |
285 | static type call(Begin const& beg, End const& end, State const& state |
286 | , Context const& context, Fun const& fun, mpl::true_) // continue |
287 | { |
288 | return next_iteration_impl::call( |
289 | fusion::next(beg) |
290 | , end |
291 | , fold_recurse_impl::call( |
292 | *beg |
293 | , state |
294 | , push_context_impl::call(beg, end, context) |
295 | , fun) |
296 | , context |
297 | , fun); |
298 | } |
299 | |
300 | BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED |
301 | static type call(Begin const& beg, End const& end, State const& state |
302 | , Context const& context, Fun const& fun, mpl::false_) // break |
303 | { |
304 | return fold_recurse_impl::call( |
305 | *beg |
306 | , state |
307 | , push_context_impl::call(beg, end, context) |
308 | , fun); |
309 | } |
310 | }; |
311 | |
312 | template <typename Begin, typename End, typename State, typename Context, typename Fun> |
313 | struct segmented_fold_until_iterate_skip_empty<Begin, End, State, Context, Fun, true> |
314 | { |
315 | typedef |
316 | segmented_fold_until_iterate< |
317 | typename result_of::next<Begin>::type |
318 | , End |
319 | , State |
320 | , Context |
321 | , Fun |
322 | > |
323 | impl; |
324 | |
325 | typedef typename impl::type type; |
326 | typedef typename impl::continue_type continue_type; |
327 | |
328 | BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED |
329 | static type call(Begin const& beg, End const& end, State const& state |
330 | , Context const& context, Fun const& fun) |
331 | { |
332 | return impl::call(fusion::next(beg), end, state, context, fun); |
333 | } |
334 | }; |
335 | |
336 | template <typename Begin, typename End, typename State, typename Context, typename Fun, bool IsDone> |
337 | struct segmented_fold_until_iterate |
338 | { |
339 | typedef |
340 | typename result_of::empty< |
341 | typename remove_reference< |
342 | typename result_of::deref<Begin>::type |
343 | >::type |
344 | >::type |
345 | empty_type; |
346 | |
347 | typedef |
348 | segmented_fold_until_iterate_skip_empty<Begin, End, State, Context, Fun, empty_type::value> |
349 | impl; |
350 | |
351 | typedef typename impl::type type; |
352 | typedef typename impl::continue_type continue_type; |
353 | |
354 | BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED |
355 | static type call(Begin const& beg, End const& end, State const& state |
356 | , Context const& context, Fun const& fun) |
357 | { |
358 | return impl::call(beg, end, state, context, fun); |
359 | } |
360 | }; |
361 | |
362 | template <typename Begin, typename End, typename State, typename Context, typename Fun> |
363 | struct segmented_fold_until_iterate<Begin, End, State, Context, Fun, true> |
364 | { |
365 | typedef State type; |
366 | typedef mpl::true_ continue_type; |
367 | |
368 | BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED |
369 | static type call(Begin const&, End const&, State const& state |
370 | , Context const&, Fun const&) |
371 | { |
372 | return state; |
373 | } |
374 | }; |
375 | |
376 | template <typename Segments, typename State, typename Context, typename Fun> |
377 | struct segmented_fold_until_on_segments |
378 | { |
379 | typedef |
380 | segmented_fold_until_iterate< |
381 | typename result_of::begin<Segments>::type |
382 | , typename result_of::end<Segments>::type |
383 | , State |
384 | , Context |
385 | , Fun |
386 | > |
387 | impl; |
388 | |
389 | typedef typename impl::type type; |
390 | typedef typename impl::continue_type continue_type; |
391 | |
392 | BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED |
393 | static type call(Segments& segs, State const& state, Context const& context, Fun const& fun) |
394 | { |
395 | return impl::call(fusion::begin(segs), fusion::end(segs), state, context, fun); |
396 | } |
397 | }; |
398 | } |
399 | }} |
400 | |
401 | #endif |
402 | |