1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright 2016, Olivier MATZ <zer0@droids-corp.org>
15 #include <ecoli_init.h>
16 #include <ecoli_malloc.h>
17 #include <ecoli_log.h>
18 #include <ecoli_test.h>
19 #include <ecoli_htable_private.h>
20 #include <ecoli_dict.h>
22 EC_LOG_TYPE_REGISTER(dict);
25 _strlen(const char *s)
33 struct ec_htable_elt htable;
36 struct ec_dict_elt_ref {
37 struct ec_htable_elt_ref htable;
41 struct ec_htable htable;
44 struct ec_dict *ec_dict(void)
46 return (struct ec_dict *)ec_htable();
49 bool ec_dict_has_key(const struct ec_dict *dict, const char *key)
51 return ec_htable_has_key(
52 &dict->htable, key, _strlen(key) + 1);
55 void *ec_dict_get(const struct ec_dict *dict, const char *key)
57 return ec_htable_get(&dict->htable, key, _strlen(key) + 1);
60 int ec_dict_del(struct ec_dict *dict, const char *key)
62 return ec_htable_del(&dict->htable, key, _strlen(key) + 1);
65 int ec_dict_set(struct ec_dict *dict, const char *key, void *val,
66 ec_dict_elt_free_t free_cb)
68 return ec_htable_set(&dict->htable, key, _strlen(key) + 1,
72 void ec_dict_free(struct ec_dict *dict)
74 ec_htable_free(&dict->htable);
77 size_t ec_dict_len(const struct ec_dict *dict)
79 return ec_htable_len(&dict->htable);
82 struct ec_dict_elt_ref *
83 ec_dict_iter(const struct ec_dict *dict)
85 return (struct ec_dict_elt_ref *)ec_htable_iter(&dict->htable);
88 struct ec_dict_elt_ref *
89 ec_dict_iter_next(struct ec_dict_elt_ref *iter)
91 return (struct ec_dict_elt_ref *)ec_htable_iter_next(&iter->htable);
95 ec_dict_iter_get_key(const struct ec_dict_elt_ref *iter)
97 return (const char *)ec_htable_iter_get_key(&iter->htable);
101 ec_dict_iter_get_val(const struct ec_dict_elt_ref *iter)
103 return (struct ec_dict_elt_ref *)ec_htable_iter_get_val(&iter->htable);
106 void ec_dict_dump(FILE *out, const struct ec_dict *dict)
108 struct ec_dict_elt_ref *iter;
111 fprintf(out, "empty dict\n");
115 fprintf(out, "dict:\n");
116 for (iter = ec_dict_iter(dict);
118 iter = ec_dict_iter_next(iter)) {
119 fprintf(out, " %s: %p\n",
120 ec_dict_iter_get_key(iter),
121 ec_dict_iter_get_val(iter));
125 struct ec_dict *ec_dict_dup(const struct ec_dict *dict)
127 return (struct ec_dict *)ec_htable_dup(&dict->htable);
130 /* LCOV_EXCL_START */
131 static int ec_dict_testcase(void)
133 struct ec_dict *dict, *dup;
134 struct ec_dict_elt_ref *iter;
137 int ret, testres = 0;
144 EC_LOG(EC_LOG_ERR, "cannot create dict\n");
149 for (iter = ec_dict_iter(dict);
151 iter = ec_dict_iter_next(iter)) {
154 testres |= EC_TEST_CHECK(count == 0, "invalid count in iterator");
156 testres |= EC_TEST_CHECK(ec_dict_len(dict) == 0, "bad dict len");
157 ret = ec_dict_set(dict, "key1", "val1", NULL);
158 testres |= EC_TEST_CHECK(ret == 0, "cannot set key");
159 ret = ec_dict_set(dict, "key2", ec_strdup("val2"), ec_free_func);
160 testres |= EC_TEST_CHECK(ret == 0, "cannot set key");
161 testres |= EC_TEST_CHECK(ec_dict_len(dict) == 2, "bad dict len");
163 val = ec_dict_get(dict, "key1");
164 testres |= EC_TEST_CHECK(val != NULL && !strcmp(val, "val1"),
165 "invalid dict value");
166 val = ec_dict_get(dict, "key2");
167 testres |= EC_TEST_CHECK(val != NULL && !strcmp(val, "val2"),
168 "invalid dict value");
169 val = ec_dict_get(dict, "key3");
170 testres |= EC_TEST_CHECK(val == NULL, "key3 should be NULL");
172 ret = ec_dict_set(dict, "key1", "another_val1", NULL);
173 testres |= EC_TEST_CHECK(ret == 0, "cannot set key");
174 ret = ec_dict_set(dict, "key2", ec_strdup("another_val2"),
176 testres |= EC_TEST_CHECK(ret == 0, "cannot set key");
177 testres |= EC_TEST_CHECK(ec_dict_len(dict) == 2,
180 val = ec_dict_get(dict, "key1");
181 testres |= EC_TEST_CHECK(val != NULL && !strcmp(val, "another_val1"),
182 "invalid dict value");
183 val = ec_dict_get(dict, "key2");
184 testres |= EC_TEST_CHECK(val != NULL && !strcmp(val, "another_val2"),
185 "invalid dict value");
186 testres |= EC_TEST_CHECK(ec_dict_has_key(dict, "key1"),
187 "key1 should be in dict");
189 f = open_memstream(&buf, &buflen);
192 ec_dict_dump(f, NULL);
198 f = open_memstream(&buf, &buflen);
201 ec_dict_dump(f, dict);
207 ret = ec_dict_del(dict, "key1");
208 testres |= EC_TEST_CHECK(ret == 0, "cannot del key1");
209 testres |= EC_TEST_CHECK(ec_dict_len(dict) == 1,
211 ret = ec_dict_del(dict, "key2");
212 testres |= EC_TEST_CHECK(ret == 0, "cannot del key2");
213 testres |= EC_TEST_CHECK(ec_dict_len(dict) == 0,
216 for (i = 0; i < 100; i++) {
218 snprintf(key, sizeof(key), "k%zd", i);
219 ret = ec_dict_set(dict, key, "val", NULL);
220 testres |= EC_TEST_CHECK(ret == 0, "cannot set key");
222 dup = ec_dict_dup(dict);
223 testres |= EC_TEST_CHECK(dup != NULL, "cannot duplicate dict");
225 for (i = 0; i < 100; i++) {
227 snprintf(key, sizeof(key), "k%zd", i);
228 val = ec_dict_get(dup, key);
229 testres |= EC_TEST_CHECK(
230 val != NULL && !strcmp(val, "val"),
231 "invalid dict value");
238 for (iter = ec_dict_iter(dict);
240 iter = ec_dict_iter_next(iter)) {
243 testres |= EC_TEST_CHECK(count == 100, "invalid count in iterator");
246 ret = ec_dict_set(dict, NULL, "val1", NULL);
247 testres |= EC_TEST_CHECK(ret == -1, "should not be able to set key");
248 val = ec_dict_get(dict, NULL);
249 testres |= EC_TEST_CHECK(val == NULL, "get(NULL) should no success");
264 static struct ec_test ec_dict_test = {
266 .test = ec_dict_testcase,
269 EC_TEST_REGISTER(ec_dict_test);