]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // Boost.Geometry (aka GGL, Generic Geometry Library) |
2 | ||
20effc67 | 3 | // Copyright (c) 2014-2020, Oracle and/or its affiliates. |
7c673cae | 4 | // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle |
20effc67 | 5 | // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle |
7c673cae FG |
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 | ||
20effc67 TL |
13 | #include <type_traits> |
14 | ||
7c673cae FG |
15 | #include <boost/iterator/iterator_facade.hpp> |
16 | #include <boost/iterator/iterator_categories.hpp> | |
17 | ||
18 | #include <boost/geometry/core/assert.hpp> | |
20effc67 | 19 | #include <boost/geometry/core/static_assert.hpp> |
7c673cae FG |
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 | |
20effc67 | 96 | = std::is_convertible |
7c673cae FG |
97 | < |
98 | OtherOuterIterator, OuterIterator | |
99 | >::value | |
20effc67 | 100 | && std::is_convertible |
7c673cae FG |
101 | < |
102 | OtherInnerIterator, InnerIterator | |
103 | >::value; | |
104 | ||
20effc67 TL |
105 | BOOST_GEOMETRY_STATIC_ASSERT((are_conv), |
106 | "Other iterators have to be convertible to member iterators.", | |
107 | OtherOuterIterator, OtherInnerIterator); | |
7c673cae FG |
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 |