7011cf398cf2a9dda0722e6ded9fddde359bacd8
[protos/libecoli.git] / lib / ecoli_strvec.c
1 /*
2  * Copyright (c) 2016, Olivier MATZ <zer0@droids-corp.org>
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
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.
15  *
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.
26  */
27
28 #include <sys/types.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <errno.h>
32
33 #include <ecoli_malloc.h>
34 #include <ecoli_strvec.h>
35
36 struct ec_strvec_elt {
37         unsigned int refcnt;
38         char *str;
39 };
40
41 struct ec_strvec {
42         size_t len;
43         struct ec_strvec_elt **vec;
44 };
45
46 struct ec_strvec *ec_strvec(void)
47 {
48         struct ec_strvec *strvec;
49
50         strvec = ec_calloc(1, sizeof(*strvec));
51         if (strvec == NULL)
52                 return NULL;
53
54         return strvec;
55 }
56
57 int ec_strvec_add(struct ec_strvec *strvec, const char *s)
58 {
59         struct ec_strvec_elt *elt, **new_vec;
60
61         new_vec = ec_realloc(strvec->vec,
62                 sizeof(*strvec->vec) * (strvec->len + 1));
63         if (new_vec == NULL)
64                 return -ENOMEM;
65
66         strvec->vec = new_vec;
67
68         elt = ec_malloc(sizeof(*elt));
69         if (elt == NULL)
70                 return -ENOMEM;
71
72         elt->str = ec_strdup(s);
73         if (elt->str == NULL) {
74                 ec_free(elt);
75                 return -ENOMEM;
76         }
77         elt->refcnt = 1;
78
79         new_vec[strvec->len] = elt;
80         strvec->len++;
81         return 0;
82 }
83
84 struct ec_strvec *ec_strvec_ndup(const struct ec_strvec *strvec, size_t off,
85         size_t len)
86 {
87         struct ec_strvec *copy = NULL;
88         size_t i, veclen;
89
90         copy = ec_strvec();
91         if (copy == NULL)
92                 goto fail;
93
94         veclen = ec_strvec_len(strvec);
95         if (off >= veclen)
96                 len = 0;
97         else if (off + len > veclen)
98                 len -= (veclen - off);
99
100         if (len == 0)
101                 return copy;
102
103         copy->vec = ec_calloc(len, sizeof(*copy->vec));
104         if (copy->vec == NULL)
105                 goto fail;
106
107         for (i = 0; i < len; i++) {
108                 copy->vec[i] = strvec->vec[i + off];
109                 copy->vec[i]->refcnt++;
110                 copy->len++;
111         }
112
113         return copy;
114
115 fail:
116         ec_strvec_free(copy);
117         return NULL;
118 }
119
120 struct ec_strvec *ec_strvec_dup(const struct ec_strvec *strvec)
121 {
122         return ec_strvec_ndup(strvec, 0, ec_strvec_len(strvec));
123 }
124
125 void ec_strvec_free(struct ec_strvec *strvec)
126 {
127         struct ec_strvec_elt *elt;
128         size_t i;
129
130         if (strvec == NULL)
131                 return;
132
133         for (i = 0; i < ec_strvec_len(strvec); i++) {
134                 elt = strvec->vec[i];
135                 elt->refcnt--;
136                 if (elt->refcnt == 0) {
137                         ec_free(elt->str);
138                         ec_free(elt);
139                 }
140         }
141
142         ec_free(strvec->vec);
143         ec_free(strvec);
144 }
145
146 size_t ec_strvec_len(const struct ec_strvec *strvec)
147 {
148         return strvec->len;
149 }
150
151 char *ec_strvec_val(const struct ec_strvec *strvec, size_t idx)
152 {
153         if (strvec == NULL || idx >= strvec->len)
154                 return NULL;
155
156         return strvec->vec[idx]->str;
157 }
158
159 void ec_strvec_dump(FILE *out, const struct ec_strvec *strvec)
160 {
161         size_t i;
162
163         if (strvec == NULL) {
164                 fprintf(out, "none\n");
165                 return;
166         }
167
168         fprintf(out, "strvec (len=%zu) [", strvec->len);
169         for (i = 0; i < ec_strvec_len(strvec); i++) {
170                 if (i == 0)
171                         fprintf(out, "%s", strvec->vec[i]->str);
172                 else
173                         fprintf(out, ", %s", strvec->vec[i]->str);
174         }
175         fprintf(out, "]\n");
176
177 }
178
179 /* XXX test case */