Chris@102
|
1 // Boost.Geometry (aka GGL, Generic Geometry Library)
|
Chris@102
|
2
|
Chris@102
|
3 // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
Chris@102
|
4
|
Chris@102
|
5 // This file was modified by Oracle on 2013, 2014, 2015.
|
Chris@102
|
6 // Modifications copyright (c) 2013-2015 Oracle and/or its affiliates.
|
Chris@102
|
7
|
Chris@102
|
8 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
Chris@102
|
9
|
Chris@102
|
10 // Use, modification and distribution is subject to the Boost Software License,
|
Chris@102
|
11 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
Chris@102
|
12 // http://www.boost.org/LICENSE_1_0.txt)
|
Chris@102
|
13
|
Chris@102
|
14 #ifndef BOOST_GEOMETRY_UTIL_RANGE_HPP
|
Chris@102
|
15 #define BOOST_GEOMETRY_UTIL_RANGE_HPP
|
Chris@102
|
16
|
Chris@102
|
17 #include <algorithm>
|
Chris@102
|
18
|
Chris@102
|
19 #include <boost/assert.hpp>
|
Chris@102
|
20 #include <boost/concept_check.hpp>
|
Chris@102
|
21 #include <boost/config.hpp>
|
Chris@102
|
22 #include <boost/range/concepts.hpp>
|
Chris@102
|
23 #include <boost/range/begin.hpp>
|
Chris@102
|
24 #include <boost/range/end.hpp>
|
Chris@102
|
25 #include <boost/range/empty.hpp>
|
Chris@102
|
26 #include <boost/range/size.hpp>
|
Chris@102
|
27 #include <boost/type_traits/is_convertible.hpp>
|
Chris@102
|
28
|
Chris@102
|
29 #include <boost/geometry/core/mutable_range.hpp>
|
Chris@102
|
30
|
Chris@102
|
31 namespace boost { namespace geometry { namespace range {
|
Chris@102
|
32
|
Chris@102
|
33 namespace detail {
|
Chris@102
|
34
|
Chris@102
|
35 // NOTE: For SinglePassRanges pos could iterate over all elements until the i-th element was met.
|
Chris@102
|
36
|
Chris@102
|
37 template <typename RandomAccessRange>
|
Chris@102
|
38 struct pos
|
Chris@102
|
39 {
|
Chris@102
|
40 typedef typename boost::range_iterator<RandomAccessRange>::type iterator;
|
Chris@102
|
41 typedef typename boost::range_size<RandomAccessRange>::type size_type;
|
Chris@102
|
42 typedef typename boost::range_difference<RandomAccessRange>::type difference_type;
|
Chris@102
|
43
|
Chris@102
|
44 static inline iterator apply(RandomAccessRange & rng, size_type i)
|
Chris@102
|
45 {
|
Chris@102
|
46 BOOST_RANGE_CONCEPT_ASSERT(( boost::RandomAccessRangeConcept<RandomAccessRange> ));
|
Chris@102
|
47 return boost::begin(rng) + static_cast<difference_type>(i);
|
Chris@102
|
48 }
|
Chris@102
|
49 };
|
Chris@102
|
50
|
Chris@102
|
51 } // namespace detail
|
Chris@102
|
52
|
Chris@102
|
53 /*!
|
Chris@102
|
54 \brief Short utility to conveniently return an iterator of a RandomAccessRange.
|
Chris@102
|
55 \ingroup utility
|
Chris@102
|
56 */
|
Chris@102
|
57 template <typename RandomAccessRange>
|
Chris@102
|
58 inline typename boost::range_iterator<RandomAccessRange const>::type
|
Chris@102
|
59 pos(RandomAccessRange const& rng,
|
Chris@102
|
60 typename boost::range_size<RandomAccessRange const>::type i)
|
Chris@102
|
61 {
|
Chris@102
|
62 BOOST_ASSERT(i <= boost::size(rng));
|
Chris@102
|
63 return detail::pos<RandomAccessRange const>::apply(rng, i);
|
Chris@102
|
64 }
|
Chris@102
|
65
|
Chris@102
|
66 /*!
|
Chris@102
|
67 \brief Short utility to conveniently return an iterator of a RandomAccessRange.
|
Chris@102
|
68 \ingroup utility
|
Chris@102
|
69 */
|
Chris@102
|
70 template <typename RandomAccessRange>
|
Chris@102
|
71 inline typename boost::range_iterator<RandomAccessRange>::type
|
Chris@102
|
72 pos(RandomAccessRange & rng,
|
Chris@102
|
73 typename boost::range_size<RandomAccessRange>::type i)
|
Chris@102
|
74 {
|
Chris@102
|
75 BOOST_ASSERT(i <= boost::size(rng));
|
Chris@102
|
76 return detail::pos<RandomAccessRange>::apply(rng, i);
|
Chris@102
|
77 }
|
Chris@102
|
78
|
Chris@102
|
79 /*!
|
Chris@102
|
80 \brief Short utility to conveniently return an element of a RandomAccessRange.
|
Chris@102
|
81 \ingroup utility
|
Chris@102
|
82 */
|
Chris@102
|
83 template <typename RandomAccessRange>
|
Chris@102
|
84 inline typename boost::range_reference<RandomAccessRange const>::type
|
Chris@102
|
85 at(RandomAccessRange const& rng,
|
Chris@102
|
86 typename boost::range_size<RandomAccessRange const>::type i)
|
Chris@102
|
87 {
|
Chris@102
|
88 BOOST_ASSERT(i < boost::size(rng));
|
Chris@102
|
89 return * detail::pos<RandomAccessRange const>::apply(rng, i);
|
Chris@102
|
90 }
|
Chris@102
|
91
|
Chris@102
|
92 /*!
|
Chris@102
|
93 \brief Short utility to conveniently return an element of a RandomAccessRange.
|
Chris@102
|
94 \ingroup utility
|
Chris@102
|
95 */
|
Chris@102
|
96 template <typename RandomAccessRange>
|
Chris@102
|
97 inline typename boost::range_reference<RandomAccessRange>::type
|
Chris@102
|
98 at(RandomAccessRange & rng,
|
Chris@102
|
99 typename boost::range_size<RandomAccessRange>::type i)
|
Chris@102
|
100 {
|
Chris@102
|
101 BOOST_ASSERT(i < boost::size(rng));
|
Chris@102
|
102 return * detail::pos<RandomAccessRange>::apply(rng, i);
|
Chris@102
|
103 }
|
Chris@102
|
104
|
Chris@102
|
105 /*!
|
Chris@102
|
106 \brief Short utility to conveniently return the front element of a Range.
|
Chris@102
|
107 \ingroup utility
|
Chris@102
|
108 */
|
Chris@102
|
109 template <typename Range>
|
Chris@102
|
110 inline typename boost::range_reference<Range const>::type
|
Chris@102
|
111 front(Range const& rng)
|
Chris@102
|
112 {
|
Chris@102
|
113 BOOST_ASSERT(!boost::empty(rng));
|
Chris@102
|
114 return *boost::begin(rng);
|
Chris@102
|
115 }
|
Chris@102
|
116
|
Chris@102
|
117 /*!
|
Chris@102
|
118 \brief Short utility to conveniently return the front element of a Range.
|
Chris@102
|
119 \ingroup utility
|
Chris@102
|
120 */
|
Chris@102
|
121 template <typename Range>
|
Chris@102
|
122 inline typename boost::range_reference<Range>::type
|
Chris@102
|
123 front(Range & rng)
|
Chris@102
|
124 {
|
Chris@102
|
125 BOOST_ASSERT(!boost::empty(rng));
|
Chris@102
|
126 return *boost::begin(rng);
|
Chris@102
|
127 }
|
Chris@102
|
128
|
Chris@102
|
129 // NOTE: For SinglePassRanges back() could iterate over all elements until the last element is met.
|
Chris@102
|
130
|
Chris@102
|
131 /*!
|
Chris@102
|
132 \brief Short utility to conveniently return the back element of a BidirectionalRange.
|
Chris@102
|
133 \ingroup utility
|
Chris@102
|
134 */
|
Chris@102
|
135 template <typename BidirectionalRange>
|
Chris@102
|
136 inline typename boost::range_reference<BidirectionalRange const>::type
|
Chris@102
|
137 back(BidirectionalRange const& rng)
|
Chris@102
|
138 {
|
Chris@102
|
139 BOOST_RANGE_CONCEPT_ASSERT(( boost::BidirectionalRangeConcept<BidirectionalRange const> ));
|
Chris@102
|
140 BOOST_ASSERT(!boost::empty(rng));
|
Chris@102
|
141 return *(boost::rbegin(rng));
|
Chris@102
|
142 }
|
Chris@102
|
143
|
Chris@102
|
144 /*!
|
Chris@102
|
145 \brief Short utility to conveniently return the back element of a BidirectionalRange.
|
Chris@102
|
146 \ingroup utility
|
Chris@102
|
147 */
|
Chris@102
|
148 template <typename BidirectionalRange>
|
Chris@102
|
149 inline typename boost::range_reference<BidirectionalRange>::type
|
Chris@102
|
150 back(BidirectionalRange & rng)
|
Chris@102
|
151 {
|
Chris@102
|
152 BOOST_RANGE_CONCEPT_ASSERT((boost::BidirectionalRangeConcept<BidirectionalRange>));
|
Chris@102
|
153 BOOST_ASSERT(!boost::empty(rng));
|
Chris@102
|
154 return *(boost::rbegin(rng));
|
Chris@102
|
155 }
|
Chris@102
|
156
|
Chris@102
|
157
|
Chris@102
|
158 /*!
|
Chris@102
|
159 \brief Short utility to conveniently clear a mutable range.
|
Chris@102
|
160 It uses traits::clear<>.
|
Chris@102
|
161 \ingroup utility
|
Chris@102
|
162 */
|
Chris@102
|
163 template <typename Range>
|
Chris@102
|
164 inline void clear(Range & rng)
|
Chris@102
|
165 {
|
Chris@102
|
166 // NOTE: this trait is probably not needed since it could be implemented using resize()
|
Chris@102
|
167 geometry::traits::clear<Range>::apply(rng);
|
Chris@102
|
168 }
|
Chris@102
|
169
|
Chris@102
|
170 /*!
|
Chris@102
|
171 \brief Short utility to conveniently insert a new element at the end of a mutable range.
|
Chris@102
|
172 It uses boost::geometry::traits::push_back<>.
|
Chris@102
|
173 \ingroup utility
|
Chris@102
|
174 */
|
Chris@102
|
175 template <typename Range>
|
Chris@102
|
176 inline void push_back(Range & rng,
|
Chris@102
|
177 typename boost::range_value<Range>::type const& value)
|
Chris@102
|
178 {
|
Chris@102
|
179 geometry::traits::push_back<Range>::apply(rng, value);
|
Chris@102
|
180 }
|
Chris@102
|
181
|
Chris@102
|
182 /*!
|
Chris@102
|
183 \brief Short utility to conveniently resize a mutable range.
|
Chris@102
|
184 It uses boost::geometry::traits::resize<>.
|
Chris@102
|
185 \ingroup utility
|
Chris@102
|
186 */
|
Chris@102
|
187 template <typename Range>
|
Chris@102
|
188 inline void resize(Range & rng,
|
Chris@102
|
189 typename boost::range_size<Range>::type new_size)
|
Chris@102
|
190 {
|
Chris@102
|
191 geometry::traits::resize<Range>::apply(rng, new_size);
|
Chris@102
|
192 }
|
Chris@102
|
193
|
Chris@102
|
194
|
Chris@102
|
195 /*!
|
Chris@102
|
196 \brief Short utility to conveniently remove an element from the back of a mutable range.
|
Chris@102
|
197 It uses resize().
|
Chris@102
|
198 \ingroup utility
|
Chris@102
|
199 */
|
Chris@102
|
200 template <typename Range>
|
Chris@102
|
201 inline void pop_back(Range & rng)
|
Chris@102
|
202 {
|
Chris@102
|
203 BOOST_ASSERT(!boost::empty(rng));
|
Chris@102
|
204 range::resize(rng, boost::size(rng) - 1);
|
Chris@102
|
205 }
|
Chris@102
|
206
|
Chris@102
|
207 namespace detail {
|
Chris@102
|
208
|
Chris@102
|
209 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
Chris@102
|
210
|
Chris@102
|
211 template <typename It,
|
Chris@102
|
212 typename OutIt,
|
Chris@102
|
213 bool UseMove = boost::is_convertible
|
Chris@102
|
214 <
|
Chris@102
|
215 typename std::iterator_traits<It>::value_type &&,
|
Chris@102
|
216 typename std::iterator_traits<OutIt>::value_type
|
Chris@102
|
217 >::value>
|
Chris@102
|
218 struct copy_or_move_impl
|
Chris@102
|
219 {
|
Chris@102
|
220 static inline OutIt apply(It first, It last, OutIt out)
|
Chris@102
|
221 {
|
Chris@102
|
222 return std::move(first, last, out);
|
Chris@102
|
223 }
|
Chris@102
|
224 };
|
Chris@102
|
225
|
Chris@102
|
226 template <typename It, typename OutIt>
|
Chris@102
|
227 struct copy_or_move_impl<It, OutIt, false>
|
Chris@102
|
228 {
|
Chris@102
|
229 static inline OutIt apply(It first, It last, OutIt out)
|
Chris@102
|
230 {
|
Chris@102
|
231 return std::copy(first, last, out);
|
Chris@102
|
232 }
|
Chris@102
|
233 };
|
Chris@102
|
234
|
Chris@102
|
235 template <typename It, typename OutIt>
|
Chris@102
|
236 inline OutIt copy_or_move(It first, It last, OutIt out)
|
Chris@102
|
237 {
|
Chris@102
|
238 return copy_or_move_impl<It, OutIt>::apply(first, last, out);
|
Chris@102
|
239 }
|
Chris@102
|
240
|
Chris@102
|
241 #else
|
Chris@102
|
242
|
Chris@102
|
243 template <typename It, typename OutIt>
|
Chris@102
|
244 inline OutIt copy_or_move(It first, It last, OutIt out)
|
Chris@102
|
245 {
|
Chris@102
|
246 return std::copy(first, last, out);
|
Chris@102
|
247 }
|
Chris@102
|
248
|
Chris@102
|
249 #endif
|
Chris@102
|
250
|
Chris@102
|
251 } // namespace detail
|
Chris@102
|
252
|
Chris@102
|
253 /*!
|
Chris@102
|
254 \brief Short utility to conveniently remove an element from a mutable range.
|
Chris@102
|
255 It uses std::copy() and resize(). Version taking mutable iterators.
|
Chris@102
|
256 \ingroup utility
|
Chris@102
|
257 */
|
Chris@102
|
258 template <typename Range>
|
Chris@102
|
259 inline typename boost::range_iterator<Range>::type
|
Chris@102
|
260 erase(Range & rng,
|
Chris@102
|
261 typename boost::range_iterator<Range>::type it)
|
Chris@102
|
262 {
|
Chris@102
|
263 BOOST_ASSERT(!boost::empty(rng));
|
Chris@102
|
264 BOOST_ASSERT(it != boost::end(rng));
|
Chris@102
|
265
|
Chris@102
|
266 typename boost::range_difference<Range>::type const
|
Chris@102
|
267 d = std::distance(boost::begin(rng), it);
|
Chris@102
|
268
|
Chris@102
|
269 typename boost::range_iterator<Range>::type
|
Chris@102
|
270 next = it;
|
Chris@102
|
271 ++next;
|
Chris@102
|
272
|
Chris@102
|
273 detail::copy_or_move(next, boost::end(rng), it);
|
Chris@102
|
274 range::resize(rng, boost::size(rng) - 1);
|
Chris@102
|
275
|
Chris@102
|
276 // NOTE: In general this should be sufficient:
|
Chris@102
|
277 // return it;
|
Chris@102
|
278 // But in MSVC using the returned iterator causes
|
Chris@102
|
279 // assertion failures when iterator debugging is enabled
|
Chris@102
|
280 // Furthermore the code below should work in the case if resize()
|
Chris@102
|
281 // invalidates iterators when the container is resized down.
|
Chris@102
|
282 return boost::begin(rng) + d;
|
Chris@102
|
283 }
|
Chris@102
|
284
|
Chris@102
|
285 /*!
|
Chris@102
|
286 \brief Short utility to conveniently remove an element from a mutable range.
|
Chris@102
|
287 It uses std::copy() and resize(). Version taking non-mutable iterators.
|
Chris@102
|
288 \ingroup utility
|
Chris@102
|
289 */
|
Chris@102
|
290 template <typename Range>
|
Chris@102
|
291 inline typename boost::range_iterator<Range>::type
|
Chris@102
|
292 erase(Range & rng,
|
Chris@102
|
293 typename boost::range_iterator<Range const>::type cit)
|
Chris@102
|
294 {
|
Chris@102
|
295 BOOST_RANGE_CONCEPT_ASSERT(( boost::RandomAccessRangeConcept<Range> ));
|
Chris@102
|
296
|
Chris@102
|
297 typename boost::range_iterator<Range>::type
|
Chris@102
|
298 it = boost::begin(rng)
|
Chris@102
|
299 + std::distance(boost::const_begin(rng), cit);
|
Chris@102
|
300
|
Chris@102
|
301 return erase(rng, it);
|
Chris@102
|
302 }
|
Chris@102
|
303
|
Chris@102
|
304 /*!
|
Chris@102
|
305 \brief Short utility to conveniently remove a range of elements from a mutable range.
|
Chris@102
|
306 It uses std::copy() and resize(). Version taking mutable iterators.
|
Chris@102
|
307 \ingroup utility
|
Chris@102
|
308 */
|
Chris@102
|
309 template <typename Range>
|
Chris@102
|
310 inline typename boost::range_iterator<Range>::type
|
Chris@102
|
311 erase(Range & rng,
|
Chris@102
|
312 typename boost::range_iterator<Range>::type first,
|
Chris@102
|
313 typename boost::range_iterator<Range>::type last)
|
Chris@102
|
314 {
|
Chris@102
|
315 typename boost::range_difference<Range>::type const
|
Chris@102
|
316 diff = std::distance(first, last);
|
Chris@102
|
317 BOOST_ASSERT(diff >= 0);
|
Chris@102
|
318
|
Chris@102
|
319 std::size_t const count = static_cast<std::size_t>(diff);
|
Chris@102
|
320 BOOST_ASSERT(count <= boost::size(rng));
|
Chris@102
|
321
|
Chris@102
|
322 if ( count > 0 )
|
Chris@102
|
323 {
|
Chris@102
|
324 typename boost::range_difference<Range>::type const
|
Chris@102
|
325 d = std::distance(boost::begin(rng), first);
|
Chris@102
|
326
|
Chris@102
|
327 detail::copy_or_move(last, boost::end(rng), first);
|
Chris@102
|
328 range::resize(rng, boost::size(rng) - count);
|
Chris@102
|
329
|
Chris@102
|
330 // NOTE: In general this should be sufficient:
|
Chris@102
|
331 // return first;
|
Chris@102
|
332 // But in MSVC using the returned iterator causes
|
Chris@102
|
333 // assertion failures when iterator debugging is enabled
|
Chris@102
|
334 // Furthermore the code below should work in the case if resize()
|
Chris@102
|
335 // invalidates iterators when the container is resized down.
|
Chris@102
|
336 return boost::begin(rng) + d;
|
Chris@102
|
337 }
|
Chris@102
|
338
|
Chris@102
|
339 return first;
|
Chris@102
|
340 }
|
Chris@102
|
341
|
Chris@102
|
342 /*!
|
Chris@102
|
343 \brief Short utility to conveniently remove a range of elements from a mutable range.
|
Chris@102
|
344 It uses std::copy() and resize(). Version taking non-mutable iterators.
|
Chris@102
|
345 \ingroup utility
|
Chris@102
|
346 */
|
Chris@102
|
347 template <typename Range>
|
Chris@102
|
348 inline typename boost::range_iterator<Range>::type
|
Chris@102
|
349 erase(Range & rng,
|
Chris@102
|
350 typename boost::range_iterator<Range const>::type cfirst,
|
Chris@102
|
351 typename boost::range_iterator<Range const>::type clast)
|
Chris@102
|
352 {
|
Chris@102
|
353 BOOST_RANGE_CONCEPT_ASSERT(( boost::RandomAccessRangeConcept<Range> ));
|
Chris@102
|
354
|
Chris@102
|
355 typename boost::range_iterator<Range>::type
|
Chris@102
|
356 first = boost::begin(rng)
|
Chris@102
|
357 + std::distance(boost::const_begin(rng), cfirst);
|
Chris@102
|
358 typename boost::range_iterator<Range>::type
|
Chris@102
|
359 last = boost::begin(rng)
|
Chris@102
|
360 + std::distance(boost::const_begin(rng), clast);
|
Chris@102
|
361
|
Chris@102
|
362 return erase(rng, first, last);
|
Chris@102
|
363 }
|
Chris@102
|
364
|
Chris@102
|
365 }}} // namespace boost::geometry::range
|
Chris@102
|
366
|
Chris@102
|
367 #endif // BOOST_GEOMETRY_UTIL_RANGE_HPP
|