1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright 2016, Olivier MATZ <zer0@droids-corp.org>
12 #include <ecoli_assert.h>
13 #include <ecoli_malloc.h>
14 #include <ecoli_log.h>
15 #include <ecoli_test.h>
16 #include <ecoli_vec.h>
18 EC_LOG_TYPE_REGISTER(vec);
24 ec_vec_elt_copy_t copy;
25 ec_vec_elt_free_t free;
29 static void *get_obj(const struct ec_vec *vec, size_t idx)
31 assert(vec->elt_size != 0);
32 return (char *)vec->vec + (idx * vec->elt_size);
36 ec_vec(size_t elt_size, size_t size, ec_vec_elt_copy_t copy,
37 ec_vec_elt_free_t free)
46 vec = ec_calloc(1, sizeof(*vec));
50 vec->elt_size = elt_size;
57 vec->vec = ec_calloc(size, vec->elt_size);
58 if (vec->vec == NULL) {
66 int ec_vec_add_by_ref(struct ec_vec *vec, void *ptr)
70 if (vec->len + 1 > vec->size) {
71 new_vec = ec_realloc(vec->vec, vec->elt_size * (vec->len + 1));
74 vec->size = vec->len + 1;
78 memcpy(get_obj(vec, vec->len), ptr, vec->elt_size);
84 int ec_vec_add_ptr(struct ec_vec *vec, void *elt)
86 EC_CHECK_ARG(vec->elt_size == sizeof(elt), -1, EINVAL);
88 return ec_vec_add_by_ref(vec, &elt);
91 int ec_vec_add_u8(struct ec_vec *vec, uint8_t elt)
93 EC_CHECK_ARG(vec->elt_size == sizeof(elt), -1, EINVAL);
95 return ec_vec_add_by_ref(vec, &elt);
98 int ec_vec_add_u16(struct ec_vec *vec, uint16_t elt)
100 EC_CHECK_ARG(vec->elt_size == sizeof(elt), -1, EINVAL);
102 return ec_vec_add_by_ref(vec, &elt);
105 int ec_vec_add_u32(struct ec_vec *vec, uint32_t elt)
107 EC_CHECK_ARG(vec->elt_size == sizeof(elt), -1, EINVAL);
109 return ec_vec_add_by_ref(vec, &elt);
112 int ec_vec_add_u64(struct ec_vec *vec, uint64_t elt)
114 EC_CHECK_ARG(vec->elt_size == sizeof(elt), -1, EINVAL);
116 return ec_vec_add_by_ref(vec, &elt);
119 struct ec_vec *ec_vec_ndup(const struct ec_vec *vec, size_t off,
122 struct ec_vec *copy = NULL;
125 veclen = ec_vec_len(vec);
126 if (off + len > veclen)
129 copy = ec_vec(vec->elt_size, len, vec->copy, vec->free);
136 for (i = 0; i < len; i++) {
138 vec->copy(get_obj(copy, i), get_obj(vec, i + off));
140 memcpy(get_obj(copy, i), get_obj(vec, i + off),
152 size_t ec_vec_len(const struct ec_vec *vec)
160 struct ec_vec *ec_vec_dup(const struct ec_vec *vec)
162 return ec_vec_ndup(vec, 0, ec_vec_len(vec));
165 void ec_vec_free(struct ec_vec *vec)
172 for (i = 0; i < ec_vec_len(vec); i++) {
174 vec->free(get_obj(vec, i));
181 int ec_vec_get(void *ptr, const struct ec_vec *vec, size_t idx)
183 if (vec == NULL || idx >= vec->len) {
188 memcpy(ptr, get_obj(vec, idx), vec->elt_size);
193 static void str_free(void *elt)
200 #define GOTO_FAIL do { \
201 EC_LOG(EC_LOG_ERR, "%s:%d: test failed\n", \
202 __FILE__, __LINE__); \
206 /* LCOV_EXCL_START */
207 static int ec_vec_testcase(void)
209 struct ec_vec *vec = NULL;
210 struct ec_vec *vec2 = NULL;
219 vec = ec_vec(sizeof(val8), 0, NULL, NULL);
223 if (ec_vec_add_u8(vec, 0) < 0)
225 if (ec_vec_add_u8(vec, 1) < 0)
227 if (ec_vec_add_u8(vec, 2) < 0)
230 if (ec_vec_add_u16(vec, 3) == 0)
232 if (ec_vec_add_u32(vec, 3) == 0)
234 if (ec_vec_add_u64(vec, 3) == 0)
236 if (ec_vec_add_ptr(vec, (void *)3) == 0)
239 if (ec_vec_get(&val8, vec, 0) < 0)
243 if (ec_vec_get(&val8, vec, 1) < 0)
247 if (ec_vec_get(&val8, vec, 2) < 0)
252 /* duplicate the vector */
253 vec2 = ec_vec_dup(vec);
256 if (ec_vec_get(&val8, vec2, 0) < 0)
260 if (ec_vec_get(&val8, vec2, 1) < 0)
264 if (ec_vec_get(&val8, vec2, 2) < 0)
272 /* dup at offset 1 */
273 vec2 = ec_vec_ndup(vec, 1, 2);
276 if (ec_vec_get(&val8, vec2, 0) < 0)
280 if (ec_vec_get(&val8, vec2, 1) < 0)
288 /* len = 0, duplicate is empty */
289 vec2 = ec_vec_ndup(vec, 2, 0);
292 if (ec_vec_get(&val8, vec2, 0) == 0)
299 vec2 = ec_vec_ndup(vec, 10, 1);
306 /* uint16_t vector */
307 vec = ec_vec(sizeof(val16), 0, NULL, NULL);
311 if (ec_vec_add_u16(vec, 0) < 0)
313 if (ec_vec_add_u16(vec, 1) < 0)
315 if (ec_vec_add_u16(vec, 2) < 0)
318 if (ec_vec_add_u8(vec, 3) == 0)
321 if (ec_vec_get(&val16, vec, 0) < 0)
325 if (ec_vec_get(&val16, vec, 1) < 0)
329 if (ec_vec_get(&val16, vec, 2) < 0)
337 /* uint32_t vector */
338 vec = ec_vec(sizeof(val32), 0, NULL, NULL);
342 if (ec_vec_add_u32(vec, 0) < 0)
344 if (ec_vec_add_u32(vec, 1) < 0)
346 if (ec_vec_add_u32(vec, 2) < 0)
349 if (ec_vec_get(&val32, vec, 0) < 0)
353 if (ec_vec_get(&val32, vec, 1) < 0)
357 if (ec_vec_get(&val32, vec, 2) < 0)
365 /* uint64_t vector */
366 vec = ec_vec(sizeof(val64), 0, NULL, NULL);
370 if (ec_vec_add_u64(vec, 0) < 0)
372 if (ec_vec_add_u64(vec, 1) < 0)
374 if (ec_vec_add_u64(vec, 2) < 0)
377 if (ec_vec_get(&val64, vec, 0) < 0)
381 if (ec_vec_get(&val64, vec, 1) < 0)
385 if (ec_vec_get(&val64, vec, 2) < 0)
394 vec = ec_vec(sizeof(valp), 0, NULL, NULL);
398 if (ec_vec_add_ptr(vec, (void *)0) < 0)
400 if (ec_vec_add_ptr(vec, (void *)1) < 0)
402 if (ec_vec_add_ptr(vec, (void *)2) < 0)
405 if (ec_vec_get(&valp, vec, 0) < 0)
407 if (valp != (void *)0)
409 if (ec_vec_get(&valp, vec, 1) < 0)
411 if (valp != (void *)1)
413 if (ec_vec_get(&valp, vec, 2) < 0)
415 if (valp != (void *)2)
422 vec = ec_vec(sizeof(valp), 0, NULL, str_free);
426 if (ec_vec_add_ptr(vec, ec_strdup("0")) < 0)
428 if (ec_vec_add_ptr(vec, ec_strdup("1")) < 0)
430 if (ec_vec_add_ptr(vec, ec_strdup("2")) < 0)
433 if (ec_vec_get(&vals, vec, 0) < 0)
435 if (vals == NULL || strcmp(vals, "0"))
437 if (ec_vec_get(&vals, vec, 1) < 0)
439 if (vals == NULL || strcmp(vals, "1"))
441 if (ec_vec_get(&vals, vec, 2) < 0)
443 if (vals == NULL || strcmp(vals, "2"))
450 vec = ec_vec(0, 0, NULL, NULL);
463 static struct ec_test ec_vec_test = {
465 .test = ec_vec_testcase,
468 EC_TEST_REGISTER(ec_vec_test);