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;
100 memcpy(get_obj(vec, vec->len), ptr, vec->elt_size);
106 int ec_vec_add_ptr(struct ec_vec *vec, void *elt)
108 if (vec->elt_size != sizeof(elt))
111 return ec_vec_add_by_ref(vec, &elt);
114 int ec_vec_add_u8(struct ec_vec *vec, uint8_t elt)
116 if (vec->elt_size != sizeof(elt))
119 return ec_vec_add_by_ref(vec, &elt);
122 int ec_vec_add_u16(struct ec_vec *vec, uint16_t elt)
124 if (vec->elt_size != sizeof(elt))
127 return ec_vec_add_by_ref(vec, &elt);
130 int ec_vec_add_u32(struct ec_vec *vec, uint32_t elt)
132 if (vec->elt_size != sizeof(elt))
135 return ec_vec_add_by_ref(vec, &elt);
138 int ec_vec_add_u64(struct ec_vec *vec, uint64_t elt)
140 if (vec->elt_size != sizeof(elt))
143 return ec_vec_add_by_ref(vec, &elt);
146 struct ec_vec *ec_vec_ndup(const struct ec_vec *vec, size_t off,
149 struct ec_vec *copy = NULL;
152 veclen = ec_vec_len(vec);
153 if (off + len > veclen)
156 copy = ec_vec(vec->elt_size, len, vec->copy, vec->free);
163 for (i = 0; i < len; i++) {
165 vec->copy(get_obj(copy, i), get_obj(vec, i + off));
167 memcpy(get_obj(copy, i), get_obj(vec, i + off),
179 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) {
215 memcpy(ptr, get_obj(vec, idx), vec->elt_size);
220 static void str_free(void *elt)
227 #define GOTO_FAIL do { \
228 EC_LOG(EC_LOG_ERR, "%s:%d: test failed\n", \
229 __FILE__, __LINE__); \
233 /* LCOV_EXCL_START */
234 static int ec_vec_testcase(void)
236 struct ec_vec *vec = NULL;
237 struct ec_vec *vec2 = NULL;
246 vec = ec_vec(sizeof(val8), 0, NULL, NULL);
250 if (ec_vec_add_u8(vec, 0) < 0)
252 if (ec_vec_add_u8(vec, 1) < 0)
254 if (ec_vec_add_u8(vec, 2) < 0)
257 if (ec_vec_add_u16(vec, 3) == 0)
259 if (ec_vec_add_u32(vec, 3) == 0)
261 if (ec_vec_add_u64(vec, 3) == 0)
263 if (ec_vec_add_ptr(vec, (void *)3) == 0)
266 if (ec_vec_get(&val8, vec, 0) < 0)
270 if (ec_vec_get(&val8, vec, 1) < 0)
274 if (ec_vec_get(&val8, vec, 2) < 0)
279 /* duplicate the vector */
280 vec2 = ec_vec_dup(vec);
283 if (ec_vec_get(&val8, vec2, 0) < 0)
287 if (ec_vec_get(&val8, vec2, 1) < 0)
291 if (ec_vec_get(&val8, vec2, 2) < 0)
299 /* dup at offset 1 */
300 vec2 = ec_vec_ndup(vec, 1, 2);
303 if (ec_vec_get(&val8, vec2, 0) < 0)
307 if (ec_vec_get(&val8, vec2, 1) < 0)
315 /* len = 0, duplicate is empty */
316 vec2 = ec_vec_ndup(vec, 2, 0);
319 if (ec_vec_get(&val8, vec2, 0) == 0)
326 vec2 = ec_vec_ndup(vec, 10, 1);
333 /* uint16_t vector */
334 vec = ec_vec(sizeof(val16), 0, NULL, NULL);
338 if (ec_vec_add_u16(vec, 0) < 0)
340 if (ec_vec_add_u16(vec, 1) < 0)
342 if (ec_vec_add_u16(vec, 2) < 0)
345 if (ec_vec_add_u8(vec, 3) == 0)
348 if (ec_vec_get(&val16, vec, 0) < 0)
352 if (ec_vec_get(&val16, vec, 1) < 0)
356 if (ec_vec_get(&val16, vec, 2) < 0)
364 /* uint32_t vector */
365 vec = ec_vec(sizeof(val32), 0, NULL, NULL);
369 if (ec_vec_add_u32(vec, 0) < 0)
371 if (ec_vec_add_u32(vec, 1) < 0)
373 if (ec_vec_add_u32(vec, 2) < 0)
376 if (ec_vec_get(&val32, vec, 0) < 0)
380 if (ec_vec_get(&val32, vec, 1) < 0)
384 if (ec_vec_get(&val32, vec, 2) < 0)
392 /* uint64_t vector */
393 vec = ec_vec(sizeof(val64), 0, NULL, NULL);
397 if (ec_vec_add_u64(vec, 0) < 0)
399 if (ec_vec_add_u64(vec, 1) < 0)
401 if (ec_vec_add_u64(vec, 2) < 0)
404 if (ec_vec_get(&val64, vec, 0) < 0)
408 if (ec_vec_get(&val64, vec, 1) < 0)
412 if (ec_vec_get(&val64, vec, 2) < 0)
421 vec = ec_vec(sizeof(valp), 0, NULL, NULL);
425 if (ec_vec_add_ptr(vec, (void *)0) < 0)
427 if (ec_vec_add_ptr(vec, (void *)1) < 0)
429 if (ec_vec_add_ptr(vec, (void *)2) < 0)
432 if (ec_vec_get(&valp, vec, 0) < 0)
434 if (valp != (void *)0)
436 if (ec_vec_get(&valp, vec, 1) < 0)
438 if (valp != (void *)1)
440 if (ec_vec_get(&valp, vec, 2) < 0)
442 if (valp != (void *)2)
449 vec = ec_vec(sizeof(valp), 0, NULL, str_free);
453 if (ec_vec_add_ptr(vec, ec_strdup("0")) < 0)
455 if (ec_vec_add_ptr(vec, ec_strdup("1")) < 0)
457 if (ec_vec_add_ptr(vec, ec_strdup("2")) < 0)
460 if (ec_vec_get(&vals, vec, 0) < 0)
462 if (vals == NULL || strcmp(vals, "0"))
464 if (ec_vec_get(&vals, vec, 1) < 0)
466 if (vals == NULL || strcmp(vals, "1"))
468 if (ec_vec_get(&vals, vec, 2) < 0)
470 if (vals == NULL || strcmp(vals, "2"))
477 vec = ec_vec(0, 0, NULL, NULL);
490 static struct ec_test ec_vec_test = {
492 .test = ec_vec_testcase,
495 EC_TEST_REGISTER(ec_vec_test);