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
|
// Copyright (c) 2001
// Kevin Atkinson
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without
// fee, provided that the above copyright notice appear in all copies
// and that both that copyright notice and this permission notice
// appear in supporting documentation. Kevin Atkinson makes no
// representations about the suitability of this software for any
// purpose. It is provided "as is" without express or implied
// warranty.
#ifndef __autil_enumeration__
#define __autil_enumeration__
#include "clone_ptr-t.hpp"
// An enumeration is an efficient way to iterate through elements much
// like a forward iterator. The at_end method is a convince method
// as enumerations will return a null pointer or some other sort of
// special end state when they are at the end.
// Unlike an iterator iterating through x elements on a list can be
// done in x function calls while an iterator will require 3*x.
// function calls.
// Example of emulator usage
// const char * word;
// while ( (word = elements->next()) != 0) { // one function call
// cout << word << endl;
// }
// And an iterator
// iterator i = container->begin();
// iterator end = container->end();
// while (i != end) { // comparison, one function call
// cout << *i << endl; // deref, total of two function calls
// ++i; // increment, total of three function calls.
// }
// Normally all three calls are inline so it doesn't really matter
// but when the container type is not visible there are not inline
// and probably even virtual.
// If you really love iterators you can very easily wrap an enumeration
// in a forward iterator.
namespace acommon {
template <typename Val>
class Enumeration {
public:
typedef Val Value;
typedef Enumeration Base;
virtual Enumeration * clone() const = 0;
virtual void assign(const Enumeration *) = 0;
virtual Value next() = 0;
virtual bool at_end() const = 0;
virtual ~Enumeration() {}
};
template <class Parms, class Enum = Enumeration<typename Parms::Value> >
// Parms is expected to have the following members:
// typename Value
// typename Iterator;
// bool endf(Iterator)
// Value end_state()
// Value deref(Iterator)
class MakeEnumeration : public Enum {
public:
typedef typename Parms::Iterator Iterator;
typedef typename Parms::Value Value;
private:
Iterator i_;
Parms parms_;
public:
MakeEnumeration(const Iterator i, const Parms & p = Parms())
: i_(i), parms_(p) {}
Enum * clone() const {
return new MakeEnumeration(*this);
}
void assign (const Enum * other) {
*this = *static_cast<const MakeEnumeration *>(other);
}
Value next() {
if (parms_.endf(i_))
return parms_.end_state();
Value temp = parms_.deref(i_);
++i_;
return temp;
}
bool at_end() const {
return parms_.endf(i_);
}
};
template <class Value>
struct MakeAlwaysEndEnumerationParms {
Value end_state() const {return Value();}
};
template <class Value>
struct MakeAlwaysEndEnumerationParms<Value *> {
Value * end_state() const {return 0;}
};
template <class Value>
class MakeAlwaysEndEnumeration : public Enumeration<Value> {
MakeAlwaysEndEnumerationParms<Value> parms_;
public:
MakeAlwaysEndEnumeration * clone() const {
return new MakeAlwaysEndEnumeration(*this);
}
void assign(const Enumeration<Value> * that) {
*this = *static_cast<const MakeAlwaysEndEnumeration *>(that);
}
Value next() {return parms_.end_state();}
bool at_end() const {return true;}
};
}
#endif
|