summaryrefslogtreecommitdiff
path: root/src/generic/util/enumerator.h
blob: 779a8b30787a6ce7fb188d32f0af70e7b38ff5d0 (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
/** \brief enumerator.h */    // -*-c++-*-

#ifndef ENUMERATOR_H
#define ENUMERATOR_H

#include <boost/shared_ptr.hpp>

namespace aptitude
{
  namespace util
  {
    /** \brief Utility class to allow generic iteration over a list.
     *
     *  Unlike an iterator, instantiations of this class can be used
     *  without the definition of the concrete object being visible to
     *  the user.  Like Java and .NET iterators, these iterators start
     *  "before" the list being iterated over and must be advanced to
     *  the first entry.
     */
    template<typename T>
    class enumerator
    {
    public:
      virtual ~enumerator() {}

      typedef T value_type;

      /** \brief Get the value at the current position. */
      virtual T get_current() = 0;

      /** \brief Advance to the next entry in the list.
       *
       *  \return \b true if there was another entry, or \b false if we
       *  reached the end of the list.
       */
      virtual bool advance() = 0;
    };

    /** \brief An enumerator over a range of STL iterators. */
    template<typename ForwardIter>
    class iterator_enumerator : public enumerator<typename ForwardIter::value_type>
    {
      ForwardIter begin, end;
      bool first;

    public:
      iterator_enumerator(ForwardIter _begin, ForwardIter _end);
      typename ForwardIter::value_type get_current();
      bool advance();
    };

    template<typename ForwardIter>
    iterator_enumerator<ForwardIter>::iterator_enumerator(ForwardIter _begin,
                                                          ForwardIter _end)
      : begin(_begin), end(_end), first(true)
    {
    }

    template<typename ForwardIter>
    typename ForwardIter::value_type
    iterator_enumerator<ForwardIter>::get_current()
    {
      return *begin;
    }

    template<typename ForwardIter>
    bool iterator_enumerator<ForwardIter>::advance()
    {
      if(begin == end)
        return false;

      if(first)
        first = false;
      else
        ++begin;

      return begin != end;
    }

    /** \brief An enumerator over an iterator range that holds a strong
     *  shared reference to an object (presumably the one containing the
     *  iterators).
     */
    template<typename ForwardIter, typename T>
    class iterator_enumerator_with_keepalive : public iterator_enumerator<ForwardIter>
    {
      boost::shared_ptr<T> keptalive;

    public:
      iterator_enumerator_with_keepalive(ForwardIter begin, ForwardIter end,
                                         boost::shared_ptr<T> _keptalive);
    };

    template<typename ForwardIter, typename T>
    iterator_enumerator_with_keepalive<ForwardIter, T>
    ::iterator_enumerator_with_keepalive(ForwardIter begin, ForwardIter end,
                                         boost::shared_ptr<T> _keptalive)
      : iterator_enumerator<ForwardIter>(begin, end),
        keptalive(_keptalive)
    {
    }
  }
}

#endif // ENUMERATOR_H