Adobe Source Libraries 1.49.0
A collection of C++ libraries.
Loading...
Searching...
No Matches
iterator.hpp
Go to the documentation of this file.
1/*
2 Copyright 2013 Adobe
3 Distributed under the Boost Software License, Version 1.0.
4 (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5*/
6/**************************************************************************************************/
7
8#ifndef ADOBE_ITERATOR_HPP
9#define ADOBE_ITERATOR_HPP
10
11#include <adobe/config.hpp>
12
13/*
14 NOTE (sparent) : GCC 3.1 defines std::distance in <algorithm> instead of <iterator> so we go
15 ahead and include both here to work around the issue.
16*/
17
18#include <algorithm>
19#include <cassert>
20#include <iterator>
21#include <utility>
22
23#include <boost/range.hpp>
24
25#include <boost/iterator/iterator_facade.hpp>
26#include <boost/iterator/iterator_traits.hpp>
27
28#include <adobe/empty.hpp>
29#include <adobe/typeinfo.hpp>
30
31#include <adobe/implementation/swap.hpp>
32
33namespace adobe {
34
35/**************************************************************************************************/
36
37/*
38 Just counts the number of outputs; doesn't copy anything. More efficient than a
39 back_insert_iterator into a container if all you're interested in is the size of
40 the result.
41*/
42
43/**************************************************************************************************/
44
50public:
51 typedef std::output_iterator_tag iterator_category;
54 typedef std::size_t size_type;
55
56 counting_output_iterator() : count_m(0) {}
57
58 counting_output_iterator(const counting_output_iterator& x) : count_m(x.count_m) {}
59
60 size_type count() const { return count_m; }
61
62 template <typename T>
63 reference operator=(const T&) {
64 return *this;
65 }
66
67 reference operator*() { return *this; }
68
69 bool operator==(counting_output_iterator const& rhs) const { return this == &rhs; }
70
72 ++count_m;
73 return *this;
74 }
75
77 ++count_m;
78 return *this;
79 }
80
81private:
82 std::size_t count_m;
83};
84
85/**************************************************************************************************/
86
87/*
88 top iterator bottom iterator
89
90 random access random access bidirectional
91 bidirectional random access bidirectional
92 forward random access forward
93 input random access forward
94 output random access ???
95
96 random access bidirectional bidirectional
97 bidirectional bidirectional bidirectional
98 forward bidirectional forward
99 input bidirectional forward
100 output bidirectional ???
101
102 random access forward forward
103 bidirectional forward forward
104 forward forward forward
105 input forward forward
106 output forward ???
107
108 random access input input
109 bidirectional input input
110 forward input input
111 input input input
112 output input ???
113
114 random access output output
115 bidirectional output output
116 forward output output
117 input output output
118 output output ???
119
120
121 if (catgory(bottom) == bidirectional && catgory(top) == bidirectional) return bidirectional
122 else if (catgory(bottom) == forward) return forward
123 else return category(bottom)
124*/
125
126template <typename I> // I models an InputIterator where value_type(I) models Range
128 : public boost::iterator_facade<
129 segmented_iterator<I>,
130 typename boost::range_value<typename boost::iterator_value<I>::type>::type,
131 std::bidirectional_iterator_tag,
132 typename boost::iterator_reference<
133 typename boost::range_iterator<typename boost::iterator_value<I>::type>::type>::type,
134 typename boost::iterator_difference<typename boost::range_iterator<
135 typename boost::iterator_value<I>::type>::type>::type> {
136public:
137 segmented_iterator() : bucket_m(), end_m(), current_m() {}
138 segmented_iterator(I first, I last) : bucket_m(first), end_m(last) {
139 while (bucket_m != end_m && boost::empty(*bucket_m)) {
140 ++bucket_m;
141 }
142 if (bucket_m != end_m)
143 current_m = boost::begin(*bucket_m);
144 }
145
147 : bucket_m(x.bucket_m), end_m(x.end_m), current_m(x.current_m) {}
148
150 swap(*this, x);
151 return *this;
152 }
153
154 friend inline void swap(segmented_iterator& x, segmented_iterator& y) {
155 swap(x.bucket_m, y.bucket_m);
156 swap(x.end_m, y.end_m);
157 swap(x.curent_m, y.curent_m);
158 }
159
160private:
161 typedef typename boost::iterator_reference<
162 typename boost::range_iterator<typename boost::iterator_value<I>::type>::type>::type
163 reference_t;
164 typedef I top_iterator_t;
165 typedef typename boost::range_iterator<typename boost::iterator_value<I>::type>::type
166 bottom_iterator_t;
167
168 top_iterator_t bucket_m;
169 top_iterator_t end_m;
170 bottom_iterator_t current_m;
171
172 // boost iterator_facade access functions
173
175
176 reference_t dereference() const { return *current_m; }
177
178 bool equal(const segmented_iterator& x) const {
179 /*
180 If the end of the top sequences are the same and we are in the same bucket then if we are
181 at the very end or we are at the same local position then we are equal.
182 */
183
184 return end_m == x.end_m && bucket_m == x.bucket_m &&
185 (bucket_m == end_m || current_m == x.current_m);
186 }
187
188 void increment() {
189 ++current_m;
190
191 while (current_m == boost::end(*bucket_m)) {
192 ++bucket_m;
193 if (bucket_m == end_m)
194 break;
195 current_m = boost::begin(*bucket_m);
196 }
197 }
198 void decrement() {
199 while (bucket_m == end_m || current_m == boost::begin(*bucket_m)) {
200 --bucket_m;
201 current_m = boost::end(*bucket_m);
202 }
203
204 --current_m;
205 }
206};
207
208
209template <typename R> // R models ConvertibleToRange
210inline boost::iterator_range<segmented_iterator<typename boost::range_iterator<R>::type>>
213
214 return boost::make_iterator_range(iterator(boost::begin(r), boost::end(r)),
215 iterator(boost::end(r), boost::end(r)));
216}
217
218
219template <typename R> // R models ConvertibleToRange
222
223 return iterator(boost::begin(r), boost::end(r));
224}
225
226/**************************************************************************************************/
227
228/*
229 NOTE (sparent) : The asserts are comment only because we don't require that our function
230 object be equality comparable.
231*/
232
233
234template <typename F, // F models Unary Function object
235 typename T, // T models Regular Type
236 typename R = T&, // R models Reference Type of T
237 typename I = std::size_t, // I models Unsigned Integer
238 typename D = std::ptrdiff_t // D models Signed Integer
239 >
240// I is convertible to argument[1] of F
241// result of F is R
242// D is the difference type of I (must be signed)
243class index_iterator : public boost::iterator_facade<index_iterator<F, T, R, I, D>, T,
244 std::random_access_iterator_tag, R, D> {
245public:
246 index_iterator() : index_m(0) {}
247 index_iterator(F f, I i) : dereference_m(f), index_m(i) {}
248
249 index_iterator(const index_iterator& x) : dereference_m(x.dereference_m), index_m(x.index_m) {}
250
252 index_iterator temp(x);
253 swap(temp, *this);
254 return *this;
255 }
256
257 friend inline void swap(index_iterator& x, index_iterator& y) {
258 swap(x.dereference_m, y.dereference_m);
259 swap(x.index_m, y.index_m);
260 }
261
262 I base() const { return index_m; }
263
264private:
265 F dereference_m;
266 I index_m;
267
268 // boost iterator_facade access functions
269
271
272 R dereference() const { return dereference_m(this->index_m); }
273
274 bool equal(const index_iterator& x) const {
275 // assert(dereference_m == x.dereference_m);
276
277 return index_m == x.index_m;
278 }
279
280 void increment() { ++index_m; }
281 void decrement() { --index_m; }
282 void advance(D x) { index_m += x; }
283
284 D distance_to(const index_iterator& x) const {
285 // assert(dereference_m == x.dereference_m);
286
287 /*
288 REVISIT (sparent) : There isn't a difference type for unsigned integers - because an
289 index is usually denoted by an unsigned type, but a difference is signed we should
290 have some mechanism to peform the subtraction and guarantee a valid result. We don't
291 currently have said mechanism, so we simply cast from (possibly)unsigned to signed.
292
293 This limits the range within which we can perform this operation, but practically it
294 shouldn't be an issue.
295 */
296 return D(x.index_m) - D(index_m);
297 }
298};
299
302// STEP ITERATOR ADAPTOR
311
312
313template <typename DERIVED, // type of the derived class
314 typename IT, // Models Iterator
315 typename S_FN>
316// A policy object that can compute the distance between two iterators of type IT
317// and can advance an iterator of type IT a given number of IT's units
319 : public boost::iterator_adaptor<DERIVED, IT, boost::use_default, boost::use_default,
320 boost::use_default, typename S_FN::difference_type> {
321public:
322 typedef boost::iterator_adaptor<DERIVED, IT, boost::use_default, boost::use_default,
323 boost::use_default, typename S_FN::difference_type>
325 typedef typename std::iterator_traits<IT>::difference_type base_difference_type;
326 typedef typename S_FN::difference_type difference_type;
327 typedef typename std::iterator_traits<IT>::reference reference;
328
330 step_iterator_adaptor(const IT& it, S_FN step_fn = S_FN())
331 : parent_type(it), _step_fn(step_fn) {}
332
333 difference_type step() const { return _step_fn.step(); }
334
335protected:
337
338private:
340
341 void increment() { _step_fn.advance(this->base_reference(), 1); }
342 void decrement() { _step_fn.advance(this->base_reference(), -1); }
343 void advance(base_difference_type d) { _step_fn.advance(this->base_reference(), d); }
344 difference_type distance_to(const step_iterator_adaptor& it) const {
345 return _step_fn.difference(this->base_reference(), it.base_reference());
346 }
347};
348
349// although boost::iterator_adaptor defines these, the default implementation computes distance and
350// compares for zero.
351// it is often faster to just apply the relation operator to the base
355template <typename D, typename IT, typename S_FN>
358 return p1.step() > 0 ? p1.base() > p2.base() : p1.base() < p2.base();
359}
360
361
362template <typename D, typename IT, typename S_FN>
365 return p1.step() > 0 ? p1.base() < p2.base() : p1.base() > p2.base();
366}
367
368template <typename D, typename IT, typename S_FN>
371 return p1.step() > 0 ? p1.base() >= p2.base() : p1.base() <= p2.base();
372}
373
374
375template <typename D, typename IT, typename S_FN>
378 return p1.step() > 0 ? p1.base() <= p2.base() : p1.base() >= p2.base();
379}
380
381
382template <typename D, typename IT, typename S_FN>
385 return p1.base() == p2.base();
386}
387
388
389template <typename D, typename IT, typename S_FN>
392 return p1.base() != p2.base();
393}
394
395/**************************************************************************************************/
396
401 typedef std::output_iterator_tag iterator_category;
403 typedef std::ptrdiff_t difference_type;
406
407 null_output_iterator_t& operator++(int) { return *this; }
409 reference operator*() { return *this; }
410
411 template <typename T>
413 return *this;
414 }
415};
416
418
419/**************************************************************************************************/
420
421} // namespace adobe
422
423/**************************************************************************************************/
424
425#endif
426
427/**************************************************************************************************/
std::output_iterator_tag iterator_category
Definition iterator.hpp:51
counting_output_iterator value_type
Definition iterator.hpp:52
counting_output_iterator & reference
Definition iterator.hpp:53
counting_output_iterator operator++(int)
Definition iterator.hpp:71
counting_output_iterator(const counting_output_iterator &x)
Definition iterator.hpp:58
reference operator=(const T &)
Definition iterator.hpp:63
bool operator==(counting_output_iterator const &rhs) const
Definition iterator.hpp:69
An iterator over elements which are the result of applying a function to an index.
Definition iterator.hpp:244
friend void swap(index_iterator &x, index_iterator &y)
Definition iterator.hpp:257
index_iterator(const index_iterator &x)
Definition iterator.hpp:249
index_iterator & operator=(const index_iterator &x)
Definition iterator.hpp:251
friend class boost::iterator_core_access
Definition iterator.hpp:270
segmented_iterator(const segmented_iterator &x)
Definition iterator.hpp:146
friend class boost::iterator_core_access
Definition iterator.hpp:174
friend void swap(segmented_iterator &x, segmented_iterator &y)
Definition iterator.hpp:154
segmented_iterator(I first, I last)
Definition iterator.hpp:138
segmented_iterator & operator=(segmented_iterator x)
Definition iterator.hpp:149
step iterator adaptor
Definition iterator.hpp:320
std::iterator_traits< IT >::reference reference
Definition iterator.hpp:327
step_iterator_adaptor(const IT &it, S_FN step_fn=S_FN())
Definition iterator.hpp:330
boost::iterator_adaptor< DERIVED, IT, boost::use_default, boost::use_default, boost::use_default, typename S_FN::difference_type > parent_type
Definition iterator.hpp:324
difference_type step() const
Definition iterator.hpp:333
S_FN::difference_type difference_type
Definition iterator.hpp:326
friend class boost::iterator_core_access
Definition iterator.hpp:339
std::iterator_traits< IT >::difference_type base_difference_type
Definition iterator.hpp:325
segmented_iterator< typename boost::range_iterator< R >::type > make_segmented_iterator(R &r)
Definition iterator.hpp:220
bool operator<(const step_iterator_adaptor< D, IT, S_FN > &p1, const step_iterator_adaptor< D, IT, S_FN > &p2)
Definition iterator.hpp:363
boost::iterator_range< segmented_iterator< typename boost::range_iterator< R >::type > > make_segmented_range(R &r)
Definition iterator.hpp:211
bool operator>=(const step_iterator_adaptor< D, IT, S_FN > &p1, const step_iterator_adaptor< D, IT, S_FN > &p2)
Definition iterator.hpp:369
bool operator>(const step_iterator_adaptor< D, IT, S_FN > &p1, const step_iterator_adaptor< D, IT, S_FN > &p2)
Definition iterator.hpp:356
bool operator<=(const step_iterator_adaptor< D, IT, S_FN > &p1, const step_iterator_adaptor< D, IT, S_FN > &p2)
Definition iterator.hpp:376
bool equal(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, BinaryPredicate pred)
Definition equal.hpp:36
bool operator==(const any_regular_t &x, const any_regular_t &y)
bool operator!=(const forest< T > &x, const forest< T > &y)
Definition forest.hpp:722
A stub iterator that models OutputIterator and outputs nothing.
Definition iterator.hpp:400
std::output_iterator_tag iterator_category
Definition iterator.hpp:401
null_output_iterator_t & operator++(int)
Definition iterator.hpp:407
null_output_iterator_t & operator++()
Definition iterator.hpp:408
null_output_iterator_t value_type
Definition iterator.hpp:402
null_output_iterator_t & operator=(const T &)
Definition iterator.hpp:412