]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/geometry/include/boost/geometry/iterators/ever_circling_iterator.hpp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / geometry / include / boost / geometry / iterators / ever_circling_iterator.hpp
1 // Boost.Geometry (aka GGL, Generic Geometry Library)
2
3 // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
4 // Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
5 // Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
6
7 // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
8 // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
9
10 // Use, modification and distribution is subject to the Boost Software License,
11 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
12 // http://www.boost.org/LICENSE_1_0.txt)
13
14 #ifndef BOOST_GEOMETRY_ITERATORS_EVER_CIRCLING_ITERATOR_HPP
15 #define BOOST_GEOMETRY_ITERATORS_EVER_CIRCLING_ITERATOR_HPP
16
17 #include <boost/range.hpp>
18 #include <boost/iterator.hpp>
19 #include <boost/iterator/iterator_adaptor.hpp>
20 #include <boost/iterator/iterator_categories.hpp>
21
22 #include <boost/geometry/iterators/base.hpp>
23
24 namespace boost { namespace geometry
25 {
26
27 /*!
28 \brief Iterator which ever circles through a range
29 \tparam Iterator iterator on which this class is based on
30 \ingroup iterators
31 \details If the iterator arrives at range.end() it restarts from the
32 beginning. So it has to be stopped in another way.
33 Don't call for(....; it++) because it will turn in an endless loop
34 \note Name inspired on David Bowie's
35 "Chant Of The Ever Circling Skeletal Family"
36 */
37 template <typename Iterator>
38 struct ever_circling_iterator :
39 public detail::iterators::iterator_base
40 <
41 ever_circling_iterator<Iterator>,
42 Iterator
43 >
44 {
45 friend class boost::iterator_core_access;
46
47 explicit inline ever_circling_iterator(Iterator begin, Iterator end,
48 bool skip_first = false)
49 : m_begin(begin)
50 , m_end(end)
51 , m_skip_first(skip_first)
52 {
53 this->base_reference() = begin;
54 }
55
56 explicit inline ever_circling_iterator(Iterator begin, Iterator end, Iterator start,
57 bool skip_first = false)
58 : m_begin(begin)
59 , m_end(end)
60 , m_skip_first(skip_first)
61 {
62 this->base_reference() = start;
63 }
64
65 /// Navigate to a certain position, should be in [start .. end], if at end
66 /// it will circle again.
67 inline void moveto(Iterator it)
68 {
69 this->base_reference() = it;
70 check_end();
71 }
72
73 private:
74
75 inline void increment(bool possibly_skip = true)
76 {
77 (this->base_reference())++;
78 check_end(possibly_skip);
79 }
80
81 inline void check_end(bool possibly_skip = true)
82 {
83 if (this->base() == this->m_end)
84 {
85 this->base_reference() = this->m_begin;
86 if (m_skip_first && possibly_skip)
87 {
88 increment(false);
89 }
90 }
91 }
92
93 Iterator m_begin;
94 Iterator m_end;
95 bool m_skip_first;
96 };
97
98 template <typename Range>
99 struct ever_circling_range_iterator
100 : public boost::iterator_facade
101 <
102 ever_circling_range_iterator<Range>,
103 typename boost::range_value<Range>::type const,
104 boost::random_access_traversal_tag
105 >
106 {
107 /// Constructor including the range it is based on
108 explicit inline ever_circling_range_iterator(Range& range)
109 : m_range(&range)
110 , m_iterator(boost::begin(range))
111 , m_size(boost::size(range))
112 , m_index(0)
113 {}
114
115 /// Default constructor
116 explicit inline ever_circling_range_iterator()
117 : m_range(NULL)
118 , m_size(0)
119 , m_index(0)
120 {}
121
122 typedef std::ptrdiff_t difference_type;
123
124 private:
125 friend class boost::iterator_core_access;
126
127 inline typename boost::range_value<Range>::type const& dereference() const
128 {
129 return *m_iterator;
130 }
131
132 inline difference_type distance_to(ever_circling_range_iterator<Range> const& other) const
133 {
134 return other.m_index - this->m_index;
135 }
136
137 inline bool equal(ever_circling_range_iterator<Range> const& other) const
138 {
139 return this->m_range == other.m_range
140 && this->m_index == other.m_index;
141 }
142
143 inline void increment()
144 {
145 ++m_index;
146 if (m_index >= 0 && m_index < m_size)
147 {
148 ++m_iterator;
149 }
150 else
151 {
152 update_iterator();
153 }
154 }
155
156 inline void decrement()
157 {
158 --m_index;
159 if (m_index >= 0 && m_index < m_size)
160 {
161 --m_iterator;
162 }
163 else
164 {
165 update_iterator();
166 }
167 }
168
169 inline void advance(difference_type n)
170 {
171 if (m_index >= 0 && m_index < m_size
172 && m_index + n >= 0 && m_index + n < m_size)
173 {
174 m_index += n;
175 m_iterator += n;
176 }
177 else
178 {
179 m_index += n;
180 update_iterator();
181 }
182 }
183
184 inline void update_iterator()
185 {
186 while (m_index < 0)
187 {
188 m_index += m_size;
189 }
190 m_index = m_index % m_size;
191 this->m_iterator = boost::begin(*m_range) + m_index;
192 }
193
194 Range* m_range;
195 typename boost::range_iterator<Range>::type m_iterator;
196 difference_type m_size;
197 difference_type m_index;
198 };
199
200
201 }} // namespace boost::geometry
202
203 #endif // BOOST_GEOMETRY_ITERATORS_EVER_CIRCLING_ITERATOR_HPP