1262395Sbapt/* Copyright (c) 2013, Vsevolod Stakhov
2262395Sbapt * All rights reserved.
3262395Sbapt *
4262395Sbapt * Redistribution and use in source and binary forms, with or without
5262395Sbapt * modification, are permitted provided that the following conditions are met:
6262395Sbapt *       * Redistributions of source code must retain the above copyright
7262395Sbapt *         notice, this list of conditions and the following disclaimer.
8262395Sbapt *       * Redistributions in binary form must reproduce the above copyright
9262395Sbapt *         notice, this list of conditions and the following disclaimer in the
10262395Sbapt *         documentation and/or other materials provided with the distribution.
11262395Sbapt *
12262395Sbapt * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY
13262395Sbapt * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
14262395Sbapt * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
15262395Sbapt * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY
16262395Sbapt * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
17262395Sbapt * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
18262395Sbapt * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
19262395Sbapt * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
20262395Sbapt * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
21262395Sbapt * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
22262395Sbapt */
23262395Sbapt
24263648Sbapt#include "ucl_internal.h"
25262395Sbapt#include "ucl_hash.h"
26279549Sbapt#include "khash.h"
27279549Sbapt#include "kvec.h"
28301339Sbapt#include "mum.h"
29262395Sbapt
30290071Sbapt#include <time.h>
31290071Sbapt#include <limits.h>
32290071Sbapt
33279549Sbaptstruct ucl_hash_elt {
34279549Sbapt	const ucl_object_t *obj;
35279549Sbapt	size_t ar_idx;
36279549Sbapt};
37279549Sbapt
38279549Sbaptstruct ucl_hash_struct {
39279549Sbapt	void *hash;
40279549Sbapt	kvec_t(const ucl_object_t *) ar;
41279549Sbapt	bool caseless;
42279549Sbapt};
43279549Sbapt
44290071Sbaptstatic uint64_t
45290071Sbaptucl_hash_seed (void)
46290071Sbapt{
47290071Sbapt	static uint64_t seed;
48290071Sbapt
49290071Sbapt	if (seed == 0) {
50290071Sbapt#ifdef UCL_RANDOM_FUNCTION
51290071Sbapt		seed = UCL_RANDOM_FUNCTION;
52290071Sbapt#else
53290071Sbapt		/* Not very random but can be useful for our purposes */
54290071Sbapt		seed = time (NULL);
55290071Sbapt#endif
56290071Sbapt	}
57290071Sbapt
58290071Sbapt	return seed;
59290071Sbapt}
60290071Sbapt
61290071Sbaptstatic const unsigned char lc_map[256] = {
62290071Sbapt		0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
63290071Sbapt		0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
64290071Sbapt		0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
65290071Sbapt		0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
66290071Sbapt		0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
67290071Sbapt		0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
68290071Sbapt		0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
69290071Sbapt		0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
70290071Sbapt		0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
71290071Sbapt		0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
72290071Sbapt		0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
73290071Sbapt		0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
74290071Sbapt		0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
75290071Sbapt		0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
76290071Sbapt		0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
77290071Sbapt		0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
78290071Sbapt		0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
79290071Sbapt		0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
80290071Sbapt		0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
81290071Sbapt		0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
82290071Sbapt		0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
83290071Sbapt		0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
84290071Sbapt		0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
85290071Sbapt		0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
86290071Sbapt		0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
87290071Sbapt		0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
88290071Sbapt		0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
89290071Sbapt		0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
90290071Sbapt		0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
91290071Sbapt		0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
92290071Sbapt		0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
93290071Sbapt		0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
94290071Sbapt};
95290071Sbapt
96290071Sbapt#if (defined(WORD_BIT) && WORD_BIT == 64) || \
97290071Sbapt	(defined(__WORDSIZE) && __WORDSIZE == 64) || \
98290071Sbapt	defined(__x86_64__) || \
99290071Sbapt	defined(__amd64__)
100290071Sbapt#define UCL64_BIT_HASH 1
101290071Sbapt#endif
102290071Sbapt
103279549Sbaptstatic inline uint32_t
104279549Sbaptucl_hash_func (const ucl_object_t *o)
105279549Sbapt{
106301339Sbapt	return mum_hash (o->key, o->keylen, ucl_hash_seed ());
107279549Sbapt}
108279549Sbaptstatic inline int
109279549Sbaptucl_hash_equal (const ucl_object_t *k1, const ucl_object_t *k2)
110279549Sbapt{
111279549Sbapt	if (k1->keylen == k2->keylen) {
112298166Sbapt		return memcmp (k1->key, k2->key, k1->keylen) == 0;
113279549Sbapt	}
114279549Sbapt
115279549Sbapt	return 0;
116279549Sbapt}
117279549Sbapt
118279549SbaptKHASH_INIT (ucl_hash_node, const ucl_object_t *, struct ucl_hash_elt, 1,
119279549Sbapt		ucl_hash_func, ucl_hash_equal)
120279549Sbapt
121279549Sbaptstatic inline uint32_t
122279549Sbaptucl_hash_caseless_func (const ucl_object_t *o)
123279549Sbapt{
124290071Sbapt	unsigned len = o->keylen;
125301339Sbapt	unsigned leftover = o->keylen % 8;
126290071Sbapt	unsigned fp, i;
127290071Sbapt	const uint8_t* s = (const uint8_t*)o->key;
128290071Sbapt	union {
129290071Sbapt		struct {
130301339Sbapt			unsigned char c1, c2, c3, c4, c5, c6, c7, c8;
131290071Sbapt		} c;
132301339Sbapt		uint64_t pp;
133290071Sbapt	} u;
134301339Sbapt	uint64_t r;
135279549Sbapt
136290071Sbapt	fp = len - leftover;
137301339Sbapt	r = ucl_hash_seed ();
138279549Sbapt
139301339Sbapt	for (i = 0; i != fp; i += 8) {
140290071Sbapt		u.c.c1 = s[i], u.c.c2 = s[i + 1], u.c.c3 = s[i + 2], u.c.c4 = s[i + 3];
141301339Sbapt		u.c.c5 = s[i + 4], u.c.c6 = s[i + 5], u.c.c7 = s[i + 6], u.c.c8 = s[i + 7];
142290071Sbapt		u.c.c1 = lc_map[u.c.c1];
143290071Sbapt		u.c.c2 = lc_map[u.c.c2];
144290071Sbapt		u.c.c3 = lc_map[u.c.c3];
145290071Sbapt		u.c.c4 = lc_map[u.c.c4];
146301339Sbapt		u.c.c1 = lc_map[u.c.c5];
147301339Sbapt		u.c.c2 = lc_map[u.c.c6];
148301339Sbapt		u.c.c3 = lc_map[u.c.c7];
149301339Sbapt		u.c.c4 = lc_map[u.c.c8];
150301339Sbapt		r = mum_hash_step (r, u.pp);
151290071Sbapt	}
152279549Sbapt
153290071Sbapt	u.pp = 0;
154290071Sbapt	switch (leftover) {
155301339Sbapt	case 7:
156301339Sbapt		u.c.c7 = lc_map[(unsigned char)s[i++]];
157301339Sbapt	case 6:
158301339Sbapt		u.c.c6 = lc_map[(unsigned char)s[i++]];
159301339Sbapt	case 5:
160301339Sbapt		u.c.c5 = lc_map[(unsigned char)s[i++]];
161301339Sbapt	case 4:
162301339Sbapt		u.c.c4 = lc_map[(unsigned char)s[i++]];
163290071Sbapt	case 3:
164290071Sbapt		u.c.c3 = lc_map[(unsigned char)s[i++]];
165290071Sbapt	case 2:
166290071Sbapt		u.c.c2 = lc_map[(unsigned char)s[i++]];
167290071Sbapt	case 1:
168290071Sbapt		u.c.c1 = lc_map[(unsigned char)s[i]];
169301339Sbapt		r = mum_hash_step (r, u.pp);
170290071Sbapt		break;
171279549Sbapt	}
172279549Sbapt
173301339Sbapt	return mum_hash_finish (r);
174290071Sbapt}
175290071Sbapt
176279549Sbaptstatic inline int
177279549Sbaptucl_hash_caseless_equal (const ucl_object_t *k1, const ucl_object_t *k2)
178279549Sbapt{
179279549Sbapt	if (k1->keylen == k2->keylen) {
180298166Sbapt		return memcmp (k1->key, k2->key, k1->keylen) == 0;
181279549Sbapt	}
182279549Sbapt
183279549Sbapt	return 0;
184279549Sbapt}
185279549Sbapt
186279549SbaptKHASH_INIT (ucl_hash_caseless_node, const ucl_object_t *, struct ucl_hash_elt, 1,
187279549Sbapt		ucl_hash_caseless_func, ucl_hash_caseless_equal)
188279549Sbapt
189262395Sbaptucl_hash_t*
190279549Sbaptucl_hash_create (bool ignore_case)
191262395Sbapt{
192262395Sbapt	ucl_hash_t *new;
193262395Sbapt
194262395Sbapt	new = UCL_ALLOC (sizeof (ucl_hash_t));
195262395Sbapt	if (new != NULL) {
196279549Sbapt		kv_init (new->ar);
197279549Sbapt
198279549Sbapt		new->caseless = ignore_case;
199279549Sbapt		if (ignore_case) {
200279549Sbapt			khash_t(ucl_hash_caseless_node) *h = kh_init (ucl_hash_caseless_node);
201279549Sbapt			new->hash = (void *)h;
202279549Sbapt		}
203279549Sbapt		else {
204279549Sbapt			khash_t(ucl_hash_node) *h = kh_init (ucl_hash_node);
205279549Sbapt			new->hash = (void *)h;
206279549Sbapt		}
207262395Sbapt	}
208262395Sbapt	return new;
209262395Sbapt}
210262395Sbapt
211298166Sbaptvoid ucl_hash_destroy (ucl_hash_t* hashlin, ucl_hash_free_func func)
212262395Sbapt{
213279549Sbapt	const ucl_object_t *cur, *tmp;
214262395Sbapt
215279549Sbapt	if (hashlin == NULL) {
216279549Sbapt		return;
217279549Sbapt	}
218279549Sbapt
219279549Sbapt	if (func != NULL) {
220279549Sbapt		/* Iterate over the hash first */
221279549Sbapt		khash_t(ucl_hash_node) *h = (khash_t(ucl_hash_node) *)
222279549Sbapt				hashlin->hash;
223279549Sbapt		khiter_t k;
224279549Sbapt
225279549Sbapt		for (k = kh_begin (h); k != kh_end (h); ++k) {
226279549Sbapt			if (kh_exist (h, k)) {
227279549Sbapt				cur = (kh_value (h, k)).obj;
228279549Sbapt				while (cur != NULL) {
229279549Sbapt					tmp = cur->next;
230279549Sbapt					func (__DECONST (ucl_object_t *, cur));
231279549Sbapt					cur = tmp;
232279549Sbapt				}
233264789Sbapt			}
234262395Sbapt		}
235262395Sbapt	}
236279549Sbapt
237279549Sbapt	if (hashlin->caseless) {
238279549Sbapt		khash_t(ucl_hash_caseless_node) *h = (khash_t(ucl_hash_caseless_node) *)
239279549Sbapt			hashlin->hash;
240279549Sbapt		kh_destroy (ucl_hash_caseless_node, h);
241279549Sbapt	}
242279549Sbapt	else {
243279549Sbapt		khash_t(ucl_hash_node) *h = (khash_t(ucl_hash_node) *)
244279549Sbapt			hashlin->hash;
245279549Sbapt		kh_destroy (ucl_hash_node, h);
246279549Sbapt	}
247279549Sbapt
248279549Sbapt	kv_destroy (hashlin->ar);
249279549Sbapt	UCL_FREE (sizeof (*hashlin), hashlin);
250262395Sbapt}
251262395Sbapt
252262395Sbaptvoid
253264789Sbaptucl_hash_insert (ucl_hash_t* hashlin, const ucl_object_t *obj,
254264789Sbapt		const char *key, unsigned keylen)
255262395Sbapt{
256279549Sbapt	khiter_t k;
257279549Sbapt	int ret;
258279549Sbapt	struct ucl_hash_elt *elt;
259262395Sbapt
260279549Sbapt	if (hashlin == NULL) {
261279549Sbapt		return;
262279549Sbapt	}
263279549Sbapt
264279549Sbapt	if (hashlin->caseless) {
265279549Sbapt		khash_t(ucl_hash_caseless_node) *h = (khash_t(ucl_hash_caseless_node) *)
266279549Sbapt				hashlin->hash;
267279549Sbapt		k = kh_put (ucl_hash_caseless_node, h, obj, &ret);
268279549Sbapt		if (ret > 0) {
269279549Sbapt			elt = &kh_value (h, k);
270279549Sbapt			kv_push (const ucl_object_t *, hashlin->ar, obj);
271279549Sbapt			elt->obj = obj;
272279549Sbapt			elt->ar_idx = kv_size (hashlin->ar) - 1;
273279549Sbapt		}
274279549Sbapt	}
275279549Sbapt	else {
276279549Sbapt		khash_t(ucl_hash_node) *h = (khash_t(ucl_hash_node) *)
277279549Sbapt				hashlin->hash;
278279549Sbapt		k = kh_put (ucl_hash_node, h, obj, &ret);
279279549Sbapt		if (ret > 0) {
280279549Sbapt			elt = &kh_value (h, k);
281279549Sbapt			kv_push (const ucl_object_t *, hashlin->ar, obj);
282279549Sbapt			elt->obj = obj;
283279549Sbapt			elt->ar_idx = kv_size (hashlin->ar) - 1;
284279549Sbapt		}
285279549Sbapt	}
286262395Sbapt}
287262395Sbapt
288275223Sbaptvoid ucl_hash_replace (ucl_hash_t* hashlin, const ucl_object_t *old,
289275223Sbapt		const ucl_object_t *new)
290275223Sbapt{
291279549Sbapt	khiter_t k;
292279549Sbapt	int ret;
293279549Sbapt	struct ucl_hash_elt elt, *pelt;
294275223Sbapt
295279549Sbapt	if (hashlin == NULL) {
296279549Sbapt		return;
297275223Sbapt	}
298279549Sbapt
299279549Sbapt	if (hashlin->caseless) {
300279549Sbapt		khash_t(ucl_hash_caseless_node) *h = (khash_t(ucl_hash_caseless_node) *)
301279549Sbapt				hashlin->hash;
302279549Sbapt		k = kh_put (ucl_hash_caseless_node, h, old, &ret);
303279549Sbapt		if (ret == 0) {
304279549Sbapt			elt = kh_value (h, k);
305279549Sbapt			kh_del (ucl_hash_caseless_node, h, k);
306279549Sbapt			k = kh_put (ucl_hash_caseless_node, h, new, &ret);
307279549Sbapt			pelt = &kh_value (h, k);
308279549Sbapt			pelt->obj = new;
309279549Sbapt			pelt->ar_idx = elt.ar_idx;
310279549Sbapt			kv_A (hashlin->ar, elt.ar_idx) = new;
311279549Sbapt		}
312279549Sbapt	}
313279549Sbapt	else {
314279549Sbapt		khash_t(ucl_hash_node) *h = (khash_t(ucl_hash_node) *)
315279549Sbapt				hashlin->hash;
316279549Sbapt		k = kh_put (ucl_hash_node, h, old, &ret);
317279549Sbapt		if (ret == 0) {
318279549Sbapt			elt = kh_value (h, k);
319279549Sbapt			kh_del (ucl_hash_node, h, k);
320279549Sbapt			k = kh_put (ucl_hash_node, h, new, &ret);
321279549Sbapt			pelt = &kh_value (h, k);
322279549Sbapt			pelt->obj = new;
323279549Sbapt			pelt->ar_idx = elt.ar_idx;
324279549Sbapt			kv_A (hashlin->ar, elt.ar_idx) = new;
325279549Sbapt		}
326279549Sbapt	}
327275223Sbapt}
328275223Sbapt
329279549Sbaptstruct ucl_hash_real_iter {
330279549Sbapt	const ucl_object_t **cur;
331279549Sbapt	const ucl_object_t **end;
332279549Sbapt};
333279549Sbapt
334264789Sbaptconst void*
335262395Sbaptucl_hash_iterate (ucl_hash_t *hashlin, ucl_hash_iter_t *iter)
336262395Sbapt{
337279549Sbapt	struct ucl_hash_real_iter *it = (struct ucl_hash_real_iter *)(*iter);
338279549Sbapt	const ucl_object_t *ret = NULL;
339262395Sbapt
340279549Sbapt	if (hashlin == NULL) {
341279549Sbapt		return NULL;
342262395Sbapt	}
343279549Sbapt
344279549Sbapt	if (it == NULL) {
345279549Sbapt		it = UCL_ALLOC (sizeof (*it));
346290071Sbapt
347290071Sbapt		if (it == NULL) {
348290071Sbapt			return NULL;
349290071Sbapt		}
350290071Sbapt
351279549Sbapt		it->cur = &hashlin->ar.a[0];
352279549Sbapt		it->end = it->cur + hashlin->ar.n;
353279549Sbapt	}
354279549Sbapt
355279549Sbapt	if (it->cur < it->end) {
356279549Sbapt		ret = *it->cur++;
357279549Sbapt	}
358279549Sbapt	else {
359279549Sbapt		UCL_FREE (sizeof (*it), it);
360279549Sbapt		*iter = NULL;
361262395Sbapt		return NULL;
362262395Sbapt	}
363262395Sbapt
364279549Sbapt	*iter = it;
365279549Sbapt
366279549Sbapt	return ret;
367262395Sbapt}
368262395Sbapt
369262395Sbaptbool
370279549Sbaptucl_hash_iter_has_next (ucl_hash_t *hashlin, ucl_hash_iter_t iter)
371262395Sbapt{
372279549Sbapt	struct ucl_hash_real_iter *it = (struct ucl_hash_real_iter *)(iter);
373262395Sbapt
374279549Sbapt	return it->cur < it->end - 1;
375262395Sbapt}
376262395Sbapt
377262395Sbapt
378264789Sbaptconst ucl_object_t*
379262395Sbaptucl_hash_search (ucl_hash_t* hashlin, const char *key, unsigned keylen)
380262395Sbapt{
381279549Sbapt	khiter_t k;
382279549Sbapt	const ucl_object_t *ret = NULL;
383279549Sbapt	ucl_object_t search;
384279549Sbapt	struct ucl_hash_elt *elt;
385262395Sbapt
386279549Sbapt	search.key = key;
387279549Sbapt	search.keylen = keylen;
388279549Sbapt
389262395Sbapt	if (hashlin == NULL) {
390262395Sbapt		return NULL;
391262395Sbapt	}
392262395Sbapt
393279549Sbapt	if (hashlin->caseless) {
394279549Sbapt		khash_t(ucl_hash_caseless_node) *h = (khash_t(ucl_hash_caseless_node) *)
395279549Sbapt						hashlin->hash;
396279549Sbapt
397279549Sbapt		k = kh_get (ucl_hash_caseless_node, h, &search);
398279549Sbapt		if (k != kh_end (h)) {
399279549Sbapt			elt = &kh_value (h, k);
400279549Sbapt			ret = elt->obj;
401279549Sbapt		}
402262395Sbapt	}
403279549Sbapt	else {
404279549Sbapt		khash_t(ucl_hash_node) *h = (khash_t(ucl_hash_node) *)
405279549Sbapt						hashlin->hash;
406279549Sbapt		k = kh_get (ucl_hash_node, h, &search);
407279549Sbapt		if (k != kh_end (h)) {
408279549Sbapt			elt = &kh_value (h, k);
409279549Sbapt			ret = elt->obj;
410279549Sbapt		}
411279549Sbapt	}
412279549Sbapt
413279549Sbapt	return ret;
414262395Sbapt}
415262395Sbapt
416262395Sbaptvoid
417264789Sbaptucl_hash_delete (ucl_hash_t* hashlin, const ucl_object_t *obj)
418262395Sbapt{
419279549Sbapt	khiter_t k;
420279549Sbapt	struct ucl_hash_elt *elt;
421262395Sbapt
422279549Sbapt	if (hashlin == NULL) {
423279549Sbapt		return;
424279549Sbapt	}
425262395Sbapt
426279549Sbapt	if (hashlin->caseless) {
427279549Sbapt		khash_t(ucl_hash_caseless_node) *h = (khash_t(ucl_hash_caseless_node) *)
428279549Sbapt			hashlin->hash;
429279549Sbapt
430279549Sbapt		k = kh_get (ucl_hash_caseless_node, h, obj);
431279549Sbapt		if (k != kh_end (h)) {
432279549Sbapt			elt = &kh_value (h, k);
433290071Sbapt			kv_del (const ucl_object_t *, hashlin->ar, elt->ar_idx);
434279549Sbapt			kh_del (ucl_hash_caseless_node, h, k);
435279549Sbapt		}
436262395Sbapt	}
437279549Sbapt	else {
438279549Sbapt		khash_t(ucl_hash_node) *h = (khash_t(ucl_hash_node) *)
439279549Sbapt			hashlin->hash;
440279549Sbapt		k = kh_get (ucl_hash_node, h, obj);
441279549Sbapt		if (k != kh_end (h)) {
442279549Sbapt			elt = &kh_value (h, k);
443290071Sbapt			kv_del (const ucl_object_t *, hashlin->ar, elt->ar_idx);
444279549Sbapt			kh_del (ucl_hash_node, h, k);
445279549Sbapt		}
446279549Sbapt	}
447262395Sbapt}
448