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