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>
33 #include <ecoli_malloc.h>
34 #include <ecoli_test.h>
35 #include <ecoli_log.h>
36 #include <ecoli_vec.h>
37 #include <ecoli_strvec.h>
39 EC_LOG_TYPE_REGISTER(strvec);
41 struct ec_strvec_elt {
48 static void ec_strvec_elt_free(void *ptr)
50 struct ec_strvec_elt **p_elt = ptr;
51 struct ec_strvec_elt *elt = *p_elt;
54 if (elt->refcnt == 0) {
60 static void ec_strvec_elt_copy(void *dst, void *src)
62 struct ec_strvec_elt **p_elt_dst = dst, **p_elt_src = src;
63 struct ec_strvec_elt *elt = *p_elt_src;
69 struct ec_strvec *ec_strvec(void)
73 vec = ec_vec(sizeof(struct ec_strvec_elt *), 0,
74 ec_strvec_elt_copy, ec_strvec_elt_free);
76 return (struct ec_strvec *)vec;
79 int ec_strvec_add(struct ec_strvec *strvec, const char *s)
81 struct ec_strvec_elt *elt = NULL;
83 elt = ec_malloc(sizeof(*elt));
87 elt->str = ec_strdup(s);
92 if (ec_vec_add_ptr((struct ec_vec *)strvec, elt) < 0)
102 struct ec_strvec *ec_strvec_ndup(const struct ec_strvec *strvec, size_t off,
105 return (struct ec_strvec *)ec_vec_ndup((struct ec_vec *)strvec,
109 struct ec_strvec *ec_strvec_dup(const struct ec_strvec *strvec)
111 return (struct ec_strvec *)ec_vec_dup((struct ec_vec *)strvec);
114 void ec_strvec_free(struct ec_strvec *strvec)
116 ec_vec_free((struct ec_vec *)strvec);
119 size_t ec_strvec_len(const struct ec_strvec *strvec)
121 return ec_vec_len((struct ec_vec *)strvec);
124 const char *ec_strvec_val(const struct ec_strvec *strvec, size_t idx)
126 struct ec_strvec_elt *elt;
128 if (ec_vec_get(&elt, (struct ec_vec *)strvec, idx) < 0)
134 void ec_strvec_dump(FILE *out, const struct ec_strvec *strvec)
139 if (strvec == NULL) {
140 fprintf(out, "none\n");
144 fprintf(out, "strvec (len=%zu) [", ec_strvec_len(strvec));
145 for (i = 0; i < ec_strvec_len(strvec); i++) {
146 s = ec_strvec_val(strvec, i);
148 fprintf(out, "%s", s);
150 fprintf(out, ", %s", s);
156 /* LCOV_EXCL_START */
157 static int ec_strvec_testcase(void)
159 struct ec_strvec *strvec = NULL;
160 struct ec_strvec *strvec2 = NULL;
162 strvec = ec_strvec();
163 if (strvec == NULL) {
164 EC_TEST_ERR("cannot create strvec\n");
167 if (ec_strvec_len(strvec) != 0) {
168 EC_TEST_ERR("bad strvec len (0)\n");
171 if (ec_strvec_add(strvec, "0") < 0) {
172 EC_TEST_ERR("cannot add (0) in strvec\n");
175 if (ec_strvec_len(strvec) != 1) {
176 EC_TEST_ERR("bad strvec len (1)\n");
179 if (ec_strvec_add(strvec, "1") < 0) {
180 EC_TEST_ERR("cannot add (1) in strvec\n");
183 if (ec_strvec_len(strvec) != 2) {
184 EC_TEST_ERR("bad strvec len (2)\n");
187 if (strcmp(ec_strvec_val(strvec, 0), "0")) {
188 EC_TEST_ERR("invalid element in strvec (0)\n");
191 if (strcmp(ec_strvec_val(strvec, 1), "1")) {
192 EC_TEST_ERR("invalid element in strvec (1)\n");
195 if (ec_strvec_val(strvec, 2) != NULL) {
196 EC_TEST_ERR("strvec val should be NULL\n");
200 strvec2 = ec_strvec_dup(strvec);
201 if (strvec2 == NULL) {
202 EC_TEST_ERR("cannot create strvec2\n");
205 if (ec_strvec_len(strvec2) != 2) {
206 EC_TEST_ERR("bad strvec2 len (2)\n");
209 if (strcmp(ec_strvec_val(strvec2, 0), "0")) {
210 EC_TEST_ERR("invalid element in strvec2 (0)\n");
213 if (strcmp(ec_strvec_val(strvec2, 1), "1")) {
214 EC_TEST_ERR("invalid element in strvec2 (1)\n");
217 if (ec_strvec_val(strvec2, 2) != NULL) {
218 EC_TEST_ERR("strvec2 val should be NULL\n");
221 ec_strvec_free(strvec2);
223 strvec2 = ec_strvec_ndup(strvec, 0, 0);
224 if (strvec2 == NULL) {
225 EC_TEST_ERR("cannot create strvec2\n");
228 if (ec_strvec_len(strvec2) != 0) {
229 EC_TEST_ERR("bad strvec2 len (0)\n");
232 if (ec_strvec_val(strvec2, 0) != NULL) {
233 EC_TEST_ERR("strvec2 val should be NULL\n");
236 ec_strvec_free(strvec2);
238 strvec2 = ec_strvec_ndup(strvec, 1, 1);
239 if (strvec2 == NULL) {
240 EC_TEST_ERR("cannot create strvec2\n");
243 if (ec_strvec_len(strvec2) != 1) {
244 EC_TEST_ERR("bad strvec2 len (1)\n");
247 if (strcmp(ec_strvec_val(strvec2, 0), "1")) {
248 EC_TEST_ERR("invalid element in strvec2 (1)\n");
251 if (ec_strvec_val(strvec2, 1) != NULL) {
252 EC_TEST_ERR("strvec2 val should be NULL\n");
255 ec_strvec_free(strvec2);
257 strvec2 = ec_strvec_ndup(strvec, 3, 1);
258 if (strvec2 != NULL) {
259 EC_TEST_ERR("strvec2 should be NULL\n");
262 ec_strvec_free(strvec2);
264 ec_strvec_dump(stdout, strvec);
265 ec_strvec_dump(stdout, NULL);
267 ec_strvec_free(strvec);
272 ec_strvec_free(strvec);
273 ec_strvec_free(strvec2);
278 static struct ec_test ec_node_str_test = {
280 .test = ec_strvec_testcase,
283 EC_TEST_REGISTER(ec_node_str_test);