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