diff options
Diffstat (limited to 'omegalib/omega/include/basic/Iterator.h')
-rw-r--r-- | omegalib/omega/include/basic/Iterator.h | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/omegalib/omega/include/basic/Iterator.h b/omegalib/omega/include/basic/Iterator.h new file mode 100644 index 0000000..8975d9e --- /dev/null +++ b/omegalib/omega/include/basic/Iterator.h @@ -0,0 +1,131 @@ +/* + * Base classes for iterators, generators + * + * These don't really work yet for constant collections. + * I'm not sure how to make that happen. + */ + +#if ! defined _Iterator_h +#define _Iterator_h 1 + +#include <basic/Collection.h> + +namespace omega { + +#define foreach(x,T,S,A) do {for (omega::Any_Iterator<T> __P_##x = (S).any_iterator();__P_##x;__P_##x++) {T & x = *__P_##x; A;}} while (0) + +#define foreachSeparated(x,T,S,A,B) do {for (omega::Any_Iterator<T> __P_##x = (S).any_iterator();__P_##x;) {T & x = *__P_##x; A; __P_##x++; if (__P_##x) B;}} while (0) + +/* + * Abstract base class Iterator<type> + * Supports two styles of iteration: + * + * for ( ... initialize i (typically i = collection) ... ; i ; i++ ) + * operate_on(*i) + * + * or + * + * for ( ... initialize i ... ; i.live() ; i.next() ) + * operate_on(i.curr()) + * + * >>> IF THE COLLECTION IS CHANGED, THE ITERATOR IS NO LONGER VALID <<< + * + * For collections that are not "Sequence"s, the order in + * which the elements are returned may not be consistent. + */ + +template<class T> class Iterator { +public: + virtual const T & operator*() const = 0; + virtual T & operator*() = 0; + + virtual void operator++(int) = 0; + virtual void operator++() = 0; + + virtual bool live() const = 0; + operator bool() const { return live(); } + + const T & curr() const { return *(*this); } + T & curr() { return *(*this); } + void next() { (*this)++; } + + virtual Iterator<T> *new_copy() const = 0; + virtual ~Iterator() {} +}; + + +// A generator is like an iterator but it gives out values, +// which may or may not exist in some writable collection + +template<class T> class Generator { +public: + virtual T operator*() const = 0; + + virtual void operator++(int) = 0; + virtual void operator++() = 0; + + virtual int live() const = 0; + operator int() const { return live(); } + + const T curr() const { return *(*this); } + T curr() { return *(*this); } + void next() { (*this)++; } +}; + + + +// Delegate to any kind of iterator (on the heap) +// If created via a reference, become a copy of the iterator +// If created via a pointer, manipulate that pointer and free *p when this dies +// +// Mostly useful for Collection::iterator +// Iterator::Iterator(Collection) + + +template<class T> class Any_Iterator : public Iterator<T> { +public: + Any_Iterator(Collection<T> &c); + Any_Iterator(const Iterator<T> &i); // copy of i + + virtual ~Any_Iterator() { delete me; } + + Any_Iterator<T> &operator=(const Any_Iterator<T> &rhs) + { delete me; me = rhs.me->new_copy(); return *this; } + + const T & operator*() const { return *(*me); } + T & operator*() { return *(*me); } + void operator++(int) { (*me)++; } + void operator++() { ++(*me); } + bool live() const { return (*me).live(); } + + Iterator<T> *new_copy() const { return new Any_Iterator<T>((*me).new_copy()); } + +private: + Any_Iterator(Iterator<T> *p) // take over *p, *p MUST BE ON THE HEAP + { me = p; } + friend class Collection<T>; +#if 0 + // Couldn't make this work with g++258 + friend Any_Iterator<T> Collection<T>::any_iterator(); +#endif + Iterator<T> *me; +}; + +template <class T> inline Any_Iterator<T>::Any_Iterator(Collection<T> &c) + { + me = c.new_iterator(); + } + +template <class T> inline Any_Iterator<T>::Any_Iterator(const Iterator<T> &i) + { + me = i.new_copy(); + } + +} // namespace + +#define instantiate_Iterator(T) template class Iterator<T>; +#define instantiate_Generator(T) template class Generator<T>; +#define instantiate_Any_Iterator(T) template class Any_Iterator<T>; \ + instantiate_Iterator(T) + +#endif |