This source file includes following definitions.
- gl_hash_nx_create_empty
- gl_hash_size
- gl_hash_search
- gl_hash_nx_add
- gl_hash_remove
- gl_hash_free
- gl_hash_iterator
- gl_hash_iterator_next
- gl_hash_iterator_free
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 #include <config.h>
19
20
21 #include "gl_hash_set.h"
22
23 #include <stdint.h>
24 #include <stdlib.h>
25
26 #include "xsize.h"
27
28
29
30 #include "gl_anyhash1.h"
31
32
33 struct gl_list_node_impl
34 {
35 struct gl_hash_entry h;
36 const void *value;
37 };
38 typedef struct gl_list_node_impl * gl_list_node_t;
39
40
41 struct gl_set_impl
42 {
43 struct gl_set_impl_base base;
44 gl_setelement_hashcode_fn hashcode_fn;
45
46 struct gl_hash_entry **table;
47 size_t table_size;
48
49 size_t count;
50 };
51
52 #define CONTAINER_T gl_set_t
53 #define CONTAINER_COUNT(set) (set)->count
54 #include "gl_anyhash2.h"
55
56
57
58 static gl_set_t
59 gl_hash_nx_create_empty (gl_set_implementation_t implementation,
60 gl_setelement_equals_fn equals_fn,
61 gl_setelement_hashcode_fn hashcode_fn,
62 gl_setelement_dispose_fn dispose_fn)
63 {
64 struct gl_set_impl *set =
65 (struct gl_set_impl *) malloc (sizeof (struct gl_set_impl));
66
67 if (set == NULL)
68 return NULL;
69
70 set->base.vtable = implementation;
71 set->base.equals_fn = equals_fn;
72 set->base.dispose_fn = dispose_fn;
73 set->hashcode_fn = hashcode_fn;
74 set->table_size = 11;
75 set->table =
76 (gl_hash_entry_t *) calloc (set->table_size, sizeof (gl_hash_entry_t));
77 if (set->table == NULL)
78 goto fail;
79 set->count = 0;
80
81 return set;
82
83 fail:
84 free (set);
85 return NULL;
86 }
87
88 static size_t _GL_ATTRIBUTE_PURE
89 gl_hash_size (gl_set_t set)
90 {
91 return set->count;
92 }
93
94 static bool _GL_ATTRIBUTE_PURE
95 gl_hash_search (gl_set_t set, const void *elt)
96 {
97 size_t hashcode =
98 (set->hashcode_fn != NULL
99 ? set->hashcode_fn (elt)
100 : (size_t)(uintptr_t) elt);
101 size_t bucket = hashcode % set->table_size;
102 gl_setelement_equals_fn equals = set->base.equals_fn;
103
104
105 gl_list_node_t node;
106
107 for (node = (gl_list_node_t) set->table[bucket];
108 node != NULL;
109 node = (gl_list_node_t) node->h.hash_next)
110 if (node->h.hashcode == hashcode
111 && (equals != NULL
112 ? equals (elt, node->value)
113 : elt == node->value))
114 return true;
115 return false;
116 }
117
118 static int
119 gl_hash_nx_add (gl_set_t set, const void *elt)
120 {
121 size_t hashcode =
122 (set->hashcode_fn != NULL
123 ? set->hashcode_fn (elt)
124 : (size_t)(uintptr_t) elt);
125 size_t bucket = hashcode % set->table_size;
126 gl_setelement_equals_fn equals = set->base.equals_fn;
127
128
129 {
130 gl_list_node_t node;
131
132 for (node = (gl_list_node_t) set->table[bucket];
133 node != NULL;
134 node = (gl_list_node_t) node->h.hash_next)
135 if (node->h.hashcode == hashcode
136 && (equals != NULL
137 ? equals (elt, node->value)
138 : elt == node->value))
139 return 0;
140 }
141
142
143 gl_list_node_t node =
144 (struct gl_list_node_impl *) malloc (sizeof (struct gl_list_node_impl));
145
146 if (node == NULL)
147 return -1;
148
149 node->value = elt;
150 node->h.hashcode = hashcode;
151
152
153 node->h.hash_next = set->table[bucket];
154 set->table[bucket] = &node->h;
155
156
157 set->count++;
158
159 hash_resize_after_add (set);
160
161 return 1;
162 }
163
164 static bool
165 gl_hash_remove (gl_set_t set, const void *elt)
166 {
167 size_t hashcode =
168 (set->hashcode_fn != NULL
169 ? set->hashcode_fn (elt)
170 : (size_t)(uintptr_t) elt);
171 size_t bucket = hashcode % set->table_size;
172 gl_setelement_equals_fn equals = set->base.equals_fn;
173
174
175 gl_list_node_t *nodep;
176
177 for (nodep = (gl_list_node_t *) &set->table[bucket];
178 *nodep != NULL;
179 nodep = (gl_list_node_t *) &(*nodep)->h.hash_next)
180 {
181 gl_list_node_t node = *nodep;
182 if (node->h.hashcode == hashcode
183 && (equals != NULL
184 ? equals (elt, node->value)
185 : elt == node->value))
186 {
187
188 *nodep = (gl_list_node_t) node->h.hash_next;
189
190
191 set->count--;
192
193 if (set->base.dispose_fn != NULL)
194 set->base.dispose_fn (node->value);
195 free (node);
196 return true;
197 }
198 }
199
200 return false;
201 }
202
203 static void
204 gl_hash_free (gl_set_t set)
205 {
206 if (set->count > 0)
207 {
208 gl_setelement_dispose_fn dispose = set->base.dispose_fn;
209 struct gl_hash_entry **table = set->table;
210 size_t i;
211
212 for (i = set->table_size; i > 0; )
213 {
214 gl_hash_entry_t node = table[--i];
215
216 while (node != NULL)
217 {
218 gl_hash_entry_t next = node->hash_next;
219
220
221 if (dispose != NULL)
222 dispose (((gl_list_node_t) node)->value);
223 free (node);
224
225 node = next;
226 }
227 }
228 }
229
230 free (set->table);
231 free (set);
232 }
233
234
235
236
237
238
239 static gl_set_iterator_t
240 gl_hash_iterator (gl_set_t set)
241 {
242 gl_set_iterator_t result;
243
244 result.vtable = set->base.vtable;
245 result.set = set;
246 result.p = NULL;
247 result.i = 0;
248 result.j = set->table_size;
249 #if defined GCC_LINT || defined lint
250 result.q = NULL;
251 result.count = 0;
252 #endif
253
254 return result;
255 }
256
257 static bool
258 gl_hash_iterator_next (gl_set_iterator_t *iterator, const void **eltp)
259 {
260 if (iterator->p != NULL)
261 {
262
263 gl_list_node_t node = (gl_list_node_t) iterator->p;
264 *eltp = node->value;
265 iterator->p = (gl_list_node_t) node->h.hash_next;
266 return true;
267 }
268 else
269 {
270
271 size_t j = iterator->j;
272 size_t i = iterator->i;
273
274 if (i < j)
275 {
276 gl_hash_entry_t *table = iterator->set->table;
277 do
278 {
279 gl_list_node_t node = (gl_list_node_t) table[i++];
280 if (node != NULL)
281 {
282 *eltp = node->value;
283 iterator->p = (gl_list_node_t) node->h.hash_next;
284 iterator->i = i;
285 return true;
286 }
287 }
288 while (i < j);
289 }
290
291 iterator->i = j;
292 return false;
293 }
294 }
295
296 static void
297 gl_hash_iterator_free (gl_set_iterator_t *iterator)
298 {
299 }
300
301
302 const struct gl_set_implementation gl_hash_set_implementation =
303 {
304 gl_hash_nx_create_empty,
305 gl_hash_size,
306 gl_hash_search,
307 gl_hash_nx_add,
308 gl_hash_remove,
309 gl_hash_free,
310 gl_hash_iterator,
311 gl_hash_iterator_next,
312 gl_hash_iterator_free
313 };