]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/geometry/include/boost/geometry/iterators/flatten_iterator.hpp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / geometry / include / boost / geometry / iterators / flatten_iterator.hpp
1 // Boost.Geometry (aka GGL, Generic Geometry Library)
2
3 // Copyright (c) 2014, Oracle and/or its affiliates.
4
5 // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
6
7 // Licensed under the Boost Software License version 1.0.
8 // http://www.boost.org/users/license.html
9
10 #ifndef BOOST_GEOMETRY_ITERATORS_FLATTEN_ITERATOR_HPP
11 #define BOOST_GEOMETRY_ITERATORS_FLATTEN_ITERATOR_HPP
12
13 #include <boost/mpl/assert.hpp>
14 #include <boost/type_traits/is_convertible.hpp>
15 #include <boost/iterator.hpp>
16 #include <boost/iterator/iterator_facade.hpp>
17 #include <boost/iterator/iterator_categories.hpp>
18
19 #include <boost/geometry/core/assert.hpp>
20
21 namespace boost { namespace geometry
22 {
23
24
25
26 template
27 <
28 typename OuterIterator,
29 typename InnerIterator,
30 typename Value,
31 typename AccessInnerBegin,
32 typename AccessInnerEnd,
33 typename Reference = Value&
34 >
35 class flatten_iterator
36 : public boost::iterator_facade
37 <
38 flatten_iterator
39 <
40 OuterIterator,
41 InnerIterator,
42 Value,
43 AccessInnerBegin,
44 AccessInnerEnd,
45 Reference
46 >,
47 Value,
48 boost::bidirectional_traversal_tag,
49 Reference
50 >
51 {
52 private:
53 OuterIterator m_outer_it, m_outer_end;
54 InnerIterator m_inner_it;
55
56 public:
57 typedef OuterIterator outer_iterator_type;
58 typedef InnerIterator inner_iterator_type;
59
60 // default constructor
61 flatten_iterator() {}
62
63 // for begin
64 flatten_iterator(OuterIterator outer_it, OuterIterator outer_end)
65 : m_outer_it(outer_it), m_outer_end(outer_end)
66 {
67 advance_through_empty();
68 }
69
70 // for end
71 flatten_iterator(OuterIterator outer_end)
72 : m_outer_it(outer_end), m_outer_end(outer_end)
73 {}
74
75 template
76 <
77 typename OtherOuterIterator, typename OtherInnerIterator,
78 typename OtherValue,
79 typename OtherAccessInnerBegin, typename OtherAccessInnerEnd,
80 typename OtherReference
81 >
82 flatten_iterator(flatten_iterator
83 <
84 OtherOuterIterator,
85 OtherInnerIterator,
86 OtherValue,
87 OtherAccessInnerBegin,
88 OtherAccessInnerEnd,
89 OtherReference
90 > const& other)
91 : m_outer_it(other.m_outer_it),
92 m_outer_end(other.m_outer_end),
93 m_inner_it(other.m_inner_it)
94 {
95 static const bool are_conv
96 = boost::is_convertible
97 <
98 OtherOuterIterator, OuterIterator
99 >::value
100 && boost::is_convertible
101 <
102 OtherInnerIterator, InnerIterator
103 >::value;
104
105 BOOST_MPL_ASSERT_MSG((are_conv),
106 NOT_CONVERTIBLE,
107 (types<OtherOuterIterator, OtherInnerIterator>));
108 }
109
110 flatten_iterator& operator=(flatten_iterator const& other)
111 {
112 m_outer_it = other.m_outer_it;
113 m_outer_end = other.m_outer_end;
114 // avoid assigning an iterator having singular value
115 if ( other.m_outer_it != other.m_outer_end )
116 {
117 m_inner_it = other.m_inner_it;
118 }
119 return *this;
120 }
121
122 private:
123 friend class boost::iterator_core_access;
124
125 template
126 <
127 typename Outer,
128 typename Inner,
129 typename V,
130 typename InnerBegin,
131 typename InnerEnd,
132 typename R
133 >
134 friend class flatten_iterator;
135
136 static inline bool empty(OuterIterator outer_it)
137 {
138 return AccessInnerBegin::apply(*outer_it)
139 == AccessInnerEnd::apply(*outer_it);
140 }
141
142 inline void advance_through_empty()
143 {
144 while ( m_outer_it != m_outer_end && empty(m_outer_it) )
145 {
146 ++m_outer_it;
147 }
148
149 if ( m_outer_it != m_outer_end )
150 {
151 m_inner_it = AccessInnerBegin::apply(*m_outer_it);
152 }
153 }
154
155 inline Reference dereference() const
156 {
157 BOOST_GEOMETRY_ASSERT( m_outer_it != m_outer_end );
158 BOOST_GEOMETRY_ASSERT( m_inner_it != AccessInnerEnd::apply(*m_outer_it) );
159 return *m_inner_it;
160 }
161
162
163 template
164 <
165 typename OtherOuterIterator,
166 typename OtherInnerIterator,
167 typename OtherValue,
168 typename OtherAccessInnerBegin,
169 typename OtherAccessInnerEnd,
170 typename OtherReference
171 >
172 inline bool equal(flatten_iterator
173 <
174 OtherOuterIterator,
175 OtherInnerIterator,
176 OtherValue,
177 OtherAccessInnerBegin,
178 OtherAccessInnerEnd,
179 OtherReference
180 > const& other) const
181 {
182 if ( m_outer_it != other.m_outer_it )
183 {
184 return false;
185 }
186
187 if ( m_outer_it == m_outer_end )
188 {
189 return true;
190 }
191
192 return m_inner_it == other.m_inner_it;
193 }
194
195 inline void increment()
196 {
197 BOOST_GEOMETRY_ASSERT( m_outer_it != m_outer_end );
198 BOOST_GEOMETRY_ASSERT( m_inner_it != AccessInnerEnd::apply(*m_outer_it) );
199
200 ++m_inner_it;
201 if ( m_inner_it == AccessInnerEnd::apply(*m_outer_it) )
202 {
203 ++m_outer_it;
204 advance_through_empty();
205 }
206 }
207
208 inline void decrement()
209 {
210 if ( m_outer_it == m_outer_end
211 || m_inner_it == AccessInnerBegin::apply(*m_outer_it) )
212 {
213 do
214 {
215 --m_outer_it;
216 }
217 while ( empty(m_outer_it) );
218 m_inner_it = AccessInnerEnd::apply(*m_outer_it);
219 }
220 --m_inner_it;
221 }
222 };
223
224
225
226 }} // namespace boost::geometry
227
228
229 #endif // BOOST_GEOMETRY_ITERATORS_FLATTEN_ITERATOR_HPP