summaryrefslogtreecommitdiff
path: root/omegalib/omega/include/basic/Iterator.h
blob: f62874c7ca3fcf7c30154e64eccfc5f2e4d637ae (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
/*
 * 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)

/*!
 * \brief 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
/*! Values 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:
    //! take over *p, *p MUST BE ON THE HEAP
    Any_Iterator(Iterator<T> *p) { me = p; }
    friend class Collection<T>;
/* 
 *   // Couldn't make this work with g++258
 *   friend Any_Iterator<T> Collection<T>::any_iterator();
 */
    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