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