File indexing completed on 2025-01-18 09:35:36
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018 #ifndef BOOST_GEOMETRY_ITERATORS_EVER_CIRCLING_ITERATOR_HPP
0019 #define BOOST_GEOMETRY_ITERATORS_EVER_CIRCLING_ITERATOR_HPP
0020
0021
0022 #include <type_traits>
0023
0024 #include <boost/iterator/iterator_adaptor.hpp>
0025 #include <boost/iterator/iterator_categories.hpp>
0026 #include <boost/range/begin.hpp>
0027 #include <boost/range/difference_type.hpp>
0028 #include <boost/range/reference.hpp>
0029 #include <boost/range/size.hpp>
0030 #include <boost/range/value_type.hpp>
0031
0032 #include <boost/geometry/core/assert.hpp>
0033
0034 #include <boost/geometry/iterators/detail/iterator_base.hpp>
0035
0036
0037 namespace boost { namespace geometry
0038 {
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050 template <typename Iterator>
0051 struct ever_circling_iterator :
0052 public detail::iterators::iterator_base
0053 <
0054 ever_circling_iterator<Iterator>,
0055 Iterator
0056 >
0057 {
0058 ever_circling_iterator() = default;
0059
0060 explicit inline ever_circling_iterator(Iterator begin, Iterator end,
0061 bool skip_first = false)
0062 : m_begin(begin)
0063 , m_end(end)
0064 , m_skip_first(skip_first)
0065 {
0066 this->base_reference() = begin;
0067 }
0068
0069 explicit inline ever_circling_iterator(Iterator begin, Iterator end, Iterator start,
0070 bool skip_first = false)
0071 : m_begin(begin)
0072 , m_end(end)
0073 , m_skip_first(skip_first)
0074 {
0075 this->base_reference() = start;
0076 }
0077
0078 template
0079 <
0080 typename OtherIterator,
0081 std::enable_if_t<std::is_convertible<OtherIterator, Iterator>::value, int> = 0
0082 >
0083 inline ever_circling_iterator(ever_circling_iterator<OtherIterator> const& other)
0084 : m_begin(other.m_begin)
0085 , m_end(other.m_end)
0086 , m_skip_first(other.m_skip_first)
0087 {}
0088
0089
0090
0091 inline void moveto(Iterator it)
0092 {
0093 this->base_reference() = it;
0094 check_end();
0095 }
0096
0097 private:
0098 template <typename OtherIterator> friend struct ever_circling_iterator;
0099 friend class boost::iterator_core_access;
0100
0101 inline void increment(bool possibly_skip = true)
0102 {
0103 (this->base_reference())++;
0104 check_end(possibly_skip);
0105 }
0106
0107 inline void check_end(bool possibly_skip = true)
0108 {
0109 if (this->base() == this->m_end)
0110 {
0111 this->base_reference() = this->m_begin;
0112 if (m_skip_first && possibly_skip)
0113 {
0114 increment(false);
0115 }
0116 }
0117 }
0118
0119 Iterator m_begin;
0120 Iterator m_end;
0121 bool m_skip_first;
0122 };
0123
0124 template <typename Range>
0125 struct ever_circling_range_iterator
0126 : public boost::iterator_facade
0127 <
0128 ever_circling_range_iterator<Range>,
0129 typename boost::range_value<Range>::type const,
0130 boost::random_access_traversal_tag,
0131 typename boost::range_reference<Range const>::type,
0132 typename boost::range_difference<Range>::type
0133 >
0134 {
0135 private:
0136 typedef boost::iterator_facade
0137 <
0138 ever_circling_range_iterator<Range>,
0139 typename boost::range_value<Range>::type const,
0140 boost::random_access_traversal_tag,
0141 typename boost::range_reference<Range const>::type,
0142 typename boost::range_difference<Range>::type
0143 > base_type;
0144
0145 public:
0146
0147 explicit inline ever_circling_range_iterator(Range const& range)
0148 : m_begin(boost::begin(range))
0149 , m_iterator(boost::begin(range))
0150 , m_size(boost::size(range))
0151 , m_index(0)
0152 {}
0153
0154
0155 explicit inline ever_circling_range_iterator()
0156 : m_size(0)
0157 , m_index(0)
0158 {}
0159
0160 template
0161 <
0162 typename OtherRange,
0163 std::enable_if_t
0164 <
0165 std::is_convertible
0166 <
0167 typename boost::range_iterator<OtherRange const>::type,
0168 typename boost::range_iterator<Range const>::type
0169 >::value,
0170 int
0171 > = 0
0172 >
0173 inline ever_circling_range_iterator(ever_circling_range_iterator<OtherRange> const& other)
0174 : m_begin(other.m_begin)
0175 , m_iterator(other.m_iterator)
0176 , m_size(other.m_size)
0177 , m_index(other.m_index)
0178 {}
0179
0180 typedef typename base_type::reference reference;
0181 typedef typename base_type::difference_type difference_type;
0182
0183 private:
0184 template <typename OtherRange> friend struct ever_circling_range_iterator;
0185 friend class boost::iterator_core_access;
0186
0187 inline reference dereference() const
0188 {
0189 return *m_iterator;
0190 }
0191
0192 inline difference_type distance_to(ever_circling_range_iterator<Range> const& other) const
0193 {
0194 return other.m_index - this->m_index;
0195 }
0196
0197 inline bool equal(ever_circling_range_iterator<Range> const& other) const
0198 {
0199 BOOST_GEOMETRY_ASSERT(m_begin == other.m_begin);
0200 return this->m_index == other.m_index;
0201 }
0202
0203 inline void increment()
0204 {
0205 ++m_index;
0206 if (m_index >= 0 && m_index < m_size)
0207 {
0208 ++m_iterator;
0209 }
0210 else
0211 {
0212 update_iterator();
0213 }
0214 }
0215
0216 inline void decrement()
0217 {
0218 --m_index;
0219 if (m_index >= 0 && m_index < m_size)
0220 {
0221 --m_iterator;
0222 }
0223 else
0224 {
0225 update_iterator();
0226 }
0227 }
0228
0229 inline void advance(difference_type n)
0230 {
0231 if (m_index >= 0 && m_index < m_size
0232 && m_index + n >= 0 && m_index + n < m_size)
0233 {
0234 m_index += n;
0235 m_iterator += n;
0236 }
0237 else
0238 {
0239 m_index += n;
0240 update_iterator();
0241 }
0242 }
0243
0244 inline void update_iterator()
0245 {
0246 while (m_index < 0)
0247 {
0248 m_index += m_size;
0249 }
0250 m_index = m_index % m_size;
0251 this->m_iterator = m_begin + m_index;
0252 }
0253
0254 typename boost::range_iterator<Range const>::type m_begin;
0255 typename boost::range_iterator<Range const>::type m_iterator;
0256 difference_type m_size;
0257 difference_type m_index;
0258 };
0259
0260
0261 }}
0262
0263 #endif