1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright 2016, Olivier MATZ <zer0@droids-corp.org>
12 #include <ecoli_malloc.h>
13 #include <ecoli_log.h>
14 #include <ecoli_test.h>
15 #include <ecoli_vec.h>
17 EC_LOG_TYPE_REGISTER(vec);
23 ec_vec_elt_copy_t copy;
24 ec_vec_elt_free_t free;
28 static void *get_obj(const struct ec_vec *vec, size_t idx)
30 assert(vec->elt_size != 0);
31 return (char *)vec->vec + (idx * vec->elt_size);
35 ec_vec(size_t elt_size, size_t size, ec_vec_elt_copy_t copy,
36 ec_vec_elt_free_t free)
45 vec = ec_calloc(1, sizeof(*vec));
49 vec->elt_size = elt_size;
56 vec->vec = ec_calloc(size, vec->elt_size);
57 if (vec->vec == NULL) {
65 int ec_vec_add_by_ref(struct ec_vec *vec, void *ptr)
69 if (vec->len + 1 > vec->size) {
70 new_vec = ec_realloc(vec->vec, vec->elt_size * (vec->len + 1));
73 vec->size = vec->len + 1;
77 memcpy(get_obj(vec, vec->len), ptr, vec->elt_size);
83 int ec_vec_add_ptr(struct ec_vec *vec, void *elt)
85 if (vec->elt_size != sizeof(elt))
88 return ec_vec_add_by_ref(vec, &elt);
91 int ec_vec_add_u8(struct ec_vec *vec, uint8_t elt)
93 if (vec->elt_size != sizeof(elt))
96 return ec_vec_add_by_ref(vec, &elt);
99 int ec_vec_add_u16(struct ec_vec *vec, uint16_t elt)
101 if (vec->elt_size != sizeof(elt))
104 return ec_vec_add_by_ref(vec, &elt);
107 int ec_vec_add_u32(struct ec_vec *vec, uint32_t elt)
109 if (vec->elt_size != sizeof(elt))
112 return ec_vec_add_by_ref(vec, &elt);
115 int ec_vec_add_u64(struct ec_vec *vec, uint64_t elt)
117 if (vec->elt_size != sizeof(elt))
120 return ec_vec_add_by_ref(vec, &elt);
123 struct ec_vec *ec_vec_ndup(const struct ec_vec *vec, size_t off,
126 struct ec_vec *copy = NULL;
129 veclen = ec_vec_len(vec);
130 if (off + len > veclen)
133 copy = ec_vec(vec->elt_size, len, vec->copy, vec->free);
140 for (i = 0; i < len; i++) {
142 vec->copy(get_obj(copy, i), get_obj(vec, i + off));
144 memcpy(get_obj(copy, i), get_obj(vec, i + off),
156 size_t ec_vec_len(const struct ec_vec *vec)
164 struct ec_vec *ec_vec_dup(const struct ec_vec *vec)
166 return ec_vec_ndup(vec, 0, ec_vec_len(vec));
169 void ec_vec_free(struct ec_vec *vec)
176 for (i = 0; i < ec_vec_len(vec); i++) {
178 vec->free(get_obj(vec, i));
185 int ec_vec_get(void *ptr, const struct ec_vec *vec, size_t idx)
187 if (vec == NULL || idx >= vec->len) {
192 memcpy(ptr, get_obj(vec, idx), vec->elt_size);
197 static void str_free(void *elt)
204 #define GOTO_FAIL do { \
205 EC_LOG(EC_LOG_ERR, "%s:%d: test failed\n", \
206 __FILE__, __LINE__); \
210 /* LCOV_EXCL_START */
211 static int ec_vec_testcase(void)
213 struct ec_vec *vec = NULL;
214 struct ec_vec *vec2 = NULL;
223 vec = ec_vec(sizeof(val8), 0, NULL, NULL);
227 if (ec_vec_add_u8(vec, 0) < 0)
229 if (ec_vec_add_u8(vec, 1) < 0)
231 if (ec_vec_add_u8(vec, 2) < 0)
234 if (ec_vec_add_u16(vec, 3) == 0)
236 if (ec_vec_add_u32(vec, 3) == 0)
238 if (ec_vec_add_u64(vec, 3) == 0)
240 if (ec_vec_add_ptr(vec, (void *)3) == 0)
243 if (ec_vec_get(&val8, vec, 0) < 0)
247 if (ec_vec_get(&val8, vec, 1) < 0)
251 if (ec_vec_get(&val8, vec, 2) < 0)
256 /* duplicate the vector */
257 vec2 = ec_vec_dup(vec);
260 if (ec_vec_get(&val8, vec2, 0) < 0)
264 if (ec_vec_get(&val8, vec2, 1) < 0)
268 if (ec_vec_get(&val8, vec2, 2) < 0)
276 /* dup at offset 1 */
277 vec2 = ec_vec_ndup(vec, 1, 2);
280 if (ec_vec_get(&val8, vec2, 0) < 0)
284 if (ec_vec_get(&val8, vec2, 1) < 0)
292 /* len = 0, duplicate is empty */
293 vec2 = ec_vec_ndup(vec, 2, 0);
296 if (ec_vec_get(&val8, vec2, 0) == 0)
303 vec2 = ec_vec_ndup(vec, 10, 1);
310 /* uint16_t vector */
311 vec = ec_vec(sizeof(val16), 0, NULL, NULL);
315 if (ec_vec_add_u16(vec, 0) < 0)
317 if (ec_vec_add_u16(vec, 1) < 0)
319 if (ec_vec_add_u16(vec, 2) < 0)
322 if (ec_vec_add_u8(vec, 3) == 0)
325 if (ec_vec_get(&val16, vec, 0) < 0)
329 if (ec_vec_get(&val16, vec, 1) < 0)
333 if (ec_vec_get(&val16, vec, 2) < 0)
341 /* uint32_t vector */
342 vec = ec_vec(sizeof(val32), 0, NULL, NULL);
346 if (ec_vec_add_u32(vec, 0) < 0)
348 if (ec_vec_add_u32(vec, 1) < 0)
350 if (ec_vec_add_u32(vec, 2) < 0)
353 if (ec_vec_get(&val32, vec, 0) < 0)
357 if (ec_vec_get(&val32, vec, 1) < 0)
361 if (ec_vec_get(&val32, vec, 2) < 0)
369 /* uint64_t vector */
370 vec = ec_vec(sizeof(val64), 0, NULL, NULL);
374 if (ec_vec_add_u64(vec, 0) < 0)
376 if (ec_vec_add_u64(vec, 1) < 0)
378 if (ec_vec_add_u64(vec, 2) < 0)
381 if (ec_vec_get(&val64, vec, 0) < 0)
385 if (ec_vec_get(&val64, vec, 1) < 0)
389 if (ec_vec_get(&val64, vec, 2) < 0)
398 vec = ec_vec(sizeof(valp), 0, NULL, NULL);
402 if (ec_vec_add_ptr(vec, (void *)0) < 0)
404 if (ec_vec_add_ptr(vec, (void *)1) < 0)
406 if (ec_vec_add_ptr(vec, (void *)2) < 0)
409 if (ec_vec_get(&valp, vec, 0) < 0)
411 if (valp != (void *)0)
413 if (ec_vec_get(&valp, vec, 1) < 0)
415 if (valp != (void *)1)
417 if (ec_vec_get(&valp, vec, 2) < 0)
419 if (valp != (void *)2)
426 vec = ec_vec(sizeof(valp), 0, NULL, str_free);
430 if (ec_vec_add_ptr(vec, ec_strdup("0")) < 0)
432 if (ec_vec_add_ptr(vec, ec_strdup("1")) < 0)
434 if (ec_vec_add_ptr(vec, ec_strdup("2")) < 0)
437 if (ec_vec_get(&vals, vec, 0) < 0)
439 if (vals == NULL || strcmp(vals, "0"))
441 if (ec_vec_get(&vals, vec, 1) < 0)
443 if (vals == NULL || strcmp(vals, "1"))
445 if (ec_vec_get(&vals, vec, 2) < 0)
447 if (vals == NULL || strcmp(vals, "2"))
454 vec = ec_vec(0, 0, NULL, NULL);
467 static struct ec_test ec_vec_test = {
469 .test = ec_vec_testcase,
472 EC_TEST_REGISTER(ec_vec_test);