]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/basic/strv.c
2 This file is part of systemd.
4 Copyright 2010 Lennart Poettering
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
27 #include "alloc-util.h"
29 #include "extract-word.h"
31 #include "string-util.h"
35 char *strv_find(char **l
, const char *name
) {
47 char *strv_find_prefix(char **l
, const char *name
) {
53 if (startswith(*i
, name
))
59 char *strv_find_startswith(char **l
, const char *name
) {
64 /* Like strv_find_prefix, but actually returns only the
65 * suffix, not the whole item */
68 e
= startswith(*i
, name
);
76 void strv_clear(char **l
) {
88 char **strv_free(char **l
) {
94 char **strv_free_erase(char **l
) {
103 char **strv_copy(char * const *l
) {
106 k
= r
= new(char*, strv_length(l
) + 1);
111 for (; *l
; k
++, l
++) {
123 unsigned strv_length(char * const *l
) {
135 char **strv_new_ap(const char *x
, va_list ap
) {
138 unsigned n
= 0, i
= 0;
141 /* As a special trick we ignore all listed strings that equal
142 * (const char*) -1. This is supposed to be used with the
143 * STRV_IFNOTNULL() macro to include possibly NULL strings in
144 * the string list. */
147 n
= x
== (const char*) -1 ? 0 : 1;
150 while ((s
= va_arg(aq
, const char*))) {
151 if (s
== (const char*) -1)
165 if (x
!= (const char*) -1) {
172 while ((s
= va_arg(ap
, const char*))) {
174 if (s
== (const char*) -1)
194 char **strv_new(const char *x
, ...) {
199 r
= strv_new_ap(x
, ap
);
205 int strv_extend_strv(char ***a
, char **b
, bool filter_duplicates
) {
207 size_t p
, q
, i
= 0, j
;
217 t
= realloc(*a
, sizeof(char*) * (p
+ q
+ 1));
226 if (filter_duplicates
&& strv_contains(t
, *s
))
242 for (j
= 0; j
< i
; j
++)
249 int strv_extend_strv_concat(char ***a
, char **b
, const char *suffix
) {
256 v
= strappend(*s
, suffix
);
270 char **strv_split(const char *s
, const char *separator
) {
271 const char *word
, *state
;
279 FOREACH_WORD_SEPARATOR(word
, l
, s
, separator
, state
)
287 FOREACH_WORD_SEPARATOR(word
, l
, s
, separator
, state
) {
288 r
[i
] = strndup(word
, l
);
301 char **strv_split_newlines(const char *s
) {
307 /* Special version of strv_split() that splits on newlines and
308 * suppresses an empty string at the end */
310 l
= strv_split(s
, NEWLINE
);
318 if (isempty(l
[n
- 1]))
319 l
[n
- 1] = mfree(l
[n
- 1]);
324 int strv_split_extract(char ***t
, const char *s
, const char *separators
, ExtractFlags flags
) {
325 _cleanup_strv_free_
char **l
= NULL
;
326 size_t n
= 0, allocated
= 0;
333 _cleanup_free_
char *word
= NULL
;
335 r
= extract_first_word(&s
, &word
, separators
, flags
);
341 if (!GREEDY_REALLOC(l
, allocated
, n
+ 2))
362 char *strv_join(char **l
, const char *separator
) {
370 k
= strlen(separator
);
386 e
= stpcpy(e
, separator
);
396 char *strv_join_quoted(char **l
) {
399 size_t allocated
= 0, len
= 0;
402 /* assuming here that escaped string cannot be more
403 * than twice as long, and reserving space for the
404 * separator and quotes.
406 _cleanup_free_
char *esc
= NULL
;
409 if (!GREEDY_REALLOC(buf
, allocated
,
410 len
+ strlen(*s
) * 2 + 3))
417 needed
= snprintf(buf
+ len
, allocated
- len
, "%s\"%s\"",
418 len
> 0 ? " " : "", esc
);
419 assert(needed
< allocated
- len
);
433 int strv_push(char ***l
, char *value
) {
442 /* Increase and check for overflow */
447 c
= realloc_multiply(*l
, sizeof(char*), m
);
458 int strv_push_pair(char ***l
, char *a
, char *b
) {
467 /* increase and check for overflow */
468 m
= n
+ !!a
+ !!b
+ 1;
472 c
= realloc_multiply(*l
, sizeof(char*), m
);
486 int strv_push_prepend(char ***l
, char *value
) {
495 /* increase and check for overflow */
504 for (i
= 0; i
< n
; i
++)
516 int strv_consume(char ***l
, char *value
) {
519 r
= strv_push(l
, value
);
526 int strv_consume_pair(char ***l
, char *a
, char *b
) {
529 r
= strv_push_pair(l
, a
, b
);
538 int strv_consume_prepend(char ***l
, char *value
) {
541 r
= strv_push_prepend(l
, value
);
548 int strv_extend(char ***l
, const char *value
) {
558 return strv_consume(l
, v
);
561 char **strv_uniq(char **l
) {
564 /* Drops duplicate entries. The first identical string will be
565 * kept, the others dropped */
568 strv_remove(i
+1, *i
);
573 bool strv_is_uniq(char **l
) {
577 if (strv_find(i
+1, *i
))
583 char **strv_remove(char **l
, const char *s
) {
591 /* Drops every occurrence of s in the string list, edits
594 for (f
= t
= l
; *f
; f
++)
604 char **strv_parse_nulstr(const char *s
, size_t l
) {
606 unsigned c
= 0, i
= 0;
612 return new0(char*, 1);
614 for (p
= s
; p
< s
+ l
; p
++)
621 v
= new0(char*, c
+1);
629 e
= memchr(p
, 0, s
+ l
- p
);
631 v
[i
] = strndup(p
, e
? e
- p
: s
+ l
- p
);
650 char **strv_split_nulstr(const char *s
) {
655 if (strv_extend(&r
, i
) < 0) {
661 return strv_new(NULL
, NULL
);
666 int strv_make_nulstr(char **l
, char **p
, size_t *q
) {
667 size_t n_allocated
= 0, n
= 0;
668 _cleanup_free_
char *m
= NULL
;
679 if (!GREEDY_REALLOC(m
, n_allocated
, n
+ z
+ 1))
682 memcpy(m
+ n
, *i
, z
+ 1);
701 bool strv_overlap(char **a
, char **b
) {
705 if (strv_contains(b
, *i
))
711 static int str_compare(const void *_a
, const void *_b
) {
712 const char **a
= (const char**) _a
, **b
= (const char**) _b
;
714 return strcmp(*a
, *b
);
717 char **strv_sort(char **l
) {
722 qsort(l
, strv_length(l
), sizeof(char*), str_compare
);
726 bool strv_equal(char **a
, char **b
) {
729 return strv_isempty(b
);
734 for ( ; *a
|| *b
; ++a
, ++b
)
735 if (!streq_ptr(*a
, *b
))
741 void strv_print(char **l
) {
748 int strv_extendf(char ***l
, const char *format
, ...) {
753 va_start(ap
, format
);
754 r
= vasprintf(&x
, format
, ap
);
760 return strv_consume(l
, x
);
763 char **strv_reverse(char **l
) {
770 for (i
= 0; i
< n
/ 2; i
++) {
781 char **strv_shell_escape(char **l
, const char *bad
) {
784 /* Escapes every character in every string in l that is in bad,
785 * edits in-place, does not roll-back on error. */
790 v
= shell_escape(*s
, bad
);
801 bool strv_fnmatch(char* const* patterns
, const char *s
, int flags
) {
804 STRV_FOREACH(p
, patterns
)
805 if (fnmatch(*p
, s
, 0) == 0)
811 char ***strv_free_free(char ***l
) {
824 char **strv_skip(char **l
, size_t n
) {
836 int strv_extend_n(char ***l
, const char *value
, size_t n
) {
847 /* Adds the value value n times to l */
851 nl
= realloc(*l
, sizeof(char*) * (k
+ n
+ 1));
857 for (i
= k
; i
< k
+ n
; i
++) {
858 nl
[i
] = strdup(value
);
867 for (j
= k
; j
< i
; j
++)
874 int fputstrv(FILE *f
, char **l
, const char *separator
, bool *space
) {
879 /* Like fputs(), but for strv, and with a less stupid argument order */
885 r
= fputs_with_space(f
, *s
, separator
, space
);