Release 0.7.8
[vala-lang.git] / gee / hashmap.vala
blob79bcf1c4de5d9be084c94de44dae9d242bed3142
1 /* hashmap.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 Map interface.
30 public class Vala.HashMap<K,V> : CollectionObject, Map<K,V> {
31 public int size {
32 get { return _nnodes; }
35 public HashFunc key_hash_func {
36 set { _key_hash_func = value; }
39 public EqualFunc key_equal_func {
40 set { _key_equal_func = value; }
43 public EqualFunc value_equal_func {
44 set { _value_equal_func = value; }
47 private int _array_size;
48 private int _nnodes;
49 private Node<K,V>[] _nodes;
51 // concurrent modification protection
52 private int _stamp = 0;
54 private HashFunc _key_hash_func;
55 private EqualFunc _key_equal_func;
56 private EqualFunc _value_equal_func;
58 private const int MIN_SIZE = 11;
59 private const int MAX_SIZE = 13845163;
61 public HashMap (HashFunc key_hash_func = GLib.direct_hash, EqualFunc key_equal_func = GLib.direct_equal, EqualFunc value_equal_func = GLib.direct_equal) {
62 this.key_hash_func = key_hash_func;
63 this.key_equal_func = key_equal_func;
64 this.value_equal_func = value_equal_func;
65 _array_size = MIN_SIZE;
66 _nodes = new Node<K,V>[_array_size];
69 public Set<K> get_keys () {
70 return new KeySet<K,V> (this);
73 public Collection<V> get_values () {
74 return new ValueCollection<K,V> (this);
77 private Node<K,V>** lookup_node (K key) {
78 uint hash_value = _key_hash_func (key);
79 Node<K,V>** node = &_nodes[hash_value % _array_size];
80 while ((*node) != null && (hash_value != (*node)->key_hash || !_key_equal_func ((*node)->key, key))) {
81 node = &((*node)->next);
83 return node;
86 public bool contains (K key) {
87 Node<K,V>** node = lookup_node (key);
88 return (*node != null);
91 public V? get (K key) {
92 Node<K,V>* node = (*lookup_node (key));
93 if (node != null) {
94 return node->value;
95 } else {
96 return null;
100 public void set (K key, V value) {
101 Node<K,V>** node = lookup_node (key);
102 if (*node != null) {
103 (*node)->value = value;
104 } else {
105 uint hash_value = _key_hash_func (key);
106 *node = new Node<K,V> (key, value, hash_value);
107 _nnodes++;
108 resize ();
110 _stamp++;
113 public bool remove (K key) {
114 Node<K,V>** node = lookup_node (key);
115 if (*node != null) {
116 Node<K,V> next = (owned) (*node)->next;
118 (*node)->key = null;
119 (*node)->value = null;
120 delete *node;
122 *node = (owned) next;
124 _nnodes--;
125 resize ();
126 _stamp++;
127 return true;
129 return false;
132 public void clear () {
133 for (int i = 0; i < _array_size; i++) {
134 Node<K,V> node = (owned) _nodes[i];
135 while (node != null) {
136 Node next = (owned) node.next;
137 node.key = null;
138 node.value = null;
139 node = (owned) next;
142 _nnodes = 0;
143 resize ();
146 private void resize () {
147 if ((_array_size >= 3 * _nnodes && _array_size >= MIN_SIZE) ||
148 (3 * _array_size <= _nnodes && _array_size < MAX_SIZE)) {
149 int new_array_size = (int) SpacedPrimes.closest (_nnodes);
150 new_array_size = new_array_size.clamp (MIN_SIZE, MAX_SIZE);
152 Node<K,V>[] new_nodes = new Node<K,V>[new_array_size];
154 for (int i = 0; i < _array_size; i++) {
155 Node<K,V> node;
156 Node<K,V> next = null;
157 for (node = (owned) _nodes[i]; node != null; node = (owned) next) {
158 next = (owned) node.next;
159 uint hash_val = node.key_hash % new_array_size;
160 node.next = (owned) new_nodes[hash_val];
161 new_nodes[hash_val] = (owned) node;
164 _nodes = (owned) new_nodes;
165 _array_size = new_array_size;
169 ~HashSet () {
170 clear ();
173 [Compact]
174 private class Node<K,V> {
175 public K key;
176 public V value;
177 public Node<K,V> next;
178 public uint key_hash;
180 public Node (owned K k, owned V v, uint hash) {
181 key = (owned) k;
182 value = (owned) v;
183 key_hash = hash;
187 private class KeySet<K,V> : CollectionObject, Iterable<K>, Collection<K>, Set<K> {
188 public HashMap<K,V> map {
189 set { _map = value; }
192 private HashMap<K,V> _map;
194 public KeySet (HashMap map) {
195 this.map = map;
198 public Type get_element_type () {
199 return typeof (K);
202 public Iterator<K> iterator () {
203 return new KeyIterator<K,V> (_map);
206 public int size {
207 get { return _map.size; }
210 public bool add (K key) {
211 assert_not_reached ();
214 public void clear () {
215 assert_not_reached ();
218 public bool remove (K key) {
219 assert_not_reached ();
222 public bool contains (K key) {
223 return _map.contains (key);
227 private class KeyIterator<K,V> : CollectionObject, Iterator<K> {
228 public HashMap<K,V> map {
229 set {
230 _map = value;
231 _stamp = _map._stamp;
235 private HashMap<K,V> _map;
236 private int _index = -1;
237 private weak Node<K,V> _node;
239 // concurrent modification protection
240 private int _stamp;
242 public KeyIterator (HashMap map) {
243 this.map = map;
246 public bool next () {
247 if (_node != null) {
248 _node = _node.next;
250 while (_node == null && _index + 1 < _map._array_size) {
251 _index++;
252 _node = _map._nodes[_index];
254 return (_node != null);
257 public K? get () {
258 assert (_stamp == _map._stamp);
259 assert (_node != null);
260 return _node.key;
264 private class ValueCollection<K,V> : CollectionObject, Iterable<V>, Collection<V> {
265 public HashMap<K,V> map {
266 set { _map = value; }
269 private HashMap<K,V> _map;
271 public ValueCollection (HashMap map) {
272 this.map = map;
275 public Type get_element_type () {
276 return typeof (V);
279 public Iterator<V> iterator () {
280 return new ValueIterator<K,V> (_map);
283 public int size {
284 get { return _map.size; }
287 public bool add (V value) {
288 assert_not_reached ();
291 public void clear () {
292 assert_not_reached ();
295 public bool remove (V value) {
296 assert_not_reached ();
299 public bool contains (V value) {
300 Iterator<V> it = iterator ();
301 while (it.next ()) {
302 if (_map._value_equal_func (it.get (), value)) {
303 return true;
306 return false;
310 private class ValueIterator<K,V> : CollectionObject, Iterator<V> {
311 public HashMap<K,V> map {
312 set {
313 _map = value;
314 _stamp = _map._stamp;
318 private HashMap<V,K> _map;
319 private int _index = -1;
320 private weak Node<K,V> _node;
322 // concurrent modification protection
323 private int _stamp;
325 public ValueIterator (HashMap map) {
326 this.map = map;
329 public bool next () {
330 if (_node != null) {
331 _node = _node.next;
333 while (_node == null && _index + 1 < _map._array_size) {
334 _index++;
335 _node = _map._nodes[_index];
337 return (_node != null);
340 public V? get () {
341 assert (_stamp == _map._stamp);
342 assert (_node != null);
343 return _node.value;