]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/basic/strv.c
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/>.
27 #include "alloc-util.h"
29 #include "string-util.h"
33 char *strv_find(char **l
, const char *name
) {
45 char *strv_find_prefix(char **l
, const char *name
) {
51 if (startswith(*i
, name
))
57 char *strv_find_startswith(char **l
, const char *name
) {
62 /* Like strv_find_prefix, but actually returns only the
63 * suffix, not the whole item */
66 e
= startswith(*i
, name
);
74 void strv_clear(char **l
) {
86 char **strv_free(char **l
) {
92 char **strv_free_erase(char **l
) {
101 char **strv_copy(char * const *l
) {
104 k
= r
= new(char*, strv_length(l
) + 1);
109 for (; *l
; k
++, l
++) {
121 unsigned strv_length(char * const *l
) {
133 char **strv_new_ap(const char *x
, va_list ap
) {
136 unsigned n
= 0, i
= 0;
139 /* As a special trick we ignore all listed strings that equal
140 * (const char*) -1. This is supposed to be used with the
141 * STRV_IFNOTNULL() macro to include possibly NULL strings in
142 * the string list. */
145 n
= x
== (const char*) -1 ? 0 : 1;
148 while ((s
= va_arg(aq
, const char*))) {
149 if (s
== (const char*) -1)
163 if (x
!= (const char*) -1) {
170 while ((s
= va_arg(ap
, const char*))) {
172 if (s
== (const char*) -1)
192 char **strv_new(const char *x
, ...) {
197 r
= strv_new_ap(x
, ap
);
203 int strv_extend_strv(char ***a
, char **b
, bool filter_duplicates
) {
205 size_t p
, q
, i
= 0, j
;
215 t
= realloc(*a
, sizeof(char*) * (p
+ q
+ 1));
224 if (filter_duplicates
&& strv_contains(t
, *s
))
240 for (j
= 0; j
< i
; j
++)
247 int strv_extend_strv_concat(char ***a
, char **b
, const char *suffix
) {
254 v
= strappend(*s
, suffix
);
268 char **strv_split(const char *s
, const char *separator
) {
269 const char *word
, *state
;
277 FOREACH_WORD_SEPARATOR(word
, l
, s
, separator
, state
)
285 FOREACH_WORD_SEPARATOR(word
, l
, s
, separator
, state
) {
286 r
[i
] = strndup(word
, l
);
299 char **strv_split_newlines(const char *s
) {
305 /* Special version of strv_split() that splits on newlines and
306 * suppresses an empty string at the end */
308 l
= strv_split(s
, NEWLINE
);
316 if (isempty(l
[n
- 1]))
317 l
[n
- 1] = mfree(l
[n
- 1]);
322 int strv_split_extract(char ***t
, const char *s
, const char *separators
, ExtractFlags flags
) {
323 _cleanup_strv_free_
char **l
= NULL
;
324 size_t n
= 0, allocated
= 0;
331 _cleanup_free_
char *word
= NULL
;
333 r
= extract_first_word(&s
, &word
, separators
, flags
);
339 if (!GREEDY_REALLOC(l
, allocated
, n
+ 2))
360 char *strv_join(char **l
, const char *separator
) {
368 k
= strlen(separator
);
384 e
= stpcpy(e
, separator
);
394 char *strv_join_quoted(char **l
) {
397 size_t allocated
= 0, len
= 0;
400 /* assuming here that escaped string cannot be more
401 * than twice as long, and reserving space for the
402 * separator and quotes.
404 _cleanup_free_
char *esc
= NULL
;
407 if (!GREEDY_REALLOC(buf
, allocated
,
408 len
+ strlen(*s
) * 2 + 3))
415 needed
= snprintf(buf
+ len
, allocated
- len
, "%s\"%s\"",
416 len
> 0 ? " " : "", esc
);
417 assert(needed
< allocated
- len
);
431 int strv_push(char ***l
, char *value
) {
440 /* Increase and check for overflow */
445 c
= realloc_multiply(*l
, sizeof(char*), m
);
456 int strv_push_pair(char ***l
, char *a
, char *b
) {
465 /* increase and check for overflow */
466 m
= n
+ !!a
+ !!b
+ 1;
470 c
= realloc_multiply(*l
, sizeof(char*), m
);
484 int strv_push_prepend(char ***l
, char *value
) {
493 /* increase and check for overflow */
502 for (i
= 0; i
< n
; i
++)
514 int strv_consume(char ***l
, char *value
) {
517 r
= strv_push(l
, value
);
524 int strv_consume_pair(char ***l
, char *a
, char *b
) {
527 r
= strv_push_pair(l
, a
, b
);
536 int strv_consume_prepend(char ***l
, char *value
) {
539 r
= strv_push_prepend(l
, value
);
546 int strv_extend(char ***l
, const char *value
) {
556 return strv_consume(l
, v
);
559 char **strv_uniq(char **l
) {
562 /* Drops duplicate entries. The first identical string will be
563 * kept, the others dropped */
566 strv_remove(i
+1, *i
);
571 bool strv_is_uniq(char **l
) {
575 if (strv_find(i
+1, *i
))
581 char **strv_remove(char **l
, const char *s
) {
589 /* Drops every occurrence of s in the string list, edits
592 for (f
= t
= l
; *f
; f
++)
602 char **strv_parse_nulstr(const char *s
, size_t l
) {
604 unsigned c
= 0, i
= 0;
610 return new0(char*, 1);
612 for (p
= s
; p
< s
+ l
; p
++)
619 v
= new0(char*, c
+1);
627 e
= memchr(p
, 0, s
+ l
- p
);
629 v
[i
] = strndup(p
, e
? e
- p
: s
+ l
- p
);
648 char **strv_split_nulstr(const char *s
) {
653 if (strv_extend(&r
, i
) < 0) {
659 return strv_new(NULL
, NULL
);
664 int strv_make_nulstr(char **l
, char **p
, size_t *q
) {
665 size_t n_allocated
= 0, n
= 0;
666 _cleanup_free_
char *m
= NULL
;
677 if (!GREEDY_REALLOC(m
, n_allocated
, n
+ z
+ 1))
680 memcpy(m
+ n
, *i
, z
+ 1);
699 bool strv_overlap(char **a
, char **b
) {
703 if (strv_contains(b
, *i
))
709 static int str_compare(const void *_a
, const void *_b
) {
710 const char **a
= (const char**) _a
, **b
= (const char**) _b
;
712 return strcmp(*a
, *b
);
715 char **strv_sort(char **l
) {
720 qsort(l
, strv_length(l
), sizeof(char*), str_compare
);
724 bool strv_equal(char **a
, char **b
) {
727 return strv_isempty(b
);
732 for ( ; *a
|| *b
; ++a
, ++b
)
733 if (!streq_ptr(*a
, *b
))
739 void strv_print(char **l
) {
746 int strv_extendf(char ***l
, const char *format
, ...) {
751 va_start(ap
, format
);
752 r
= vasprintf(&x
, format
, ap
);
758 return strv_consume(l
, x
);
761 char **strv_reverse(char **l
) {
768 for (i
= 0; i
< n
/ 2; i
++) {
779 char **strv_shell_escape(char **l
, const char *bad
) {
782 /* Escapes every character in every string in l that is in bad,
783 * edits in-place, does not roll-back on error. */
788 v
= shell_escape(*s
, bad
);
799 bool strv_fnmatch(char* const* patterns
, const char *s
, int flags
) {
802 STRV_FOREACH(p
, patterns
)
803 if (fnmatch(*p
, s
, 0) == 0)
809 char ***strv_free_free(char ***l
) {
822 char **strv_skip(char **l
, size_t n
) {
834 int strv_extend_n(char ***l
, const char *value
, size_t n
) {
845 /* Adds the value value n times to l */
849 nl
= realloc(*l
, sizeof(char*) * (k
+ n
+ 1));
855 for (i
= k
; i
< k
+ n
; i
++) {
856 nl
[i
] = strdup(value
);
865 for (j
= k
; j
< i
; j
++)