]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/poly_collection/detail/segment_split.hpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / boost / poly_collection / detail / segment_split.hpp
1 /* Copyright 2016-2017 Joaquin M Lopez Munoz.
2 * Distributed under the Boost Software License, Version 1.0.
3 * (See accompanying file LICENSE_1_0.txt or copy at
4 * http://www.boost.org/LICENSE_1_0.txt)
5 *
6 * See http://www.boost.org/libs/poly_collection for library home page.
7 */
8
9 #ifndef BOOST_POLY_COLLECTION_DETAIL_SEGMENT_SPLIT_HPP
10 #define BOOST_POLY_COLLECTION_DETAIL_SEGMENT_SPLIT_HPP
11
12 #if defined(_MSC_VER)
13 #pragma once
14 #endif
15
16 #include <boost/iterator/iterator_facade.hpp>
17 #include <boost/poly_collection/detail/iterator_traits.hpp>
18 #include <typeinfo>
19 #include <utility>
20
21 namespace boost{
22
23 namespace poly_collection{
24
25 namespace detail{
26
27 /* breakdown of an iterator range into local_base_iterator segments */
28
29 template<typename PolyCollectionIterator>
30 class segment_splitter
31 {
32 using traits=iterator_traits<PolyCollectionIterator>;
33 using local_base_iterator=typename traits::local_base_iterator;
34 using base_segment_info_iterator=typename traits::base_segment_info_iterator;
35
36 public:
37 struct info
38 {
39 const std::type_info& type_info()const noexcept{return *pinfo_;}
40 local_base_iterator begin()const noexcept{return begin_;}
41 local_base_iterator end()const noexcept{return end_;}
42
43 const std::type_info* pinfo_;
44 local_base_iterator begin_,end_;
45 };
46
47 struct iterator:iterator_facade<iterator,info,std::input_iterator_tag,info>
48 {
49 iterator()=default;
50
51 private:
52 friend class segment_splitter;
53 friend class boost::iterator_core_access;
54
55 iterator(
56 base_segment_info_iterator it,
57 const PolyCollectionIterator& first,const PolyCollectionIterator& last):
58 it{it},pfirst{&first},plast{&last}{}
59 iterator(
60 const PolyCollectionIterator& first,const PolyCollectionIterator& last):
61 it{traits::base_segment_info_iterator_from(first)},
62 pfirst{&first},plast{&last}
63 {}
64
65 info dereference()const noexcept
66 {
67 return {
68 &it->type_info(),
69 it==traits::base_segment_info_iterator_from(*pfirst)?
70 traits::local_base_iterator_from(*pfirst):it->begin(),
71 it==traits::base_segment_info_iterator_from(*plast)?
72 traits::local_base_iterator_from(*plast):it->end()
73 };
74 }
75
76 bool equal(const iterator& x)const noexcept{return it==x.it;}
77 void increment()noexcept{++it;}
78
79 base_segment_info_iterator it;
80 const PolyCollectionIterator* pfirst;
81 const PolyCollectionIterator* plast;
82 };
83
84 segment_splitter(
85 const PolyCollectionIterator& first,const PolyCollectionIterator& last):
86 pfirst{&first},plast{&last}{}
87
88 iterator begin()const noexcept{return {*pfirst,*plast};}
89
90 iterator end()const noexcept
91 {
92 auto slast=traits::base_segment_info_iterator_from(*plast);
93 if(slast!=traits::end_base_segment_info_iterator_from(*plast))++slast;
94 return {slast,*plast,*plast};
95 }
96
97 private:
98 const PolyCollectionIterator* pfirst;
99 const PolyCollectionIterator* plast;
100 };
101
102 template<typename PolyCollectionIterator>
103 segment_splitter<PolyCollectionIterator>
104 segment_split(
105 const PolyCollectionIterator& first,const PolyCollectionIterator& last)
106 {
107 return {first,last};
108 }
109
110 #if 1
111 /* equivalent to for(auto i:segment_split(first,last))f(i) */
112
113 template<typename PolyCollectionIterator,typename F>
114 void for_each_segment(
115 const PolyCollectionIterator& first,const PolyCollectionIterator& last,F&& f)
116 {
117 using traits=iterator_traits<PolyCollectionIterator>;
118 using info=typename segment_splitter<PolyCollectionIterator>::info;
119
120 auto sfirst=traits::base_segment_info_iterator_from(first),
121 slast=traits::base_segment_info_iterator_from(last),
122 send=traits::end_base_segment_info_iterator_from(last);
123 auto lbfirst=traits::local_base_iterator_from(first),
124 lblast=traits::local_base_iterator_from(last);
125
126 if(sfirst!=slast){
127 for(;;){
128 f(info{&sfirst->type_info(),lbfirst,sfirst->end()});
129 ++sfirst;
130 if(sfirst==slast)break;
131 lbfirst=sfirst->begin();
132 }
133 if(sfirst!=send)f(info{&sfirst->type_info(),sfirst->begin(),lblast});
134 }
135 else if(sfirst!=send){
136 f(info{&sfirst->type_info(),lbfirst,lblast});
137 }
138 }
139 #else
140 template<typename PolyCollectionIterator,typename F>
141 void for_each_segment(
142 const PolyCollectionIterator& first,const PolyCollectionIterator& last,F&& f)
143 {
144 for(auto i:segment_split(first,last))f(i);
145 }
146 #endif
147
148 } /* namespace poly_collection::detail */
149
150 } /* namespace poly_collection */
151
152 } /* namespace boost */
153
154 #endif