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 * Hashtable implementation of the Map interface.
30 public class Vala
.HashMap
<K
,V
> : CollectionObject
, Map
<K
,V
> {
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
;
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
);
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
));
100 public void set (K key
, V value
) {
101 Node
<K
,V
>** node
= lookup_node (key
);
103 (*node
)->value
= value
;
105 uint hash_value
= _key_hash_func (key
);
106 *node
= new Node
<K
,V
> (key
, value
, hash_value
);
113 public bool remove (K key
) {
114 Node
<K
,V
>** node
= lookup_node (key
);
116 Node
<K
,V
> next
= (owned
) (*node
)->next
;
119 (*node
)->value
= null;
122 *node
= (owned
) next
;
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
;
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
++) {
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
;
174 private class Node
<K
,V
> {
177 public Node
<K
,V
> next
;
178 public uint key_hash
;
180 public Node (owned K k
, owned V v
, uint 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
) {
198 public Type
get_element_type () {
202 public Iterator
<K
> iterator () {
203 return new KeyIterator
<K
,V
> (_map
);
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
{
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
242 public KeyIterator (HashMap map
) {
246 public bool next () {
250 while (_node
== null && _index
+ 1 < _map
._array_size
) {
252 _node
= _map
._nodes
[_index
];
254 return (_node
!= null);
258 assert (_stamp
== _map
._stamp
);
259 assert (_node
!= null);
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
) {
275 public Type
get_element_type () {
279 public Iterator
<V
> iterator () {
280 return new ValueIterator
<K
,V
> (_map
);
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 ();
302 if (_map
._value_equal_func (it
.get (), value
)) {
310 private class ValueIterator
<K
,V
> : CollectionObject
, Iterator
<V
> {
311 public HashMap
<K
,V
> map
{
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
325 public ValueIterator (HashMap map
) {
329 public bool next () {
333 while (_node
== null && _index
+ 1 < _map
._array_size
) {
335 _node
= _map
._nodes
[_index
];
337 return (_node
!= null);
341 assert (_stamp
== _map
._stamp
);
342 assert (_node
!= null);