]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/basic/strv.c
tree-wide: drop {} from one-line if blocks
[thirdparty/systemd.git] / src / basic / strv.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
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 Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <stdlib.h>
23 #include <stdarg.h>
24 #include <string.h>
25 #include <errno.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(name);
34
35 STRV_FOREACH(i, l)
36 if (streq(*i, name))
37 return *i;
38
39 return NULL;
40 }
41
42 char *strv_find_prefix(char **l, const char *name) {
43 char **i;
44
45 assert(name);
46
47 STRV_FOREACH(i, l)
48 if (startswith(*i, name))
49 return *i;
50
51 return NULL;
52 }
53
54 char *strv_find_startswith(char **l, const char *name) {
55 char **i, *e;
56
57 assert(name);
58
59 /* Like strv_find_prefix, but actually returns only the
60 * suffix, not the whole item */
61
62 STRV_FOREACH(i, l) {
63 e = startswith(*i, name);
64 if (e)
65 return e;
66 }
67
68 return NULL;
69 }
70
71 void strv_clear(char **l) {
72 char **k;
73
74 if (!l)
75 return;
76
77 for (k = l; *k; k++)
78 free(*k);
79
80 *l = NULL;
81 }
82
83 char **strv_free(char **l) {
84 strv_clear(l);
85 free(l);
86 return NULL;
87 }
88
89 char **strv_copy(char * const *l) {
90 char **r, **k;
91
92 k = r = new(char*, strv_length(l) + 1);
93 if (!r)
94 return NULL;
95
96 if (l)
97 for (; *l; k++, l++) {
98 *k = strdup(*l);
99 if (!*k) {
100 strv_free(r);
101 return NULL;
102 }
103 }
104
105 *k = NULL;
106 return r;
107 }
108
109 unsigned strv_length(char * const *l) {
110 unsigned n = 0;
111
112 if (!l)
113 return 0;
114
115 for (; *l; l++)
116 n++;
117
118 return n;
119 }
120
121 char **strv_new_ap(const char *x, va_list ap) {
122 const char *s;
123 char **a;
124 unsigned n = 0, i = 0;
125 va_list aq;
126
127 /* As a special trick we ignore all listed strings that equal
128 * (const char*) -1. This is supposed to be used with the
129 * STRV_IFNOTNULL() macro to include possibly NULL strings in
130 * the string list. */
131
132 if (x) {
133 n = x == (const char*) -1 ? 0 : 1;
134
135 va_copy(aq, ap);
136 while ((s = va_arg(aq, const char*))) {
137 if (s == (const char*) -1)
138 continue;
139
140 n++;
141 }
142
143 va_end(aq);
144 }
145
146 a = new(char*, n+1);
147 if (!a)
148 return NULL;
149
150 if (x) {
151 if (x != (const char*) -1) {
152 a[i] = strdup(x);
153 if (!a[i])
154 goto fail;
155 i++;
156 }
157
158 while ((s = va_arg(ap, const char*))) {
159
160 if (s == (const char*) -1)
161 continue;
162
163 a[i] = strdup(s);
164 if (!a[i])
165 goto fail;
166
167 i++;
168 }
169 }
170
171 a[i] = NULL;
172
173 return a;
174
175 fail:
176 strv_free(a);
177 return NULL;
178 }
179
180 char **strv_new(const char *x, ...) {
181 char **r;
182 va_list ap;
183
184 va_start(ap, x);
185 r = strv_new_ap(x, ap);
186 va_end(ap);
187
188 return r;
189 }
190
191 int strv_extend_strv(char ***a, char **b) {
192 int r;
193 char **s;
194
195 STRV_FOREACH(s, b) {
196 r = strv_extend(a, *s);
197 if (r < 0)
198 return r;
199 }
200
201 return 0;
202 }
203
204 int strv_extend_strv_concat(char ***a, char **b, const char *suffix) {
205 int r;
206 char **s;
207
208 STRV_FOREACH(s, b) {
209 char *v;
210
211 v = strappend(*s, suffix);
212 if (!v)
213 return -ENOMEM;
214
215 r = strv_push(a, v);
216 if (r < 0) {
217 free(v);
218 return r;
219 }
220 }
221
222 return 0;
223 }
224
225 char **strv_split(const char *s, const char *separator) {
226 const char *word, *state;
227 size_t l;
228 unsigned n, i;
229 char **r;
230
231 assert(s);
232
233 n = 0;
234 FOREACH_WORD_SEPARATOR(word, l, s, separator, state)
235 n++;
236
237 r = new(char*, n+1);
238 if (!r)
239 return NULL;
240
241 i = 0;
242 FOREACH_WORD_SEPARATOR(word, l, s, separator, state) {
243 r[i] = strndup(word, l);
244 if (!r[i]) {
245 strv_free(r);
246 return NULL;
247 }
248
249 i++;
250 }
251
252 r[i] = NULL;
253 return r;
254 }
255
256 char **strv_split_newlines(const char *s) {
257 char **l;
258 unsigned n;
259
260 assert(s);
261
262 /* Special version of strv_split() that splits on newlines and
263 * suppresses an empty string at the end */
264
265 l = strv_split(s, NEWLINE);
266 if (!l)
267 return NULL;
268
269 n = strv_length(l);
270 if (n <= 0)
271 return l;
272
273 if (isempty(l[n - 1]))
274 l[n - 1] = mfree(l[n - 1]);
275
276 return l;
277 }
278
279 int strv_split_extract(char ***t, const char *s, const char *separators, ExtractFlags flags) {
280 size_t n = 0, allocated = 0;
281 _cleanup_strv_free_ char **l = NULL;
282 int r;
283
284 assert(t);
285 assert(s);
286
287 for (;;) {
288 _cleanup_free_ char *word = NULL;
289
290 r = extract_first_word(&s, &word, separators, flags);
291 if (r < 0)
292 return r;
293 if (r == 0)
294 break;
295
296 if (!GREEDY_REALLOC(l, allocated, n + 2))
297 return -ENOMEM;
298
299 l[n++] = word;
300 word = NULL;
301
302 l[n] = NULL;
303 }
304
305 if (!l)
306 l = new0(char*, 1);
307
308 *t = l;
309 l = NULL;
310
311 return 0;
312 }
313
314 char *strv_join(char **l, const char *separator) {
315 char *r, *e;
316 char **s;
317 size_t n, k;
318
319 if (!separator)
320 separator = " ";
321
322 k = strlen(separator);
323
324 n = 0;
325 STRV_FOREACH(s, l) {
326 if (n != 0)
327 n += k;
328 n += strlen(*s);
329 }
330
331 r = new(char, n+1);
332 if (!r)
333 return NULL;
334
335 e = r;
336 STRV_FOREACH(s, l) {
337 if (e != r)
338 e = stpcpy(e, separator);
339
340 e = stpcpy(e, *s);
341 }
342
343 *e = 0;
344
345 return r;
346 }
347
348 char *strv_join_quoted(char **l) {
349 char *buf = NULL;
350 char **s;
351 size_t allocated = 0, len = 0;
352
353 STRV_FOREACH(s, l) {
354 /* assuming here that escaped string cannot be more
355 * than twice as long, and reserving space for the
356 * separator and quotes.
357 */
358 _cleanup_free_ char *esc = NULL;
359 size_t needed;
360
361 if (!GREEDY_REALLOC(buf, allocated,
362 len + strlen(*s) * 2 + 3))
363 goto oom;
364
365 esc = cescape(*s);
366 if (!esc)
367 goto oom;
368
369 needed = snprintf(buf + len, allocated - len, "%s\"%s\"",
370 len > 0 ? " " : "", esc);
371 assert(needed < allocated - len);
372 len += needed;
373 }
374
375 if (!buf)
376 buf = malloc0(1);
377
378 return buf;
379
380 oom:
381 free(buf);
382 return NULL;
383 }
384
385 int strv_push(char ***l, char *value) {
386 char **c;
387 unsigned n, m;
388
389 if (!value)
390 return 0;
391
392 n = strv_length(*l);
393
394 /* Increase and check for overflow */
395 m = n + 2;
396 if (m < n)
397 return -ENOMEM;
398
399 c = realloc_multiply(*l, sizeof(char*), m);
400 if (!c)
401 return -ENOMEM;
402
403 c[n] = value;
404 c[n+1] = NULL;
405
406 *l = c;
407 return 0;
408 }
409
410 int strv_push_pair(char ***l, char *a, char *b) {
411 char **c;
412 unsigned n, m;
413
414 if (!a && !b)
415 return 0;
416
417 n = strv_length(*l);
418
419 /* increase and check for overflow */
420 m = n + !!a + !!b + 1;
421 if (m < n)
422 return -ENOMEM;
423
424 c = realloc_multiply(*l, sizeof(char*), m);
425 if (!c)
426 return -ENOMEM;
427
428 if (a)
429 c[n++] = a;
430 if (b)
431 c[n++] = b;
432 c[n] = NULL;
433
434 *l = c;
435 return 0;
436 }
437
438 int strv_push_prepend(char ***l, char *value) {
439 char **c;
440 unsigned n, m, i;
441
442 if (!value)
443 return 0;
444
445 n = strv_length(*l);
446
447 /* increase and check for overflow */
448 m = n + 2;
449 if (m < n)
450 return -ENOMEM;
451
452 c = new(char*, m);
453 if (!c)
454 return -ENOMEM;
455
456 for (i = 0; i < n; i++)
457 c[i+1] = (*l)[i];
458
459 c[0] = value;
460 c[n+1] = NULL;
461
462 free(*l);
463 *l = c;
464
465 return 0;
466 }
467
468 int strv_consume(char ***l, char *value) {
469 int r;
470
471 r = strv_push(l, value);
472 if (r < 0)
473 free(value);
474
475 return r;
476 }
477
478 int strv_consume_pair(char ***l, char *a, char *b) {
479 int r;
480
481 r = strv_push_pair(l, a, b);
482 if (r < 0) {
483 free(a);
484 free(b);
485 }
486
487 return r;
488 }
489
490 int strv_consume_prepend(char ***l, char *value) {
491 int r;
492
493 r = strv_push_prepend(l, value);
494 if (r < 0)
495 free(value);
496
497 return r;
498 }
499
500 int strv_extend(char ***l, const char *value) {
501 char *v;
502
503 if (!value)
504 return 0;
505
506 v = strdup(value);
507 if (!v)
508 return -ENOMEM;
509
510 return strv_consume(l, v);
511 }
512
513 char **strv_uniq(char **l) {
514 char **i;
515
516 /* Drops duplicate entries. The first identical string will be
517 * kept, the others dropped */
518
519 STRV_FOREACH(i, l)
520 strv_remove(i+1, *i);
521
522 return l;
523 }
524
525 bool strv_is_uniq(char **l) {
526 char **i;
527
528 STRV_FOREACH(i, l)
529 if (strv_find(i+1, *i))
530 return false;
531
532 return true;
533 }
534
535 char **strv_remove(char **l, const char *s) {
536 char **f, **t;
537
538 if (!l)
539 return NULL;
540
541 assert(s);
542
543 /* Drops every occurrence of s in the string list, edits
544 * in-place. */
545
546 for (f = t = l; *f; f++)
547 if (streq(*f, s))
548 free(*f);
549 else
550 *(t++) = *f;
551
552 *t = NULL;
553 return l;
554 }
555
556 char **strv_parse_nulstr(const char *s, size_t l) {
557 const char *p;
558 unsigned c = 0, i = 0;
559 char **v;
560
561 assert(s || l <= 0);
562
563 if (l <= 0)
564 return new0(char*, 1);
565
566 for (p = s; p < s + l; p++)
567 if (*p == 0)
568 c++;
569
570 if (s[l-1] != 0)
571 c++;
572
573 v = new0(char*, c+1);
574 if (!v)
575 return NULL;
576
577 p = s;
578 while (p < s + l) {
579 const char *e;
580
581 e = memchr(p, 0, s + l - p);
582
583 v[i] = strndup(p, e ? e - p : s + l - p);
584 if (!v[i]) {
585 strv_free(v);
586 return NULL;
587 }
588
589 i++;
590
591 if (!e)
592 break;
593
594 p = e + 1;
595 }
596
597 assert(i == c);
598
599 return v;
600 }
601
602 char **strv_split_nulstr(const char *s) {
603 const char *i;
604 char **r = NULL;
605
606 NULSTR_FOREACH(i, s)
607 if (strv_extend(&r, i) < 0) {
608 strv_free(r);
609 return NULL;
610 }
611
612 if (!r)
613 return strv_new(NULL, NULL);
614
615 return r;
616 }
617
618 bool strv_overlap(char **a, char **b) {
619 char **i;
620
621 STRV_FOREACH(i, a)
622 if (strv_contains(b, *i))
623 return true;
624
625 return false;
626 }
627
628 static int str_compare(const void *_a, const void *_b) {
629 const char **a = (const char**) _a, **b = (const char**) _b;
630
631 return strcmp(*a, *b);
632 }
633
634 char **strv_sort(char **l) {
635
636 if (strv_isempty(l))
637 return l;
638
639 qsort(l, strv_length(l), sizeof(char*), str_compare);
640 return l;
641 }
642
643 bool strv_equal(char **a, char **b) {
644 if (!a || !b)
645 return a == b;
646
647 for ( ; *a || *b; ++a, ++b)
648 if (!streq_ptr(*a, *b))
649 return false;
650
651 return true;
652 }
653
654 void strv_print(char **l) {
655 char **s;
656
657 STRV_FOREACH(s, l)
658 puts(*s);
659 }
660
661 int strv_extendf(char ***l, const char *format, ...) {
662 va_list ap;
663 char *x;
664 int r;
665
666 va_start(ap, format);
667 r = vasprintf(&x, format, ap);
668 va_end(ap);
669
670 if (r < 0)
671 return -ENOMEM;
672
673 return strv_consume(l, x);
674 }
675
676 char **strv_reverse(char **l) {
677 unsigned n, i;
678
679 n = strv_length(l);
680 if (n <= 1)
681 return l;
682
683 for (i = 0; i < n / 2; i++) {
684 char *t;
685
686 t = l[i];
687 l[i] = l[n-1-i];
688 l[n-1-i] = t;
689 }
690
691 return l;
692 }
693
694 char **strv_shell_escape(char **l, const char *bad) {
695 char **s;
696
697 /* Escapes every character in every string in l that is in bad,
698 * edits in-place, does not roll-back on error. */
699
700 STRV_FOREACH(s, l) {
701 char *v;
702
703 v = shell_escape(*s, bad);
704 if (!v)
705 return NULL;
706
707 free(*s);
708 *s = v;
709 }
710
711 return l;
712 }
713
714 bool strv_fnmatch(char* const* patterns, const char *s, int flags) {
715 char* const* p;
716
717 STRV_FOREACH(p, patterns)
718 if (fnmatch(*p, s, 0) == 0)
719 return true;
720
721 return false;
722 }