summaryrefslogtreecommitdiff
path: root/omegalib/omega/include/basic/Iterator.h
diff options
context:
space:
mode:
Diffstat (limited to 'omegalib/omega/include/basic/Iterator.h')
-rw-r--r--omegalib/omega/include/basic/Iterator.h131
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