]> git.ipfire.org Git - people/ms/systemd.git/blob - strv.c
Remove .h files from _SOURCES
[people/ms/systemd.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 #include <errno.h>
27
28 #include "util.h"
29 #include "strv.h"
30
31 char *strv_find(char **l, const char *name) {
32 char **i;
33
34 assert(l);
35 assert(name);
36
37 STRV_FOREACH(i, l)
38 if (streq(*i, name))
39 return *i;
40
41 return NULL;
42 }
43
44 void strv_free(char **l) {
45 char **k;
46
47 if (!l)
48 return;
49
50 for (k = l; *k; k++)
51 free(*k);
52
53 free(l);
54 }
55
56 char **strv_copy(char **l) {
57 char **r, **k;
58
59 if (!(r = new(char*, strv_length(l)+1)))
60 return NULL;
61
62 for (k = r; *l; k++, l++)
63 if (!(*k = strdup(*l)))
64 goto fail;
65
66 *k = NULL;
67 return r;
68
69 fail:
70 for (k--, l--; k >= r; k--, l--)
71 free(*k);
72
73 return NULL;
74 }
75
76 unsigned strv_length(char **l) {
77 unsigned n = 0;
78
79 if (!l)
80 return 0;
81
82 for (; *l; l++)
83 n++;
84
85 return n;
86 }
87
88 char **strv_new_ap(const char *x, va_list ap) {
89 const char *s;
90 char **a;
91 unsigned n = 0, i = 0;
92 va_list aq;
93
94
95 if (x) {
96 n = 1;
97
98 va_copy(aq, ap);
99 while (va_arg(aq, const char*))
100 n++;
101 va_end(aq);
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 while ((s = va_arg(ap, const char*))) {
116 if (!(a[i] = strdup(s)))
117 goto fail;
118
119 i++;
120 }
121 }
122
123 a[i] = NULL;
124
125 return a;
126
127 fail:
128
129 for (; i > 0; i--)
130 if (a[i-1])
131 free(a[i-1]);
132
133 free(a);
134
135 return NULL;
136 }
137
138 char **strv_new(const char *x, ...) {
139 char **r;
140 va_list ap;
141
142 va_start(ap, x);
143 r = strv_new_ap(x, ap);
144 va_end(ap);
145
146 return r;
147 }
148
149 char **strv_merge(char **a, char **b) {
150 char **r, **k;
151
152 if (!a)
153 return strv_copy(b);
154
155 if (!b)
156 return strv_copy(a);
157
158 if (!(r = new(char*, strv_length(a)+strv_length(b)+1)))
159 return NULL;
160
161 for (k = r; *a; k++, a++)
162 if (!(*k = strdup(*a)))
163 goto fail;
164 for (; *b; k++, b++)
165 if (!(*k = strdup(*b)))
166 goto fail;
167
168 *k = NULL;
169 return r;
170
171 fail:
172 for (k--; k >= r; k--)
173 free(*k);
174
175 free(r);
176
177 return NULL;
178 }
179
180 char **strv_merge_concat(char **a, char **b, const char *suffix) {
181 char **r, **k;
182
183 /* Like strv_merge(), but appends suffix to all strings in b, before adding */
184
185 if (!b)
186 return strv_copy(a);
187
188 if (!(r = new(char*, strv_length(a)+strv_length(b)+1)))
189 return NULL;
190
191 for (k = r; *a; k++, a++)
192 if (!(*k = strdup(*a)))
193 goto fail;
194 for (; *b; k++, b++)
195 if (!(*k = strappend(*b, suffix)))
196 goto fail;
197
198 *k = NULL;
199 return r;
200
201 fail:
202 for (k--; k >= r; k--)
203 free(*k);
204
205 free(r);
206
207 return NULL;
208
209 }
210
211 char **strv_split(const char *s, const char *separator) {
212 char *state;
213 char *w;
214 size_t l;
215 unsigned n, i;
216 char **r;
217
218 assert(s);
219
220 n = 0;
221 FOREACH_WORD_SEPARATOR(w, l, s, separator, state)
222 n++;
223
224 if (!(r = new(char*, n+1)))
225 return NULL;
226
227 i = 0;
228 FOREACH_WORD_SEPARATOR(w, l, s, separator, state)
229 if (!(r[i++] = strndup(w, l))) {
230 strv_free(r);
231 return NULL;
232 }
233
234 r[i] = NULL;
235 return r;
236 }
237
238 char **strv_split_quoted(const char *s) {
239 char *state;
240 char *w;
241 size_t l;
242 unsigned n, i;
243 char **r;
244
245 assert(s);
246
247 n = 0;
248 FOREACH_WORD_QUOTED(w, l, s, state)
249 n++;
250
251 if (!(r = new(char*, n+1)))
252 return NULL;
253
254 i = 0;
255 FOREACH_WORD_QUOTED(w, l, s, state)
256 if (!(r[i++] = strndup(w, l))) {
257 strv_free(r);
258 return NULL;
259 }
260
261 r[i] = NULL;
262 return r;
263 }
264
265 char *strv_join(char **l, const char *separator) {
266 char *r, *e;
267 char **s;
268 size_t n, k;
269
270 if (!separator)
271 separator = " ";
272
273 k = strlen(separator);
274
275 n = 0;
276 STRV_FOREACH(s, l) {
277 if (n != 0)
278 n += k;
279 n += strlen(*s);
280 }
281
282 if (!(r = new(char, n+1)))
283 return NULL;
284
285 e = r;
286 STRV_FOREACH(s, l) {
287 if (e != r)
288 e = stpcpy(e, separator);
289
290 e = stpcpy(e, *s);
291 }
292
293 *e = 0;
294
295 return r;
296 }
297
298 char **strv_append(char **l, const char *s) {
299 char **r, **k;
300
301 if (!l)
302 return strv_new(s, NULL);
303
304 if (!s)
305 return strv_copy(l);
306
307 if (!(r = new(char*, strv_length(l)+2)))
308 return NULL;
309
310 for (k = r; *l; k++, l++)
311 if (!(*k = strdup(*l)))
312 goto fail;
313
314 if (!(*(k++) = strdup(s)))
315 goto fail;
316
317 *k = NULL;
318 return r;
319
320 fail:
321 for (k--; k >= r; k--)
322 free(*k);
323
324 free(r);
325
326 return NULL;
327 }
328
329 char **strv_uniq(char **l) {
330 char **i;
331
332 /* Drops duplicate entries. The first identical string will be
333 * kept, the others dropped */
334
335 STRV_FOREACH(i, l)
336 strv_remove(i+1, *i);
337
338 return l;
339 }
340
341 char **strv_remove(char **l, const char *s) {
342 char **f, **t;
343
344 if (!l)
345 return NULL;
346
347 /* Drops every occurence of s in the string list */
348
349 for (f = t = l; *f; f++) {
350
351 if (streq(*f, s)) {
352 free(*f);
353 continue;
354 }
355
356 *(t++) = *f;
357 }
358
359 *t = NULL;
360 return l;
361 }
362
363 static int env_append(char **r, char ***k, char **a) {
364 assert(r);
365 assert(k);
366 assert(a);
367
368 /* Add the entries of a to *k unless they already exist in *r
369 * in which case they are overriden instead. This assumes
370 * there is enough space in the r */
371
372 for (; *a; a++) {
373 char **j;
374 size_t n = strcspn(*a, "=") + 1;
375
376 for (j = r; j < *k; j++)
377 if (strncmp(*j, *a, n) == 0)
378 break;
379
380 if (j >= *k)
381 (*k)++;
382 else
383 free(*j);
384
385 if (!(*j = strdup(*a)))
386 return -ENOMEM;
387 }
388
389 return 0;
390 }
391
392 char **strv_env_merge(char **x, ...) {
393 size_t n = 0;
394 char **l, **k, **r;
395 va_list ap;
396
397 /* Merges an arbitrary number of environment sets */
398
399 if (x) {
400 n += strv_length(x);
401
402 va_start(ap, x);
403 while ((l = va_arg(ap, char**)))
404 n += strv_length(l);
405 va_end(ap);
406 }
407
408
409 if (!(r = new(char*, n+1)))
410 return NULL;
411
412 k = r;
413
414 if (x) {
415 if (env_append(r, &k, x) < 0)
416 goto fail;
417
418 va_start(ap, x);
419 while ((l = va_arg(ap, char**)))
420 if (env_append(r, &k, l) < 0)
421 goto fail;
422 va_end(ap);
423 }
424
425 *k = NULL;
426
427 return r;
428
429 fail:
430 for (k--; k >= r; k--)
431 free(*k);
432
433 free(r);
434
435 return NULL;
436 }
437
438 static bool env_match(const char *t, const char *pattern) {
439 assert(t);
440 assert(pattern);
441
442 /* pattern a matches string a
443 * a matches a=
444 * a matches a=b
445 * a= matches a=
446 * a=b matches a=b
447 * a= does not match a
448 * a=b does not match a=
449 * a=b does not match a
450 * a=b does not match a=c */
451
452 if (streq(t, pattern))
453 return true;
454
455 if (!strchr(pattern, '=')) {
456 size_t l = strlen(pattern);
457
458 return strncmp(t, pattern, l) == 0 && t[l] == '=';
459 }
460
461 return false;
462 }
463
464 char **strv_env_delete(char **x, ...) {
465 size_t n = 0, i = 0;
466 char **l, **k, **r, **j;
467 va_list ap;
468
469 /* Deletes every entry fromx that is mentioned in the other
470 * string lists */
471
472 n = strv_length(x);
473
474 if (!(r = new(char*, n+1)))
475 return NULL;
476
477 STRV_FOREACH(k, x) {
478 va_start(ap, x);
479
480 while ((l = va_arg(ap, char**)))
481 STRV_FOREACH(j, l)
482 if (env_match(*k, *j))
483 goto delete;
484
485 va_end(ap);
486
487 if (!(r[i++] = strdup(*k))) {
488 strv_free(r);
489 return NULL;
490 }
491
492 continue;
493
494 delete:
495 va_end(ap);
496 }
497
498 r[i] = NULL;
499
500 assert(i <= n);
501
502 return r;
503 }