]> git.ipfire.org Git - thirdparty/systemd.git/blob - 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
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 <errno.h>
23 #include <stdarg.h>
24 #include <stdlib.h>
25 #include <string.h>
26
27 #include "escape.h"
28 #include "string-util.h"
29 #include "util.h"
30 #include "strv.h"
31
32 char *strv_find(char **l, const char *name) {
33 char **i;
34
35 assert(name);
36
37 STRV_FOREACH(i, l)
38 if (streq(*i, name))
39 return *i;
40
41 return NULL;
42 }
43
44 char *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
56 char *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
73 void strv_clear(char **l) {
74 char **k;
75
76 if (!l)
77 return;
78
79 for (k = l; *k; k++)
80 free(*k);
81
82 *l = NULL;
83 }
84
85 char **strv_free(char **l) {
86 strv_clear(l);
87 free(l);
88 return NULL;
89 }
90
91 char **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
100 char **strv_copy(char * const *l) {
101 char **r, **k;
102
103 k = r = new(char*, strv_length(l) + 1);
104 if (!r)
105 return NULL;
106
107 if (l)
108 for (; *l; k++, l++) {
109 *k = strdup(*l);
110 if (!*k) {
111 strv_free(r);
112 return NULL;
113 }
114 }
115
116 *k = NULL;
117 return r;
118 }
119
120 unsigned strv_length(char * const *l) {
121 unsigned n = 0;
122
123 if (!l)
124 return 0;
125
126 for (; *l; l++)
127 n++;
128
129 return n;
130 }
131
132 char **strv_new_ap(const char *x, va_list ap) {
133 const char *s;
134 char **a;
135 unsigned n = 0, i = 0;
136 va_list aq;
137
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
143 if (x) {
144 n = x == (const char*) -1 ? 0 : 1;
145
146 va_copy(aq, ap);
147 while ((s = va_arg(aq, const char*))) {
148 if (s == (const char*) -1)
149 continue;
150
151 n++;
152 }
153
154 va_end(aq);
155 }
156
157 a = new(char*, n+1);
158 if (!a)
159 return NULL;
160
161 if (x) {
162 if (x != (const char*) -1) {
163 a[i] = strdup(x);
164 if (!a[i])
165 goto fail;
166 i++;
167 }
168
169 while ((s = va_arg(ap, const char*))) {
170
171 if (s == (const char*) -1)
172 continue;
173
174 a[i] = strdup(s);
175 if (!a[i])
176 goto fail;
177
178 i++;
179 }
180 }
181
182 a[i] = NULL;
183
184 return a;
185
186 fail:
187 strv_free(a);
188 return NULL;
189 }
190
191 char **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
202 int 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;
220
221 STRV_FOREACH(s, b) {
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;
232 }
233
234 assert(i <= q);
235
236 return (int) i;
237
238 rollback:
239 for (j = 0; j < i; j++)
240 free(t[p + j]);
241
242 t[p] = NULL;
243 return -ENOMEM;
244 }
245
246 int strv_extend_strv_concat(char ***a, char **b, const char *suffix) {
247 int r;
248 char **s;
249
250 STRV_FOREACH(s, b) {
251 char *v;
252
253 v = strappend(*s, suffix);
254 if (!v)
255 return -ENOMEM;
256
257 r = strv_push(a, v);
258 if (r < 0) {
259 free(v);
260 return r;
261 }
262 }
263
264 return 0;
265 }
266
267 char **strv_split(const char *s, const char *separator) {
268 const char *word, *state;
269 size_t l;
270 unsigned n, i;
271 char **r;
272
273 assert(s);
274
275 n = 0;
276 FOREACH_WORD_SEPARATOR(word, l, s, separator, state)
277 n++;
278
279 r = new(char*, n+1);
280 if (!r)
281 return NULL;
282
283 i = 0;
284 FOREACH_WORD_SEPARATOR(word, l, s, separator, state) {
285 r[i] = strndup(word, l);
286 if (!r[i]) {
287 strv_free(r);
288 return NULL;
289 }
290
291 i++;
292 }
293
294 r[i] = NULL;
295 return r;
296 }
297
298 char **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
315 if (isempty(l[n - 1]))
316 l[n - 1] = mfree(l[n - 1]);
317
318 return l;
319 }
320
321 int strv_split_extract(char ***t, const char *s, const char *separators, ExtractFlags flags) {
322 _cleanup_strv_free_ char **l = NULL;
323 size_t n = 0, allocated = 0;
324 int r;
325
326 assert(t);
327 assert(s);
328
329 for (;;) {
330 _cleanup_free_ char *word = NULL;
331
332 r = extract_first_word(&s, &word, separators, flags);
333 if (r < 0)
334 return r;
335 if (r == 0)
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
347 if (!l) {
348 l = new0(char*, 1);
349 if (!l)
350 return -ENOMEM;
351 }
352
353 *t = l;
354 l = NULL;
355
356 return (int) n;
357 }
358
359 char *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
376 r = new(char, n+1);
377 if (!r)
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
388 *e = 0;
389
390 return r;
391 }
392
393 char *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
430 int strv_push(char ***l, char *value) {
431 char **c;
432 unsigned n, m;
433
434 if (!value)
435 return 0;
436
437 n = strv_length(*l);
438
439 /* Increase and check for overflow */
440 m = n + 2;
441 if (m < n)
442 return -ENOMEM;
443
444 c = realloc_multiply(*l, sizeof(char*), m);
445 if (!c)
446 return -ENOMEM;
447
448 c[n] = value;
449 c[n+1] = NULL;
450
451 *l = c;
452 return 0;
453 }
454
455 int 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
483 int strv_push_prepend(char ***l, char *value) {
484 char **c;
485 unsigned n, m, i;
486
487 if (!value)
488 return 0;
489
490 n = strv_length(*l);
491
492 /* increase and check for overflow */
493 m = n + 2;
494 if (m < n)
495 return -ENOMEM;
496
497 c = new(char*, m);
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
513 int strv_consume(char ***l, char *value) {
514 int r;
515
516 r = strv_push(l, value);
517 if (r < 0)
518 free(value);
519
520 return r;
521 }
522
523 int 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
535 int 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
542 return r;
543 }
544
545 int strv_extend(char ***l, const char *value) {
546 char *v;
547
548 if (!value)
549 return 0;
550
551 v = strdup(value);
552 if (!v)
553 return -ENOMEM;
554
555 return strv_consume(l, v);
556 }
557
558 char **strv_uniq(char **l) {
559 char **i;
560
561 /* Drops duplicate entries. The first identical string will be
562 * kept, the others dropped */
563
564 STRV_FOREACH(i, l)
565 strv_remove(i+1, *i);
566
567 return l;
568 }
569
570 bool 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
580 char **strv_remove(char **l, const char *s) {
581 char **f, **t;
582
583 if (!l)
584 return NULL;
585
586 assert(s);
587
588 /* Drops every occurrence of s in the string list, edits
589 * in-place. */
590
591 for (f = t = l; *f; f++)
592 if (streq(*f, s))
593 free(*f);
594 else
595 *(t++) = *f;
596
597 *t = NULL;
598 return l;
599 }
600
601 char **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)
609 return new0(char*, 1);
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
618 v = new0(char*, c+1);
619 if (!v)
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
628 v[i] = strndup(p, e ? e - p : s + l - p);
629 if (!v[i]) {
630 strv_free(v);
631 return NULL;
632 }
633
634 i++;
635
636 if (!e)
637 break;
638
639 p = e + 1;
640 }
641
642 assert(i == c);
643
644 return v;
645 }
646
647 char **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
663 int 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
698 bool strv_overlap(char **a, char **b) {
699 char **i;
700
701 STRV_FOREACH(i, a)
702 if (strv_contains(b, *i))
703 return true;
704
705 return false;
706 }
707
708 static 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
714 char **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 }
722
723 bool strv_equal(char **a, char **b) {
724
725 if (strv_isempty(a))
726 return strv_isempty(b);
727
728 if (strv_isempty(b))
729 return false;
730
731 for ( ; *a || *b; ++a, ++b)
732 if (!streq_ptr(*a, *b))
733 return false;
734
735 return true;
736 }
737
738 void strv_print(char **l) {
739 char **s;
740
741 STRV_FOREACH(s, l)
742 puts(*s);
743 }
744
745 int 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 }
759
760 char **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 }
777
778 char **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
798 bool strv_fnmatch(char* const* patterns, const char *s, int flags) {
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 }
807
808 char ***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 }
820
821 char **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 }
832
833 int 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
863 rollback:
864 for (j = k; j < i; j++)
865 free(nl[j]);
866
867 nl[k] = NULL;
868 return -ENOMEM;
869 }