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 (void* v);
29 public delegate bool EqualDataFunc (void* a, void* 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; }
50 * The elements' hash function.
52 public HashDataFunc<G> hash_func { private set; get; }
55 * The elements' equality testing function.
57 public EqualDataFunc<G> equal_func { private set; get; }
59 private int _array_size;
61 private Node<G>[] _nodes;
63 // concurrent modification protection
64 private int _stamp = 0;
66 private const int MIN_SIZE = 11;
67 private const int MAX_SIZE = 13845163;
70 * Constructs a new, empty hash set.
72 * If not provided, the functions parameters are requested to the
73 * {@link Functions} function factory methods.
75 * @param hash_func an optional hash function
76 * @param equal_func an optional equality testing function
78 public HashSet (owned HashDataFunc? hash_func = null, owned EqualDataFunc? equal_func = null) {
79 if (hash_func == null) {
80 hash_func = Functions.get_hash_func_for (typeof (G));
82 if (equal_func == null) {
83 equal_func = Functions.get_equal_func_for (typeof (G));
85 this.hash_func = hash_func;
86 this.equal_func = equal_func;
87 _array_size = MIN_SIZE;
88 _nodes = new Node<G>[_array_size];
91 private Node<G>** lookup_node (G key) {
92 uint hash_value = hash_func (key);
93 Node<G>** node = &_nodes[hash_value % _array_size];
94 while ((*node) != null && (hash_value != (*node)->key_hash || !equal_func ((*node)->key, key))) {
95 node = &((*node)->next);
103 public override bool contains (G key) {
104 Node<G>** node = lookup_node (key);
105 return (*node != null);
111 public override Gee.Iterator<G> iterator () {
112 return new Iterator<G> (this);
118 public override bool add (G key) {
119 Node<G>** node = lookup_node (key);
123 uint hash_value = hash_func (key);
124 *node = new Node<G> (key, hash_value);
135 public override bool remove (G key) {
136 Node<G>** node = lookup_node (key);
138 assert (*node != null);
139 Node<G> next = (owned) (*node)->next;
144 *node = (owned) next;
157 public override void clear () {
158 for (int i = 0; i < _array_size; i++) {
159 Node<G> node = (owned) _nodes[i];
160 while (node != null) {
161 Node next = (owned) node.next;
170 private void resize () {
171 if ((_array_size >= 3 * _nnodes && _array_size >= MIN_SIZE) ||
172 (3 * _array_size <= _nnodes && _array_size < MAX_SIZE)) {
173 int new_array_size = (int) SpacedPrimes.closest (_nnodes);
174 new_array_size = new_array_size.clamp (MIN_SIZE, MAX_SIZE);
176 Node<G>[] new_nodes = new Node<G>[new_array_size];
178 for (int i = 0; i < _array_size; i++) {
181 for (node = (owned) _nodes[i]; node != null; node = (owned) next) {
182 next = (owned) node.next;
183 uint hash_val = node.key_hash % new_array_size;
184 node.next = (owned) new_nodes[hash_val];
185 new_nodes[hash_val] = (owned) node;
188 _nodes = (owned) new_nodes;
189 _array_size = new_array_size;
198 private class Node<G> {
201 public uint key_hash;
203 public Node (owned G k, uint hash) {
209 private class Iterator<G> : Object, Gee.Iterator<G> {
210 private HashSet<G> _set;
211 private int _index = -1;
212 private weak Node<G> _node;
213 private weak Node<G> _next;
215 // concurrent modification protection
216 private int _stamp = 0;
218 public Iterator (HashSet set) {
220 _stamp = _set._stamp;
223 public bool next () {
224 assert (_stamp == _set._stamp);
230 return (_node != null);
233 public bool has_next () {
234 assert (_stamp == _set._stamp);
240 while (_next == null && _index + 1 < _set._array_size) {
242 _next = _set._nodes[_index];
245 return (_next != null);
248 public new G get () {
249 assert (_stamp == _set._stamp);
250 assert (_node != null);
254 public void remove () {
255 assert (_stamp == _set._stamp);
256 assert (_node != null);
258 _set.remove (_node.key);
260 _stamp = _set._stamp;