Updated documentation
[libs.git] / src / Sylph / Core / Iterator.h
blobb50d6add77d8a12b360edd2c8ae6a29dc1093474
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 pointer operator->() {
85 if (_end_reached_) sthrow(IteratorException,
86 "Tried to dereference an beyond-end iterator");
87 return &current();
90 const pointer 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_;
192 * @todo Write documentation!
194 template<class T, class I>
195 class BidirectionalIterator : public ForwardIterator<T, I> {
196 public:
197 typedef std::bidirectional_iterator_tag iterator_category;
198 typedef ForwardIterator<T, I> super;
199 typedef BidirectionalIterator<T, I> self_type;
200 public:
202 BidirectionalIterator(bool begin = false) : super(begin) {
205 BidirectionalIterator(const BidirectionalIterator<T, I>& other) :
206 ForwardIterator<T, I>(other) {
209 I & operator--() {
210 if (super::_end_reached_) {
211 super::_end_reached_ = false;
212 return *static_cast<I*> (this);
213 } else if (!hasPrevious()) {
214 sthrow(IteratorException, "Begin of iterator");
215 } else {
216 previous();
217 return *static_cast<I*> (this);
221 const I & operator--() const {
222 if (super::_end_reached_) {
223 super::_end_reached_ = false;
224 return *static_cast<I*> (this);
225 } else if (!hasPrevious()) {
226 sthrow(IteratorException, "Begin of iterator");
227 } else {
228 previous();
229 return *static_cast<I*> (this);
233 I operator--(int) {
234 I toReturn(*static_cast<I*> (this));
235 if (super::_end_reached_) {
236 super::_end_reached_ = false;
237 return toReturn;
238 } else if (!hasPrevious()) {
239 sthrow(IteratorException, "Begin of iterator");
240 } else {
241 previous();
242 return toReturn;
246 const I operator--(int) const {
247 I toReturn(*static_cast<I*> (this));
248 if (super::_end_reached_) {
249 super::_end_reached_ = false;
250 return toReturn;
251 } else if (!hasPrevious()) {
252 sthrow(IteratorException, "Begin of iterator");
253 } else {
254 previous();
255 return toReturn;
259 virtual bool operator==(const I& other) const {
260 return ((super::_end_reached_ == other._end_reached_) ||
261 (hasPrevious() == other.hasPrevious()))
262 && super::operator==(other);
264 public:
265 virtual bool hasPrevious() const = 0;
266 virtual void previous() const = 0;
270 * @todo Write documentation!
272 template<class T, class I>
273 class RandomAccessIterator : public BidirectionalIterator<T, I> {
274 public:
275 typedef std::random_access_iterator_tag iterator_category;
276 typedef BidirectionalIterator<T, I> super;
277 typedef RandomAccessIterator<T, I> self_type;
278 public:
280 RandomAccessIterator(bool begin = false) : super(begin) {}
282 RandomAccessIterator(const self_type& other) :
283 super(other) {
286 I & operator+=(unsigned int i) {
287 ptrdiff_t diff = i;
288 if (i >= 0) while (diff--) ++(*this);
289 else while (diff++) --(*this);
290 return *static_cast<I*>(this);
293 const I & operator+=(unsigned int i) const {
294 ptrdiff_t diff = i;
295 if (i >= 0) while (diff--) ++(*this);
296 else while (diff++) --(*this);
297 return *static_cast<const I*>(this);
300 I & operator-=(unsigned int i) {
301 return *static_cast<I*>(&(*this += -i));
304 const I & operator-=(unsigned int i) const {
305 return &*static_cast<I*>(&(*this += -i));
308 const I operator+(unsigned int i) const {
309 I toReturn(*static_cast<const I*>(this));
310 return toReturn += i;
313 I operator-(unsigned int i) {
314 return *static_cast<I*>(&(*this + -i));
317 ptrdiff_t operator-(const I& other) const {
318 if (*this > other) return this->currentIndex() - other.currentIndex();
319 else return other.currentIndex() - this->currentIndex();
322 const typename super::reference operator[](unsigned int offset) const {
323 return *(*this +offset);
326 typename super::reference operator[](unsigned int offset) {
327 return *(*this +offset);
330 bool operator>(const I& other) const {
331 return this->currentIndex() > other.currentIndex();
334 bool operator<(const I& other) const {
335 return this->currentIndex() < other.currentIndex();
338 bool operator>=(const I& other) const {
340 return this->currentIndex() >= other.currentIndex();
343 bool operator<=(const I& other) const {
344 return this->currentIndex() <= other.currentIndex();
347 public:
348 virtual idx_t currentIndex() const = 0;
349 virtual size_t length() const = 0;
352 template<class T, class I>
353 I operator+(unsigned int i, const I itr) {
354 return itr + i;
358 * SylphIterator provides a easier-to-use wrapper around STL iterators. The
359 * interface of a SylphIterator is similar to a Java-style iterator, but it is
360 * backed by a STL iterator and can therefore be used for any class supporitng
361 * STL iterators. <p>
363 template<class Iter>
364 class SylphIterator : public virtual Object {
365 public:
368 * Creates a new Iterator from an STL-iterator. An Iterator can either be
369 * constructed explicitly with this constructor, in which case the correct
370 * type of Iterator for the particular collection needs to be known, or
371 * through Iterable::iterator() or Iterable::mutableIterator() .
372 * @param it The iterable to iterate over.
374 inline SylphIterator(Iter & it) : itr(it) {
378 * Destructor. This destructor does nothing.
380 inline virtual ~SylphIterator() {
384 * Checks if this iterator has any more entries in forward direction.
385 * @return <i>true</i> if there are more entries, <i>false</i> otherwise.
387 virtual bool hasNext() const {
388 return itr.hasNext();
392 * Returns the next entry in the forward direction and moves the iterator
393 * one place forward.
394 * @throw Exception if there are no more entries.
395 * @return The next entry
397 virtual const typename Iter::reference next() const {
398 typename Iter::reference toReturn = *itr;
399 ++itr;
400 return toReturn;
404 * Checks if this iterator has any more entries in backward direction.
405 * @return <i>true</i> if there are more entries, <i>false</i> otherwise.
406 * @note This requires that the backing iterator is a bidirectional
407 * iterator.
409 virtual bool hasPrevious() const {
410 return itr.hasPrevious();
414 * Returns the next entry in the backward direction and moves the iterator
415 * one place backward.
416 * @throw Exception if there are no more entries.
417 * @return The previous entry
418 * @note This requires that the backing iterator is a bidirectional
419 * iterator.
421 virtual const typename Iter::reference previous() const {
422 --itr;
423 return *itr;
427 * Moves the Iterator to the place "before" the first item, that is,
428 * it gives the pointer in the iterator such a value that hasPrevious
429 * returns false.
430 * @note This requires that the backing iterator is a bidirectional
431 * iterator.
433 virtual void front() const {
434 while (itr.hasPrevious()) --itr;
438 * Moves the Iterator to the place "after" the last item, that is,
439 * it gives the pointer in the iterator such a value that hasNext
440 * returns false.
441 * <p> This method is useful for backward iterating, i.e.
442 * <pre>Iterator it = coll.getIterator(); // normal 'forward' iterator
443 * it.back(); // ready for backward iteration </pre>
445 virtual void back() const {
446 while (itr.hasNext()) ++itr;
450 * Returns the next index of the Iterable in the forward direction.
451 * @throw Exception if there are no more entries.
452 * @return The next index in the Iterable
453 * @note This method requires the backing iterator to be a random-access
454 * iterator.
456 virtual std::idx_t nextIndex() const {
457 return itr.currentIndex();
461 * Returns the next index of the Iterable in the backward direction.
462 * @throw Exception if there are no more entries.
463 * @return The previous index in the Iterable
464 * @note This method requires the backing iterator to be a random-access
465 * iterator.
467 virtual std::idx_t previousIndex() const {
468 return itr.currentIndex() - 1;
472 * Replaces the last item returned by next() or previous() with the given
473 * item
474 * @param t The item to replace the last returned item with.
476 virtual void set(typename Iter::reference t) {
477 *itr = t;
481 * Synonymous for next()
483 const typename Iter::reference operator++() const {
484 return next();
488 * Synonymous for previous()
490 const typename Iter::reference operator--() const {
491 return previous();
495 * Synoynmous for next().
496 * @note No copy of this iterator is made.
498 const typename Iter::reference operator++(int) const {
499 return next();
503 * Synonymous for previous()
504 * @note No copy is of this iterator is made.
506 const typename Iter::reference operator--(int) const {
507 return previous();
509 private:
510 Iter itr;
513 template<class Collection>
514 const SylphIterator<typename Collection::const_iterator> SylphItr(
515 const Collection& col) {
516 return SylphIterator<typename Collection::const_iterator > (col.begin());
519 template<class Collection>
520 SylphIterator<typename Collection::iterator> SylphMitr(Collection & col) {
521 return SylphIterator<typename Collection::iterator > (col.begin());
525 SYLPH_END_NAMESPACE
527 // Previously defined here, now defined elsewhere
528 #include "Foreach.h"
530 #endif /* ITERATOR_H_ */