3 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * Copyright (C) 1997-2000 GLib Team and others
5 * Copyright (C) 2007-2009 Jürg Billeter
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 * Jürg Billeter <j@bitron.ch>
28 public delegate uint HashDataFunc<T> (T v);
29 public delegate bool EqualDataFunc<T> (T a, T b);
33 * Hash table implementation of the {@link Set} interface.
35 * This implementation is better fit for highly heterogenous values.
36 * In case of high value hashes redundancy or higher amount of data prefer using
37 * tree implementation like {@link TreeSet}.
41 public class Gee.HashSet<G> : AbstractSet<G> {
45 public override int size {
46 get { return _nnodes; }
52 public override bool read_only {
57 * The elements' hash function.
59 [CCode (notify = false)]
60 public HashDataFunc<G> hash_func { private set; get; }
63 * The elements' equality testing function.
65 [CCode (notify = false)]
66 public EqualDataFunc<G> equal_func { private set; get; }
68 private int _array_size;
70 private Node<G>[] _nodes;
72 // concurrent modification protection
73 private int _stamp = 0;
75 private const int MIN_SIZE = 11;
76 private const int MAX_SIZE = 13845163;
79 * Constructs a new, empty hash set.
81 * If not provided, the functions parameters are requested to the
82 * {@link Functions} function factory methods.
84 * @param hash_func an optional hash function
85 * @param equal_func an optional equality testing function
87 public HashSet (owned HashDataFunc? hash_func = null, owned EqualDataFunc? equal_func = null) {
88 if (hash_func == null) {
89 hash_func = Functions.get_hash_func_for (typeof (G));
91 if (equal_func == null) {
92 equal_func = Functions.get_equal_func_for (typeof (G));
94 this.hash_func = hash_func;
95 this.equal_func = equal_func;
96 _array_size = MIN_SIZE;
97 _nodes = new Node<G>[_array_size];
100 private Node<G>** lookup_node (G key) {
101 uint hash_value = hash_func (key);
102 Node<G>** node = &_nodes[hash_value % _array_size];
103 while ((*node) != null && (hash_value != (*node)->key_hash || !equal_func ((*node)->key, key))) {
104 node = &((*node)->next);
112 public override bool contains (G key) {
113 Node<G>** node = lookup_node (key);
114 return (*node != null);
120 public override Gee.Iterator<G> iterator () {
121 return new Iterator<G> (this);
127 public override bool add (G key) {
128 Node<G>** node = lookup_node (key);
132 uint hash_value = hash_func (key);
133 *node = new Node<G> (key, hash_value);
144 public override bool remove (G key) {
145 bool b = remove_helper(key);
155 public override void clear () {
156 for (int i = 0; i < _array_size; i++) {
157 Node<G> node = (owned) _nodes[i];
158 while (node != null) {
159 Node next = (owned) node.next;
168 private inline bool remove_helper (G key) {
169 Node<G>** node = lookup_node (key);
171 assert (*node != null);
172 Node<G> next = (owned) (*node)->next;
177 *node = (owned) next;
186 private void resize () {
187 if ((_array_size >= 3 * _nnodes && _array_size >= MIN_SIZE) ||
188 (3 * _array_size <= _nnodes && _array_size < MAX_SIZE)) {
189 int new_array_size = (int) SpacedPrimes.closest (_nnodes);
190 new_array_size = new_array_size.clamp (MIN_SIZE, MAX_SIZE);
192 Node<G>[] new_nodes = new Node<G>[new_array_size];
194 for (int i = 0; i < _array_size; i++) {
197 for (node = (owned) _nodes[i]; node != null; node = (owned) next) {
198 next = (owned) node.next;
199 uint hash_val = node.key_hash % new_array_size;
200 node.next = (owned) new_nodes[hash_val];
201 new_nodes[hash_val] = (owned) node;
204 _nodes = (owned) new_nodes;
205 _array_size = new_array_size;
214 private class Node<G> {
217 public uint key_hash;
219 public Node (owned G k, uint hash) {
225 private class Iterator<G> : Object, Traversable<G>, Gee.Iterator<G> {
226 private HashSet<G> _set;
227 private int _index = -1;
228 private weak Node<G> _node;
229 private weak Node<G> _next;
231 // concurrent modification protection
232 private int _stamp = 0;
234 public Iterator (HashSet set) {
236 _stamp = _set._stamp;
239 public bool next () {
240 assert (_stamp == _set._stamp);
246 return (_node != null);
249 public bool has_next () {
250 assert (_stamp == _set._stamp);
256 while (_next == null && _index + 1 < _set._array_size) {
258 _next = _set._nodes[_index];
261 return (_next != null);
264 public new G get () {
265 assert (_stamp == _set._stamp);
266 assert (_node != null);
270 public void remove () {
271 assert (_stamp == _set._stamp);
272 assert (_node != null);
274 _set.remove_helper (_node.key);
276 _stamp = _set._stamp;
279 public bool read_only {
287 return _node != null;
291 public bool foreach (ForallFunc<G> f) {
292 assert (_stamp == _set._stamp);
294 if (!f (_node.key)) {
298 while (_index + 1 < _set._array_size || _next != null) {
301 if (!f (_node.key)) {
307 _next = _set._nodes[_index];