]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/basic/strv.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
9 #include "alloc-util.h"
11 #include "extract-word.h"
13 #include "memory-util.h"
14 #include "nulstr-util.h"
15 #include "sort-util.h"
16 #include "string-util.h"
19 char *strv_find(char * const *l
, const char *name
) {
31 char *strv_find_prefix(char * const *l
, const char *name
) {
37 if (startswith(*i
, name
))
43 char *strv_find_startswith(char * const *l
, const char *name
) {
48 /* Like strv_find_prefix, but actually returns only the
49 * suffix, not the whole item */
52 e
= startswith(*i
, name
);
60 void strv_clear(char **l
) {
72 char **strv_free(char **l
) {
77 char **strv_free_erase(char **l
) {
86 char **strv_copy(char * const *l
) {
89 k
= r
= new(char*, strv_length(l
) + 1);
94 for (; *l
; k
++, l
++) {
106 size_t strv_length(char * const *l
) {
118 char **strv_new_ap(const char *x
, va_list ap
) {
120 _cleanup_strv_free_
char **a
= NULL
;
124 /* As a special trick we ignore all listed strings that equal
125 * STRV_IGNORE. This is supposed to be used with the
126 * STRV_IFNOTNULL() macro to include possibly NULL strings in
127 * the string list. */
130 n
= x
== STRV_IGNORE
? 0 : 1;
133 while ((s
= va_arg(aq
, const char*))) {
134 if (s
== STRV_IGNORE
)
148 if (x
!= STRV_IGNORE
) {
155 while ((s
= va_arg(ap
, const char*))) {
157 if (s
== STRV_IGNORE
)
173 char **strv_new_internal(const char *x
, ...) {
178 r
= strv_new_ap(x
, ap
);
184 int strv_extend_strv(char ***a
, char * const *b
, bool filter_duplicates
) {
185 char * const *s
, **t
;
186 size_t p
, q
, i
= 0, j
;
196 if (p
>= SIZE_MAX
- q
)
199 t
= reallocarray(*a
, GREEDY_ALLOC_ROUND_UP(p
+ q
+ 1), sizeof(char *));
208 if (filter_duplicates
&& strv_contains(t
, *s
))
224 for (j
= 0; j
< i
; j
++)
231 int strv_extend_strv_concat(char ***a
, char * const *b
, const char *suffix
) {
238 v
= strjoin(*s
, suffix
);
252 char **strv_split_full(const char *s
, const char *separator
, SplitFlags flags
) {
253 const char *word
, *state
;
261 separator
= WHITESPACE
;
263 s
+= strspn(s
, separator
);
265 return new0(char*, 1);
268 _FOREACH_WORD(word
, l
, s
, separator
, flags
, state
)
276 _FOREACH_WORD(word
, l
, s
, separator
, flags
, state
) {
277 r
[i
] = strndup(word
, l
);
290 char **strv_split_newlines(const char *s
) {
296 /* Special version of strv_split() that splits on newlines and
297 * suppresses an empty string at the end */
299 l
= strv_split(s
, NEWLINE
);
307 if (isempty(l
[n
- 1]))
308 l
[n
- 1] = mfree(l
[n
- 1]);
313 int strv_split_extract(char ***t
, const char *s
, const char *separators
, ExtractFlags flags
) {
314 _cleanup_strv_free_
char **l
= NULL
;
315 size_t n
= 0, allocated
= 0;
322 _cleanup_free_
char *word
= NULL
;
324 r
= extract_first_word(&s
, &word
, separators
, flags
);
330 if (!GREEDY_REALLOC(l
, allocated
, n
+ 2))
333 l
[n
++] = TAKE_PTR(word
);
349 char *strv_join_prefix(char * const *l
, const char *separator
, const char *prefix
) {
357 k
= strlen(separator
);
358 m
= strlen_ptr(prefix
);
374 e
= stpcpy(e
, separator
);
377 e
= stpcpy(e
, prefix
);
387 int strv_push(char ***l
, char *value
) {
396 /* Check for overflow */
400 c
= reallocarray(*l
, GREEDY_ALLOC_ROUND_UP(n
+ 2), sizeof(char*));
411 int strv_push_pair(char ***l
, char *a
, char *b
) {
420 /* Check for overflow */
424 /* increase and check for overflow */
425 c
= reallocarray(*l
, GREEDY_ALLOC_ROUND_UP(n
+ !!a
+ !!b
+ 1), sizeof(char*));
439 int strv_insert(char ***l
, size_t position
, char *value
) {
447 position
= MIN(position
, n
);
449 /* increase and check for overflow */
458 for (i
= 0; i
< position
; i
++)
461 for (i
= position
; i
< n
; i
++)
472 int strv_consume(char ***l
, char *value
) {
475 r
= strv_push(l
, value
);
482 int strv_consume_pair(char ***l
, char *a
, char *b
) {
485 r
= strv_push_pair(l
, a
, b
);
494 int strv_consume_prepend(char ***l
, char *value
) {
497 r
= strv_push_prepend(l
, value
);
504 int strv_extend(char ***l
, const char *value
) {
514 return strv_consume(l
, v
);
517 int strv_extend_front(char ***l
, const char *value
) {
523 /* Like strv_extend(), but prepends rather than appends the new entry */
530 /* Increase and overflow check. */
539 c
= reallocarray(*l
, m
, sizeof(char*));
545 memmove(c
+1, c
, n
* sizeof(char*));
553 char **strv_uniq(char **l
) {
556 /* Drops duplicate entries. The first identical string will be
557 * kept, the others dropped */
560 strv_remove(i
+1, *i
);
565 bool strv_is_uniq(char * const *l
) {
569 if (strv_find(i
+1, *i
))
575 char **strv_remove(char **l
, const char *s
) {
583 /* Drops every occurrence of s in the string list, edits
586 for (f
= t
= l
; *f
; f
++)
596 char **strv_parse_nulstr(const char *s
, size_t l
) {
597 /* l is the length of the input data, which will be split at NULs into
598 * elements of the resulting strv. Hence, the number of items in the resulting strv
599 * will be equal to one plus the number of NUL bytes in the l bytes starting at s,
600 * unless s[l-1] is NUL, in which case the final empty string is not stored in
601 * the resulting strv, and length is equal to the number of NUL bytes.
603 * Note that contrary to a normal nulstr which cannot contain empty strings, because
604 * the input data is terminated by any two consequent NUL bytes, this parser accepts
605 * empty strings in s.
615 return new0(char*, 1);
617 for (p
= s
; p
< s
+ l
; p
++)
624 v
= new0(char*, c
+1);
632 e
= memchr(p
, 0, s
+ l
- p
);
634 v
[i
] = strndup(p
, e
? e
- p
: s
+ l
- p
);
653 char **strv_split_nulstr(const char *s
) {
658 if (strv_extend(&r
, i
) < 0) {
664 return strv_new(NULL
);
669 int strv_make_nulstr(char * const *l
, char **ret
, size_t *ret_size
) {
670 /* A valid nulstr with two NULs at the end will be created, but
671 * q will be the length without the two trailing NULs. Thus the output
672 * string is a valid nulstr and can be iterated over using NULSTR_FOREACH,
673 * and can also be parsed by strv_parse_nulstr as long as the length
674 * is provided separately.
677 size_t n_allocated
= 0, n
= 0;
678 _cleanup_free_
char *m
= NULL
;
689 if (!GREEDY_REALLOC(m
, n_allocated
, n
+ z
+ 2))
692 memcpy(m
+ n
, *i
, z
+ 1);
702 /* make sure there is a second extra NUL at the end of resulting nulstr */
714 bool strv_overlap(char * const *a
, char * const *b
) {
718 if (strv_contains(b
, *i
))
724 static int str_compare(char * const *a
, char * const *b
) {
725 return strcmp(*a
, *b
);
728 char **strv_sort(char **l
) {
729 typesafe_qsort(l
, strv_length(l
), str_compare
);
733 bool strv_equal(char * const *a
, char * const *b
) {
736 return strv_isempty(b
);
741 for ( ; *a
|| *b
; ++a
, ++b
)
742 if (!streq_ptr(*a
, *b
))
748 void strv_print(char * const *l
) {
755 int strv_extendf(char ***l
, const char *format
, ...) {
760 va_start(ap
, format
);
761 r
= vasprintf(&x
, format
, ap
);
767 return strv_consume(l
, x
);
770 char **strv_reverse(char **l
) {
777 for (i
= 0; i
< n
/ 2; i
++)
778 SWAP_TWO(l
[i
], l
[n
-1-i
]);
783 char **strv_shell_escape(char **l
, const char *bad
) {
786 /* Escapes every character in every string in l that is in bad,
787 * edits in-place, does not roll-back on error. */
792 v
= shell_escape(*s
, bad
);
803 bool strv_fnmatch(char* const* patterns
, const char *s
, int flags
) {
806 STRV_FOREACH(p
, patterns
)
807 if (fnmatch(*p
, s
, flags
) == 0)
813 char ***strv_free_free(char ***l
) {
825 char **strv_skip(char **l
, size_t n
) {
837 int strv_extend_n(char ***l
, const char *value
, size_t n
) {
848 /* Adds the value n times to l */
851 if (n
>= SIZE_MAX
- k
)
854 nl
= reallocarray(*l
, GREEDY_ALLOC_ROUND_UP(k
+ n
+ 1), sizeof(char *));
860 for (i
= k
; i
< k
+ n
; i
++) {
861 nl
[i
] = strdup(value
);
870 for (j
= k
; j
< i
; j
++)
877 int fputstrv(FILE *f
, char * const *l
, const char *separator
, bool *space
) {
882 /* Like fputs(), but for strv, and with a less stupid argument order */
888 r
= fputs_with_space(f
, *s
, separator
, space
);
896 static int string_strv_hashmap_put_internal(Hashmap
*h
, const char *key
, const char *value
) {
900 l
= hashmap_get(h
, key
);
902 /* A list for this key already exists, let's append to it if it is not listed yet */
903 if (strv_contains(l
, value
))
906 r
= strv_extend(&l
, value
);
910 assert_se(hashmap_update(h
, key
, l
) >= 0);
912 /* No list for this key exists yet, create one */
913 _cleanup_strv_free_
char **l2
= NULL
;
914 _cleanup_free_
char *t
= NULL
;
920 r
= strv_extend(&l2
, value
);
924 r
= hashmap_put(h
, t
, l2
);
934 int string_strv_hashmap_put(Hashmap
**h
, const char *key
, const char *value
) {
937 r
= hashmap_ensure_allocated(h
, &string_strv_hash_ops
);
941 return string_strv_hashmap_put_internal(*h
, key
, value
);
944 int string_strv_ordered_hashmap_put(OrderedHashmap
**h
, const char *key
, const char *value
) {
947 r
= ordered_hashmap_ensure_allocated(h
, &string_strv_hash_ops
);
951 return string_strv_hashmap_put_internal(PLAIN_HASHMAP(*h
), key
, value
);
954 DEFINE_HASH_OPS_FULL(string_strv_hash_ops
, char, string_hash_func
, string_compare_func
, free
, char*, strv_free
);