blob: d4a079971b15a8cd64474ff2a726b78a414e969e [file] [log] [blame]
Marshall Clow354d39c2014-01-16 16:58:45 +00001//===----------------------------------------------------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Howard Hinnantc1198c32010-07-16 19:08:36 +000010#ifndef ITERATORS_H
11#define ITERATORS_H
12
13#include <iterator>
Marshall Clow76b4afc2016-01-13 21:54:34 +000014#include <stdexcept>
Eric Fiselier71c425f2016-05-27 23:43:29 +000015#include <cstddef>
Marshall Clow29298662014-09-17 04:09:35 +000016#include <cassert>
Howard Hinnantc1198c32010-07-16 19:08:36 +000017
Marshall Clow76b4afc2016-01-13 21:54:34 +000018#include "test_macros.h"
19
Eric Fiselier847ee132014-10-27 20:26:25 +000020#ifndef _LIBCPP_HAS_NO_DELETED_FUNCTIONS
21#define DELETE_FUNCTION = delete
22#else
23#define DELETE_FUNCTION
24#endif
25
Howard Hinnantc1198c32010-07-16 19:08:36 +000026template <class It>
Howard Hinnant48b242a2010-08-14 18:14:02 +000027class output_iterator
28{
29 It it_;
30
31 template <class U> friend class output_iterator;
32public:
33 typedef std::output_iterator_tag iterator_category;
Marshall Clow44761002013-01-09 17:20:02 +000034 typedef void value_type;
Howard Hinnant48b242a2010-08-14 18:14:02 +000035 typedef typename std::iterator_traits<It>::difference_type difference_type;
36 typedef It pointer;
37 typedef typename std::iterator_traits<It>::reference reference;
38
39 It base() const {return it_;}
40
Marshall Clowcf1589f2013-01-03 02:29:29 +000041 output_iterator () {}
Howard Hinnant48b242a2010-08-14 18:14:02 +000042 explicit output_iterator(It it) : it_(it) {}
43 template <class U>
44 output_iterator(const output_iterator<U>& u) :it_(u.it_) {}
45
46 reference operator*() const {return *it_;}
47
48 output_iterator& operator++() {++it_; return *this;}
49 output_iterator operator++(int)
50 {output_iterator tmp(*this); ++(*this); return tmp;}
Eric Fiselier910285b2014-10-27 19:28:20 +000051
52 template <class T>
Eric Fiselier847ee132014-10-27 20:26:25 +000053 void operator,(T const &) DELETE_FUNCTION;
Howard Hinnant48b242a2010-08-14 18:14:02 +000054};
55
56template <class It>
Howard Hinnantc1198c32010-07-16 19:08:36 +000057class input_iterator
58{
59 It it_;
60
61 template <class U> friend class input_iterator;
62public:
63 typedef std::input_iterator_tag iterator_category;
64 typedef typename std::iterator_traits<It>::value_type value_type;
65 typedef typename std::iterator_traits<It>::difference_type difference_type;
66 typedef It pointer;
67 typedef typename std::iterator_traits<It>::reference reference;
68
69 It base() const {return it_;}
70
71 input_iterator() : it_() {}
72 explicit input_iterator(It it) : it_(it) {}
73 template <class U>
74 input_iterator(const input_iterator<U>& u) :it_(u.it_) {}
75
76 reference operator*() const {return *it_;}
77 pointer operator->() const {return it_;}
78
79 input_iterator& operator++() {++it_; return *this;}
80 input_iterator operator++(int)
81 {input_iterator tmp(*this); ++(*this); return tmp;}
82
83 friend bool operator==(const input_iterator& x, const input_iterator& y)
84 {return x.it_ == y.it_;}
85 friend bool operator!=(const input_iterator& x, const input_iterator& y)
86 {return !(x == y);}
Eric Fiselier910285b2014-10-27 19:28:20 +000087
88 template <class T>
Eric Fiselier847ee132014-10-27 20:26:25 +000089 void operator,(T const &) DELETE_FUNCTION;
Howard Hinnantc1198c32010-07-16 19:08:36 +000090};
91
92template <class T, class U>
93inline
94bool
95operator==(const input_iterator<T>& x, const input_iterator<U>& y)
96{
97 return x.base() == y.base();
98}
99
100template <class T, class U>
101inline
102bool
103operator!=(const input_iterator<T>& x, const input_iterator<U>& y)
104{
105 return !(x == y);
106}
107
108template <class It>
109class forward_iterator
110{
111 It it_;
112
113 template <class U> friend class forward_iterator;
114public:
115 typedef std::forward_iterator_tag iterator_category;
116 typedef typename std::iterator_traits<It>::value_type value_type;
117 typedef typename std::iterator_traits<It>::difference_type difference_type;
118 typedef It pointer;
119 typedef typename std::iterator_traits<It>::reference reference;
120
121 It base() const {return it_;}
122
123 forward_iterator() : it_() {}
124 explicit forward_iterator(It it) : it_(it) {}
125 template <class U>
126 forward_iterator(const forward_iterator<U>& u) :it_(u.it_) {}
127
128 reference operator*() const {return *it_;}
129 pointer operator->() const {return it_;}
130
131 forward_iterator& operator++() {++it_; return *this;}
132 forward_iterator operator++(int)
133 {forward_iterator tmp(*this); ++(*this); return tmp;}
134
135 friend bool operator==(const forward_iterator& x, const forward_iterator& y)
136 {return x.it_ == y.it_;}
137 friend bool operator!=(const forward_iterator& x, const forward_iterator& y)
138 {return !(x == y);}
Eric Fiselier910285b2014-10-27 19:28:20 +0000139
140 template <class T>
Eric Fiselier847ee132014-10-27 20:26:25 +0000141 void operator,(T const &) DELETE_FUNCTION;
Howard Hinnantc1198c32010-07-16 19:08:36 +0000142};
143
144template <class T, class U>
145inline
146bool
147operator==(const forward_iterator<T>& x, const forward_iterator<U>& y)
148{
149 return x.base() == y.base();
150}
151
152template <class T, class U>
153inline
154bool
155operator!=(const forward_iterator<T>& x, const forward_iterator<U>& y)
156{
157 return !(x == y);
158}
159
160template <class It>
161class bidirectional_iterator
162{
163 It it_;
164
165 template <class U> friend class bidirectional_iterator;
166public:
167 typedef std::bidirectional_iterator_tag iterator_category;
168 typedef typename std::iterator_traits<It>::value_type value_type;
169 typedef typename std::iterator_traits<It>::difference_type difference_type;
170 typedef It pointer;
171 typedef typename std::iterator_traits<It>::reference reference;
172
173 It base() const {return it_;}
174
175 bidirectional_iterator() : it_() {}
176 explicit bidirectional_iterator(It it) : it_(it) {}
177 template <class U>
178 bidirectional_iterator(const bidirectional_iterator<U>& u) :it_(u.it_) {}
179
180 reference operator*() const {return *it_;}
181 pointer operator->() const {return it_;}
182
183 bidirectional_iterator& operator++() {++it_; return *this;}
184 bidirectional_iterator operator++(int)
185 {bidirectional_iterator tmp(*this); ++(*this); return tmp;}
186
187 bidirectional_iterator& operator--() {--it_; return *this;}
188 bidirectional_iterator operator--(int)
189 {bidirectional_iterator tmp(*this); --(*this); return tmp;}
Eric Fiselier910285b2014-10-27 19:28:20 +0000190
191 template <class T>
Eric Fiselier847ee132014-10-27 20:26:25 +0000192 void operator,(T const &) DELETE_FUNCTION;
Howard Hinnantc1198c32010-07-16 19:08:36 +0000193};
194
195template <class T, class U>
196inline
197bool
198operator==(const bidirectional_iterator<T>& x, const bidirectional_iterator<U>& y)
199{
200 return x.base() == y.base();
201}
202
203template <class T, class U>
204inline
205bool
206operator!=(const bidirectional_iterator<T>& x, const bidirectional_iterator<U>& y)
207{
208 return !(x == y);
209}
210
211template <class It>
212class random_access_iterator
213{
214 It it_;
215
216 template <class U> friend class random_access_iterator;
217public:
218 typedef std::random_access_iterator_tag iterator_category;
219 typedef typename std::iterator_traits<It>::value_type value_type;
220 typedef typename std::iterator_traits<It>::difference_type difference_type;
221 typedef It pointer;
222 typedef typename std::iterator_traits<It>::reference reference;
223
224 It base() const {return it_;}
225
226 random_access_iterator() : it_() {}
227 explicit random_access_iterator(It it) : it_(it) {}
228 template <class U>
229 random_access_iterator(const random_access_iterator<U>& u) :it_(u.it_) {}
230
231 reference operator*() const {return *it_;}
232 pointer operator->() const {return it_;}
233
234 random_access_iterator& operator++() {++it_; return *this;}
235 random_access_iterator operator++(int)
236 {random_access_iterator tmp(*this); ++(*this); return tmp;}
237
238 random_access_iterator& operator--() {--it_; return *this;}
239 random_access_iterator operator--(int)
240 {random_access_iterator tmp(*this); --(*this); return tmp;}
241
242 random_access_iterator& operator+=(difference_type n) {it_ += n; return *this;}
243 random_access_iterator operator+(difference_type n) const
244 {random_access_iterator tmp(*this); tmp += n; return tmp;}
245 friend random_access_iterator operator+(difference_type n, random_access_iterator x)
246 {x += n; return x;}
247 random_access_iterator& operator-=(difference_type n) {return *this += -n;}
248 random_access_iterator operator-(difference_type n) const
249 {random_access_iterator tmp(*this); tmp -= n; return tmp;}
250
251 reference operator[](difference_type n) const {return it_[n];}
Eric Fiselier910285b2014-10-27 19:28:20 +0000252
253 template <class T>
Eric Fiselier847ee132014-10-27 20:26:25 +0000254 void operator,(T const &) DELETE_FUNCTION;
Howard Hinnantc1198c32010-07-16 19:08:36 +0000255};
256
257template <class T, class U>
258inline
259bool
260operator==(const random_access_iterator<T>& x, const random_access_iterator<U>& y)
261{
262 return x.base() == y.base();
263}
264
265template <class T, class U>
266inline
267bool
268operator!=(const random_access_iterator<T>& x, const random_access_iterator<U>& y)
269{
270 return !(x == y);
271}
272
273template <class T, class U>
274inline
275bool
276operator<(const random_access_iterator<T>& x, const random_access_iterator<U>& y)
277{
278 return x.base() < y.base();
279}
280
281template <class T, class U>
282inline
283bool
284operator<=(const random_access_iterator<T>& x, const random_access_iterator<U>& y)
285{
286 return !(y < x);
287}
288
289template <class T, class U>
290inline
291bool
292operator>(const random_access_iterator<T>& x, const random_access_iterator<U>& y)
293{
294 return y < x;
295}
296
297template <class T, class U>
298inline
299bool
300operator>=(const random_access_iterator<T>& x, const random_access_iterator<U>& y)
301{
302 return !(x < y);
303}
304
305template <class T, class U>
306inline
307typename std::iterator_traits<T>::difference_type
308operator-(const random_access_iterator<T>& x, const random_access_iterator<U>& y)
309{
310 return x.base() - y.base();
311}
312
Marshall Clowf8c2b822013-01-04 18:24:04 +0000313template <class Iter>
314inline Iter base(output_iterator<Iter> i) { return i.base(); }
315
316template <class Iter>
317inline Iter base(input_iterator<Iter> i) { return i.base(); }
318
319template <class Iter>
320inline Iter base(forward_iterator<Iter> i) { return i.base(); }
321
322template <class Iter>
323inline Iter base(bidirectional_iterator<Iter> i) { return i.base(); }
324
325template <class Iter>
326inline Iter base(random_access_iterator<Iter> i) { return i.base(); }
327
Howard Hinnante0fe3d22013-07-08 21:06:38 +0000328template <class Iter> // everything else
Marshall Clowf8c2b822013-01-04 18:24:04 +0000329inline Iter base(Iter i) { return i; }
330
Marshall Clow76b4afc2016-01-13 21:54:34 +0000331template <typename T>
332struct ThrowingIterator {
333 typedef std::bidirectional_iterator_tag iterator_category;
334 typedef ptrdiff_t difference_type;
335 typedef const T value_type;
336 typedef const T * pointer;
337 typedef const T & reference;
338
Marshall Clow64ca6862016-01-20 03:37:46 +0000339 enum ThrowingAction { TAIncrement, TADecrement, TADereference, TAAssignment, TAComparison };
Marshall Clow76b4afc2016-01-13 21:54:34 +0000340
Marshall Clow64ca6862016-01-20 03:37:46 +0000341// Constructors
342 ThrowingIterator ()
343 : begin_(nullptr), end_(nullptr), current_(nullptr), action_(TADereference), index_(0) {}
344 ThrowingIterator (const T *first, const T *last, size_t index = 0, ThrowingAction action = TADereference)
345 : begin_(first), end_(last), current_(first), action_(action), index_(index) {}
346 ThrowingIterator (const ThrowingIterator &rhs)
347 : begin_(rhs.begin_), end_(rhs.end_), current_(rhs.current_), action_(rhs.action_), index_(rhs.index_) {}
348 ThrowingIterator & operator= (const ThrowingIterator &rhs)
349 {
350 if (action_ == TAAssignment)
351 {
352 if (index_ == 0)
Marshall Clow9d10d272016-01-20 03:19:15 +0000353#ifndef TEST_HAS_NO_EXCEPTIONS
Marshall Clow64ca6862016-01-20 03:37:46 +0000354 throw std::runtime_error ("throw from iterator assignment");
Marshall Clow9d10d272016-01-20 03:19:15 +0000355#else
Marshall Clow64ca6862016-01-20 03:37:46 +0000356 assert(false);
Marshall Clow9d10d272016-01-20 03:19:15 +0000357#endif
358
Marshall Clow64ca6862016-01-20 03:37:46 +0000359 else
360 --index_;
361 }
362 begin_ = rhs.begin_;
363 end_ = rhs.end_;
364 current_ = rhs.current_;
365 action_ = rhs.action_;
366 index_ = rhs.index_;
367 return *this;
368 }
Marshall Clow76b4afc2016-01-13 21:54:34 +0000369
Marshall Clow64ca6862016-01-20 03:37:46 +0000370// iterator operations
371 reference operator*() const
372 {
373 if (action_ == TADereference)
374 {
375 if (index_ == 0)
Marshall Clow9d10d272016-01-20 03:19:15 +0000376#ifndef TEST_HAS_NO_EXCEPTIONS
Marshall Clow64ca6862016-01-20 03:37:46 +0000377 throw std::runtime_error ("throw from iterator dereference");
Marshall Clow9d10d272016-01-20 03:19:15 +0000378#else
Marshall Clow64ca6862016-01-20 03:37:46 +0000379 assert(false);
Marshall Clow9d10d272016-01-20 03:19:15 +0000380#endif
Marshall Clow64ca6862016-01-20 03:37:46 +0000381 else
382 --index_;
383 }
384 return *current_;
385 }
Marshall Clow76b4afc2016-01-13 21:54:34 +0000386
Marshall Clow64ca6862016-01-20 03:37:46 +0000387 ThrowingIterator & operator++()
388 {
389 if (action_ == TAIncrement)
390 {
391 if (index_ == 0)
Marshall Clow9d10d272016-01-20 03:19:15 +0000392#ifndef TEST_HAS_NO_EXCEPTIONS
Marshall Clow64ca6862016-01-20 03:37:46 +0000393 throw std::runtime_error ("throw from iterator increment");
Marshall Clow9d10d272016-01-20 03:19:15 +0000394#else
Marshall Clow64ca6862016-01-20 03:37:46 +0000395 assert(false);
Marshall Clow9d10d272016-01-20 03:19:15 +0000396#endif
Marshall Clow64ca6862016-01-20 03:37:46 +0000397 else
398 --index_;
399 }
400 ++current_;
401 return *this;
402 }
Eric Fiselierd04c6852016-06-01 21:35:39 +0000403
Marshall Clow64ca6862016-01-20 03:37:46 +0000404 ThrowingIterator operator++(int)
405 {
406 ThrowingIterator temp = *this;
407 ++(*this);
408 return temp;
409 }
Marshall Clow76b4afc2016-01-13 21:54:34 +0000410
Marshall Clow64ca6862016-01-20 03:37:46 +0000411 ThrowingIterator & operator--()
412 {
413 if (action_ == TADecrement)
414 {
415 if (index_ == 0)
Marshall Clow9d10d272016-01-20 03:19:15 +0000416#ifndef TEST_HAS_NO_EXCEPTIONS
Marshall Clow64ca6862016-01-20 03:37:46 +0000417 throw std::runtime_error ("throw from iterator decrement");
Marshall Clow9d10d272016-01-20 03:19:15 +0000418#else
Marshall Clow64ca6862016-01-20 03:37:46 +0000419 assert(false);
Marshall Clow9d10d272016-01-20 03:19:15 +0000420#endif
Marshall Clow64ca6862016-01-20 03:37:46 +0000421 else
422 --index_;
423 }
424 --current_;
425 return *this;
426 }
Marshall Clow76b4afc2016-01-13 21:54:34 +0000427
Marshall Clow64ca6862016-01-20 03:37:46 +0000428 ThrowingIterator operator--(int) {
429 ThrowingIterator temp = *this;
430 --(*this);
431 return temp;
432 }
Marshall Clow76b4afc2016-01-13 21:54:34 +0000433
Marshall Clow64ca6862016-01-20 03:37:46 +0000434 bool operator== (const ThrowingIterator &rhs) const
435 {
436 if (action_ == TAComparison)
437 {
438 if (index_ == 0)
Marshall Clow9d10d272016-01-20 03:19:15 +0000439#ifndef TEST_HAS_NO_EXCEPTIONS
Marshall Clow64ca6862016-01-20 03:37:46 +0000440 throw std::runtime_error ("throw from iterator comparison");
Marshall Clow9d10d272016-01-20 03:19:15 +0000441#else
Marshall Clow64ca6862016-01-20 03:37:46 +0000442 assert(false);
Marshall Clow9d10d272016-01-20 03:19:15 +0000443#endif
Marshall Clow64ca6862016-01-20 03:37:46 +0000444 else
445 --index_;
446 }
447 bool atEndL = current_ == end_;
448 bool atEndR = rhs.current_ == rhs.end_;
449 if (atEndL != atEndR) return false; // one is at the end (or empty), the other is not.
450 if (atEndL) return true; // both are at the end (or empty)
451 return current_ == rhs.current_;
452 }
Marshall Clow76b4afc2016-01-13 21:54:34 +0000453
454private:
Marshall Clow64ca6862016-01-20 03:37:46 +0000455 const T* begin_;
456 const T* end_;
457 const T* current_;
458 ThrowingAction action_;
459 mutable size_t index_;
Marshall Clow76b4afc2016-01-13 21:54:34 +0000460};
461
462template <typename T>
463bool operator== (const ThrowingIterator<T>& a, const ThrowingIterator<T>& b)
Marshall Clow64ca6862016-01-20 03:37:46 +0000464{ return a.operator==(b); }
Marshall Clow76b4afc2016-01-13 21:54:34 +0000465
466template <typename T>
467bool operator!= (const ThrowingIterator<T>& a, const ThrowingIterator<T>& b)
Marshall Clow64ca6862016-01-20 03:37:46 +0000468{ return !a.operator==(b); }
Eric Fiselierd04c6852016-06-01 21:35:39 +0000469
Marshall Clow76b4afc2016-01-13 21:54:34 +0000470template <typename T>
471struct NonThrowingIterator {
472 typedef std::bidirectional_iterator_tag iterator_category;
473 typedef ptrdiff_t difference_type;
474 typedef const T value_type;
475 typedef const T * pointer;
476 typedef const T & reference;
477
Marshall Clow64ca6862016-01-20 03:37:46 +0000478// Constructors
479 NonThrowingIterator ()
480 : begin_(nullptr), end_(nullptr), current_(nullptr) {}
481 NonThrowingIterator (const T *first, const T* last)
482 : begin_(first), end_(last), current_(first) {}
483 NonThrowingIterator (const NonThrowingIterator &rhs)
484 : begin_(rhs.begin_), end_(rhs.end_), current_(rhs.current_) {}
485 NonThrowingIterator & operator= (const NonThrowingIterator &rhs) TEST_NOEXCEPT
486 {
487 begin_ = rhs.begin_;
488 end_ = rhs.end_;
489 current_ = rhs.current_;
490 return *this;
491 }
Marshall Clow76b4afc2016-01-13 21:54:34 +0000492
Marshall Clow64ca6862016-01-20 03:37:46 +0000493// iterator operations
494 reference operator*() const TEST_NOEXCEPT
495 {
496 return *current_;
497 }
Marshall Clow76b4afc2016-01-13 21:54:34 +0000498
Marshall Clow64ca6862016-01-20 03:37:46 +0000499 NonThrowingIterator & operator++() TEST_NOEXCEPT
500 {
501 ++current_;
502 return *this;
503 }
Eric Fiselierd04c6852016-06-01 21:35:39 +0000504
Marshall Clow64ca6862016-01-20 03:37:46 +0000505 NonThrowingIterator operator++(int) TEST_NOEXCEPT
506 {
507 NonThrowingIterator temp = *this;
508 ++(*this);
509 return temp;
510 }
Marshall Clow76b4afc2016-01-13 21:54:34 +0000511
Marshall Clow64ca6862016-01-20 03:37:46 +0000512 NonThrowingIterator & operator--() TEST_NOEXCEPT
513 {
514 --current_;
515 return *this;
516 }
Marshall Clow76b4afc2016-01-13 21:54:34 +0000517
Marshall Clow64ca6862016-01-20 03:37:46 +0000518 NonThrowingIterator operator--(int) TEST_NOEXCEPT
519 {
520 NonThrowingIterator temp = *this;
521 --(*this);
522 return temp;
523 }
Marshall Clow76b4afc2016-01-13 21:54:34 +0000524
Marshall Clow64ca6862016-01-20 03:37:46 +0000525 bool operator== (const NonThrowingIterator &rhs) const TEST_NOEXCEPT
526 {
527 bool atEndL = current_ == end_;
528 bool atEndR = rhs.current_ == rhs.end_;
529 if (atEndL != atEndR) return false; // one is at the end (or empty), the other is not.
530 if (atEndL) return true; // both are at the end (or empty)
531 return current_ == rhs.current_;
532 }
Marshall Clow76b4afc2016-01-13 21:54:34 +0000533
534private:
Marshall Clow64ca6862016-01-20 03:37:46 +0000535 const T* begin_;
536 const T* end_;
537 const T* current_;
Marshall Clow76b4afc2016-01-13 21:54:34 +0000538};
539
540template <typename T>
541bool operator== (const NonThrowingIterator<T>& a, const NonThrowingIterator<T>& b) TEST_NOEXCEPT
Marshall Clow64ca6862016-01-20 03:37:46 +0000542{ return a.operator==(b); }
Marshall Clow76b4afc2016-01-13 21:54:34 +0000543
544template <typename T>
545bool operator!= (const NonThrowingIterator<T>& a, const NonThrowingIterator<T>& b) TEST_NOEXCEPT
Marshall Clow64ca6862016-01-20 03:37:46 +0000546{ return !a.operator==(b); }
Marshall Clow76b4afc2016-01-13 21:54:34 +0000547
Eric Fiselier847ee132014-10-27 20:26:25 +0000548#undef DELETE_FUNCTION
549
Howard Hinnantf36101d2010-08-22 00:45:01 +0000550#endif // ITERATORS_H