Release 0.7.8
[vala-lang.git] / gee / hashset.vala
blob7f188e18ab7b80b26febf4b20eb9432a93d47d73
1 /* hashset.vala
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
21 * Author:
22 * Jürg Billeter <j@bitron.ch>
25 using GLib;
27 /**
28 * Hashtable implementation of the Set interface.
30 public class Vala.HashSet<G> : CollectionObject, Iterable<G>, Collection<G>, Set<G> {
31 public int size {
32 get { return _nnodes; }
35 public HashFunc hash_func {
36 set { _hash_func = value; }
39 public EqualFunc equal_func {
40 set { _equal_func = value; }
43 private int _array_size;
44 private int _nnodes;
45 private Node<G>[] _nodes;
47 // concurrent modification protection
48 private int _stamp = 0;
50 private HashFunc _hash_func;
51 private EqualFunc _equal_func;
53 private const int MIN_SIZE = 11;
54 private const int MAX_SIZE = 13845163;
56 public HashSet (HashFunc hash_func = GLib.direct_hash, EqualFunc equal_func = GLib.direct_equal) {
57 this.hash_func = hash_func;
58 this.equal_func = equal_func;
59 _array_size = MIN_SIZE;
60 _nodes = new Node<G>[_array_size];
63 private Node<G>** lookup_node (G key) {
64 uint hash_value = _hash_func (key);
65 Node<G>** node = &_nodes[hash_value % _array_size];
66 while ((*node) != null && (hash_value != (*node)->key_hash || !_equal_func ((*node)->key, key))) {
67 node = &((*node)->next);
69 return node;
72 public bool contains (G key) {
73 Node<G>** node = lookup_node (key);
74 return (*node != null);
77 public Type get_element_type () {
78 return typeof (G);
81 public Vala.Iterator<G> iterator () {
82 return new Iterator<G> (this);
85 public bool add (G key) {
86 Node<G>** node = lookup_node (key);
87 if (*node != null) {
88 return false;
89 } else {
90 uint hash_value = _hash_func (key);
91 *node = new Node<G> (key, hash_value);
92 _nnodes++;
93 resize ();
94 _stamp++;
95 return true;
99 public bool remove (G key) {
100 Node<G>** node = lookup_node (key);
101 if (*node != null) {
102 Node<G> next = (owned) (*node)->next;
104 (*node)->key = null;
105 delete *node;
107 *node = (owned) next;
109 _nnodes--;
110 resize ();
111 _stamp++;
112 return true;
114 return false;
117 public void clear () {
118 for (int i = 0; i < _array_size; i++) {
119 Node<G> node = (owned) _nodes[i];
120 while (node != null) {
121 Node next = (owned) node.next;
122 node.key = null;
123 node = (owned) next;
126 _nnodes = 0;
127 resize ();
130 private void resize () {
131 if ((_array_size >= 3 * _nnodes && _array_size >= MIN_SIZE) ||
132 (3 * _array_size <= _nnodes && _array_size < MAX_SIZE)) {
133 int new_array_size = (int) SpacedPrimes.closest (_nnodes);
134 new_array_size = new_array_size.clamp (MIN_SIZE, MAX_SIZE);
136 Node<G>[] new_nodes = new Node<G>[new_array_size];
138 for (int i = 0; i < _array_size; i++) {
139 Node<G> node;
140 Node<G> next = null;
141 for (node = (owned) _nodes[i]; node != null; node = (owned) next) {
142 next = (owned) node.next;
143 uint hash_val = node.key_hash % new_array_size;
144 node.next = (owned) new_nodes[hash_val];
145 new_nodes[hash_val] = (owned) node;
148 _nodes = (owned) new_nodes;
149 _array_size = new_array_size;
153 ~HashSet () {
154 clear ();
157 [Compact]
158 private class Node<G> {
159 public G key;
160 public Node<G> next;
161 public uint key_hash;
163 public Node (owned G k, uint hash) {
164 key = (owned) k;
165 key_hash = hash;
169 private class Iterator<G> : CollectionObject, Vala.Iterator<G> {
170 public HashSet<G> set {
171 set {
172 _set = value;
173 _stamp = _set._stamp;
177 private HashSet<G> _set;
178 private int _index = -1;
179 private weak Node<G> _node;
181 // concurrent modification protection
182 private int _stamp = 0;
184 public Iterator (HashSet set) {
185 this.set = set;
188 public bool next () {
189 if (_node != null) {
190 _node = _node.next;
192 while (_node == null && _index + 1 < _set._array_size) {
193 _index++;
194 _node = _set._nodes[_index];
196 return (_node != null);
199 public G? get () {
200 assert (_stamp == _set._stamp);
201 assert (_node != null);
202 return _node.key;