2 * Copyright (c) 2016, Olivier MATZ <zer0@droids-corp.org>
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the University of California, Berkeley nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 #include <sys/types.h>
35 #include <ecoli_malloc.h>
36 #include <ecoli_log.h>
37 #include <ecoli_test.h>
38 #include <ecoli_vec.h>
40 EC_LOG_TYPE_REGISTER(vec);
46 ec_vec_elt_copy_t copy;
47 ec_vec_elt_free_t free;
51 static void *get_obj(const struct ec_vec *vec, size_t idx)
53 assert(vec->elt_size != 0);
54 return (char *)vec->vec + (idx * vec->elt_size);
58 ec_vec(size_t elt_size, size_t size, ec_vec_elt_copy_t copy,
59 ec_vec_elt_free_t free)
68 vec = ec_calloc(1, sizeof(*vec));
72 vec->elt_size = elt_size;
79 vec->vec = ec_calloc(size, vec->elt_size);
80 if (vec->vec == NULL) {
88 int ec_vec_add_by_ref(struct ec_vec *vec, void *ptr)
92 if (vec->len + 1 > vec->size) {
93 new_vec = ec_realloc(vec->vec, vec->elt_size * (vec->len + 1));
96 vec->size = vec->len + 1;
101 vec->copy(get_obj(vec, vec->len), ptr);
103 memcpy(get_obj(vec, vec->len), ptr, vec->elt_size);
109 int ec_vec_add_ptr(struct ec_vec *vec, void *elt)
111 if (vec->elt_size != sizeof(elt))
114 return ec_vec_add_by_ref(vec, &elt);
117 int ec_vec_add_u8(struct ec_vec *vec, uint8_t elt)
119 if (vec->elt_size != sizeof(elt))
122 return ec_vec_add_by_ref(vec, &elt);
125 int ec_vec_add_u16(struct ec_vec *vec, uint16_t elt)
127 if (vec->elt_size != sizeof(elt))
130 return ec_vec_add_by_ref(vec, &elt);
133 int ec_vec_add_u32(struct ec_vec *vec, uint32_t elt)
135 if (vec->elt_size != sizeof(elt))
138 return ec_vec_add_by_ref(vec, &elt);
141 int ec_vec_add_u64(struct ec_vec *vec, uint64_t elt)
143 if (vec->elt_size != sizeof(elt))
146 return ec_vec_add_by_ref(vec, &elt);
149 struct ec_vec *ec_vec_ndup(const struct ec_vec *vec, size_t off,
152 struct ec_vec *copy = NULL;
155 veclen = ec_vec_len(vec);
156 if (off + len > veclen)
159 copy = ec_vec(vec->elt_size, len, vec->copy, vec->free);
166 for (i = 0; i < len; i++) {
168 vec->copy(get_obj(copy, i), get_obj(vec, i + off));
170 memcpy(get_obj(copy, i), get_obj(vec, i + off),
182 size_t ec_vec_len(const struct ec_vec *vec)
187 struct ec_vec *ec_vec_dup(const struct ec_vec *vec)
189 return ec_vec_ndup(vec, 0, ec_vec_len(vec));
192 void ec_vec_free(struct ec_vec *vec)
199 for (i = 0; i < ec_vec_len(vec); i++) {
201 vec->free(get_obj(vec, i));
208 int ec_vec_get(void *ptr, const struct ec_vec *vec, size_t idx)
210 if (vec == NULL || idx >= vec->len)
214 vec->copy(ptr, get_obj(vec, idx));
216 memcpy(ptr, get_obj(vec, idx), vec->elt_size);
221 static void str_free(void *elt)
228 #define GOTO_FAIL do { \
229 EC_LOG(EC_LOG_ERR, "%s:%d: test failed\n", \
230 __FILE__, __LINE__); \
234 /* LCOV_EXCL_START */
235 static int ec_vec_testcase(void)
237 struct ec_vec *vec = NULL;
238 struct ec_vec *vec2 = NULL;
247 vec = ec_vec(sizeof(val8), 0, NULL, NULL);
251 if (ec_vec_add_u8(vec, 0) < 0)
253 if (ec_vec_add_u8(vec, 1) < 0)
255 if (ec_vec_add_u8(vec, 2) < 0)
258 if (ec_vec_add_u16(vec, 3) == 0)
260 if (ec_vec_add_u32(vec, 3) == 0)
262 if (ec_vec_add_u64(vec, 3) == 0)
264 if (ec_vec_add_ptr(vec, (void *)3) == 0)
267 if (ec_vec_get(&val8, vec, 0) < 0)
271 if (ec_vec_get(&val8, vec, 1) < 0)
275 if (ec_vec_get(&val8, vec, 2) < 0)
280 /* duplicate the vector */
281 vec2 = ec_vec_dup(vec);
284 if (ec_vec_get(&val8, vec2, 0) < 0)
288 if (ec_vec_get(&val8, vec2, 1) < 0)
292 if (ec_vec_get(&val8, vec2, 2) < 0)
300 /* dup at offset 1 */
301 vec2 = ec_vec_ndup(vec, 1, 2);
304 if (ec_vec_get(&val8, vec2, 0) < 0)
308 if (ec_vec_get(&val8, vec2, 1) < 0)
316 /* len = 0, duplicate is empty */
317 vec2 = ec_vec_ndup(vec, 2, 0);
320 if (ec_vec_get(&val8, vec2, 0) == 0)
327 vec2 = ec_vec_ndup(vec, 10, 1);
334 /* uint16_t vector */
335 vec = ec_vec(sizeof(val16), 0, NULL, NULL);
339 if (ec_vec_add_u16(vec, 0) < 0)
341 if (ec_vec_add_u16(vec, 1) < 0)
343 if (ec_vec_add_u16(vec, 2) < 0)
346 if (ec_vec_add_u8(vec, 3) == 0)
349 if (ec_vec_get(&val16, vec, 0) < 0)
353 if (ec_vec_get(&val16, vec, 1) < 0)
357 if (ec_vec_get(&val16, vec, 2) < 0)
365 /* uint32_t vector */
366 vec = ec_vec(sizeof(val32), 0, NULL, NULL);
370 if (ec_vec_add_u32(vec, 0) < 0)
372 if (ec_vec_add_u32(vec, 1) < 0)
374 if (ec_vec_add_u32(vec, 2) < 0)
377 if (ec_vec_get(&val32, vec, 0) < 0)
381 if (ec_vec_get(&val32, vec, 1) < 0)
385 if (ec_vec_get(&val32, vec, 2) < 0)
393 /* uint64_t vector */
394 vec = ec_vec(sizeof(val64), 0, NULL, NULL);
398 if (ec_vec_add_u64(vec, 0) < 0)
400 if (ec_vec_add_u64(vec, 1) < 0)
402 if (ec_vec_add_u64(vec, 2) < 0)
405 if (ec_vec_get(&val64, vec, 0) < 0)
409 if (ec_vec_get(&val64, vec, 1) < 0)
413 if (ec_vec_get(&val64, vec, 2) < 0)
422 vec = ec_vec(sizeof(valp), 0, NULL, NULL);
426 if (ec_vec_add_ptr(vec, (void *)0) < 0)
428 if (ec_vec_add_ptr(vec, (void *)1) < 0)
430 if (ec_vec_add_ptr(vec, (void *)2) < 0)
433 if (ec_vec_get(&valp, vec, 0) < 0)
435 if (valp != (void *)0)
437 if (ec_vec_get(&valp, vec, 1) < 0)
439 if (valp != (void *)1)
441 if (ec_vec_get(&valp, vec, 2) < 0)
443 if (valp != (void *)2)
450 vec = ec_vec(sizeof(valp), 0, NULL, str_free);
454 if (ec_vec_add_ptr(vec, ec_strdup("0")) < 0)
456 if (ec_vec_add_ptr(vec, ec_strdup("1")) < 0)
458 if (ec_vec_add_ptr(vec, ec_strdup("2")) < 0)
461 if (ec_vec_get(&vals, vec, 0) < 0)
463 if (strcmp(vals, "0"))
465 if (ec_vec_get(&vals, vec, 1) < 0)
467 if (strcmp(vals, "1"))
469 if (ec_vec_get(&vals, vec, 2) < 0)
471 if (strcmp(vals, "2"))
478 vec = ec_vec(0, 0, NULL, NULL);
491 static struct ec_test ec_vec_test = {
493 .test = ec_vec_testcase,
496 EC_TEST_REGISTER(ec_vec_test);