File indexing completed on 2025-01-18 09:35:36
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef BOOST_GEOMETRY_ITERATORS_FLATTEN_ITERATOR_HPP
0011 #define BOOST_GEOMETRY_ITERATORS_FLATTEN_ITERATOR_HPP
0012
0013
0014 #include <type_traits>
0015
0016 #include <boost/iterator/iterator_facade.hpp>
0017 #include <boost/iterator/iterator_categories.hpp>
0018
0019 #include <boost/geometry/core/assert.hpp>
0020
0021
0022 namespace boost { namespace geometry
0023 {
0024
0025
0026
0027 template
0028 <
0029 typename OuterIterator,
0030 typename InnerIterator,
0031 typename Value,
0032 typename AccessInnerBegin,
0033 typename AccessInnerEnd,
0034 typename Reference = Value&
0035 >
0036 class flatten_iterator
0037 : public boost::iterator_facade
0038 <
0039 flatten_iterator
0040 <
0041 OuterIterator,
0042 InnerIterator,
0043 Value,
0044 AccessInnerBegin,
0045 AccessInnerEnd,
0046 Reference
0047 >,
0048 Value,
0049 boost::bidirectional_traversal_tag,
0050 Reference
0051 >
0052 {
0053 private:
0054 OuterIterator m_outer_it, m_outer_end;
0055 InnerIterator m_inner_it;
0056
0057 public:
0058 typedef OuterIterator outer_iterator_type;
0059 typedef InnerIterator inner_iterator_type;
0060
0061
0062 flatten_iterator() = default;
0063
0064
0065 flatten_iterator(OuterIterator outer_it, OuterIterator outer_end)
0066 : m_outer_it(outer_it), m_outer_end(outer_end)
0067 {
0068 advance_through_empty();
0069 }
0070
0071
0072 flatten_iterator(OuterIterator outer_end)
0073 : m_outer_it(outer_end), m_outer_end(outer_end)
0074 {}
0075
0076 template
0077 <
0078 typename OtherOuterIterator, typename OtherInnerIterator,
0079 typename OtherValue,
0080 typename OtherAccessInnerBegin, typename OtherAccessInnerEnd,
0081 typename OtherReference,
0082 std::enable_if_t
0083 <
0084 std::is_convertible<OtherOuterIterator, OuterIterator>::value
0085 && std::is_convertible<OtherInnerIterator, InnerIterator>::value,
0086 int
0087 > = 0
0088 >
0089 flatten_iterator(flatten_iterator
0090 <
0091 OtherOuterIterator,
0092 OtherInnerIterator,
0093 OtherValue,
0094 OtherAccessInnerBegin,
0095 OtherAccessInnerEnd,
0096 OtherReference
0097 > const& other)
0098 : m_outer_it(other.m_outer_it),
0099 m_outer_end(other.m_outer_end),
0100 m_inner_it(other.m_inner_it)
0101 {}
0102
0103 flatten_iterator(flatten_iterator const& other) = default;
0104
0105 flatten_iterator& operator=(flatten_iterator const& other)
0106 {
0107 m_outer_it = other.m_outer_it;
0108 m_outer_end = other.m_outer_end;
0109
0110 if ( other.m_outer_it != other.m_outer_end )
0111 {
0112 m_inner_it = other.m_inner_it;
0113 }
0114 return *this;
0115 }
0116
0117 private:
0118 friend class boost::iterator_core_access;
0119
0120 template
0121 <
0122 typename Outer,
0123 typename Inner,
0124 typename V,
0125 typename InnerBegin,
0126 typename InnerEnd,
0127 typename R
0128 >
0129 friend class flatten_iterator;
0130
0131 static inline bool empty(OuterIterator outer_it)
0132 {
0133 return AccessInnerBegin::apply(*outer_it)
0134 == AccessInnerEnd::apply(*outer_it);
0135 }
0136
0137 inline void advance_through_empty()
0138 {
0139 while ( m_outer_it != m_outer_end && empty(m_outer_it) )
0140 {
0141 ++m_outer_it;
0142 }
0143
0144 if ( m_outer_it != m_outer_end )
0145 {
0146 m_inner_it = AccessInnerBegin::apply(*m_outer_it);
0147 }
0148 }
0149
0150 inline Reference dereference() const
0151 {
0152 BOOST_GEOMETRY_ASSERT( m_outer_it != m_outer_end );
0153 BOOST_GEOMETRY_ASSERT( m_inner_it != AccessInnerEnd::apply(*m_outer_it) );
0154 return *m_inner_it;
0155 }
0156
0157
0158 template
0159 <
0160 typename OtherOuterIterator,
0161 typename OtherInnerIterator,
0162 typename OtherValue,
0163 typename OtherAccessInnerBegin,
0164 typename OtherAccessInnerEnd,
0165 typename OtherReference
0166 >
0167 inline bool equal(flatten_iterator
0168 <
0169 OtherOuterIterator,
0170 OtherInnerIterator,
0171 OtherValue,
0172 OtherAccessInnerBegin,
0173 OtherAccessInnerEnd,
0174 OtherReference
0175 > const& other) const
0176 {
0177 if ( m_outer_it != other.m_outer_it )
0178 {
0179 return false;
0180 }
0181
0182 if ( m_outer_it == m_outer_end )
0183 {
0184 return true;
0185 }
0186
0187 return m_inner_it == other.m_inner_it;
0188 }
0189
0190 inline void increment()
0191 {
0192 BOOST_GEOMETRY_ASSERT( m_outer_it != m_outer_end );
0193 BOOST_GEOMETRY_ASSERT( m_inner_it != AccessInnerEnd::apply(*m_outer_it) );
0194
0195 ++m_inner_it;
0196 if ( m_inner_it == AccessInnerEnd::apply(*m_outer_it) )
0197 {
0198 ++m_outer_it;
0199 advance_through_empty();
0200 }
0201 }
0202
0203 inline void decrement()
0204 {
0205 if ( m_outer_it == m_outer_end
0206 || m_inner_it == AccessInnerBegin::apply(*m_outer_it) )
0207 {
0208 do
0209 {
0210 --m_outer_it;
0211 }
0212 while ( empty(m_outer_it) );
0213 m_inner_it = AccessInnerEnd::apply(*m_outer_it);
0214 }
0215 --m_inner_it;
0216 }
0217 };
0218
0219
0220
0221 }}
0222
0223
0224 #endif