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 Set interface.
30 public class Vala
.HashSet
<G
> : Set
<G
> {
31 public override int size
{
32 get { return _nnodes
; }
35 public HashFunc
<G
> hash_func
{
36 set { _hash_func
= value
; }
39 public EqualFunc
<G
> equal_func
{
40 set { _equal_func
= value
; }
43 private int _array_size
;
45 private Node
<G
>[] _nodes
;
47 // concurrent modification protection
48 private int _stamp
= 0;
50 private HashFunc
<G
> _hash_func
;
51 private EqualFunc
<G
> _equal_func
;
53 private const int MIN_SIZE
= 11;
54 private const int MAX_SIZE
= 13845163;
56 public HashSet (HashFunc
<G
> hash_func
= GLib
.direct_hash
, EqualFunc
<G
> 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
);
72 public override bool contains (G key
) {
73 Node
<G
>** node
= lookup_node (key
);
74 return (*node
!= null);
77 public override Type
get_element_type () {
81 public override Vala
.Iterator
<G
> iterator () {
82 return new Iterator
<G
> (this
);
85 public override bool add (G key
) {
86 Node
<G
>** node
= lookup_node (key
);
90 uint hash_value
= _hash_func (key
);
91 *node
= new Node
<G
> (key
, hash_value
);
99 public override bool remove (G key
) {
100 Node
<G
>** node
= lookup_node (key
);
102 Node
<G
> next
= (owned
) (*node
)->next
;
107 *node
= (owned
) next
;
117 public override 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
;
130 private inline
bool remove_helper (G key
) {
131 Node
<G
>** node
= lookup_node (key
);
133 assert (*node
!= null);
134 Node
<G
> next
= (owned
) (*node
)->next
;
139 *node
= (owned
) next
;
148 private void resize () {
149 if ((_array_size
>= 3 * _nnodes
&& _array_size
>= MIN_SIZE
) ||
150 (3 * _array_size
<= _nnodes
&& _array_size
< MAX_SIZE
)) {
151 int new_array_size
= (int) SpacedPrimes
.closest (_nnodes
);
152 new_array_size
= new_array_size
.clamp (MIN_SIZE
, MAX_SIZE
);
154 Node
<G
>[] new_nodes
= new Node
<G
>[new_array_size
];
156 for (int i
= 0; i
< _array_size
; i
++) {
159 for (node
= (owned
) _nodes
[i
]; node
!= null; node
= (owned
) next
) {
160 next
= (owned
) node
.next
;
161 uint hash_val
= node
.key_hash
% new_array_size
;
162 node
.next
= (owned
) new_nodes
[hash_val
];
163 new_nodes
[hash_val
] = (owned
) node
;
166 _nodes
= (owned
) new_nodes
;
167 _array_size
= new_array_size
;
176 private class Node
<G
> {
179 public uint key_hash
;
181 public Node (owned G k
, uint hash
) {
187 private class Iterator
<G
> : Vala
.Iterator
<G
> {
188 public HashSet
<G
> set {
191 _stamp
= _set
._stamp
;
195 private HashSet
<G
> _set
;
196 private int _index
= -1;
197 private weak Node
<G
> _node
;
198 private weak Node
<G
> _next
;
200 // concurrent modification protection
201 private int _stamp
= 0;
203 public Iterator (HashSet
set) {
207 public override bool next () {
208 assert (_stamp
== _set
._stamp
);
214 return (_node
!= null);
217 public override bool has_next () {
218 assert (_stamp
== _set
._stamp
);
224 while (_next
== null && _index
+ 1 < _set
._array_size
) {
226 _next
= _set
._nodes
[_index
];
229 return (_next
!= null);
232 public override G?
get () {
233 assert (_stamp
== _set
._stamp
);
234 assert (_node
!= null);
238 public override void remove () {
239 assert (_stamp
== _set
._stamp
);
240 assert (_node
!= null);
242 _set
.remove_helper (_node
.key
);
244 _stamp
= _set
._stamp
;
247 public override bool valid
{
249 return _node
!= null;