File: enumeration.hpp

package info (click to toggle)
aspell 0.60.6-1
  • links: PTS
  • area: main
  • in suites: lenny
  • size: 10,000 kB
  • ctags: 4,862
  • sloc: sh: 48,145; cpp: 22,153; perl: 1,546; ansic: 1,535; makefile: 684; sed: 16
file content (123 lines) | stat: -rw-r--r-- 3,743 bytes parent folder | download | duplicates (12)
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