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
25 #include "Exception.h"
28 //#include "Foreach.h" -- this line is at the bottom of the file ;)
33 S_CREATE_EXCEPTION(IteratorException
);
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
{
52 typedef std::forward_iterator_tag iterator_category
;
54 typedef ptrdiff_t difference_type
;
57 typedef ForwardIterator
<T
, I
> self_type
;
59 // Implementation of the required functions in terms of the overridable
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");
78 const reference
operator*() const {
79 if (_end_reached_
) sthrow(IteratorException
,
80 "Tried to dereference an beyond-end iterator");
84 pointer
operator->() {
85 if (_end_reached_
) sthrow(IteratorException
,
86 "Tried to dereference an beyond-end iterator");
90 const pointer
operator->() const {
91 if (_end_reached_
) sthrow(IteratorException
,
92 "Tried to dereference an beyond-end iterator");
96 const I
& operator++() const {
97 if (_end_reached_
) sthrow(IteratorException
, "End of iterator");
98 else if (!hasNext()) {
100 return *static_cast<I
*> (this);
103 return *static_cast<I
*> (this);
108 if (_end_reached_
) sthrow(IteratorException
, "End of iterator");
109 else if (!hasNext()) {
110 _end_reached_
= true;
111 return *static_cast<I
*> (this);
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;
131 I
toReturn(*static_cast<I
*> (this));
132 if (_end_reached_
) sthrow(IteratorException
, "End of iterator");
133 else if (!hasNext()) {
134 _end_reached_
= true;
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
);
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
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
> {
197 typedef std::bidirectional_iterator_tag iterator_category
;
198 typedef ForwardIterator
<T
, I
> super
;
199 typedef BidirectionalIterator
<T
, I
> self_type
;
202 BidirectionalIterator(bool begin
= false) : super(begin
) {
205 BidirectionalIterator(const BidirectionalIterator
<T
, I
>& other
) :
206 ForwardIterator
<T
, I
>(other
) {
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");
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");
229 return *static_cast<I
*> (this);
234 I
toReturn(*static_cast<I
*> (this));
235 if (super::_end_reached_
) {
236 super::_end_reached_
= false;
238 } else if (!hasPrevious()) {
239 sthrow(IteratorException
, "Begin of iterator");
246 const I
operator--(int) const {
247 I
toReturn(*static_cast<I
*> (this));
248 if (super::_end_reached_
) {
249 super::_end_reached_
= false;
251 } else if (!hasPrevious()) {
252 sthrow(IteratorException
, "Begin of iterator");
259 virtual bool operator==(const I
& other
) const {
260 return ((super::_end_reached_
== other
._end_reached_
) ||
261 (hasPrevious() == other
.hasPrevious()))
262 && super::operator==(other
);
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
> {
275 typedef std::random_access_iterator_tag iterator_category
;
276 typedef BidirectionalIterator
<T
, I
> super
;
277 typedef RandomAccessIterator
<T
, I
> self_type
;
280 RandomAccessIterator(bool begin
= false) : super(begin
) {}
282 RandomAccessIterator(const self_type
& other
) :
286 I
& operator+=(unsigned int 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 {
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();
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
) {
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
364 class SylphIterator
: public virtual Object
{
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
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
;
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
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
421 virtual const typename
Iter::reference
previous() const {
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
430 * @note This requires that the backing iterator is a bidirectional
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
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
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
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
474 * @param t The item to replace the last returned item with.
476 virtual void set(typename
Iter::reference t
) {
481 * Synonymous for next()
483 const typename
Iter::reference
operator++() const {
488 * Synonymous for previous()
490 const typename
Iter::reference
operator--() const {
495 * Synoynmous for next().
496 * @note No copy of this iterator is made.
498 const typename
Iter::reference
operator++(int) const {
503 * Synonymous for previous()
504 * @note No copy is of this iterator is made.
506 const typename
Iter::reference
operator--(int) const {
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());
527 // Previously defined here, now defined elsewhere
530 #endif /* ITERATOR_H_ */