]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/basic/strv.c
Merge pull request #13120 from keszybz/journal-min-use
[thirdparty/systemd.git] / src / basic / strv.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2
3 #include <errno.h>
4 #include <fnmatch.h>
5 #include <stdarg.h>
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9
10 #include "alloc-util.h"
11 #include "escape.h"
12 #include "extract-word.h"
13 #include "fileio.h"
14 #include "memory-util.h"
15 #include "nulstr-util.h"
16 #include "sort-util.h"
17 #include "string-util.h"
18 #include "strv.h"
19
20 char *strv_find(char **l, const char *name) {
21 char **i;
22
23 assert(name);
24
25 STRV_FOREACH(i, l)
26 if (streq(*i, name))
27 return *i;
28
29 return NULL;
30 }
31
32 char *strv_find_prefix(char **l, const char *name) {
33 char **i;
34
35 assert(name);
36
37 STRV_FOREACH(i, l)
38 if (startswith(*i, name))
39 return *i;
40
41 return NULL;
42 }
43
44 char *strv_find_startswith(char **l, const char *name) {
45 char **i, *e;
46
47 assert(name);
48
49 /* Like strv_find_prefix, but actually returns only the
50 * suffix, not the whole item */
51
52 STRV_FOREACH(i, l) {
53 e = startswith(*i, name);
54 if (e)
55 return e;
56 }
57
58 return NULL;
59 }
60
61 void strv_clear(char **l) {
62 char **k;
63
64 if (!l)
65 return;
66
67 for (k = l; *k; k++)
68 free(*k);
69
70 *l = NULL;
71 }
72
73 char **strv_free(char **l) {
74 strv_clear(l);
75 return mfree(l);
76 }
77
78 char **strv_free_erase(char **l) {
79 char **i;
80
81 STRV_FOREACH(i, l)
82 erase_and_freep(i);
83
84 return mfree(l);
85 }
86
87 char **strv_copy(char * const *l) {
88 char **r, **k;
89
90 k = r = new(char*, strv_length(l) + 1);
91 if (!r)
92 return NULL;
93
94 if (l)
95 for (; *l; k++, l++) {
96 *k = strdup(*l);
97 if (!*k) {
98 strv_free(r);
99 return NULL;
100 }
101 }
102
103 *k = NULL;
104 return r;
105 }
106
107 size_t strv_length(char * const *l) {
108 size_t n = 0;
109
110 if (!l)
111 return 0;
112
113 for (; *l; l++)
114 n++;
115
116 return n;
117 }
118
119 char **strv_new_ap(const char *x, va_list ap) {
120 const char *s;
121 _cleanup_strv_free_ char **a = NULL;
122 size_t n = 0, i = 0;
123 va_list aq;
124
125 /* As a special trick we ignore all listed strings that equal
126 * STRV_IGNORE. This is supposed to be used with the
127 * STRV_IFNOTNULL() macro to include possibly NULL strings in
128 * the string list. */
129
130 if (x) {
131 n = x == STRV_IGNORE ? 0 : 1;
132
133 va_copy(aq, ap);
134 while ((s = va_arg(aq, const char*))) {
135 if (s == STRV_IGNORE)
136 continue;
137
138 n++;
139 }
140
141 va_end(aq);
142 }
143
144 a = new(char*, n+1);
145 if (!a)
146 return NULL;
147
148 if (x) {
149 if (x != STRV_IGNORE) {
150 a[i] = strdup(x);
151 if (!a[i])
152 return NULL;
153 i++;
154 }
155
156 while ((s = va_arg(ap, const char*))) {
157
158 if (s == STRV_IGNORE)
159 continue;
160
161 a[i] = strdup(s);
162 if (!a[i])
163 return NULL;
164
165 i++;
166 }
167 }
168
169 a[i] = NULL;
170
171 return TAKE_PTR(a);
172 }
173
174 char **strv_new_internal(const char *x, ...) {
175 char **r;
176 va_list ap;
177
178 va_start(ap, x);
179 r = strv_new_ap(x, ap);
180 va_end(ap);
181
182 return r;
183 }
184
185 int strv_extend_strv(char ***a, char **b, bool filter_duplicates) {
186 char **s, **t;
187 size_t p, q, i = 0, j;
188
189 assert(a);
190
191 if (strv_isempty(b))
192 return 0;
193
194 p = strv_length(*a);
195 q = strv_length(b);
196
197 t = reallocarray(*a, p + q + 1, sizeof(char *));
198 if (!t)
199 return -ENOMEM;
200
201 t[p] = NULL;
202 *a = t;
203
204 STRV_FOREACH(s, b) {
205
206 if (filter_duplicates && strv_contains(t, *s))
207 continue;
208
209 t[p+i] = strdup(*s);
210 if (!t[p+i])
211 goto rollback;
212
213 i++;
214 t[p+i] = NULL;
215 }
216
217 assert(i <= q);
218
219 return (int) i;
220
221 rollback:
222 for (j = 0; j < i; j++)
223 free(t[p + j]);
224
225 t[p] = NULL;
226 return -ENOMEM;
227 }
228
229 int strv_extend_strv_concat(char ***a, char **b, const char *suffix) {
230 int r;
231 char **s;
232
233 STRV_FOREACH(s, b) {
234 char *v;
235
236 v = strjoin(*s, suffix);
237 if (!v)
238 return -ENOMEM;
239
240 r = strv_push(a, v);
241 if (r < 0) {
242 free(v);
243 return r;
244 }
245 }
246
247 return 0;
248 }
249
250 char **strv_split_full(const char *s, const char *separator, SplitFlags flags) {
251 const char *word, *state;
252 size_t l;
253 size_t n, i;
254 char **r;
255
256 assert(s);
257
258 if (!separator)
259 separator = WHITESPACE;
260
261 s += strspn(s, separator);
262 if (isempty(s))
263 return new0(char*, 1);
264
265 n = 0;
266 _FOREACH_WORD(word, l, s, separator, flags, state)
267 n++;
268
269 r = new(char*, n+1);
270 if (!r)
271 return NULL;
272
273 i = 0;
274 _FOREACH_WORD(word, l, s, separator, flags, state) {
275 r[i] = strndup(word, l);
276 if (!r[i]) {
277 strv_free(r);
278 return NULL;
279 }
280
281 i++;
282 }
283
284 r[i] = NULL;
285 return r;
286 }
287
288 char **strv_split_newlines(const char *s) {
289 char **l;
290 size_t n;
291
292 assert(s);
293
294 /* Special version of strv_split() that splits on newlines and
295 * suppresses an empty string at the end */
296
297 l = strv_split(s, NEWLINE);
298 if (!l)
299 return NULL;
300
301 n = strv_length(l);
302 if (n <= 0)
303 return l;
304
305 if (isempty(l[n - 1]))
306 l[n - 1] = mfree(l[n - 1]);
307
308 return l;
309 }
310
311 int strv_split_extract(char ***t, const char *s, const char *separators, ExtractFlags flags) {
312 _cleanup_strv_free_ char **l = NULL;
313 size_t n = 0, allocated = 0;
314 int r;
315
316 assert(t);
317 assert(s);
318
319 for (;;) {
320 _cleanup_free_ char *word = NULL;
321
322 r = extract_first_word(&s, &word, separators, flags);
323 if (r < 0)
324 return r;
325 if (r == 0)
326 break;
327
328 if (!GREEDY_REALLOC(l, allocated, n + 2))
329 return -ENOMEM;
330
331 l[n++] = TAKE_PTR(word);
332
333 l[n] = NULL;
334 }
335
336 if (!l) {
337 l = new0(char*, 1);
338 if (!l)
339 return -ENOMEM;
340 }
341
342 *t = TAKE_PTR(l);
343
344 return (int) n;
345 }
346
347 char *strv_join_prefix(char **l, const char *separator, const char *prefix) {
348 char *r, *e;
349 char **s;
350 size_t n, k, m;
351
352 if (!separator)
353 separator = " ";
354
355 k = strlen(separator);
356 m = strlen_ptr(prefix);
357
358 n = 0;
359 STRV_FOREACH(s, l) {
360 if (s != l)
361 n += k;
362 n += m + strlen(*s);
363 }
364
365 r = new(char, n+1);
366 if (!r)
367 return NULL;
368
369 e = r;
370 STRV_FOREACH(s, l) {
371 if (s != l)
372 e = stpcpy(e, separator);
373
374 if (prefix)
375 e = stpcpy(e, prefix);
376
377 e = stpcpy(e, *s);
378 }
379
380 *e = 0;
381
382 return r;
383 }
384
385 int strv_push(char ***l, char *value) {
386 char **c;
387 size_t 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 = reallocarray(*l, m, sizeof(char*));
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 size_t 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 = reallocarray(*l, m, sizeof(char*));
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_insert(char ***l, size_t position, char *value) {
439 char **c;
440 size_t n, m, i;
441
442 if (!value)
443 return 0;
444
445 n = strv_length(*l);
446 position = MIN(position, n);
447
448 /* increase and check for overflow */
449 m = n + 2;
450 if (m < n)
451 return -ENOMEM;
452
453 c = new(char*, m);
454 if (!c)
455 return -ENOMEM;
456
457 for (i = 0; i < position; i++)
458 c[i] = (*l)[i];
459 c[position] = value;
460 for (i = position; i < n; i++)
461 c[i+1] = (*l)[i];
462
463 c[n+1] = NULL;
464
465 free(*l);
466 *l = c;
467
468 return 0;
469 }
470
471 int strv_consume(char ***l, char *value) {
472 int r;
473
474 r = strv_push(l, value);
475 if (r < 0)
476 free(value);
477
478 return r;
479 }
480
481 int strv_consume_pair(char ***l, char *a, char *b) {
482 int r;
483
484 r = strv_push_pair(l, a, b);
485 if (r < 0) {
486 free(a);
487 free(b);
488 }
489
490 return r;
491 }
492
493 int strv_consume_prepend(char ***l, char *value) {
494 int r;
495
496 r = strv_push_prepend(l, value);
497 if (r < 0)
498 free(value);
499
500 return r;
501 }
502
503 int strv_extend(char ***l, const char *value) {
504 char *v;
505
506 if (!value)
507 return 0;
508
509 v = strdup(value);
510 if (!v)
511 return -ENOMEM;
512
513 return strv_consume(l, v);
514 }
515
516 int strv_extend_front(char ***l, const char *value) {
517 size_t n, m;
518 char *v, **c;
519
520 assert(l);
521
522 /* Like strv_extend(), but prepends rather than appends the new entry */
523
524 if (!value)
525 return 0;
526
527 n = strv_length(*l);
528
529 /* Increase and overflow check. */
530 m = n + 2;
531 if (m < n)
532 return -ENOMEM;
533
534 v = strdup(value);
535 if (!v)
536 return -ENOMEM;
537
538 c = reallocarray(*l, m, sizeof(char*));
539 if (!c) {
540 free(v);
541 return -ENOMEM;
542 }
543
544 memmove(c+1, c, n * sizeof(char*));
545 c[0] = v;
546 c[n+1] = NULL;
547
548 *l = c;
549 return 0;
550 }
551
552 char **strv_uniq(char **l) {
553 char **i;
554
555 /* Drops duplicate entries. The first identical string will be
556 * kept, the others dropped */
557
558 STRV_FOREACH(i, l)
559 strv_remove(i+1, *i);
560
561 return l;
562 }
563
564 bool strv_is_uniq(char **l) {
565 char **i;
566
567 STRV_FOREACH(i, l)
568 if (strv_find(i+1, *i))
569 return false;
570
571 return true;
572 }
573
574 char **strv_remove(char **l, const char *s) {
575 char **f, **t;
576
577 if (!l)
578 return NULL;
579
580 assert(s);
581
582 /* Drops every occurrence of s in the string list, edits
583 * in-place. */
584
585 for (f = t = l; *f; f++)
586 if (streq(*f, s))
587 free(*f);
588 else
589 *(t++) = *f;
590
591 *t = NULL;
592 return l;
593 }
594
595 char **strv_parse_nulstr(const char *s, size_t l) {
596 /* l is the length of the input data, which will be split at NULs into
597 * elements of the resulting strv. Hence, the number of items in the resulting strv
598 * will be equal to one plus the number of NUL bytes in the l bytes starting at s,
599 * unless s[l-1] is NUL, in which case the final empty string is not stored in
600 * the resulting strv, and length is equal to the number of NUL bytes.
601 *
602 * Note that contrary to a normal nulstr which cannot contain empty strings, because
603 * the input data is terminated by any two consequent NUL bytes, this parser accepts
604 * empty strings in s.
605 */
606
607 const char *p;
608 size_t c = 0, i = 0;
609 char **v;
610
611 assert(s || l <= 0);
612
613 if (l <= 0)
614 return new0(char*, 1);
615
616 for (p = s; p < s + l; p++)
617 if (*p == 0)
618 c++;
619
620 if (s[l-1] != 0)
621 c++;
622
623 v = new0(char*, c+1);
624 if (!v)
625 return NULL;
626
627 p = s;
628 while (p < s + l) {
629 const char *e;
630
631 e = memchr(p, 0, s + l - p);
632
633 v[i] = strndup(p, e ? e - p : s + l - p);
634 if (!v[i]) {
635 strv_free(v);
636 return NULL;
637 }
638
639 i++;
640
641 if (!e)
642 break;
643
644 p = e + 1;
645 }
646
647 assert(i == c);
648
649 return v;
650 }
651
652 char **strv_split_nulstr(const char *s) {
653 const char *i;
654 char **r = NULL;
655
656 NULSTR_FOREACH(i, s)
657 if (strv_extend(&r, i) < 0) {
658 strv_free(r);
659 return NULL;
660 }
661
662 if (!r)
663 return strv_new(NULL);
664
665 return r;
666 }
667
668 int strv_make_nulstr(char **l, char **p, size_t *q) {
669 /* A valid nulstr with two NULs at the end will be created, but
670 * q will be the length without the two trailing NULs. Thus the output
671 * string is a valid nulstr and can be iterated over using NULSTR_FOREACH,
672 * and can also be parsed by strv_parse_nulstr as long as the length
673 * is provided separately.
674 */
675
676 size_t n_allocated = 0, n = 0;
677 _cleanup_free_ char *m = NULL;
678 char **i;
679
680 assert(p);
681 assert(q);
682
683 STRV_FOREACH(i, l) {
684 size_t z;
685
686 z = strlen(*i);
687
688 if (!GREEDY_REALLOC(m, n_allocated, n + z + 2))
689 return -ENOMEM;
690
691 memcpy(m + n, *i, z + 1);
692 n += z + 1;
693 }
694
695 if (!m) {
696 m = new0(char, 1);
697 if (!m)
698 return -ENOMEM;
699 n = 1;
700 } else
701 /* make sure there is a second extra NUL at the end of resulting nulstr */
702 m[n] = '\0';
703
704 assert(n > 0);
705 *p = m;
706 *q = n - 1;
707
708 m = NULL;
709
710 return 0;
711 }
712
713 bool strv_overlap(char **a, char **b) {
714 char **i;
715
716 STRV_FOREACH(i, a)
717 if (strv_contains(b, *i))
718 return true;
719
720 return false;
721 }
722
723 static int str_compare(char * const *a, char * const *b) {
724 return strcmp(*a, *b);
725 }
726
727 char **strv_sort(char **l) {
728 typesafe_qsort(l, strv_length(l), str_compare);
729 return l;
730 }
731
732 bool strv_equal(char **a, char **b) {
733
734 if (strv_isempty(a))
735 return strv_isempty(b);
736
737 if (strv_isempty(b))
738 return false;
739
740 for ( ; *a || *b; ++a, ++b)
741 if (!streq_ptr(*a, *b))
742 return false;
743
744 return true;
745 }
746
747 void strv_print(char **l) {
748 char **s;
749
750 STRV_FOREACH(s, l)
751 puts(*s);
752 }
753
754 int strv_extendf(char ***l, const char *format, ...) {
755 va_list ap;
756 char *x;
757 int r;
758
759 va_start(ap, format);
760 r = vasprintf(&x, format, ap);
761 va_end(ap);
762
763 if (r < 0)
764 return -ENOMEM;
765
766 return strv_consume(l, x);
767 }
768
769 char **strv_reverse(char **l) {
770 size_t n, i;
771
772 n = strv_length(l);
773 if (n <= 1)
774 return l;
775
776 for (i = 0; i < n / 2; i++)
777 SWAP_TWO(l[i], l[n-1-i]);
778
779 return l;
780 }
781
782 char **strv_shell_escape(char **l, const char *bad) {
783 char **s;
784
785 /* Escapes every character in every string in l that is in bad,
786 * edits in-place, does not roll-back on error. */
787
788 STRV_FOREACH(s, l) {
789 char *v;
790
791 v = shell_escape(*s, bad);
792 if (!v)
793 return NULL;
794
795 free(*s);
796 *s = v;
797 }
798
799 return l;
800 }
801
802 bool strv_fnmatch(char* const* patterns, const char *s, int flags) {
803 char* const* p;
804
805 STRV_FOREACH(p, patterns)
806 if (fnmatch(*p, s, flags) == 0)
807 return true;
808
809 return false;
810 }
811
812 char ***strv_free_free(char ***l) {
813 char ***i;
814
815 if (!l)
816 return NULL;
817
818 for (i = l; *i; i++)
819 strv_free(*i);
820
821 return mfree(l);
822 }
823
824 char **strv_skip(char **l, size_t n) {
825
826 while (n > 0) {
827 if (strv_isempty(l))
828 return l;
829
830 l++, n--;
831 }
832
833 return l;
834 }
835
836 int strv_extend_n(char ***l, const char *value, size_t n) {
837 size_t i, j, k;
838 char **nl;
839
840 assert(l);
841
842 if (!value)
843 return 0;
844 if (n == 0)
845 return 0;
846
847 /* Adds the value n times to l */
848
849 k = strv_length(*l);
850
851 nl = reallocarray(*l, k + n + 1, sizeof(char *));
852 if (!nl)
853 return -ENOMEM;
854
855 *l = nl;
856
857 for (i = k; i < k + n; i++) {
858 nl[i] = strdup(value);
859 if (!nl[i])
860 goto rollback;
861 }
862
863 nl[i] = NULL;
864 return 0;
865
866 rollback:
867 for (j = k; j < i; j++)
868 free(nl[j]);
869
870 nl[k] = NULL;
871 return -ENOMEM;
872 }
873
874 int fputstrv(FILE *f, char **l, const char *separator, bool *space) {
875 bool b = false;
876 char **s;
877 int r;
878
879 /* Like fputs(), but for strv, and with a less stupid argument order */
880
881 if (!space)
882 space = &b;
883
884 STRV_FOREACH(s, l) {
885 r = fputs_with_space(f, *s, separator, space);
886 if (r < 0)
887 return r;
888 }
889
890 return 0;
891 }
892
893 static int string_strv_hashmap_put_internal(Hashmap *h, const char *key, const char *value) {
894 char **l;
895 int r;
896
897 l = hashmap_get(h, key);
898 if (l) {
899 /* A list for this key already exists, let's append to it if it is not listed yet */
900 if (strv_contains(l, value))
901 return 0;
902
903 r = strv_extend(&l, value);
904 if (r < 0)
905 return r;
906
907 assert_se(hashmap_update(h, key, l) >= 0);
908 } else {
909 /* No list for this key exists yet, create one */
910 _cleanup_strv_free_ char **l2 = NULL;
911 _cleanup_free_ char *t = NULL;
912
913 t = strdup(key);
914 if (!t)
915 return -ENOMEM;
916
917 r = strv_extend(&l2, value);
918 if (r < 0)
919 return r;
920
921 r = hashmap_put(h, t, l2);
922 if (r < 0)
923 return r;
924 TAKE_PTR(t);
925 TAKE_PTR(l2);
926 }
927
928 return 1;
929 }
930
931 int string_strv_hashmap_put(Hashmap **h, const char *key, const char *value) {
932 int r;
933
934 r = hashmap_ensure_allocated(h, &string_strv_hash_ops);
935 if (r < 0)
936 return r;
937
938 return string_strv_hashmap_put_internal(*h, key, value);
939 }
940
941 int string_strv_ordered_hashmap_put(OrderedHashmap **h, const char *key, const char *value) {
942 int r;
943
944 r = ordered_hashmap_ensure_allocated(h, &string_strv_hash_ops);
945 if (r < 0)
946 return r;
947
948 return string_strv_hashmap_put_internal(PLAIN_HASHMAP(*h), key, value);
949 }
950
951 DEFINE_HASH_OPS_FULL(string_strv_hash_ops, char, string_hash_func, string_compare_func, free, char*, strv_free);