]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/basic/strv.c
0a3d15706f7f89cbfeb7949b89ed925d965957c0
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
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.
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.
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/>.
29 #include "alloc-util.h"
31 #include "extract-word.h"
32 #include "string-util.h"
36 char *strv_find(char **l
, const char *name
) {
48 char *strv_find_prefix(char **l
, const char *name
) {
54 if (startswith(*i
, name
))
60 char *strv_find_startswith(char **l
, const char *name
) {
65 /* Like strv_find_prefix, but actually returns only the
66 * suffix, not the whole item */
69 e
= startswith(*i
, name
);
77 void strv_clear(char **l
) {
89 char **strv_free(char **l
) {
95 char **strv_free_erase(char **l
) {
104 char **strv_copy(char * const *l
) {
107 k
= r
= new(char*, strv_length(l
) + 1);
112 for (; *l
; k
++, l
++) {
124 unsigned strv_length(char * const *l
) {
136 char **strv_new_ap(const char *x
, va_list ap
) {
139 unsigned n
= 0, i
= 0;
142 /* As a special trick we ignore all listed strings that equal
143 * (const char*) -1. This is supposed to be used with the
144 * STRV_IFNOTNULL() macro to include possibly NULL strings in
145 * the string list. */
148 n
= x
== (const char*) -1 ? 0 : 1;
151 while ((s
= va_arg(aq
, const char*))) {
152 if (s
== (const char*) -1)
166 if (x
!= (const char*) -1) {
173 while ((s
= va_arg(ap
, const char*))) {
175 if (s
== (const char*) -1)
195 char **strv_new(const char *x
, ...) {
200 r
= strv_new_ap(x
, ap
);
206 int strv_extend_strv(char ***a
, char **b
, bool filter_duplicates
) {
208 size_t p
, q
, i
= 0, j
;
218 t
= realloc(*a
, sizeof(char*) * (p
+ q
+ 1));
227 if (filter_duplicates
&& strv_contains(t
, *s
))
243 for (j
= 0; j
< i
; j
++)
250 int strv_extend_strv_concat(char ***a
, char **b
, const char *suffix
) {
257 v
= strappend(*s
, suffix
);
271 char **strv_split(const char *s
, const char *separator
) {
272 const char *word
, *state
;
280 FOREACH_WORD_SEPARATOR(word
, l
, s
, separator
, state
)
288 FOREACH_WORD_SEPARATOR(word
, l
, s
, separator
, state
) {
289 r
[i
] = strndup(word
, l
);
302 char **strv_split_newlines(const char *s
) {
308 /* Special version of strv_split() that splits on newlines and
309 * suppresses an empty string at the end */
311 l
= strv_split(s
, NEWLINE
);
319 if (isempty(l
[n
- 1]))
320 l
[n
- 1] = mfree(l
[n
- 1]);
325 int strv_split_extract(char ***t
, const char *s
, const char *separators
, ExtractFlags flags
) {
326 _cleanup_strv_free_
char **l
= NULL
;
327 size_t n
= 0, allocated
= 0;
334 _cleanup_free_
char *word
= NULL
;
336 r
= extract_first_word(&s
, &word
, separators
, flags
);
342 if (!GREEDY_REALLOC(l
, allocated
, n
+ 2))
363 char *strv_join(char **l
, const char *separator
) {
371 k
= strlen(separator
);
387 e
= stpcpy(e
, separator
);
397 char *strv_join_quoted(char **l
) {
400 size_t allocated
= 0, len
= 0;
403 /* assuming here that escaped string cannot be more
404 * than twice as long, and reserving space for the
405 * separator and quotes.
407 _cleanup_free_
char *esc
= NULL
;
410 if (!GREEDY_REALLOC(buf
, allocated
,
411 len
+ strlen(*s
) * 2 + 3))
418 needed
= snprintf(buf
+ len
, allocated
- len
, "%s\"%s\"",
419 len
> 0 ? " " : "", esc
);
420 assert(needed
< allocated
- len
);
434 int strv_push(char ***l
, char *value
) {
443 /* Increase and check for overflow */
448 c
= realloc_multiply(*l
, sizeof(char*), m
);
459 int strv_push_pair(char ***l
, char *a
, char *b
) {
468 /* increase and check for overflow */
469 m
= n
+ !!a
+ !!b
+ 1;
473 c
= realloc_multiply(*l
, sizeof(char*), m
);
487 int strv_push_prepend(char ***l
, char *value
) {
496 /* increase and check for overflow */
505 for (i
= 0; i
< n
; i
++)
517 int strv_consume(char ***l
, char *value
) {
520 r
= strv_push(l
, value
);
527 int strv_consume_pair(char ***l
, char *a
, char *b
) {
530 r
= strv_push_pair(l
, a
, b
);
539 int strv_consume_prepend(char ***l
, char *value
) {
542 r
= strv_push_prepend(l
, value
);
549 int strv_extend(char ***l
, const char *value
) {
559 return strv_consume(l
, v
);
562 char **strv_uniq(char **l
) {
565 /* Drops duplicate entries. The first identical string will be
566 * kept, the others dropped */
569 strv_remove(i
+1, *i
);
574 bool strv_is_uniq(char **l
) {
578 if (strv_find(i
+1, *i
))
584 char **strv_remove(char **l
, const char *s
) {
592 /* Drops every occurrence of s in the string list, edits
595 for (f
= t
= l
; *f
; f
++)
605 char **strv_parse_nulstr(const char *s
, size_t l
) {
607 unsigned c
= 0, i
= 0;
613 return new0(char*, 1);
615 for (p
= s
; p
< s
+ l
; p
++)
622 v
= new0(char*, c
+1);
630 e
= memchr(p
, 0, s
+ l
- p
);
632 v
[i
] = strndup(p
, e
? e
- p
: s
+ l
- p
);
651 char **strv_split_nulstr(const char *s
) {
656 if (strv_extend(&r
, i
) < 0) {
662 return strv_new(NULL
, NULL
);
667 int strv_make_nulstr(char **l
, char **p
, size_t *q
) {
668 size_t n_allocated
= 0, n
= 0;
669 _cleanup_free_
char *m
= NULL
;
680 if (!GREEDY_REALLOC(m
, n_allocated
, n
+ z
+ 1))
683 memcpy(m
+ n
, *i
, z
+ 1);
702 bool strv_overlap(char **a
, char **b
) {
706 if (strv_contains(b
, *i
))
712 static int str_compare(const void *_a
, const void *_b
) {
713 const char **a
= (const char**) _a
, **b
= (const char**) _b
;
715 return strcmp(*a
, *b
);
718 char **strv_sort(char **l
) {
723 qsort(l
, strv_length(l
), sizeof(char*), str_compare
);
727 bool strv_equal(char **a
, char **b
) {
730 return strv_isempty(b
);
735 for ( ; *a
|| *b
; ++a
, ++b
)
736 if (!streq_ptr(*a
, *b
))
742 void strv_print(char **l
) {
749 int strv_extendf(char ***l
, const char *format
, ...) {
754 va_start(ap
, format
);
755 r
= vasprintf(&x
, format
, ap
);
761 return strv_consume(l
, x
);
764 char **strv_reverse(char **l
) {
771 for (i
= 0; i
< n
/ 2; i
++) {
782 char **strv_shell_escape(char **l
, const char *bad
) {
785 /* Escapes every character in every string in l that is in bad,
786 * edits in-place, does not roll-back on error. */
791 v
= shell_escape(*s
, bad
);
802 bool strv_fnmatch(char* const* patterns
, const char *s
, int flags
) {
805 STRV_FOREACH(p
, patterns
)
806 if (fnmatch(*p
, s
, 0) == 0)
812 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 value n times to l */
852 nl
= realloc(*l
, sizeof(char*) * (k
+ n
+ 1));
858 for (i
= k
; i
< k
+ n
; i
++) {
859 nl
[i
] = strdup(value
);
868 for (j
= k
; j
< i
; j
++)