]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/basic/strv.c
util-lib: split our string related calls from util.[ch] into its own file string...
[thirdparty/systemd.git] / src / basic / strv.c
CommitLineData
d6c9574f 1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
60918275 2
a7334b09
LP
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
5430f7f2
LP
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
a7334b09
LP
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
5430f7f2 16 Lesser General Public License for more details.
a7334b09 17
5430f7f2 18 You should have received a copy of the GNU Lesser General Public License
a7334b09
LP
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
07630cea 22#include <errno.h>
60918275 23#include <stdarg.h>
07630cea 24#include <stdlib.h>
60918275
LP
25#include <string.h>
26
4f5dd394 27#include "escape.h"
07630cea 28#include "string-util.h"
60918275
LP
29#include "util.h"
30#include "strv.h"
31
32char *strv_find(char **l, const char *name) {
5f9a22c3
LP
33 char **i;
34
60918275
LP
35 assert(name);
36
5f9a22c3
LP
37 STRV_FOREACH(i, l)
38 if (streq(*i, name))
39 return *i;
60918275
LP
40
41 return NULL;
42}
43
a4bfb399
LP
44char *strv_find_prefix(char **l, const char *name) {
45 char **i;
46
47 assert(name);
48
49 STRV_FOREACH(i, l)
50 if (startswith(*i, name))
51 return *i;
52
53 return NULL;
54}
55
28849dba
LP
56char *strv_find_startswith(char **l, const char *name) {
57 char **i, *e;
58
59 assert(name);
60
61 /* Like strv_find_prefix, but actually returns only the
62 * suffix, not the whole item */
63
64 STRV_FOREACH(i, l) {
65 e = startswith(*i, name);
66 if (e)
67 return e;
68 }
69
70 return NULL;
71}
72
dd9c7723 73void strv_clear(char **l) {
60918275
LP
74 char **k;
75
76 if (!l)
77 return;
78
79 for (k = l; *k; k++)
80 free(*k);
81
dd9c7723
TG
82 *l = NULL;
83}
84
33c2ce7b 85char **strv_free(char **l) {
dd9c7723 86 strv_clear(l);
60918275 87 free(l);
33c2ce7b 88 return NULL;
60918275
LP
89}
90
ab84f5b9
ZJS
91char **strv_free_erase(char **l) {
92 char **i;
93
94 STRV_FOREACH(i, l)
95 string_erase(*i);
96
97 return strv_free(l);
98}
99
2fd9ae2e 100char **strv_copy(char * const *l) {
60918275
LP
101 char **r, **k;
102
1fd8d04e
LP
103 k = r = new(char*, strv_length(l) + 1);
104 if (!r)
60918275
LP
105 return NULL;
106
ede27aab 107 if (l)
1fd8d04e
LP
108 for (; *l; k++, l++) {
109 *k = strdup(*l);
110 if (!*k) {
111 strv_free(r);
112 return NULL;
113 }
114 }
60918275
LP
115
116 *k = NULL;
117 return r;
60918275
LP
118}
119
2fd9ae2e 120unsigned strv_length(char * const *l) {
60918275
LP
121 unsigned n = 0;
122
123 if (!l)
124 return 0;
125
126 for (; *l; l++)
127 n++;
128
129 return n;
130}
131
257eca1a 132char **strv_new_ap(const char *x, va_list ap) {
60918275
LP
133 const char *s;
134 char **a;
135 unsigned n = 0, i = 0;
257eca1a
LP
136 va_list aq;
137
07719a21
LP
138 /* As a special trick we ignore all listed strings that equal
139 * (const char*) -1. This is supposed to be used with the
140 * STRV_IFNOTNULL() macro to include possibly NULL strings in
141 * the string list. */
142
60918275 143 if (x) {
07719a21 144 n = x == (const char*) -1 ? 0 : 1;
60918275 145
257eca1a 146 va_copy(aq, ap);
07719a21
LP
147 while ((s = va_arg(aq, const char*))) {
148 if (s == (const char*) -1)
149 continue;
150
60918275 151 n++;
07719a21
LP
152 }
153
257eca1a 154 va_end(aq);
60918275
LP
155 }
156
07719a21
LP
157 a = new(char*, n+1);
158 if (!a)
60918275
LP
159 return NULL;
160
161 if (x) {
07719a21
LP
162 if (x != (const char*) -1) {
163 a[i] = strdup(x);
164 if (!a[i])
165 goto fail;
166 i++;
60918275
LP
167 }
168
60918275 169 while ((s = va_arg(ap, const char*))) {
07719a21
LP
170
171 if (s == (const char*) -1)
172 continue;
173
174 a[i] = strdup(s);
175 if (!a[i])
60918275
LP
176 goto fail;
177
178 i++;
179 }
60918275
LP
180 }
181
182 a[i] = NULL;
257eca1a 183
60918275
LP
184 return a;
185
186fail:
1fd8d04e 187 strv_free(a);
60918275
LP
188 return NULL;
189}
034c6ed7 190
257eca1a
LP
191char **strv_new(const char *x, ...) {
192 char **r;
193 va_list ap;
194
195 va_start(ap, x);
196 r = strv_new_ap(x, ap);
197 va_end(ap);
198
199 return r;
200}
201
e287086b
LP
202int strv_extend_strv(char ***a, char **b, bool filter_duplicates) {
203 char **s, **t;
204 size_t p, q, i = 0, j;
205
206 assert(a);
207
208 if (strv_isempty(b))
209 return 0;
210
211 p = strv_length(*a);
212 q = strv_length(b);
213
214 t = realloc(*a, sizeof(char*) * (p + q + 1));
215 if (!t)
216 return -ENOMEM;
217
218 t[p] = NULL;
219 *a = t;
07719a21 220
e3e45d4f 221 STRV_FOREACH(s, b) {
e287086b
LP
222
223 if (filter_duplicates && strv_contains(t, *s))
224 continue;
225
226 t[p+i] = strdup(*s);
227 if (!t[p+i])
228 goto rollback;
229
230 i++;
231 t[p+i] = NULL;
07719a21 232 }
034c6ed7 233
e287086b
LP
234 assert(i <= q);
235
236 return (int) i;
237
238rollback:
239 for (j = 0; j < i; j++)
240 free(t[p + j]);
241
242 t[p] = NULL;
243 return -ENOMEM;
5f9a22c3
LP
244}
245
e3e45d4f
SP
246int strv_extend_strv_concat(char ***a, char **b, const char *suffix) {
247 int r;
248 char **s;
5f9a22c3 249
e3e45d4f
SP
250 STRV_FOREACH(s, b) {
251 char *v;
5f9a22c3 252
e3e45d4f
SP
253 v = strappend(*s, suffix);
254 if (!v)
255 return -ENOMEM;
5f9a22c3 256
e3e45d4f
SP
257 r = strv_push(a, v);
258 if (r < 0) {
259 free(v);
260 return r;
8ea913b2 261 }
8ea913b2 262 }
5f9a22c3 263
e3e45d4f 264 return 0;
5f9a22c3
LP
265}
266
267char **strv_split(const char *s, const char *separator) {
a2a5291b 268 const char *word, *state;
5f9a22c3
LP
269 size_t l;
270 unsigned n, i;
271 char **r;
272
273 assert(s);
274
275 n = 0;
a2a5291b 276 FOREACH_WORD_SEPARATOR(word, l, s, separator, state)
5f9a22c3
LP
277 n++;
278
1fd8d04e
LP
279 r = new(char*, n+1);
280 if (!r)
5f9a22c3
LP
281 return NULL;
282
283 i = 0;
a2a5291b
ZJS
284 FOREACH_WORD_SEPARATOR(word, l, s, separator, state) {
285 r[i] = strndup(word, l);
1fd8d04e 286 if (!r[i]) {
5f9a22c3
LP
287 strv_free(r);
288 return NULL;
289 }
290
1fd8d04e
LP
291 i++;
292 }
293
5f9a22c3
LP
294 r[i] = NULL;
295 return r;
296}
297
26d04f86
LP
298char **strv_split_newlines(const char *s) {
299 char **l;
300 unsigned n;
301
302 assert(s);
303
304 /* Special version of strv_split() that splits on newlines and
305 * suppresses an empty string at the end */
306
307 l = strv_split(s, NEWLINE);
308 if (!l)
309 return NULL;
310
311 n = strv_length(l);
312 if (n <= 0)
313 return l;
314
ece174c5 315 if (isempty(l[n - 1]))
a1e58e8e 316 l[n - 1] = mfree(l[n - 1]);
26d04f86
LP
317
318 return l;
319}
320
8adaf7bd 321int strv_split_extract(char ***t, const char *s, const char *separators, ExtractFlags flags) {
f88e6be5 322 _cleanup_strv_free_ char **l = NULL;
8dd4c05b 323 size_t n = 0, allocated = 0;
f88e6be5
LP
324 int r;
325
326 assert(t);
327 assert(s);
328
329 for (;;) {
330 _cleanup_free_ char *word = NULL;
331
8adaf7bd 332 r = extract_first_word(&s, &word, separators, flags);
f88e6be5
LP
333 if (r < 0)
334 return r;
ece174c5 335 if (r == 0)
f88e6be5
LP
336 break;
337
338 if (!GREEDY_REALLOC(l, allocated, n + 2))
339 return -ENOMEM;
340
341 l[n++] = word;
342 word = NULL;
343
344 l[n] = NULL;
345 }
346
8dd4c05b 347 if (!l) {
f88e6be5 348 l = new0(char*, 1);
8dd4c05b
LP
349 if (!l)
350 return -ENOMEM;
351 }
f88e6be5
LP
352
353 *t = l;
354 l = NULL;
355
8dd4c05b 356 return (int) n;
f88e6be5
LP
357}
358
5f9a22c3
LP
359char *strv_join(char **l, const char *separator) {
360 char *r, *e;
361 char **s;
362 size_t n, k;
363
364 if (!separator)
365 separator = " ";
366
367 k = strlen(separator);
368
369 n = 0;
370 STRV_FOREACH(s, l) {
371 if (n != 0)
372 n += k;
373 n += strlen(*s);
374 }
375
1fd8d04e
LP
376 r = new(char, n+1);
377 if (!r)
5f9a22c3
LP
378 return NULL;
379
380 e = r;
381 STRV_FOREACH(s, l) {
382 if (e != r)
383 e = stpcpy(e, separator);
384
385 e = stpcpy(e, *s);
386 }
387
8d49745c
LP
388 *e = 0;
389
5f9a22c3
LP
390 return r;
391}
392
a6fde353
ZJS
393char *strv_join_quoted(char **l) {
394 char *buf = NULL;
395 char **s;
396 size_t allocated = 0, len = 0;
397
398 STRV_FOREACH(s, l) {
399 /* assuming here that escaped string cannot be more
400 * than twice as long, and reserving space for the
401 * separator and quotes.
402 */
403 _cleanup_free_ char *esc = NULL;
404 size_t needed;
405
406 if (!GREEDY_REALLOC(buf, allocated,
407 len + strlen(*s) * 2 + 3))
408 goto oom;
409
410 esc = cescape(*s);
411 if (!esc)
412 goto oom;
413
414 needed = snprintf(buf + len, allocated - len, "%s\"%s\"",
415 len > 0 ? " " : "", esc);
416 assert(needed < allocated - len);
417 len += needed;
418 }
419
420 if (!buf)
421 buf = malloc0(1);
422
423 return buf;
424
425 oom:
426 free(buf);
427 return NULL;
428}
429
4468addc 430int strv_push(char ***l, char *value) {
5926ccca 431 char **c;
97569e15 432 unsigned n, m;
5926ccca
LP
433
434 if (!value)
435 return 0;
436
82dde599 437 n = strv_length(*l);
97569e15 438
98940a3c 439 /* Increase and check for overflow */
97569e15
LP
440 m = n + 2;
441 if (m < n)
442 return -ENOMEM;
443
14f27b4e 444 c = realloc_multiply(*l, sizeof(char*), m);
4468addc 445 if (!c)
82dde599 446 return -ENOMEM;
82dde599 447
4468addc 448 c[n] = value;
82dde599
LP
449 c[n+1] = NULL;
450
5926ccca
LP
451 *l = c;
452 return 0;
453}
454
98940a3c
LP
455int strv_push_pair(char ***l, char *a, char *b) {
456 char **c;
457 unsigned n, m;
458
459 if (!a && !b)
460 return 0;
461
462 n = strv_length(*l);
463
464 /* increase and check for overflow */
465 m = n + !!a + !!b + 1;
466 if (m < n)
467 return -ENOMEM;
468
469 c = realloc_multiply(*l, sizeof(char*), m);
470 if (!c)
471 return -ENOMEM;
472
473 if (a)
474 c[n++] = a;
475 if (b)
476 c[n++] = b;
477 c[n] = NULL;
478
479 *l = c;
480 return 0;
481}
482
9a00f57a
LP
483int strv_push_prepend(char ***l, char *value) {
484 char **c;
97569e15 485 unsigned n, m, i;
9a00f57a
LP
486
487 if (!value)
488 return 0;
489
490 n = strv_length(*l);
97569e15
LP
491
492 /* increase and check for overflow */
493 m = n + 2;
494 if (m < n)
495 return -ENOMEM;
496
497 c = new(char*, m);
9a00f57a
LP
498 if (!c)
499 return -ENOMEM;
500
501 for (i = 0; i < n; i++)
502 c[i+1] = (*l)[i];
503
504 c[0] = value;
505 c[n+1] = NULL;
506
507 free(*l);
508 *l = c;
509
510 return 0;
511}
512
6e18964d
ZJS
513int strv_consume(char ***l, char *value) {
514 int r;
515
516 r = strv_push(l, value);
517 if (r < 0)
518 free(value);
519
9a00f57a
LP
520 return r;
521}
522
98940a3c
LP
523int strv_consume_pair(char ***l, char *a, char *b) {
524 int r;
525
526 r = strv_push_pair(l, a, b);
527 if (r < 0) {
528 free(a);
529 free(b);
530 }
531
532 return r;
533}
534
9a00f57a
LP
535int strv_consume_prepend(char ***l, char *value) {
536 int r;
537
538 r = strv_push_prepend(l, value);
539 if (r < 0)
540 free(value);
541
6e18964d
ZJS
542 return r;
543}
544
4468addc
LP
545int strv_extend(char ***l, const char *value) {
546 char *v;
4468addc
LP
547
548 if (!value)
549 return 0;
550
551 v = strdup(value);
552 if (!v)
553 return -ENOMEM;
554
6e18964d 555 return strv_consume(l, v);
4468addc
LP
556}
557
5f9a22c3 558char **strv_uniq(char **l) {
cba8922f
LP
559 char **i;
560
5f9a22c3
LP
561 /* Drops duplicate entries. The first identical string will be
562 * kept, the others dropped */
563
cba8922f 564 STRV_FOREACH(i, l)
5f9a22c3
LP
565 strv_remove(i+1, *i);
566
567 return l;
568}
569
e1dd6790
LP
570bool strv_is_uniq(char **l) {
571 char **i;
572
573 STRV_FOREACH(i, l)
574 if (strv_find(i+1, *i))
575 return false;
576
577 return true;
578}
579
5f9a22c3
LP
580char **strv_remove(char **l, const char *s) {
581 char **f, **t;
582
583 if (!l)
584 return NULL;
585
5d6ab905
LP
586 assert(s);
587
588 /* Drops every occurrence of s in the string list, edits
589 * in-place. */
5f9a22c3 590
e3e45d4f
SP
591 for (f = t = l; *f; f++)
592 if (streq(*f, s))
71ecc858 593 free(*f);
e3e45d4f
SP
594 else
595 *(t++) = *f;
71ecc858
LP
596
597 *t = NULL;
598 return l;
599}
600
21bc923a
LP
601char **strv_parse_nulstr(const char *s, size_t l) {
602 const char *p;
603 unsigned c = 0, i = 0;
604 char **v;
605
606 assert(s || l <= 0);
607
608 if (l <= 0)
49b832c5 609 return new0(char*, 1);
21bc923a
LP
610
611 for (p = s; p < s + l; p++)
612 if (*p == 0)
613 c++;
614
615 if (s[l-1] != 0)
616 c++;
617
1fd8d04e
LP
618 v = new0(char*, c+1);
619 if (!v)
21bc923a
LP
620 return NULL;
621
622 p = s;
623 while (p < s + l) {
624 const char *e;
625
626 e = memchr(p, 0, s + l - p);
627
1fd8d04e
LP
628 v[i] = strndup(p, e ? e - p : s + l - p);
629 if (!v[i]) {
21bc923a
LP
630 strv_free(v);
631 return NULL;
632 }
633
1fd8d04e
LP
634 i++;
635
21bc923a
LP
636 if (!e)
637 break;
638
639 p = e + 1;
640 }
641
642 assert(i == c);
643
644 return v;
645}
0c85a4f3 646
fabe5c0e
LP
647char **strv_split_nulstr(const char *s) {
648 const char *i;
649 char **r = NULL;
650
651 NULSTR_FOREACH(i, s)
652 if (strv_extend(&r, i) < 0) {
653 strv_free(r);
654 return NULL;
655 }
656
657 if (!r)
658 return strv_new(NULL, NULL);
659
660 return r;
661}
662
e287086b
LP
663int strv_make_nulstr(char **l, char **p, size_t *q) {
664 size_t n_allocated = 0, n = 0;
665 _cleanup_free_ char *m = NULL;
666 char **i;
667
668 assert(p);
669 assert(q);
670
671 STRV_FOREACH(i, l) {
672 size_t z;
673
674 z = strlen(*i);
675
676 if (!GREEDY_REALLOC(m, n_allocated, n + z + 1))
677 return -ENOMEM;
678
679 memcpy(m + n, *i, z + 1);
680 n += z + 1;
681 }
682
683 if (!m) {
684 m = new0(char, 1);
685 if (!m)
686 return -ENOMEM;
687 n = 0;
688 }
689
690 *p = m;
691 *q = n;
692
693 m = NULL;
694
695 return 0;
696}
697
0c85a4f3 698bool strv_overlap(char **a, char **b) {
e3e45d4f 699 char **i;
0c85a4f3 700
e3e45d4f
SP
701 STRV_FOREACH(i, a)
702 if (strv_contains(b, *i))
703 return true;
0c85a4f3
LP
704
705 return false;
706}
857a493d
LP
707
708static int str_compare(const void *_a, const void *_b) {
709 const char **a = (const char**) _a, **b = (const char**) _b;
710
711 return strcmp(*a, *b);
712}
713
714char **strv_sort(char **l) {
715
716 if (strv_isempty(l))
717 return l;
718
719 qsort(l, strv_length(l), sizeof(char*), str_compare);
720 return l;
721}
7c2d8094 722
0f84a72e 723bool strv_equal(char **a, char **b) {
e287086b
LP
724
725 if (strv_isempty(a))
726 return strv_isempty(b);
727
728 if (strv_isempty(b))
729 return false;
0f84a72e
DH
730
731 for ( ; *a || *b; ++a, ++b)
732 if (!streq_ptr(*a, *b))
733 return false;
734
735 return true;
736}
737
7c2d8094
TA
738void strv_print(char **l) {
739 char **s;
740
7c2d8094
TA
741 STRV_FOREACH(s, l)
742 puts(*s);
743}
4de33e7f
LP
744
745int strv_extendf(char ***l, const char *format, ...) {
746 va_list ap;
747 char *x;
748 int r;
749
750 va_start(ap, format);
751 r = vasprintf(&x, format, ap);
752 va_end(ap);
753
754 if (r < 0)
755 return -ENOMEM;
756
757 return strv_consume(l, x);
758}
e1dd6790
LP
759
760char **strv_reverse(char **l) {
761 unsigned n, i;
762
763 n = strv_length(l);
764 if (n <= 1)
765 return l;
766
767 for (i = 0; i < n / 2; i++) {
768 char *t;
769
770 t = l[i];
771 l[i] = l[n-1-i];
772 l[n-1-i] = t;
773 }
774
775 return l;
776}
bceccd5e 777
04c14b25
RM
778char **strv_shell_escape(char **l, const char *bad) {
779 char **s;
780
781 /* Escapes every character in every string in l that is in bad,
782 * edits in-place, does not roll-back on error. */
783
784 STRV_FOREACH(s, l) {
785 char *v;
786
787 v = shell_escape(*s, bad);
788 if (!v)
789 return NULL;
790
791 free(*s);
792 *s = v;
793 }
794
795 return l;
796}
797
2404701e 798bool strv_fnmatch(char* const* patterns, const char *s, int flags) {
bceccd5e
ZJS
799 char* const* p;
800
801 STRV_FOREACH(p, patterns)
802 if (fnmatch(*p, s, 0) == 0)
803 return true;
804
805 return false;
806}
fe382237
LP
807
808char ***strv_free_free(char ***l) {
809 char ***i;
810
811 if (!l)
812 return NULL;
813
814 for (i = l; *i; i++)
815 strv_free(*i);
816
817 free(l);
818 return NULL;
819}
e3ead6bb
LP
820
821char **strv_skip(char **l, size_t n) {
822
823 while (n > 0) {
824 if (strv_isempty(l))
825 return l;
826
827 l++, n--;
828 }
829
830 return l;
831}
8dd4c05b
LP
832
833int strv_extend_n(char ***l, const char *value, size_t n) {
834 size_t i, j, k;
835 char **nl;
836
837 assert(l);
838
839 if (!value)
840 return 0;
841 if (n == 0)
842 return 0;
843
844 /* Adds the value value n times to l */
845
846 k = strv_length(*l);
847
848 nl = realloc(*l, sizeof(char*) * (k + n + 1));
849 if (!nl)
850 return -ENOMEM;
851
852 *l = nl;
853
854 for (i = k; i < k + n; i++) {
855 nl[i] = strdup(value);
856 if (!nl[i])
857 goto rollback;
858 }
859
860 nl[i] = NULL;
861 return 0;
862
863rollback:
6fff8ac4 864 for (j = k; j < i; j++)
8dd4c05b
LP
865 free(nl[j]);
866
867 nl[k] = NULL;
5b700370 868 return -ENOMEM;
8dd4c05b 869}