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 Gee
.HashSet
<G
> : CollectionObject
, Iterable
<G
>, Collection
<G
>, Set
<G
> {
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
;
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
);
72 public bool contains (G key
) {
73 Node
<G
>** node
= lookup_node (key
);
74 return (*node
!= null);
77 public Type
get_element_type () {
81 public Gee
.Iterator
<G
> iterator () {
82 return new Iterator
<G
> (this
);
85 public 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 bool remove (G key
) {
100 Node
<G
>** node
= lookup_node (key
);
103 *node
= (*node
)->next
;
112 public void clear () {
113 for (int i
= 0; i
< _array_size
; i
++) {
114 Node
<G
> node
= (owned
) _nodes
[i
];
115 while (node
!= null) {
116 Node next
= (owned
) node
.next
;
125 private void resize () {
126 if ((_array_size
>= 3 * _nnodes
&& _array_size
>= MIN_SIZE
) ||
127 (3 * _array_size
<= _nnodes
&& _array_size
< MAX_SIZE
)) {
128 int new_array_size
= (int) SpacedPrimes
.closest (_nnodes
);
129 new_array_size
= new_array_size
.clamp (MIN_SIZE
, MAX_SIZE
);
131 Node
<G
>[] new_nodes
= new Node
<G
>[new_array_size
];
133 for (int i
= 0; i
< _array_size
; i
++) {
136 for (node
= (owned
) _nodes
[i
]; node
!= null; node
= (owned
) next
) {
137 next
= (owned
) node
.next
;
138 uint hash_val
= node
.key_hash
% new_array_size
;
139 node
.next
= (owned
) new_nodes
[hash_val
];
140 new_nodes
[hash_val
] = (owned
) node
;
143 _nodes
= (owned
) new_nodes
;
144 _array_size
= new_array_size
;
153 private class Node
<G
> {
156 public uint key_hash
;
158 public Node (owned G k
, uint hash
) {
164 private class Iterator
<G
> : CollectionObject
, Gee
.Iterator
<G
> {
165 public HashSet
<G
> set {
168 _stamp
= _set
._stamp
;
172 private HashSet
<G
> _set
;
173 private int _index
= -1;
174 private weak Node
<G
> _node
;
176 // concurrent modification protection
177 private int _stamp
= 0;
179 public Iterator (HashSet
set) {
183 public bool next () {
187 while (_node
== null && _index
+ 1 < _set
._array_size
) {
189 _node
= _set
._nodes
[_index
];
191 return (_node
!= null);
195 assert (_stamp
== _set
._stamp
);
196 assert (_node
!= null);