xref: /freebsd/contrib/libucl/src/ucl_hash.c (revision 38f0b757fd84d17d0fc24739a7cda160c4516d81)
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  *         notice, this list of conditions and the following disclaimer in the
10  *         documentation and/or other materials provided with the distribution.
11  *
12  * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY
13  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
14  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
15  * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY
16  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
17  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
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"
27 
28 ucl_hash_t*
29 ucl_hash_create (void)
30 {
31 	ucl_hash_t *new;
32 
33 	new = UCL_ALLOC (sizeof (ucl_hash_t));
34 	if (new != NULL) {
35 		new->buckets = NULL;
36 	}
37 	return new;
38 }
39 
40 void ucl_hash_destroy (ucl_hash_t* hashlin, ucl_hash_free_func *func)
41 {
42 	ucl_hash_node_t *elt, *tmp;
43 
44 	HASH_ITER (hh, hashlin->buckets, elt, tmp) {
45 		HASH_DELETE (hh, hashlin->buckets, elt);
46 		if (func) {
47 			func (elt->data);
48 		}
49 		UCL_FREE (sizeof (ucl_hash_node_t), elt);
50 	}
51 	UCL_FREE (sizeof (ucl_hash_t), hashlin);
52 }
53 
54 void
55 ucl_hash_insert (ucl_hash_t* hashlin, ucl_object_t *obj, const char *key, unsigned keylen)
56 {
57 	ucl_hash_node_t *node;
58 
59 	node = UCL_ALLOC (sizeof (ucl_hash_node_t));
60 	node->data = obj;
61 	HASH_ADD_KEYPTR (hh, hashlin->buckets, key, keylen, node);
62 }
63 
64 void*
65 ucl_hash_iterate (ucl_hash_t *hashlin, ucl_hash_iter_t *iter)
66 {
67 	ucl_hash_node_t *elt = *iter;
68 
69 	if (elt == NULL) {
70 		if (hashlin == NULL || hashlin->buckets == NULL) {
71 			return NULL;
72 		}
73 		elt = hashlin->buckets;
74 		if (elt == NULL) {
75 			return NULL;
76 		}
77 	}
78 	else if (elt == hashlin->buckets) {
79 		return NULL;
80 	}
81 
82 	*iter = elt->hh.next ? elt->hh.next : hashlin->buckets;
83 	return elt->data;
84 }
85 
86 bool
87 ucl_hash_iter_has_next (ucl_hash_iter_t iter)
88 {
89 	ucl_hash_node_t *elt = iter;
90 
91 	return (elt == NULL || elt->hh.prev != NULL);
92 }
93 
94 
95 ucl_object_t*
96 ucl_hash_search (ucl_hash_t* hashlin, const char *key, unsigned keylen)
97 {
98 	ucl_hash_node_t *found;
99 
100 	if (hashlin == NULL) {
101 		return NULL;
102 	}
103 	HASH_FIND (hh, hashlin->buckets, key, keylen, found);
104 
105 	if (found) {
106 		return found->data;
107 	}
108 	return NULL;
109 }
110 
111 void
112 ucl_hash_delete (ucl_hash_t* hashlin, ucl_object_t *obj)
113 {
114 	ucl_hash_node_t *found;
115 
116 	HASH_FIND (hh, hashlin->buckets, obj->key, obj->keylen, found);
117 
118 	if (found) {
119 		HASH_DELETE (hh, hashlin->buckets, found);
120 	}
121 }
122