1 // Boost.Geometry (aka GGL, Generic Geometry Library)
3 // Copyright (c) 2014, Oracle and/or its affiliates.
5 // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
7 // Licensed under the Boost Software License version 1.0.
8 // http://www.boost.org/users/license.html
10 #ifndef BOOST_GEOMETRY_ITERATORS_FLATTEN_ITERATOR_HPP
11 #define BOOST_GEOMETRY_ITERATORS_FLATTEN_ITERATOR_HPP
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>
19 #include <boost/geometry/core/assert.hpp>
21 namespace boost { namespace geometry
28 typename OuterIterator,
29 typename InnerIterator,
31 typename AccessInnerBegin,
32 typename AccessInnerEnd,
33 typename Reference = Value&
35 class flatten_iterator
36 : public boost::iterator_facade
48 boost::bidirectional_traversal_tag,
53 OuterIterator m_outer_it, m_outer_end;
54 InnerIterator m_inner_it;
57 typedef OuterIterator outer_iterator_type;
58 typedef InnerIterator inner_iterator_type;
60 // default constructor
64 flatten_iterator(OuterIterator outer_it, OuterIterator outer_end)
65 : m_outer_it(outer_it), m_outer_end(outer_end)
67 advance_through_empty();
71 flatten_iterator(OuterIterator outer_end)
72 : m_outer_it(outer_end), m_outer_end(outer_end)
77 typename OtherOuterIterator, typename OtherInnerIterator,
79 typename OtherAccessInnerBegin, typename OtherAccessInnerEnd,
80 typename OtherReference
82 flatten_iterator(flatten_iterator
87 OtherAccessInnerBegin,
91 : m_outer_it(other.m_outer_it),
92 m_outer_end(other.m_outer_end),
93 m_inner_it(other.m_inner_it)
95 static const bool are_conv
96 = boost::is_convertible
98 OtherOuterIterator, OuterIterator
100 && boost::is_convertible
102 OtherInnerIterator, InnerIterator
105 BOOST_MPL_ASSERT_MSG((are_conv),
107 (types<OtherOuterIterator, OtherInnerIterator>));
110 flatten_iterator& operator=(flatten_iterator const& other)
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 )
117 m_inner_it = other.m_inner_it;
123 friend class boost::iterator_core_access;
134 friend class flatten_iterator;
136 static inline bool empty(OuterIterator outer_it)
138 return AccessInnerBegin::apply(*outer_it)
139 == AccessInnerEnd::apply(*outer_it);
142 inline void advance_through_empty()
144 while ( m_outer_it != m_outer_end && empty(m_outer_it) )
149 if ( m_outer_it != m_outer_end )
151 m_inner_it = AccessInnerBegin::apply(*m_outer_it);
155 inline Reference dereference() const
157 BOOST_GEOMETRY_ASSERT( m_outer_it != m_outer_end );
158 BOOST_GEOMETRY_ASSERT( m_inner_it != AccessInnerEnd::apply(*m_outer_it) );
165 typename OtherOuterIterator,
166 typename OtherInnerIterator,
168 typename OtherAccessInnerBegin,
169 typename OtherAccessInnerEnd,
170 typename OtherReference
172 inline bool equal(flatten_iterator
177 OtherAccessInnerBegin,
180 > const& other) const
182 if ( m_outer_it != other.m_outer_it )
187 if ( m_outer_it == m_outer_end )
192 return m_inner_it == other.m_inner_it;
195 inline void increment()
197 BOOST_GEOMETRY_ASSERT( m_outer_it != m_outer_end );
198 BOOST_GEOMETRY_ASSERT( m_inner_it != AccessInnerEnd::apply(*m_outer_it) );
201 if ( m_inner_it == AccessInnerEnd::apply(*m_outer_it) )
204 advance_through_empty();
208 inline void decrement()
210 if ( m_outer_it == m_outer_end
211 || m_inner_it == AccessInnerBegin::apply(*m_outer_it) )
217 while ( empty(m_outer_it) );
218 m_inner_it = AccessInnerEnd::apply(*m_outer_it);
226 }} // namespace boost::geometry
229 #endif // BOOST_GEOMETRY_ITERATORS_FLATTEN_ITERATOR_HPP