chiark / gitweb /
util: unify code to check whether certain file names should be ignored when listing...
[elogind.git] / strv.c
1 /*-*- Mode: C; c-basic-offset: 8 -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2010 Lennart Poettering
7
8   systemd is free software; you can redistribute it and/or modify it
9   under the terms of the GNU General Public License as published by
10   the Free Software Foundation; either version 2 of the License, or
11   (at your option) any later version.
12
13   systemd is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16   General Public License for more details.
17
18   You should have received a copy of the GNU General Public License
19   along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <assert.h>
23 #include <stdlib.h>
24 #include <stdarg.h>
25 #include <string.h>
26
27 #include "util.h"
28 #include "strv.h"
29
30 char *strv_find(char **l, const char *name) {
31         char **i;
32
33         assert(l);
34         assert(name);
35
36         STRV_FOREACH(i, l)
37                 if (streq(*i, name))
38                         return *i;
39
40         return NULL;
41 }
42
43 void strv_free(char **l) {
44         char **k;
45
46         if (!l)
47                 return;
48
49         for (k = l; *k; k++)
50                 free(*k);
51
52         free(l);
53 }
54
55 char **strv_copy(char **l) {
56         char **r, **k;
57
58         if (!(r = new(char*, strv_length(l)+1)))
59                 return NULL;
60
61         for (k = r; *l; k++, l++)
62                 if (!(*k = strdup(*l)))
63                         goto fail;
64
65         *k = NULL;
66         return r;
67
68 fail:
69         for (k--, l--; k >= r; k--, l--)
70                 free(*k);
71
72         return NULL;
73 }
74
75 unsigned strv_length(char **l) {
76         unsigned n = 0;
77
78         if (!l)
79                 return 0;
80
81         for (; *l; l++)
82                 n++;
83
84         return n;
85 }
86
87 char **strv_new(const char *x, ...) {
88         const char *s;
89         char **a;
90         unsigned n = 0, i = 0;
91         va_list ap;
92
93         if (x) {
94                 n = 1;
95
96                 va_start(ap, x);
97
98                 while (va_arg(ap, const char*))
99                         n++;
100
101                 va_end(ap);
102         }
103
104         if (!(a = new(char*, n+1)))
105                 return NULL;
106
107         if (x) {
108                 if (!(a[i] = strdup(x))) {
109                         free(a);
110                         return NULL;
111                 }
112
113                 i++;
114
115                 va_start(ap, x);
116
117                 while ((s = va_arg(ap, const char*))) {
118                         if (!(a[i] = strdup(s)))
119                                 goto fail;
120
121                         i++;
122                 }
123
124                 va_end(ap);
125         }
126
127         a[i] = NULL;
128         return a;
129
130 fail:
131
132         for (; i > 0; i--)
133                 if (a[i-1])
134                         free(a[i-1]);
135
136         free(a);
137         return NULL;
138 }
139
140 char **strv_merge(char **a, char **b) {
141         char **r, **k;
142
143         if (!a)
144                 return strv_copy(b);
145
146         if (!b)
147                 return strv_copy(a);
148
149         if (!(r = new(char*, strv_length(a)+strv_length(b)+1)))
150                 return NULL;
151
152         for (k = r; *a; k++, a++)
153                 if (!(*k = strdup(*a)))
154                         goto fail;
155         for (; *b; k++, b++)
156                 if (!(*k = strdup(*b)))
157                         goto fail;
158
159         *k = NULL;
160         return r;
161
162 fail:
163         for (k--; k >= r; k--)
164                 free(*k);
165
166         return NULL;
167 }
168
169 char **strv_merge_concat(char **a, char **b, const char *suffix) {
170         char **r, **k;
171
172         /* Like strv_merge(), but appends suffix to all strings in b, before adding */
173
174         if (!b)
175                 return strv_copy(a);
176
177         if (!(r = new(char*, strv_length(a)+strv_length(b)+1)))
178                 return NULL;
179
180         for (k = r; *a; k++, a++)
181                 if (!(*k = strdup(*a)))
182                         goto fail;
183         for (; *b; k++, b++)
184                 if (!(*k = strappend(*b, suffix)))
185                         goto fail;
186
187         *k = NULL;
188         return r;
189
190 fail:
191         for (k--; k >= r; k--)
192                 free(*k);
193
194         return NULL;
195
196 }
197
198 char **strv_split(const char *s, const char *separator) {
199         char *state;
200         char *w;
201         size_t l;
202         unsigned n, i;
203         char **r;
204
205         assert(s);
206
207         n = 0;
208         FOREACH_WORD_SEPARATOR(w, l, s, separator, state)
209                 n++;
210
211         if (!(r = new(char*, n+1)))
212                 return NULL;
213
214         i = 0;
215         FOREACH_WORD_SEPARATOR(w, l, s, separator, state)
216                 if (!(r[i++] = strndup(w, l))) {
217                         strv_free(r);
218                         return NULL;
219                 }
220
221         r[i] = NULL;
222         return r;
223 }
224
225 char **strv_split_quoted(const char *s) {
226         char *state;
227         char *w;
228         size_t l;
229         unsigned n, i;
230         char **r;
231
232         assert(s);
233
234         n = 0;
235         FOREACH_WORD_QUOTED(w, l, s, state)
236                 n++;
237
238         if (!(r = new(char*, n+1)))
239                 return NULL;
240
241         i = 0;
242         FOREACH_WORD_QUOTED(w, l, s, state)
243                 if (!(r[i++] = strndup(w, l))) {
244                         strv_free(r);
245                         return NULL;
246                 }
247
248         r[i] = NULL;
249         return r;
250 }
251
252 char *strv_join(char **l, const char *separator) {
253         char *r, *e;
254         char **s;
255         size_t n, k;
256
257         if (!separator)
258                 separator = " ";
259
260         k = strlen(separator);
261
262         n = 0;
263         STRV_FOREACH(s, l) {
264                 if (n != 0)
265                         n += k;
266                 n += strlen(*s);
267         }
268
269         if (!(r = new(char, n+1)))
270                 return NULL;
271
272         e = r;
273         STRV_FOREACH(s, l) {
274                 if (e != r)
275                         e = stpcpy(e, separator);
276
277                 e = stpcpy(e, *s);
278         }
279
280         return r;
281 }
282
283 char **strv_append(char **l, const char *s) {
284         char **r, **k;
285
286         if (!l)
287                 return strv_new(s, NULL);
288
289         if (!s)
290                 return strv_copy(l);
291
292         if (!(r = new(char*, strv_length(l)+2)))
293                 return NULL;
294
295         for (k = r; *l; k++, l++)
296                 if (!(*k = strdup(*l)))
297                         goto fail;
298         if (!(*(k++) = strdup(s)))
299                 goto fail;
300
301         *k = NULL;
302         return r;
303
304 fail:
305         for (k--; k >= r; k--)
306                 free(*k);
307
308         return NULL;
309 }
310
311 char **strv_uniq(char **l) {
312         char **i;
313
314         /* Drops duplicate entries. The first identical string will be
315          * kept, the others dropped */
316
317         STRV_FOREACH(i, l)
318                 strv_remove(i+1, *i);
319
320         return l;
321 }
322
323 char **strv_remove(char **l, const char *s) {
324         char **f, **t;
325
326         if (!l)
327                 return NULL;
328
329         /* Drops every occurence of s in the string list */
330
331         for (f = t = l; *f; f++) {
332
333                 if (streq(*f, s)) {
334                         free(*f);
335                         continue;
336                 }
337
338                 *(t++) = *f;
339         }
340
341         *t = NULL;
342         return l;
343 }