Deleted Added
full compact
ucl_hash.c (275223) ucl_hash.c (279549)
1/* Copyright (c) 2013, Vsevolod Stakhov
2 * All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 * * Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * * Redistributions in binary form must reproduce the above copyright

--- 9 unchanged lines hidden (view full) ---

18 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
19 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
20 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
21 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
22 */
23
24#include "ucl_internal.h"
25#include "ucl_hash.h"
1/* Copyright (c) 2013, Vsevolod Stakhov
2 * All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 * * Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * * Redistributions in binary form must reproduce the above copyright

--- 9 unchanged lines hidden (view full) ---

18 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
19 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
20 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
21 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
22 */
23
24#include "ucl_internal.h"
25#include "ucl_hash.h"
26#include "utlist.h"
26#include "khash.h"
27#include "kvec.h"
27
28
29struct ucl_hash_elt {
30 const ucl_object_t *obj;
31 size_t ar_idx;
32};
33
34struct ucl_hash_struct {
35 void *hash;
36 kvec_t(const ucl_object_t *) ar;
37 bool caseless;
38};
39
40static inline uint32_t
41ucl_hash_func (const ucl_object_t *o)
42{
43 return XXH32 (o->key, o->keylen, 0xdeadbeef);
44}
45
46static inline int
47ucl_hash_equal (const ucl_object_t *k1, const ucl_object_t *k2)
48{
49 if (k1->keylen == k2->keylen) {
50 return strncmp (k1->key, k2->key, k1->keylen) == 0;
51 }
52
53 return 0;
54}
55
56KHASH_INIT (ucl_hash_node, const ucl_object_t *, struct ucl_hash_elt, 1,
57 ucl_hash_func, ucl_hash_equal)
58
59static inline uint32_t
60ucl_hash_caseless_func (const ucl_object_t *o)
61{
62 void *xxh = XXH32_init (0xdeadbeef);
63 char hash_buf[64], *c;
64 const char *p;
65 ssize_t remain = o->keylen;
66
67 p = o->key;
68 c = &hash_buf[0];
69
70 while (remain > 0) {
71 *c++ = tolower (*p++);
72
73 if (c - &hash_buf[0] == sizeof (hash_buf)) {
74 XXH32_update (xxh, hash_buf, sizeof (hash_buf));
75 c = &hash_buf[0];
76 }
77 remain --;
78 }
79
80 if (c - &hash_buf[0] != 0) {
81 XXH32_update (xxh, hash_buf, c - &hash_buf[0]);
82 }
83
84 return XXH32_digest (xxh);
85}
86
87static inline int
88ucl_hash_caseless_equal (const ucl_object_t *k1, const ucl_object_t *k2)
89{
90 if (k1->keylen == k2->keylen) {
91 return strncasecmp (k1->key, k2->key, k1->keylen) == 0;
92 }
93
94 return 0;
95}
96
97KHASH_INIT (ucl_hash_caseless_node, const ucl_object_t *, struct ucl_hash_elt, 1,
98 ucl_hash_caseless_func, ucl_hash_caseless_equal)
99
28ucl_hash_t*
100ucl_hash_t*
29ucl_hash_create (void)
101ucl_hash_create (bool ignore_case)
30{
31 ucl_hash_t *new;
32
33 new = UCL_ALLOC (sizeof (ucl_hash_t));
34 if (new != NULL) {
102{
103 ucl_hash_t *new;
104
105 new = UCL_ALLOC (sizeof (ucl_hash_t));
106 if (new != NULL) {
35 new->buckets = NULL;
107 kv_init (new->ar);
108
109 new->caseless = ignore_case;
110 if (ignore_case) {
111 khash_t(ucl_hash_caseless_node) *h = kh_init (ucl_hash_caseless_node);
112 new->hash = (void *)h;
113 }
114 else {
115 khash_t(ucl_hash_node) *h = kh_init (ucl_hash_node);
116 new->hash = (void *)h;
117 }
36 }
37 return new;
38}
39
40void ucl_hash_destroy (ucl_hash_t* hashlin, ucl_hash_free_func *func)
41{
118 }
119 return new;
120}
121
122void ucl_hash_destroy (ucl_hash_t* hashlin, ucl_hash_free_func *func)
123{
42 ucl_hash_node_t *elt, *tmp;
43 const ucl_object_t *cur, *otmp;
124 const ucl_object_t *cur, *tmp;
44
125
45 HASH_ITER (hh, hashlin->buckets, elt, tmp) {
46 HASH_DELETE (hh, hashlin->buckets, elt);
47 if (func) {
48 DL_FOREACH_SAFE (elt->data, cur, otmp) {
49 /* Need to deconst here */
50 func (__DECONST (ucl_object_t *, cur));
126 if (hashlin == NULL) {
127 return;
128 }
129
130 if (func != NULL) {
131 /* Iterate over the hash first */
132 khash_t(ucl_hash_node) *h = (khash_t(ucl_hash_node) *)
133 hashlin->hash;
134 khiter_t k;
135
136 for (k = kh_begin (h); k != kh_end (h); ++k) {
137 if (kh_exist (h, k)) {
138 cur = (kh_value (h, k)).obj;
139 while (cur != NULL) {
140 tmp = cur->next;
141 func (__DECONST (ucl_object_t *, cur));
142 cur = tmp;
143 }
51 }
52 }
144 }
145 }
53 UCL_FREE (sizeof (ucl_hash_node_t), elt);
54 }
146 }
55 UCL_FREE (sizeof (ucl_hash_t), hashlin);
147
148 if (hashlin->caseless) {
149 khash_t(ucl_hash_caseless_node) *h = (khash_t(ucl_hash_caseless_node) *)
150 hashlin->hash;
151 kh_destroy (ucl_hash_caseless_node, h);
152 }
153 else {
154 khash_t(ucl_hash_node) *h = (khash_t(ucl_hash_node) *)
155 hashlin->hash;
156 kh_destroy (ucl_hash_node, h);
157 }
158
159 kv_destroy (hashlin->ar);
160 UCL_FREE (sizeof (*hashlin), hashlin);
56}
57
58void
59ucl_hash_insert (ucl_hash_t* hashlin, const ucl_object_t *obj,
60 const char *key, unsigned keylen)
61{
161}
162
163void
164ucl_hash_insert (ucl_hash_t* hashlin, const ucl_object_t *obj,
165 const char *key, unsigned keylen)
166{
62 ucl_hash_node_t *node;
167 khiter_t k;
168 int ret;
169 struct ucl_hash_elt *elt;
63
170
64 node = UCL_ALLOC (sizeof (ucl_hash_node_t));
65 node->data = obj;
66 HASH_ADD_KEYPTR (hh, hashlin->buckets, key, keylen, node);
171 if (hashlin == NULL) {
172 return;
173 }
174
175 if (hashlin->caseless) {
176 khash_t(ucl_hash_caseless_node) *h = (khash_t(ucl_hash_caseless_node) *)
177 hashlin->hash;
178 k = kh_put (ucl_hash_caseless_node, h, obj, &ret);
179 if (ret > 0) {
180 elt = &kh_value (h, k);
181 kv_push (const ucl_object_t *, hashlin->ar, obj);
182 elt->obj = obj;
183 elt->ar_idx = kv_size (hashlin->ar) - 1;
184 }
185 }
186 else {
187 khash_t(ucl_hash_node) *h = (khash_t(ucl_hash_node) *)
188 hashlin->hash;
189 k = kh_put (ucl_hash_node, h, obj, &ret);
190 if (ret > 0) {
191 elt = &kh_value (h, k);
192 kv_push (const ucl_object_t *, hashlin->ar, obj);
193 elt->obj = obj;
194 elt->ar_idx = kv_size (hashlin->ar) - 1;
195 }
196 }
67}
68
69void ucl_hash_replace (ucl_hash_t* hashlin, const ucl_object_t *old,
70 const ucl_object_t *new)
71{
197}
198
199void ucl_hash_replace (ucl_hash_t* hashlin, const ucl_object_t *old,
200 const ucl_object_t *new)
201{
72 ucl_hash_node_t *node;
202 khiter_t k;
203 int ret;
204 struct ucl_hash_elt elt, *pelt;
73
205
74 HASH_FIND (hh, hashlin->buckets, old->key, old->keylen, node);
75 if (node != NULL) {
76 /* Direct replacement */
77 node->data = new;
78 node->hh.key = new->key;
79 node->hh.keylen = new->keylen;
206 if (hashlin == NULL) {
207 return;
80 }
208 }
209
210 if (hashlin->caseless) {
211 khash_t(ucl_hash_caseless_node) *h = (khash_t(ucl_hash_caseless_node) *)
212 hashlin->hash;
213 k = kh_put (ucl_hash_caseless_node, h, old, &ret);
214 if (ret == 0) {
215 elt = kh_value (h, k);
216 kh_del (ucl_hash_caseless_node, h, k);
217 k = kh_put (ucl_hash_caseless_node, h, new, &ret);
218 pelt = &kh_value (h, k);
219 pelt->obj = new;
220 pelt->ar_idx = elt.ar_idx;
221 kv_A (hashlin->ar, elt.ar_idx) = new;
222 }
223 }
224 else {
225 khash_t(ucl_hash_node) *h = (khash_t(ucl_hash_node) *)
226 hashlin->hash;
227 k = kh_put (ucl_hash_node, h, old, &ret);
228 if (ret == 0) {
229 elt = kh_value (h, k);
230 kh_del (ucl_hash_node, h, k);
231 k = kh_put (ucl_hash_node, h, new, &ret);
232 pelt = &kh_value (h, k);
233 pelt->obj = new;
234 pelt->ar_idx = elt.ar_idx;
235 kv_A (hashlin->ar, elt.ar_idx) = new;
236 }
237 }
81}
82
238}
239
240struct ucl_hash_real_iter {
241 const ucl_object_t **cur;
242 const ucl_object_t **end;
243};
244
83const void*
84ucl_hash_iterate (ucl_hash_t *hashlin, ucl_hash_iter_t *iter)
85{
245const void*
246ucl_hash_iterate (ucl_hash_t *hashlin, ucl_hash_iter_t *iter)
247{
86 ucl_hash_node_t *elt = *iter;
248 struct ucl_hash_real_iter *it = (struct ucl_hash_real_iter *)(*iter);
249 const ucl_object_t *ret = NULL;
87
250
88 if (elt == NULL) {
89 if (hashlin == NULL || hashlin->buckets == NULL) {
90 return NULL;
91 }
92 elt = hashlin->buckets;
93 if (elt == NULL) {
94 return NULL;
95 }
251 if (hashlin == NULL) {
252 return NULL;
96 }
253 }
97 else if (elt == hashlin->buckets) {
254
255 if (it == NULL) {
256 it = UCL_ALLOC (sizeof (*it));
257 it->cur = &hashlin->ar.a[0];
258 it->end = it->cur + hashlin->ar.n;
259 }
260
261 if (it->cur < it->end) {
262 ret = *it->cur++;
263 }
264 else {
265 UCL_FREE (sizeof (*it), it);
266 *iter = NULL;
98 return NULL;
99 }
100
267 return NULL;
268 }
269
101 *iter = elt->hh.next ? elt->hh.next : hashlin->buckets;
102 return elt->data;
270 *iter = it;
271
272 return ret;
103}
104
105bool
273}
274
275bool
106ucl_hash_iter_has_next (ucl_hash_iter_t iter)
276ucl_hash_iter_has_next (ucl_hash_t *hashlin, ucl_hash_iter_t iter)
107{
277{
108 ucl_hash_node_t *elt = iter;
278 struct ucl_hash_real_iter *it = (struct ucl_hash_real_iter *)(iter);
109
279
110 return (elt == NULL || elt->hh.prev != NULL);
280 return it->cur < it->end - 1;
111}
112
113
114const ucl_object_t*
115ucl_hash_search (ucl_hash_t* hashlin, const char *key, unsigned keylen)
116{
281}
282
283
284const ucl_object_t*
285ucl_hash_search (ucl_hash_t* hashlin, const char *key, unsigned keylen)
286{
117 ucl_hash_node_t *found;
287 khiter_t k;
288 const ucl_object_t *ret = NULL;
289 ucl_object_t search;
290 struct ucl_hash_elt *elt;
118
291
292 search.key = key;
293 search.keylen = keylen;
294
119 if (hashlin == NULL) {
120 return NULL;
121 }
295 if (hashlin == NULL) {
296 return NULL;
297 }
122 HASH_FIND (hh, hashlin->buckets, key, keylen, found);
123
298
124 if (found) {
125 return found->data;
299 if (hashlin->caseless) {
300 khash_t(ucl_hash_caseless_node) *h = (khash_t(ucl_hash_caseless_node) *)
301 hashlin->hash;
302
303 k = kh_get (ucl_hash_caseless_node, h, &search);
304 if (k != kh_end (h)) {
305 elt = &kh_value (h, k);
306 ret = elt->obj;
307 }
126 }
308 }
127 return NULL;
309 else {
310 khash_t(ucl_hash_node) *h = (khash_t(ucl_hash_node) *)
311 hashlin->hash;
312 k = kh_get (ucl_hash_node, h, &search);
313 if (k != kh_end (h)) {
314 elt = &kh_value (h, k);
315 ret = elt->obj;
316 }
317 }
318
319 return ret;
128}
129
130void
131ucl_hash_delete (ucl_hash_t* hashlin, const ucl_object_t *obj)
132{
320}
321
322void
323ucl_hash_delete (ucl_hash_t* hashlin, const ucl_object_t *obj)
324{
133 ucl_hash_node_t *found;
325 khiter_t k;
326 struct ucl_hash_elt *elt;
134
327
135 HASH_FIND (hh, hashlin->buckets, obj->key, obj->keylen, found);
328 if (hashlin == NULL) {
329 return;
330 }
136
331
137 if (found) {
138 HASH_DELETE (hh, hashlin->buckets, found);
139 UCL_FREE (sizeof (ucl_hash_node_t), found);
332 if (hashlin->caseless) {
333 khash_t(ucl_hash_caseless_node) *h = (khash_t(ucl_hash_caseless_node) *)
334 hashlin->hash;
335
336 k = kh_get (ucl_hash_caseless_node, h, obj);
337 if (k != kh_end (h)) {
338 elt = &kh_value (h, k);
339 kv_A (hashlin->ar, elt->ar_idx) = NULL;
340 kh_del (ucl_hash_caseless_node, h, k);
341 }
140 }
342 }
343 else {
344 khash_t(ucl_hash_node) *h = (khash_t(ucl_hash_node) *)
345 hashlin->hash;
346 k = kh_get (ucl_hash_node, h, obj);
347 if (k != kh_end (h)) {
348 elt = &kh_value (h, k);
349 kv_A (hashlin->ar, elt->ar_idx) = NULL;
350 kh_del (ucl_hash_node, h, k);
351 }
352 }
141}
353}