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 reference
operator->() {
85 if (_end_reached_
) sthrow(IteratorException
,
86 "Tried to dereference an beyond-end iterator");
90 const reference
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_
;
191 template<class T
, class I
>
192 class BidirectionalIterator
: public ForwardIterator
<T
, I
> {
194 typedef std::bidirectional_iterator_tag iterator_category
;
195 typedef ForwardIterator
<T
, I
> super
;
196 typedef BidirectionalIterator
<T
, I
> self_type
;
199 BidirectionalIterator(bool begin
= false) : super(begin
) {
202 BidirectionalIterator(const BidirectionalIterator
<T
, I
>& other
) :
203 ForwardIterator
<T
, I
>(other
) {
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");
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");
226 return *static_cast<I
*> (this);
231 I
toReturn(*static_cast<I
*> (this));
232 if (super::_end_reached_
) {
233 super::_end_reached_
= false;
235 } else if (!hasPrevious()) {
236 sthrow(IteratorException
, "Begin of iterator");
243 const I
operator--(int) const {
244 I
toReturn(*static_cast<I
*> (this));
245 if (super::_end_reached_
) {
246 super::_end_reached_
= false;
248 } else if (!hasPrevious()) {
249 sthrow(IteratorException
, "Begin of iterator");
256 virtual bool operator==(const I
& other
) const {
257 return ((super::_end_reached_
== other
._end_reached_
) ||
258 (hasPrevious() == other
.hasPrevious()))
259 && super::operator==(other
);
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
> {
269 typedef std::random_access_iterator_tag iterator_category
;
270 typedef BidirectionalIterator
<T
, I
> super
;
271 typedef RandomAccessIterator
<T
, I
> self_type
;
274 RandomAccessIterator(bool begin
= false) : super(begin
) {}
276 RandomAccessIterator(const self_type
& other
) :
280 I
& operator+=(unsigned int 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 {
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();
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
) {
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
358 class SylphIterator
: public virtual Object
{
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
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
;
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
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
415 virtual const typename
Iter::reference
previous() const {
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
424 * @note This requires that the backing iterator is a bidirectional
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
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
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
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
468 * @param t The item to replace the last returned item with.
470 virtual void set(typename
Iter::reference t
) {
475 * Synonymous for next()
477 const typename
Iter::reference
operator++() const {
482 * Synonymous for previous()
484 const typename
Iter::reference
operator--() const {
489 * Synoynmous for next().
490 * @note No copy of this iterator is made.
492 const typename
Iter::reference
operator++(int) const {
497 * Synonymous for previous()
498 * @note No copy is of this iterator is made.
500 const typename
Iter::reference
operator--(int) const {
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());
521 // Previously defined here, now defined elsewhere
524 #endif /* ITERATOR_H_ */