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 24268896Sbapt#include "ucl_internal.h" 25262395Sbapt#include "ucl_hash.h" 26262395Sbapt#include "utlist.h" 27262395Sbapt 28262395Sbaptucl_hash_t* 29262395Sbaptucl_hash_create (void) 30262395Sbapt{ 31262395Sbapt ucl_hash_t *new; 32262395Sbapt 33262395Sbapt new = UCL_ALLOC (sizeof (ucl_hash_t)); 34262395Sbapt if (new != NULL) { 35262395Sbapt new->buckets = NULL; 36262395Sbapt } 37262395Sbapt return new; 38262395Sbapt} 39262395Sbapt 40262395Sbaptvoid ucl_hash_destroy (ucl_hash_t* hashlin, ucl_hash_free_func *func) 41262395Sbapt{ 42262395Sbapt ucl_hash_node_t *elt, *tmp; 43268896Sbapt const ucl_object_t *cur, *otmp; 44262395Sbapt 45262395Sbapt HASH_ITER (hh, hashlin->buckets, elt, tmp) { 46262395Sbapt HASH_DELETE (hh, hashlin->buckets, elt); 47262395Sbapt if (func) { 48268896Sbapt DL_FOREACH_SAFE (elt->data, cur, otmp) { 49268896Sbapt /* Need to deconst here */ 50268896Sbapt func (__DECONST (ucl_object_t *, cur)); 51268896Sbapt } 52262395Sbapt } 53262395Sbapt UCL_FREE (sizeof (ucl_hash_node_t), elt); 54262395Sbapt } 55262395Sbapt UCL_FREE (sizeof (ucl_hash_t), hashlin); 56262395Sbapt} 57262395Sbapt 58262395Sbaptvoid 59268896Sbaptucl_hash_insert (ucl_hash_t* hashlin, const ucl_object_t *obj, 60268896Sbapt const char *key, unsigned keylen) 61262395Sbapt{ 62262395Sbapt ucl_hash_node_t *node; 63262395Sbapt 64262395Sbapt node = UCL_ALLOC (sizeof (ucl_hash_node_t)); 65262395Sbapt node->data = obj; 66262395Sbapt HASH_ADD_KEYPTR (hh, hashlin->buckets, key, keylen, node); 67262395Sbapt} 68262395Sbapt 69268896Sbaptconst void* 70262395Sbaptucl_hash_iterate (ucl_hash_t *hashlin, ucl_hash_iter_t *iter) 71262395Sbapt{ 72262395Sbapt ucl_hash_node_t *elt = *iter; 73262395Sbapt 74262395Sbapt if (elt == NULL) { 75262395Sbapt if (hashlin == NULL || hashlin->buckets == NULL) { 76262395Sbapt return NULL; 77262395Sbapt } 78262395Sbapt elt = hashlin->buckets; 79262395Sbapt if (elt == NULL) { 80262395Sbapt return NULL; 81262395Sbapt } 82262395Sbapt } 83262395Sbapt else if (elt == hashlin->buckets) { 84262395Sbapt return NULL; 85262395Sbapt } 86262395Sbapt 87262395Sbapt *iter = elt->hh.next ? elt->hh.next : hashlin->buckets; 88262395Sbapt return elt->data; 89262395Sbapt} 90262395Sbapt 91262395Sbaptbool 92262395Sbaptucl_hash_iter_has_next (ucl_hash_iter_t iter) 93262395Sbapt{ 94262395Sbapt ucl_hash_node_t *elt = iter; 95262395Sbapt 96262395Sbapt return (elt == NULL || elt->hh.prev != NULL); 97262395Sbapt} 98262395Sbapt 99262395Sbapt 100268896Sbaptconst ucl_object_t* 101262395Sbaptucl_hash_search (ucl_hash_t* hashlin, const char *key, unsigned keylen) 102262395Sbapt{ 103262395Sbapt ucl_hash_node_t *found; 104262395Sbapt 105262395Sbapt if (hashlin == NULL) { 106262395Sbapt return NULL; 107262395Sbapt } 108262395Sbapt HASH_FIND (hh, hashlin->buckets, key, keylen, found); 109262395Sbapt 110262395Sbapt if (found) { 111262395Sbapt return found->data; 112262395Sbapt } 113262395Sbapt return NULL; 114262395Sbapt} 115262395Sbapt 116262395Sbaptvoid 117268896Sbaptucl_hash_delete (ucl_hash_t* hashlin, const ucl_object_t *obj) 118262395Sbapt{ 119262395Sbapt ucl_hash_node_t *found; 120262395Sbapt 121262395Sbapt HASH_FIND (hh, hashlin->buckets, obj->key, obj->keylen, found); 122262395Sbapt 123262395Sbapt if (found) { 124262395Sbapt HASH_DELETE (hh, hashlin->buckets, found); 125262395Sbapt } 126262395Sbapt} 127