]> git.lyx.org Git - lyx.git/blob - 3rdparty/boost/boost/fusion/view/iterator_range/detail/segmented_iterator_range.hpp
Update to boost 1.72
[lyx.git] / 3rdparty / boost / boost / fusion / view / iterator_range / detail / segmented_iterator_range.hpp
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_ITERATOR_RANGE_HPP_INCLUDED)
8 #define BOOST_FUSION_SEGMENTED_ITERATOR_RANGE_HPP_INCLUDED
9
10 #include <boost/fusion/support/config.hpp>
11 #include <boost/detail/workaround.hpp>
12 #include <boost/mpl/assert.hpp>
13 #include <boost/type_traits/add_const.hpp>
14 #include <boost/type_traits/remove_reference.hpp>
15 #include <boost/fusion/support/tag_of.hpp>
16 #include <boost/fusion/sequence/intrinsic/begin.hpp>
17 #include <boost/fusion/sequence/intrinsic/end.hpp>
18 #include <boost/fusion/iterator/next.hpp>
19 #include <boost/fusion/iterator/deref.hpp>
20 #include <boost/fusion/sequence/intrinsic/segments.hpp>
21 #include <boost/fusion/algorithm/transformation/push_back.hpp>
22 #include <boost/fusion/algorithm/transformation/push_front.hpp>
23 #include <boost/fusion/iterator/equal_to.hpp>
24 #include <boost/fusion/container/list/detail/reverse_cons.hpp>
25 #include <boost/fusion/iterator/detail/segment_sequence.hpp>
26 #include <boost/fusion/support/is_sequence.hpp>
27 #include <boost/utility/enable_if.hpp>
28
29 //  Invariants:
30 //  - Each segmented iterator has a stack
31 //  - Each value in the stack is an iterator range
32 //  - The range at the top of the stack points to values
33 //  - All other ranges point to ranges
34 //  - The front of each range in the stack (besides the
35 //    topmost) is the range above it
36
37 namespace boost { namespace fusion
38 {
39     template <typename First, typename Last>
40     struct iterator_range;
41
42     namespace result_of
43     {
44         template <typename Sequence, typename T>
45         struct push_back;
46
47         template <typename Sequence, typename T>
48         struct push_front;
49     }
50
51     template <typename Sequence, typename T>
52     BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED
53     inline typename
54         lazy_enable_if<
55             traits::is_sequence<Sequence>
56           , result_of::push_back<Sequence const, T>
57         >::type
58     push_back(Sequence const& seq, T const& x);
59
60     template <typename Sequence, typename T>
61     BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED
62     inline typename
63         lazy_enable_if<
64             traits::is_sequence<Sequence>
65           , result_of::push_front<Sequence const, T>
66         >::type
67     push_front(Sequence const& seq, T const& x);
68 }}
69
70 namespace boost { namespace fusion { namespace detail
71 {
72     //auto make_segment_sequence_front(stack_begin)
73     //{
74     //  switch (size(stack_begin))
75     //  {
76     //  case 1:
77     //    return nil_;
78     //  case 2:
79     //    // car(cdr(stack_begin)) is a range over values.
80     //    assert(end(front(car(stack_begin))) == end(car(cdr(stack_begin))));
81     //    return iterator_range(begin(car(cdr(stack_begin))), end(front(car(stack_begin))));
82     //  default:
83     //    // car(cdr(stack_begin)) is a range over segments. We replace the
84     //    // front with a view that is restricted.
85     //    assert(end(segments(front(car(stack_begin)))) == end(car(cdr(stack_begin))));
86     //    return segment_sequence(
87     //      push_front(
88     //        // The following could be a segment_sequence. It then gets wrapped
89     //        // in a single_view, and push_front puts it in a join_view with the
90     //        // following iterator_range.
91     //        iterator_range(next(begin(car(cdr(stack_begin)))), end(segments(front(car(stack_begin))))),
92     //        make_segment_sequence_front(cdr(stack_begin))));
93     //  }
94     //}
95
96     template <typename Stack, std::size_t Size = Stack::size::value>
97     struct make_segment_sequence_front
98     {
99         // assert(end(segments(front(car(stack_begin)))) == end(car(cdr(stack_begin))));
100         BOOST_MPL_ASSERT((
101             result_of::equal_to<
102                 typename result_of::end<
103                     typename remove_reference<
104                         typename add_const<
105                             typename result_of::segments<
106                                 typename remove_reference<
107                                     typename add_const<
108                                         typename result_of::deref<
109                                             typename Stack::car_type::begin_type
110                                         >::type
111                                     >::type
112                                 >::type
113                             >::type
114                         >::type
115                     >::type
116                 >::type
117               , typename Stack::cdr_type::car_type::end_type
118             >));
119
120         typedef
121             iterator_range<
122                 typename result_of::next<
123                     typename Stack::cdr_type::car_type::begin_type
124                 >::type
125               , typename result_of::end<
126                     typename remove_reference<
127                         typename add_const<
128                             typename result_of::segments<
129                                 typename remove_reference<
130                                     typename add_const<
131                                         typename result_of::deref<
132                                             typename Stack::car_type::begin_type
133                                         >::type
134                                     >::type
135                                 >::type
136                             >::type
137                         >::type
138                     >::type
139                 >::type
140             >
141         rest_type;
142
143         typedef
144             make_segment_sequence_front<typename Stack::cdr_type>
145         recurse;
146
147         typedef
148             segment_sequence<
149                 typename result_of::push_front<
150                     rest_type const
151                   , typename recurse::type
152                 >::type
153             >
154         type;
155
156         BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
157         static type call(Stack const& stack)
158         {
159             //return segment_sequence(
160             //  push_front(
161             //    iterator_range(next(begin(car(cdr(stack_begin)))), end(segments(front(car(stack_begin))))),
162             //    make_segment_sequence_front(cdr(stack_begin))));
163             return type(
164                 fusion::push_front(
165                     rest_type(fusion::next(stack.cdr.car.first), fusion::end(fusion::segments(*stack.car.first)))
166                   , recurse::call(stack.cdr)));
167         }
168     };
169
170     template <typename Stack>
171     struct make_segment_sequence_front<Stack, 2>
172     {
173         // assert(end(front(car(stack_begin))) == end(car(cdr(stack_begin))));
174         BOOST_MPL_ASSERT((
175             result_of::equal_to<
176                 typename result_of::end<
177                     typename remove_reference<
178                         typename add_const<
179                             typename result_of::deref<
180                                 typename Stack::car_type::begin_type
181                             >::type
182                         >::type
183                     >::type
184                 >::type
185               , typename Stack::cdr_type::car_type::end_type
186             >));
187
188         typedef
189             iterator_range<
190                 typename Stack::cdr_type::car_type::begin_type
191               , typename result_of::end<
192                     typename remove_reference<
193                         typename add_const<
194                             typename result_of::deref<
195                                 typename Stack::car_type::begin_type
196                             >::type
197                         >::type
198                     >::type
199                 >::type
200             >
201         type;
202
203         BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
204         static type call(Stack const& stack)
205         {
206             // return iterator_range(begin(car(cdr(stack_begin))), end(front(car(stack_begin))));
207             return type(stack.cdr.car.first, fusion::end(*stack.car.first));
208         }
209     };
210
211     template <typename Stack>
212     struct make_segment_sequence_front<Stack, 1>
213     {
214         typedef typename Stack::cdr_type type; // nil_
215
216         BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
217         static type call(Stack const &stack)
218         {
219             return stack.cdr;
220         }
221     };
222
223     //auto make_segment_sequence_back(stack_end)
224     //{
225     //  switch (size(stack_end))
226     //  {
227     //  case 1:
228     //    return nil_;
229     //  case 2:
230     //    // car(cdr(stack_back)) is a range over values.
231     //    assert(end(front(car(stack_end))) == end(car(cdr(stack_end))));
232     //    return iterator_range(begin(front(car(stack_end))), begin(car(cdr(stack_end))));
233     //  default:
234     //    // car(cdr(stack_begin)) is a range over segments. We replace the
235     //    // back with a view that is restricted.
236     //    assert(end(segments(front(car(stack_end)))) == end(car(cdr(stack_end))));
237     //    return segment_sequence(
238     //      push_back(
239     //        iterator_range(begin(segments(front(car(stack_end)))), begin(car(cdr(stack_end)))),
240     //        make_segment_sequence_back(cdr(stack_end))));
241     //  }
242     //}
243
244     template <typename Stack, std::size_t Size = Stack::size::value>
245     struct make_segment_sequence_back
246     {
247         // assert(end(segments(front(car(stack_begin)))) == end(car(cdr(stack_begin))));
248         BOOST_MPL_ASSERT((
249             result_of::equal_to<
250                 typename result_of::end<
251                     typename remove_reference<
252                         typename add_const<
253                             typename result_of::segments<
254                                 typename remove_reference<
255                                     typename add_const<
256                                         typename result_of::deref<
257                                             typename Stack::car_type::begin_type
258                                         >::type
259                                     >::type
260                                 >::type
261                             >::type
262                         >::type
263                     >::type
264                 >::type
265               , typename Stack::cdr_type::car_type::end_type
266             >));
267
268         typedef
269             iterator_range<
270                 typename result_of::begin<
271                     typename remove_reference<
272                         typename add_const<
273                             typename result_of::segments<
274                                 typename remove_reference<
275                                     typename add_const<
276                                         typename result_of::deref<
277                                             typename Stack::car_type::begin_type
278                                         >::type
279                                     >::type
280                                 >::type
281                             >::type
282                         >::type
283                     >::type
284                 >::type
285               , typename Stack::cdr_type::car_type::begin_type
286             >
287         rest_type;
288
289         typedef
290             make_segment_sequence_back<typename Stack::cdr_type>
291         recurse;
292
293         typedef
294             segment_sequence<
295                 typename result_of::push_back<
296                     rest_type const
297                   , typename recurse::type
298                 >::type
299             >
300         type;
301
302         BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
303         static type call(Stack const& stack)
304         {
305             //  return segment_sequence(
306             //    push_back(
307             //      iterator_range(begin(segments(front(car(stack_end)))), begin(car(cdr(stack_end)))),
308             //      make_segment_sequence_back(cdr(stack_end))));
309             return type(
310                 fusion::push_back(
311                     rest_type(fusion::begin(fusion::segments(*stack.car.first)), stack.cdr.car.first)
312                   , recurse::call(stack.cdr)));
313         }
314     };
315
316     template <typename Stack>
317     struct make_segment_sequence_back<Stack, 2>
318     {
319         // assert(end(front(car(stack_end))) == end(car(cdr(stack_end))));
320         BOOST_MPL_ASSERT((
321             result_of::equal_to<
322                 typename result_of::end<
323                     typename remove_reference<
324                         typename add_const<
325                             typename result_of::deref<
326                                 typename Stack::car_type::begin_type
327                             >::type
328                         >::type
329                     >::type
330                 >::type
331               , typename Stack::cdr_type::car_type::end_type
332             >));
333
334         typedef
335             iterator_range<
336                 typename result_of::begin<
337                     typename remove_reference<
338                         typename add_const<
339                             typename result_of::deref<
340                                 typename Stack::car_type::begin_type
341                             >::type
342                         >::type
343                     >::type
344                 >::type
345               , typename Stack::cdr_type::car_type::begin_type
346             >
347         type;
348
349         BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
350         static type call(Stack const& stack)
351         {
352             // return iterator_range(begin(front(car(stack_end))), begin(car(cdr(stack_end))));
353             return type(fusion::begin(*stack.car.first), stack.cdr.car.first);
354         }
355     };
356
357     template <typename Stack>
358     struct make_segment_sequence_back<Stack, 1>
359     {
360         typedef typename Stack::cdr_type type; // nil_
361
362         BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
363         static type call(Stack const& stack)
364         {
365             return stack.cdr;
366         }
367     };
368
369     //auto make_segmented_range_reduce(stack_begin, stack_end)
370     //{
371     //  if (size(stack_begin) == 1 && size(stack_end) == 1)
372     //  {
373     //    return segment_sequence(
374     //      single_view(
375     //        iterator_range(begin(car(stack_begin)), begin(car(stack_end)))));
376     //  }
377     //  else
378     //  {
379     //    // We are in the case where both begin_stack and/or end_stack have
380     //    // more than one element. Throw away any part of the tree where
381     //    // begin and end refer to the same segment.
382     //    if (begin(car(stack_begin)) == begin(car(stack_end)))
383     //    {
384     //      return make_segmented_range_reduce(cdr(stack_begin), cdr(stack_end));
385     //    }
386     //    else
387     //    {
388     //      // We are in the case where begin_stack and end_stack (a) have
389     //      // more than one element each, and (b) they point to different
390     //      // segments. We must construct a segmented sequence.
391     //      return segment_sequence(
392     //          push_back(
393     //            push_front(
394     //                iterator_range(
395     //                    fusion::next(begin(car(stack_begin))),
396     //                    begin(car(stack_end))),                 // a range of (possibly segmented) ranges.
397     //              make_segment_sequence_front(stack_begin)),    // should be a (possibly segmented) range.
398     //            make_segment_sequence_back(stack_end)));        // should be a (possibly segmented) range.
399     //    }
400     //  }
401     //}
402
403     template <
404         typename StackBegin
405       , typename StackEnd
406       , int StackBeginSize = StackBegin::size::value
407       , int StackEndSize   = StackEnd::size::value>
408     struct make_segmented_range_reduce;
409
410     template <
411         typename StackBegin
412       , typename StackEnd
413       , bool SameSegment
414 #if !(BOOST_WORKAROUND(BOOST_GCC, >= 40000) && BOOST_WORKAROUND(BOOST_GCC, < 40200))
415           = result_of::equal_to<
416                 typename StackBegin::car_type::begin_type
417               , typename StackEnd::car_type::begin_type
418             >::type::value
419 #endif
420     >
421     struct make_segmented_range_reduce2
422     {
423         typedef
424             iterator_range<
425                 typename result_of::next<
426                     typename StackBegin::car_type::begin_type
427                 >::type
428               , typename StackEnd::car_type::begin_type
429             >
430         rest_type;
431
432         typedef
433             segment_sequence<
434                 typename result_of::push_back<
435                     typename result_of::push_front<
436                         rest_type const
437                       , typename make_segment_sequence_front<StackBegin>::type
438                     >::type const
439                   , typename make_segment_sequence_back<StackEnd>::type
440                 >::type
441             >
442         type;
443
444         BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
445         static type call(StackBegin stack_begin, StackEnd stack_end)
446         {
447             //return segment_sequence(
448             //    push_back(
449             //      push_front(
450             //        iterator_range(
451             //            fusion::next(begin(car(stack_begin))),
452             //            begin(car(stack_end))),                 // a range of (possibly segmented) ranges.
453             //        make_segment_sequence_front(stack_begin)),  // should be a (possibly segmented) range.
454             //      make_segment_sequence_back(stack_end)));      // should be a (possibly segmented) range.
455             return type(
456                 fusion::push_back(
457                     fusion::push_front(
458                         rest_type(fusion::next(stack_begin.car.first), stack_end.car.first)
459                       , make_segment_sequence_front<StackBegin>::call(stack_begin))
460                   , make_segment_sequence_back<StackEnd>::call(stack_end)));
461         }
462     };
463
464     template <typename StackBegin, typename StackEnd>
465     struct make_segmented_range_reduce2<StackBegin, StackEnd, true>
466     {
467         typedef
468             make_segmented_range_reduce<
469                 typename StackBegin::cdr_type
470               , typename StackEnd::cdr_type
471             >
472         impl;
473
474         typedef
475             typename impl::type
476         type;
477
478         BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
479         static type call(StackBegin stack_begin, StackEnd stack_end)
480         {
481             return impl::call(stack_begin.cdr, stack_end.cdr);
482         }
483     };
484
485     template <typename StackBegin, typename StackEnd, int StackBeginSize, int StackEndSize>
486     struct make_segmented_range_reduce
487       : make_segmented_range_reduce2<StackBegin, StackEnd
488 #if BOOST_WORKAROUND(BOOST_GCC, >= 40000) && BOOST_WORKAROUND(BOOST_GCC, < 40200)
489           , result_of::equal_to<
490                 typename StackBegin::car_type::begin_type
491               , typename StackEnd::car_type::begin_type
492             >::type::value
493 #endif
494         >
495     {};
496
497     template <typename StackBegin, typename StackEnd>
498     struct make_segmented_range_reduce<StackBegin, StackEnd, 1, 1>
499     {
500         typedef
501             iterator_range<
502                 typename StackBegin::car_type::begin_type
503               , typename StackEnd::car_type::begin_type
504             >
505         range_type;
506
507         typedef
508             single_view<range_type>
509         segment_type;
510
511         typedef
512             segment_sequence<segment_type>
513         type;
514
515         BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
516         static type call(StackBegin stack_begin, StackEnd stack_end)
517         {
518             //return segment_sequence(
519             //  single_view(
520             //    iterator_range(begin(car(stack_begin)), begin(car(stack_end)))));
521             return type(segment_type(range_type(stack_begin.car.first, stack_end.car.first)));
522         }
523     };
524
525     //auto make_segmented_range(begin, end)
526     //{
527     //  return make_segmented_range_reduce(reverse(begin.context), reverse(end.context));
528     //}
529
530     template <typename Begin, typename End>
531     struct make_segmented_range
532     {
533         typedef reverse_cons<typename Begin::context_type>   reverse_begin_cons;
534         typedef reverse_cons<typename End::context_type>     reverse_end_cons;
535
536         typedef
537             make_segmented_range_reduce<
538                 typename reverse_begin_cons::type
539               , typename reverse_end_cons::type
540             >
541         impl;
542
543         typedef typename impl::type type;
544
545         BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
546         static type call(Begin const& begin, End const& end)
547         {
548             return impl::call(
549                 reverse_begin_cons::call(begin.context)
550               , reverse_end_cons::call(end.context));
551         }
552     };
553
554 }}}
555
556 #endif