* Fixed error on TestArray::testIterator
[libs.git] / src / Sylph / Core / Iterator.h
blob98d6f67dc3968275c62089c6dacb127a7f65e720
1 /*
2 * LibSylph Class Library
3 * Copyright (C) 2009 Frank "SeySayux" Erens <seysayux@gmail.com>
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the LibSylph Pulbic License as published
7 * by the LibSylph Developers; either version 1.0 of the License, or
8 * (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the LibSylph
13 * Public License for more details.
15 * You should have received a copy of the LibSylph Public License
16 * along with this Library, if not, contact the LibSylph Developers.
18 * Created on 6 december 2008, 17:16
21 #ifndef ITERATOR_H_
22 #define ITERATOR_H_
24 #include "Object.h"
25 #include "Exception.h"
26 #include "Iterable.h"
27 #include <iterator>
28 //#include "Foreach.h" -- this line is at the bottom of the file ;)
30 SYLPH_BEGIN_NAMESPACE
31 SYLPH_PUBLIC
33 S_CREATE_EXCEPTION(IteratorException);
35 /**
36 * Facade used to simplify usage of forward iterators. This class provides
37 * several methods to override, which will be used to make a correct
38 * implementation of a forward iterator.<p>
39 * Note that this class already correctly implements the difference between
40 * a const_iterator and a normal iterator, i.e. a const ForwardIterator conforms
41 * as a const_iterator, and a non-const ForwardIterator conforms as a non-const
42 * iterator. Therefore, when implementing this class, make sure that you
43 * flag any fields that can be changed (such as indices or pointers to the
44 * current item) as <code>mutable</code>. <p>
45 * In order for your own types to be correctly identified as a ForwardIterator,
46 * please use the <code>S_FORWARD_ITERATOR(</code><i>iterator-name, type-name,
47 * object-to-iterate-over</i><code>)</code>
49 template<class T, class I>
50 class ForwardIterator : public Object {
51 public:
52 typedef std::forward_iterator_tag iterator_category;
53 typedef T value_type;
54 typedef ptrdiff_t difference_type;
55 typedef T* pointer;
56 typedef T& reference;
57 typedef ForwardIterator<T, I> self_type;
58 public:
59 // Implementation of the required functions in terms of the overridable
60 // functions
62 ForwardIterator(bool begin = false) : _end_reached_(!begin) {
65 ForwardIterator(const ForwardIterator<T, I>& other) :
66 _end_reached_(other._end_reached_) {
69 virtual ~ForwardIterator() {
72 reference operator*() {
73 if (_end_reached_) sthrow(IteratorException,
74 "Tried to dereference an beyond-end iterator");
75 return current();
78 const reference operator*() const {
79 if (_end_reached_) sthrow(IteratorException,
80 "Tried to dereference an beyond-end iterator");
81 return current();
84 reference operator->() {
85 if (_end_reached_) sthrow(IteratorException,
86 "Tried to dereference an beyond-end iterator");
87 return current();
90 const reference operator->() const {
91 if (_end_reached_) sthrow(IteratorException,
92 "Tried to dereference an beyond-end iterator");
93 return current();
96 const I & operator++() const {
97 if (_end_reached_) sthrow(IteratorException, "End of iterator");
98 else if (!hasNext()) {
99 _end_reached_ = true;
100 return *static_cast<I*> (this);
101 } else {
102 next();
103 return *static_cast<I*> (this);
107 I & operator++() {
108 if (_end_reached_) sthrow(IteratorException, "End of iterator");
109 else if (!hasNext()) {
110 _end_reached_ = true;
111 return *static_cast<I*> (this);
112 } else {
113 next();
114 return *static_cast<I*> (this);
118 const I operator++(int) const {
119 I toReturn(*static_cast<I*> (this));
120 if (_end_reached_) sthrow(IteratorException, "End of iterator");
121 else if (!hasNext()) {
122 _end_reached_ = true;
123 return toReturn;
124 } else {
125 next();
126 return toReturn;
130 I operator++(int) {
131 I toReturn(*static_cast<I*> (this));
132 if (_end_reached_) sthrow(IteratorException, "End of iterator");
133 else if (!hasNext()) {
134 _end_reached_ = true;
135 return toReturn;
136 } else {
137 next();
138 return toReturn;
142 virtual bool operator==(const I& other) const {
143 return (_end_reached_ == other._end_reached_) && equals(other);
146 bool operator!=(const ForwardIterator<T, I>& other) const {
147 return !(*this == other);
149 void construct(bool begin, void* obj) {
150 construct(begin,obj);
153 public:
154 // Overridable functions
156 * <b>OVERRIDE THIS METHOD</b> Returns a reference to the object the iterator
157 * is currently pointing at. Note that no beyond-the-end checking needs
158 * to be done, this is all done automagically for you.
159 * @return The object this iterator is currently pointing at.
161 virtual reference current() const = 0;
163 * <b>OVERRIDE THIS METHOD</b> Sets the iterator one place forward. Note
164 * that no beyond-the-end checking needs to be done, this is all done
165 * automagically for you.
167 virtual void next() const = 0;
169 * <b>OVERRIDE THIS METHOD</b> Tells wheter there are any objects left
170 * in the collection. This method should not take the past-the-end item into
171 * account.
172 * @return <i>true</i> true if there are any next items, <i>false<i> if
173 * there are no more items left.
175 virtual bool hasNext() const = 0;
177 * <b>OVERRIDE THIS METHOD</b> Tells wheter this Iterator is equal to any
178 * other Iterator over the same type of collection.
179 * @param other An other ForwardIterator to compare this one against.
180 * @return <i>true</i> iff the two iterators are completely equal (i.e.
181 * they iteratate over the same collection and currently point to the same
182 * object), false otherwise.
184 virtual bool equals(const I& other) const = 0;
186 * Do not use or modify!
188 mutable bool _end_reached_;
191 template<class T, class I>
192 class BidirectionalIterator : public ForwardIterator<T, I> {
193 public:
194 typedef std::bidirectional_iterator_tag iterator_category;
195 typedef ForwardIterator<T, I> super;
196 typedef BidirectionalIterator<T, I> self_type;
197 public:
199 BidirectionalIterator(bool begin = false) : super(begin) {
202 BidirectionalIterator(const BidirectionalIterator<T, I>& other) :
203 ForwardIterator<T, I>(other) {
206 I & operator--() {
207 if (super::_end_reached_) {
208 super::_end_reached_ = false;
209 return *static_cast<I*> (this);
210 } else if (!hasPrevious()) {
211 sthrow(IteratorException, "Begin of iterator");
212 } else {
213 previous();
214 return *static_cast<I*> (this);
218 const I & operator--() const {
219 if (super::_end_reached_) {
220 super::_end_reached_ = false;
221 return *static_cast<I*> (this);
222 } else if (!hasPrevious()) {
223 sthrow(IteratorException, "Begin of iterator");
224 } else {
225 previous();
226 return *static_cast<I*> (this);
230 I operator--(int) {
231 I toReturn(*static_cast<I*> (this));
232 if (super::_end_reached_) {
233 super::_end_reached_ = false;
234 return toReturn;
235 } else if (!hasPrevious()) {
236 sthrow(IteratorException, "Begin of iterator");
237 } else {
238 previous();
239 return toReturn;
243 const I operator--(int) const {
244 I toReturn(*static_cast<I*> (this));
245 if (super::_end_reached_) {
246 super::_end_reached_ = false;
247 return toReturn;
248 } else if (!hasPrevious()) {
249 sthrow(IteratorException, "Begin of iterator");
250 } else {
251 previous();
252 return toReturn;
256 virtual bool operator==(const I& other) const {
257 return ((super::_end_reached_ == other._end_reached_) ||
258 (hasPrevious() == other.hasPrevious()))
259 && super::operator==(other);
261 public:
262 virtual bool hasPrevious() const = 0;
263 virtual void previous() const = 0;
266 template<class T, class I>
267 class RandomAccessIterator : public BidirectionalIterator<T, I> {
268 public:
269 typedef std::random_access_iterator_tag iterator_category;
270 typedef BidirectionalIterator<T, I> super;
271 typedef RandomAccessIterator<T, I> self_type;
272 public:
274 RandomAccessIterator(bool begin = false) : super(begin) {}
276 RandomAccessIterator(const self_type& other) :
277 super(other) {
280 I & operator+=(unsigned int i) {
281 ptrdiff_t diff = i;
282 if (i >= 0) while (diff--) ++(*this);
283 else while (diff++) --(*this);
284 return *static_cast<I*>(this);
287 const I & operator+=(unsigned int i) const {
288 ptrdiff_t diff = i;
289 if (i >= 0) while (diff--) ++(*this);
290 else while (diff++) --(*this);
291 return *static_cast<const I*>(this);
294 I & operator-=(unsigned int i) {
295 return *static_cast<I*>(&(*this += -i));
298 const I & operator-=(unsigned int i) const {
299 return &*static_cast<I*>(&(*this += -i));
302 const I operator+(unsigned int i) const {
303 I toReturn(*static_cast<const I*>(this));
304 return toReturn += i;
307 I operator-(unsigned int i) {
308 return *static_cast<I*>(&(*this + -i));
311 ptrdiff_t operator-(const I& other) const {
312 if (*this > other) return this->currentIndex() - other.currentIndex();
313 else return other.currentIndex() - this->currentIndex();
316 const typename super::reference operator[](unsigned int offset) const {
317 return *(*this +offset);
320 typename super::reference operator[](unsigned int offset) {
321 return *(*this +offset);
324 bool operator>(const I& other) const {
325 return this->currentIndex() > other.currentIndex();
328 bool operator<(const I& other) const {
329 return this->currentIndex() < other.currentIndex();
332 bool operator>=(const I& other) const {
334 return this->currentIndex() >= other.currentIndex();
337 bool operator<=(const I& other) const {
338 return this->currentIndex() <= other.currentIndex();
341 public:
342 virtual idx_t currentIndex() const = 0;
343 virtual size_t length() const = 0;
346 template<class T, class I>
347 I operator+(unsigned int i, const I itr) {
348 return itr + i;
352 * SylphIterator provides a easier-to-use wrapper around STL iterators. The
353 * interface of a SylphIterator is similar to a Java-style iterator, but it is
354 * backed by a STL iterator and can therefore be used for any class supporitng
355 * STL iterators. <p>
357 template<class Iter>
358 class SylphIterator : public virtual Object {
359 public:
362 * Creates a new Iterator from an STL-iterator. An Iterator can either be
363 * constructed explicitly with this constructor, in which case the correct
364 * type of Iterator for the particular collection needs to be known, or
365 * through Iterable::iterator() or Iterable::mutableIterator() .
366 * @param it The iterable to iterate over.
368 inline SylphIterator(Iter & it) : itr(it) {
372 * Destructor. This destructor does nothing.
374 inline virtual ~SylphIterator() {
378 * Checks if this iterator has any more entries in forward direction.
379 * @return <i>true</i> if there are more entries, <i>false</i> otherwise.
381 virtual bool hasNext() const {
382 return itr.hasNext();
386 * Returns the next entry in the forward direction and moves the iterator
387 * one place forward.
388 * @throw Exception if there are no more entries.
389 * @return The next entry
391 virtual const typename Iter::reference next() const {
392 typename Iter::reference toReturn = *itr;
393 ++itr;
394 return toReturn;
398 * Checks if this iterator has any more entries in backward direction.
399 * @return <i>true</i> if there are more entries, <i>false</i> otherwise.
400 * @note This requires that the backing iterator is a bidirectional
401 * iterator.
403 virtual bool hasPrevious() const {
404 return itr.hasPrevious();
408 * Returns the next entry in the backward direction and moves the iterator
409 * one place backward.
410 * @throw Exception if there are no more entries.
411 * @return The previous entry
412 * @note This requires that the backing iterator is a bidirectional
413 * iterator.
415 virtual const typename Iter::reference previous() const {
416 --itr;
417 return *itr;
421 * Moves the Iterator to the place "before" the first item, that is,
422 * it gives the pointer in the iterator such a value that hasPrevious
423 * returns false.
424 * @note This requires that the backing iterator is a bidirectional
425 * iterator.
427 virtual void front() const {
428 while (itr.hasPrevious()) --itr;
432 * Moves the Iterator to the place "after" the last item, that is,
433 * it gives the pointer in the iterator such a value that hasNext
434 * returns false.
435 * <p> This method is useful for backward iterating, i.e.
436 * <pre>Iterator it = coll.getIterator(); // normal 'forward' iterator
437 * it.back(); // ready for backward iteration </pre>
439 virtual void back() const {
440 while (itr.hasNext()) ++itr;
444 * Returns the next index of the Iterable in the forward direction.
445 * @throw Exception if there are no more entries.
446 * @return The next index in the Iterable
447 * @note This method requires the backing iterator to be a random-access
448 * iterator.
450 virtual std::idx_t nextIndex() const {
451 return itr.currentIndex();
455 * Returns the next index of the Iterable in the backward direction.
456 * @throw Exception if there are no more entries.
457 * @return The previous index in the Iterable
458 * @note This method requires the backing iterator to be a random-access
459 * iterator.
461 virtual std::idx_t previousIndex() const {
462 return itr.currentIndex() - 1;
466 * Replaces the last item returned by next() or previous() with the given
467 * item
468 * @param t The item to replace the last returned item with.
470 virtual void set(typename Iter::reference t) {
471 *itr = t;
475 * Synonymous for next()
477 const typename Iter::reference operator++() const {
478 return next();
482 * Synonymous for previous()
484 const typename Iter::reference operator--() const {
485 return previous();
489 * Synoynmous for next().
490 * @note No copy of this iterator is made.
492 const typename Iter::reference operator++(int) const {
493 return next();
497 * Synonymous for previous()
498 * @note No copy is of this iterator is made.
500 const typename Iter::reference operator--(int) const {
501 return previous();
503 private:
504 Iter itr;
507 template<class Collection>
508 const SylphIterator<typename Collection::const_iterator> SylphItr(
509 const Collection& col) {
510 return SylphIterator<typename Collection::const_iterator > (col.begin());
513 template<class Collection>
514 SylphIterator<typename Collection::iterator> SylphMitr(Collection & col) {
515 return SylphIterator<typename Collection::iterator > (col.begin());
519 SYLPH_END_NAMESPACE
521 // Previously defined here, now defined elsewhere
522 #include "Foreach.h"
524 #endif /* ITERATOR_H_ */