summaryrefslogtreecommitdiff
path: root/lib/gl_set.hh
blob: 338baa8b0f2db8d4966eeb107f1ea2ea85d9be93 (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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
/* Abstract set data type as a C++ class.
   Copyright (C) 2006-2021 Free Software Foundation, Inc.
   Written by Bruno Haible <bruno@clisp.org>, 2018.

   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */

#ifndef _GL_SET_HH
#define _GL_SET_HH

#include "gl_set.h"
#include "gl_xset.h"

#include <stdlib.h>     /* because Gnulib's <stdlib.h> may '#define free ...' */

/* gl_Set is a C++ wrapper around the gl_set data type.
   Its element type is 'ELTYPE *'.

   It is merely a pointer, not a smart pointer. In other words:
   it does NOT do reference-counting, and the destructor does nothing.  */

template <class T> class gl_Set;

template <class ELTYPE>
class gl_Set<ELTYPE *>
{
public:
  // ------------------------------ Constructors ------------------------------

  gl_Set ()
    : _ptr (NULL)
    {}

  /* Creates an empty set.
     IMPLEMENTATION is one of GL_ARRAY_SET, GL_LINKEDHASH_SET, GL_HASH_SET.
     EQUALS_FN is an element comparison function or NULL.
     HASHCODE_FN is an element hash code function or NULL.
     DISPOSE_FN is an element disposal function or NULL.  */
  gl_Set (gl_set_implementation_t implementation,
          bool (*equals_fn) (ELTYPE * /*elt1*/, ELTYPE * /*elt2*/),
          size_t (*hashcode_fn) (ELTYPE *),
          void (*dispose_fn) (ELTYPE *))
    : _ptr (gl_set_create_empty (implementation,
                                 reinterpret_cast<gl_setelement_equals_fn>(equals_fn),
                                 reinterpret_cast<gl_setelement_hashcode_fn>(hashcode_fn),
                                 reinterpret_cast<gl_setelement_dispose_fn>(dispose_fn)))
    {}

  /* Copy constructor.  */
  gl_Set (const gl_Set& x)
    { _ptr = x._ptr; }

  /* Assignment operator.  */
  gl_Set& operator= (const gl_Set& x)
    { _ptr = x._ptr; return *this; }

  // ------------------------------- Destructor -------------------------------

  ~gl_Set ()
    { _ptr = NULL; }

  // ----------------------- Read-only member functions -----------------------

  /* Returns the current number of elements in the set.  */
  size_t size () const
    { return gl_set_size (_ptr); }

  /* Searches whether an element is already in the set.
     Returns true if found, or false if not present in the set.  */
  bool search (ELTYPE * elt) const
    { return gl_set_search (_ptr, elt); }

  // ----------------------- Modifying member functions -----------------------

  /* Adds an element to the set.
     Returns true if it was not already in the set and added, false otherwise.  */
  bool add (ELTYPE * elt)
    { return gl_set_add (_ptr, elt); }

  /* Removes an element from the set.
     Returns true if it was found and removed.  */
  bool remove (ELTYPE * elt)
    { return gl_set_remove (_ptr, elt); }

  /* Frees the entire set.
     (But this call does not free the elements of the set.  It only invokes
     the DISPOSE_FN on each of the elements of the set.)  */
  void free ()
    { gl_set_free (_ptr); _ptr = NULL; }

  // ------------------------------ Private stuff ------------------------------

private:
  gl_set_t _ptr;

public:
  // -------------------------------- Iterators --------------------------------
  // Only a forward iterator.
  // Does not implement the STL operations (++, *, and != .end()), but a simpler
  // interface that needs only one virtual function call per iteration instead
  // of three.

  class iterator {
  public:

    /* If there is a next element, stores the next element in ELT, advances the
       iterator and returns true.  Otherwise, returns false.  */
    bool next (ELTYPE *& elt)
      {
        const void *next_elt;
        bool has_next = gl_set_iterator_next (&_state, &next_elt);
        if (has_next)
          elt = static_cast<ELTYPE *>(next_elt);
        return has_next;
      }

    ~iterator ()
      { gl_set_iterator_free (&_state); }

  #if defined __xlC__ || defined __HP_aCC || defined __SUNPRO_CC
  public:
  #else
  private:
    friend iterator gl_Set::begin ();
  #endif

    iterator (gl_set_t ptr)
      : _state (gl_set_iterator (ptr))
      {}

  private:

    gl_set_iterator_t _state;
  };

  /* Creates an iterator traversing the set.
     The set's contents must not be modified while the iterator is in use,
     except for removing the last returned element.  */
  iterator begin ()
    { return iterator (_ptr); }
};

#endif /* _GL_SET_HH */