LCOV - code coverage report
Current view: top level - basic - strv.c (source / functions) Hit Total Coverage
Test: main_coverage.info Lines: 399 496 80.4 %
Date: 2019-08-22 15:41:25 Functions: 45 48 93.8 %

          Line data    Source code
       1             : /* SPDX-License-Identifier: LGPL-2.1+ */
       2             : 
       3             : #include <errno.h>
       4             : #include <fnmatch.h>
       5             : #include <stdarg.h>
       6             : #include <stdio.h>
       7             : #include <stdlib.h>
       8             : #include <string.h>
       9             : 
      10             : #include "alloc-util.h"
      11             : #include "escape.h"
      12             : #include "extract-word.h"
      13             : #include "fileio.h"
      14             : #include "memory-util.h"
      15             : #include "nulstr-util.h"
      16             : #include "sort-util.h"
      17             : #include "string-util.h"
      18             : #include "strv.h"
      19             : 
      20      582645 : char *strv_find(char **l, const char *name) {
      21             :         char **i;
      22             : 
      23      582645 :         assert(name);
      24             : 
      25    10431683 :         STRV_FOREACH(i, l)
      26     9849837 :                 if (streq(*i, name))
      27         799 :                         return *i;
      28             : 
      29      581846 :         return NULL;
      30             : }
      31             : 
      32           5 : char *strv_find_prefix(char **l, const char *name) {
      33             :         char **i;
      34             : 
      35           5 :         assert(name);
      36             : 
      37          11 :         STRV_FOREACH(i, l)
      38           9 :                 if (startswith(*i, name))
      39           3 :                         return *i;
      40             : 
      41           2 :         return NULL;
      42             : }
      43             : 
      44           5 : char *strv_find_startswith(char **l, const char *name) {
      45             :         char **i, *e;
      46             : 
      47           5 :         assert(name);
      48             : 
      49             :         /* Like strv_find_prefix, but actually returns only the
      50             :          * suffix, not the whole item */
      51             : 
      52          11 :         STRV_FOREACH(i, l) {
      53           9 :                 e = startswith(*i, name);
      54           9 :                 if (e)
      55           3 :                         return e;
      56             :         }
      57             : 
      58           2 :         return NULL;
      59             : }
      60             : 
      61      118682 : void strv_clear(char **l) {
      62             :         char **k;
      63             : 
      64      118682 :         if (!l)
      65       24474 :                 return;
      66             : 
      67      219802 :         for (k = l; *k; k++)
      68      125594 :                 free(*k);
      69             : 
      70       94208 :         *l = NULL;
      71             : }
      72             : 
      73       30264 : char **strv_free(char **l) {
      74       30264 :         strv_clear(l);
      75       30264 :         return mfree(l);
      76             : }
      77             : 
      78           9 : char **strv_free_erase(char **l) {
      79             :         char **i;
      80             : 
      81          36 :         STRV_FOREACH(i, l)
      82          27 :                 erase_and_freep(i);
      83             : 
      84           9 :         return mfree(l);
      85             : }
      86             : 
      87         957 : char **strv_copy(char * const *l) {
      88             :         char **r, **k;
      89             : 
      90         957 :         k = r = new(char*, strv_length(l) + 1);
      91         957 :         if (!r)
      92           0 :                 return NULL;
      93             : 
      94         957 :         if (l)
      95       13886 :                 for (; *l; k++, l++) {
      96       12930 :                         *k = strdup(*l);
      97       12930 :                         if (!*k) {
      98           0 :                                 strv_free(r);
      99           0 :                                 return NULL;
     100             :                         }
     101             :                 }
     102             : 
     103         957 :         *k = NULL;
     104         957 :         return r;
     105             : }
     106             : 
     107      107414 : size_t strv_length(char * const *l) {
     108      107414 :         size_t n = 0;
     109             : 
     110      107414 :         if (!l)
     111        4303 :                 return 0;
     112             : 
     113      204280 :         for (; *l; l++)
     114      101169 :                 n++;
     115             : 
     116      103111 :         return n;
     117             : }
     118             : 
     119         332 : char **strv_new_ap(const char *x, va_list ap) {
     120             :         const char *s;
     121         332 :         _cleanup_strv_free_ char **a = NULL;
     122         332 :         size_t n = 0, i = 0;
     123             :         va_list aq;
     124             : 
     125             :         /* As a special trick we ignore all listed strings that equal
     126             :          * STRV_IGNORE. This is supposed to be used with the
     127             :          * STRV_IFNOTNULL() macro to include possibly NULL strings in
     128             :          * the string list. */
     129             : 
     130         332 :         if (x) {
     131         330 :                 n = x == STRV_IGNORE ? 0 : 1;
     132             : 
     133         330 :                 va_copy(aq, ap);
     134        4242 :                 while ((s = va_arg(aq, const char*))) {
     135        3912 :                         if (s == STRV_IGNORE)
     136         245 :                                 continue;
     137             : 
     138        3667 :                         n++;
     139             :                 }
     140             : 
     141         330 :                 va_end(aq);
     142             :         }
     143             : 
     144         332 :         a = new(char*, n+1);
     145         332 :         if (!a)
     146           0 :                 return NULL;
     147             : 
     148         332 :         if (x) {
     149         330 :                 if (x != STRV_IGNORE) {
     150         328 :                         a[i] = strdup(x);
     151         328 :                         if (!a[i])
     152           0 :                                 return NULL;
     153         328 :                         i++;
     154             :                 }
     155             : 
     156        4242 :                 while ((s = va_arg(ap, const char*))) {
     157             : 
     158        3912 :                         if (s == STRV_IGNORE)
     159         245 :                                 continue;
     160             : 
     161        3667 :                         a[i] = strdup(s);
     162        3667 :                         if (!a[i])
     163           0 :                                 return NULL;
     164             : 
     165        3667 :                         i++;
     166             :                 }
     167             :         }
     168             : 
     169         332 :         a[i] = NULL;
     170             : 
     171         332 :         return TAKE_PTR(a);
     172             : }
     173             : 
     174         328 : char **strv_new_internal(const char *x, ...) {
     175             :         char **r;
     176             :         va_list ap;
     177             : 
     178         328 :         va_start(ap, x);
     179         328 :         r = strv_new_ap(x, ap);
     180         328 :         va_end(ap);
     181             : 
     182         328 :         return r;
     183             : }
     184             : 
     185          16 : int strv_extend_strv(char ***a, char **b, bool filter_duplicates) {
     186             :         char **s, **t;
     187          16 :         size_t p, q, i = 0, j;
     188             : 
     189          16 :         assert(a);
     190             : 
     191          16 :         if (strv_isempty(b))
     192           2 :                 return 0;
     193             : 
     194          14 :         p = strv_length(*a);
     195          14 :         q = strv_length(b);
     196             : 
     197          14 :         t = reallocarray(*a, p + q + 1, sizeof(char *));
     198          14 :         if (!t)
     199           0 :                 return -ENOMEM;
     200             : 
     201          14 :         t[p] = NULL;
     202          14 :         *a = t;
     203             : 
     204          55 :         STRV_FOREACH(s, b) {
     205             : 
     206          41 :                 if (filter_duplicates && strv_contains(t, *s))
     207           1 :                         continue;
     208             : 
     209          40 :                 t[p+i] = strdup(*s);
     210          40 :                 if (!t[p+i])
     211           0 :                         goto rollback;
     212             : 
     213          40 :                 i++;
     214          40 :                 t[p+i] = NULL;
     215             :         }
     216             : 
     217          14 :         assert(i <= q);
     218             : 
     219          14 :         return (int) i;
     220             : 
     221           0 : rollback:
     222           0 :         for (j = 0; j < i; j++)
     223           0 :                 free(t[p + j]);
     224             : 
     225           0 :         t[p] = NULL;
     226           0 :         return -ENOMEM;
     227             : }
     228             : 
     229          92 : int strv_extend_strv_concat(char ***a, char **b, const char *suffix) {
     230             :         int r;
     231             :         char **s;
     232             : 
     233         278 :         STRV_FOREACH(s, b) {
     234             :                 char *v;
     235             : 
     236         186 :                 v = strjoin(*s, suffix);
     237         186 :                 if (!v)
     238           0 :                         return -ENOMEM;
     239             : 
     240         186 :                 r = strv_push(a, v);
     241         186 :                 if (r < 0) {
     242           0 :                         free(v);
     243           0 :                         return r;
     244             :                 }
     245             :         }
     246             : 
     247          92 :         return 0;
     248             : }
     249             : 
     250         184 : char **strv_split_full(const char *s, const char *separator, SplitFlags flags) {
     251             :         const char *word, *state;
     252             :         size_t l;
     253             :         size_t n, i;
     254             :         char **r;
     255             : 
     256         184 :         assert(s);
     257             : 
     258         184 :         if (!separator)
     259          14 :                 separator = WHITESPACE;
     260             : 
     261         184 :         s += strspn(s, separator);
     262         184 :         if (isempty(s))
     263          13 :                 return new0(char*, 1);
     264             : 
     265         171 :         n = 0;
     266         523 :         _FOREACH_WORD(word, l, s, separator, flags, state)
     267         352 :                 n++;
     268             : 
     269         171 :         r = new(char*, n+1);
     270         171 :         if (!r)
     271           0 :                 return NULL;
     272             : 
     273         171 :         i = 0;
     274         523 :         _FOREACH_WORD(word, l, s, separator, flags, state) {
     275         352 :                 r[i] = strndup(word, l);
     276         352 :                 if (!r[i]) {
     277           0 :                         strv_free(r);
     278           0 :                         return NULL;
     279             :                 }
     280             : 
     281         352 :                 i++;
     282             :         }
     283             : 
     284         171 :         r[i] = NULL;
     285         171 :         return r;
     286             : }
     287             : 
     288           8 : char **strv_split_newlines(const char *s) {
     289             :         char **l;
     290             :         size_t n;
     291             : 
     292           8 :         assert(s);
     293             : 
     294             :         /* Special version of strv_split() that splits on newlines and
     295             :          * suppresses an empty string at the end */
     296             : 
     297           8 :         l = strv_split(s, NEWLINE);
     298           8 :         if (!l)
     299           0 :                 return NULL;
     300             : 
     301           8 :         n = strv_length(l);
     302           8 :         if (n <= 0)
     303           0 :                 return l;
     304             : 
     305           8 :         if (isempty(l[n - 1]))
     306           0 :                 l[n - 1] = mfree(l[n - 1]);
     307             : 
     308           8 :         return l;
     309             : }
     310             : 
     311         746 : int strv_split_extract(char ***t, const char *s, const char *separators, ExtractFlags flags) {
     312         746 :         _cleanup_strv_free_ char **l = NULL;
     313         746 :         size_t n = 0, allocated = 0;
     314             :         int r;
     315             : 
     316         746 :         assert(t);
     317         746 :         assert(s);
     318             : 
     319        3523 :         for (;;) {
     320        4269 :                 _cleanup_free_ char *word = NULL;
     321             : 
     322        4269 :                 r = extract_first_word(&s, &word, separators, flags);
     323        4269 :                 if (r < 0)
     324           7 :                         return r;
     325        4262 :                 if (r == 0)
     326         739 :                         break;
     327             : 
     328        3523 :                 if (!GREEDY_REALLOC(l, allocated, n + 2))
     329           0 :                         return -ENOMEM;
     330             : 
     331        3523 :                 l[n++] = TAKE_PTR(word);
     332             : 
     333        3523 :                 l[n] = NULL;
     334             :         }
     335             : 
     336         739 :         if (!l) {
     337           3 :                 l = new0(char*, 1);
     338           3 :                 if (!l)
     339           0 :                         return -ENOMEM;
     340             :         }
     341             : 
     342         739 :         *t = TAKE_PTR(l);
     343             : 
     344         739 :         return (int) n;
     345             : }
     346             : 
     347         602 : char *strv_join_prefix(char **l, const char *separator, const char *prefix) {
     348             :         char *r, *e;
     349             :         char **s;
     350             :         size_t n, k, m;
     351             : 
     352         602 :         if (!separator)
     353           2 :                 separator = " ";
     354             : 
     355         602 :         k = strlen(separator);
     356         602 :         m = strlen_ptr(prefix);
     357             : 
     358         602 :         n = 0;
     359        1451 :         STRV_FOREACH(s, l) {
     360         849 :                 if (s != l)
     361         266 :                         n += k;
     362         849 :                 n += m + strlen(*s);
     363             :         }
     364             : 
     365         602 :         r = new(char, n+1);
     366         602 :         if (!r)
     367           0 :                 return NULL;
     368             : 
     369         602 :         e = r;
     370        1451 :         STRV_FOREACH(s, l) {
     371         849 :                 if (s != l)
     372         266 :                         e = stpcpy(e, separator);
     373             : 
     374         849 :                 if (prefix)
     375          13 :                         e = stpcpy(e, prefix);
     376             : 
     377         849 :                 e = stpcpy(e, *s);
     378             :         }
     379             : 
     380         602 :         *e = 0;
     381             : 
     382         602 :         return r;
     383             : }
     384             : 
     385      103093 : int strv_push(char ***l, char *value) {
     386             :         char **c;
     387             :         size_t n, m;
     388             : 
     389      103093 :         if (!value)
     390           0 :                 return 0;
     391             : 
     392      103093 :         n = strv_length(*l);
     393             : 
     394             :         /* Increase and check for overflow */
     395      103093 :         m = n + 2;
     396      103093 :         if (m < n)
     397           0 :                 return -ENOMEM;
     398             : 
     399      103093 :         c = reallocarray(*l, m, sizeof(char*));
     400      103093 :         if (!c)
     401           0 :                 return -ENOMEM;
     402             : 
     403      103093 :         c[n] = value;
     404      103093 :         c[n+1] = NULL;
     405             : 
     406      103093 :         *l = c;
     407      103093 :         return 0;
     408             : }
     409             : 
     410          12 : int strv_push_pair(char ***l, char *a, char *b) {
     411             :         char **c;
     412             :         size_t n, m;
     413             : 
     414          12 :         if (!a && !b)
     415           0 :                 return 0;
     416             : 
     417          12 :         n = strv_length(*l);
     418             : 
     419             :         /* increase and check for overflow */
     420          12 :         m = n + !!a + !!b + 1;
     421          12 :         if (m < n)
     422           0 :                 return -ENOMEM;
     423             : 
     424          12 :         c = reallocarray(*l, m, sizeof(char*));
     425          12 :         if (!c)
     426           0 :                 return -ENOMEM;
     427             : 
     428          12 :         if (a)
     429          12 :                 c[n++] = a;
     430          12 :         if (b)
     431          12 :                 c[n++] = b;
     432          12 :         c[n] = NULL;
     433             : 
     434          12 :         *l = c;
     435          12 :         return 0;
     436             : }
     437             : 
     438          19 : int strv_insert(char ***l, size_t position, char *value) {
     439             :         char **c;
     440             :         size_t n, m, i;
     441             : 
     442          19 :         if (!value)
     443           1 :                 return 0;
     444             : 
     445          18 :         n = strv_length(*l);
     446          18 :         position = MIN(position, n);
     447             : 
     448             :         /* increase and check for overflow */
     449          18 :         m = n + 2;
     450          18 :         if (m < n)
     451           0 :                 return -ENOMEM;
     452             : 
     453          18 :         c = new(char*, m);
     454          18 :         if (!c)
     455           0 :                 return -ENOMEM;
     456             : 
     457          34 :         for (i = 0; i < position; i++)
     458          16 :                 c[i] = (*l)[i];
     459          18 :         c[position] = value;
     460          33 :         for (i = position; i < n; i++)
     461          15 :                 c[i+1] = (*l)[i];
     462             : 
     463          18 :         c[n+1] = NULL;
     464             : 
     465          18 :         free(*l);
     466          18 :         *l = c;
     467             : 
     468          18 :         return 0;
     469             : }
     470             : 
     471      102748 : int strv_consume(char ***l, char *value) {
     472             :         int r;
     473             : 
     474      102748 :         r = strv_push(l, value);
     475      102748 :         if (r < 0)
     476           0 :                 free(value);
     477             : 
     478      102748 :         return r;
     479             : }
     480             : 
     481           0 : int strv_consume_pair(char ***l, char *a, char *b) {
     482             :         int r;
     483             : 
     484           0 :         r = strv_push_pair(l, a, b);
     485           0 :         if (r < 0) {
     486           0 :                 free(a);
     487           0 :                 free(b);
     488             :         }
     489             : 
     490           0 :         return r;
     491             : }
     492             : 
     493           1 : int strv_consume_prepend(char ***l, char *value) {
     494             :         int r;
     495             : 
     496           1 :         r = strv_push_prepend(l, value);
     497           1 :         if (r < 0)
     498           0 :                 free(value);
     499             : 
     500           1 :         return r;
     501             : }
     502             : 
     503        1683 : int strv_extend(char ***l, const char *value) {
     504             :         char *v;
     505             : 
     506        1683 :         if (!value)
     507           1 :                 return 0;
     508             : 
     509        1682 :         v = strdup(value);
     510        1682 :         if (!v)
     511           0 :                 return -ENOMEM;
     512             : 
     513        1682 :         return strv_consume(l, v);
     514             : }
     515             : 
     516           0 : int strv_extend_front(char ***l, const char *value) {
     517             :         size_t n, m;
     518             :         char *v, **c;
     519             : 
     520           0 :         assert(l);
     521             : 
     522             :         /* Like strv_extend(), but prepends rather than appends the new entry */
     523             : 
     524           0 :         if (!value)
     525           0 :                 return 0;
     526             : 
     527           0 :         n = strv_length(*l);
     528             : 
     529             :         /* Increase and overflow check. */
     530           0 :         m = n + 2;
     531           0 :         if (m < n)
     532           0 :                 return -ENOMEM;
     533             : 
     534           0 :         v = strdup(value);
     535           0 :         if (!v)
     536           0 :                 return -ENOMEM;
     537             : 
     538           0 :         c = reallocarray(*l, m, sizeof(char*));
     539           0 :         if (!c) {
     540           0 :                 free(v);
     541           0 :                 return -ENOMEM;
     542             :         }
     543             : 
     544           0 :         memmove(c+1, c, n * sizeof(char*));
     545           0 :         c[0] = v;
     546           0 :         c[n+1] = NULL;
     547             : 
     548           0 :         *l = c;
     549           0 :         return 0;
     550             : }
     551             : 
     552        1283 : char **strv_uniq(char **l) {
     553             :         char **i;
     554             : 
     555             :         /* Drops duplicate entries. The first identical string will be
     556             :          * kept, the others dropped */
     557             : 
     558       16271 :         STRV_FOREACH(i, l)
     559       14988 :                 strv_remove(i+1, *i);
     560             : 
     561        1283 :         return l;
     562             : }
     563             : 
     564           4 : bool strv_is_uniq(char **l) {
     565             :         char **i;
     566             : 
     567           8 :         STRV_FOREACH(i, l)
     568           5 :                 if (strv_find(i+1, *i))
     569           1 :                         return false;
     570             : 
     571           3 :         return true;
     572             : }
     573             : 
     574       14988 : char **strv_remove(char **l, const char *s) {
     575             :         char **f, **t;
     576             : 
     577       14988 :         if (!l)
     578           0 :                 return NULL;
     579             : 
     580       14988 :         assert(s);
     581             : 
     582             :         /* Drops every occurrence of s in the string list, edits
     583             :          * in-place. */
     584             : 
     585      114245 :         for (f = t = l; *f; f++)
     586       99257 :                 if (streq(*f, s))
     587         968 :                         free(*f);
     588             :                 else
     589       98289 :                         *(t++) = *f;
     590             : 
     591       14988 :         *t = NULL;
     592       14988 :         return l;
     593             : }
     594             : 
     595           9 : char **strv_parse_nulstr(const char *s, size_t l) {
     596             :         /* l is the length of the input data, which will be split at NULs into
     597             :          * elements of the resulting strv. Hence, the number of items in the resulting strv
     598             :          * will be equal to one plus the number of NUL bytes in the l bytes starting at s,
     599             :          * unless s[l-1] is NUL, in which case the final empty string is not stored in
     600             :          * the resulting strv, and length is equal to the number of NUL bytes.
     601             :          *
     602             :          * Note that contrary to a normal nulstr which cannot contain empty strings, because
     603             :          * the input data is terminated by any two consequent NUL bytes, this parser accepts
     604             :          * empty strings in s.
     605             :          */
     606             : 
     607             :         const char *p;
     608           9 :         size_t c = 0, i = 0;
     609             :         char **v;
     610             : 
     611           9 :         assert(s || l <= 0);
     612             : 
     613           9 :         if (l <= 0)
     614           2 :                 return new0(char*, 1);
     615             : 
     616         197 :         for (p = s; p < s + l; p++)
     617         190 :                 if (*p == 0)
     618          20 :                         c++;
     619             : 
     620           7 :         if (s[l-1] != 0)
     621           4 :                 c++;
     622             : 
     623           7 :         v = new0(char*, c+1);
     624           7 :         if (!v)
     625           0 :                 return NULL;
     626             : 
     627           7 :         p = s;
     628          27 :         while (p < s + l) {
     629             :                 const char *e;
     630             : 
     631          24 :                 e = memchr(p, 0, s + l - p);
     632             : 
     633          24 :                 v[i] = strndup(p, e ? e - p : s + l - p);
     634          24 :                 if (!v[i]) {
     635           0 :                         strv_free(v);
     636           0 :                         return NULL;
     637             :                 }
     638             : 
     639          24 :                 i++;
     640             : 
     641          24 :                 if (!e)
     642           4 :                         break;
     643             : 
     644          20 :                 p = e + 1;
     645             :         }
     646             : 
     647           7 :         assert(i == c);
     648             : 
     649           7 :         return v;
     650             : }
     651             : 
     652          59 : char **strv_split_nulstr(const char *s) {
     653             :         const char *i;
     654          59 :         char **r = NULL;
     655             : 
     656         289 :         NULSTR_FOREACH(i, s)
     657         230 :                 if (strv_extend(&r, i) < 0) {
     658           0 :                         strv_free(r);
     659           0 :                         return NULL;
     660             :                 }
     661             : 
     662          59 :         if (!r)
     663           0 :                 return strv_new(NULL);
     664             : 
     665          59 :         return r;
     666             : }
     667             : 
     668          10 : int strv_make_nulstr(char **l, char **p, size_t *q) {
     669             :         /* A valid nulstr with two NULs at the end will be created, but
     670             :          * q will be the length without the two trailing NULs. Thus the output
     671             :          * string is a valid nulstr and can be iterated over using NULSTR_FOREACH,
     672             :          * and can also be parsed by strv_parse_nulstr as long as the length
     673             :          * is provided separately.
     674             :          */
     675             : 
     676          10 :         size_t n_allocated = 0, n = 0;
     677          10 :         _cleanup_free_ char *m = NULL;
     678             :         char **i;
     679             : 
     680          10 :         assert(p);
     681          10 :         assert(q);
     682             : 
     683          22 :         STRV_FOREACH(i, l) {
     684             :                 size_t z;
     685             : 
     686          12 :                 z = strlen(*i);
     687             : 
     688          12 :                 if (!GREEDY_REALLOC(m, n_allocated, n + z + 2))
     689           0 :                         return -ENOMEM;
     690             : 
     691          12 :                 memcpy(m + n, *i, z + 1);
     692          12 :                 n += z + 1;
     693             :         }
     694             : 
     695          10 :         if (!m) {
     696           4 :                 m = new0(char, 1);
     697           4 :                 if (!m)
     698           0 :                         return -ENOMEM;
     699           4 :                 n = 1;
     700             :         } else
     701             :                 /* make sure there is a second extra NUL at the end of resulting nulstr */
     702           6 :                 m[n] = '\0';
     703             : 
     704          10 :         assert(n > 0);
     705          10 :         *p = m;
     706          10 :         *q = n - 1;
     707             : 
     708          10 :         m = NULL;
     709             : 
     710          10 :         return 0;
     711             : }
     712             : 
     713           2 : bool strv_overlap(char **a, char **b) {
     714             :         char **i;
     715             : 
     716           6 :         STRV_FOREACH(i, a)
     717           5 :                 if (strv_contains(b, *i))
     718           1 :                         return true;
     719             : 
     720           1 :         return false;
     721             : }
     722             : 
     723       13465 : static int str_compare(char * const *a, char * const *b) {
     724       13465 :         return strcmp(*a, *b);
     725             : }
     726             : 
     727          21 : char **strv_sort(char **l) {
     728          21 :         typesafe_qsort(l, strv_length(l), str_compare);
     729          21 :         return l;
     730             : }
     731             : 
     732        1274 : bool strv_equal(char **a, char **b) {
     733             : 
     734        1274 :         if (strv_isempty(a))
     735        1205 :                 return strv_isempty(b);
     736             : 
     737          69 :         if (strv_isempty(b))
     738           1 :                 return false;
     739             : 
     740         246 :         for ( ; *a || *b; ++a, ++b)
     741         180 :                 if (!streq_ptr(*a, *b))
     742           2 :                         return false;
     743             : 
     744          66 :         return true;
     745             : }
     746             : 
     747           5 : void strv_print(char **l) {
     748             :         char **s;
     749             : 
     750          22 :         STRV_FOREACH(s, l)
     751          17 :                 puts(*s);
     752           5 : }
     753             : 
     754           2 : int strv_extendf(char ***l, const char *format, ...) {
     755             :         va_list ap;
     756             :         char *x;
     757             :         int r;
     758             : 
     759           2 :         va_start(ap, format);
     760           2 :         r = vasprintf(&x, format, ap);
     761           2 :         va_end(ap);
     762             : 
     763           2 :         if (r < 0)
     764           0 :                 return -ENOMEM;
     765             : 
     766           2 :         return strv_consume(l, x);
     767             : }
     768             : 
     769           4 : char **strv_reverse(char **l) {
     770             :         size_t n, i;
     771             : 
     772           4 :         n = strv_length(l);
     773           4 :         if (n <= 1)
     774           2 :                 return l;
     775             : 
     776           4 :         for (i = 0; i < n / 2; i++)
     777           2 :                 SWAP_TWO(l[i], l[n-1-i]);
     778             : 
     779           2 :         return l;
     780             : }
     781             : 
     782           1 : char **strv_shell_escape(char **l, const char *bad) {
     783             :         char **s;
     784             : 
     785             :         /* Escapes every character in every string in l that is in bad,
     786             :          * edits in-place, does not roll-back on error. */
     787             : 
     788           4 :         STRV_FOREACH(s, l) {
     789             :                 char *v;
     790             : 
     791           3 :                 v = shell_escape(*s, bad);
     792           3 :                 if (!v)
     793           0 :                         return NULL;
     794             : 
     795           3 :                 free(*s);
     796           3 :                 *s = v;
     797             :         }
     798             : 
     799           1 :         return l;
     800             : }
     801             : 
     802           3 : bool strv_fnmatch(char* const* patterns, const char *s, int flags) {
     803             :         char* const* p;
     804             : 
     805           4 :         STRV_FOREACH(p, patterns)
     806           2 :                 if (fnmatch(*p, s, flags) == 0)
     807           1 :                         return true;
     808             : 
     809           2 :         return false;
     810             : }
     811             : 
     812           1 : char ***strv_free_free(char ***l) {
     813             :         char ***i;
     814             : 
     815           1 :         if (!l)
     816           0 :                 return NULL;
     817             : 
     818           3 :         for (i = l; *i; i++)
     819           2 :                 strv_free(*i);
     820             : 
     821           1 :         return mfree(l);
     822             : }
     823             : 
     824          13 : char **strv_skip(char **l, size_t n) {
     825             : 
     826          28 :         while (n > 0) {
     827          20 :                 if (strv_isempty(l))
     828           5 :                         return l;
     829             : 
     830          15 :                 l++, n--;
     831             :         }
     832             : 
     833           8 :         return l;
     834             : }
     835             : 
     836           4 : int strv_extend_n(char ***l, const char *value, size_t n) {
     837             :         size_t i, j, k;
     838             :         char **nl;
     839             : 
     840           4 :         assert(l);
     841             : 
     842           4 :         if (!value)
     843           0 :                 return 0;
     844           4 :         if (n == 0)
     845           1 :                 return 0;
     846             : 
     847             :         /* Adds the value n times to l */
     848             : 
     849           3 :         k = strv_length(*l);
     850             : 
     851           3 :         nl = reallocarray(*l, k + n + 1, sizeof(char *));
     852           3 :         if (!nl)
     853           0 :                 return -ENOMEM;
     854             : 
     855           3 :         *l = nl;
     856             : 
     857           9 :         for (i = k; i < k + n; i++) {
     858           6 :                 nl[i] = strdup(value);
     859           6 :                 if (!nl[i])
     860           0 :                         goto rollback;
     861             :         }
     862             : 
     863           3 :         nl[i] = NULL;
     864           3 :         return 0;
     865             : 
     866           0 : rollback:
     867           0 :         for (j = k; j < i; j++)
     868           0 :                 free(nl[j]);
     869             : 
     870           0 :         nl[k] = NULL;
     871           0 :         return -ENOMEM;
     872             : }
     873             : 
     874           0 : int fputstrv(FILE *f, char **l, const char *separator, bool *space) {
     875           0 :         bool b = false;
     876             :         char **s;
     877             :         int r;
     878             : 
     879             :         /* Like fputs(), but for strv, and with a less stupid argument order */
     880             : 
     881           0 :         if (!space)
     882           0 :                 space = &b;
     883             : 
     884           0 :         STRV_FOREACH(s, l) {
     885           0 :                 r = fputs_with_space(f, *s, separator, space);
     886           0 :                 if (r < 0)
     887           0 :                         return r;
     888             :         }
     889             : 
     890           0 :         return 0;
     891             : }
     892             : 
     893         844 : static int string_strv_hashmap_put_internal(Hashmap *h, const char *key, const char *value) {
     894             :         char **l;
     895             :         int r;
     896             : 
     897         844 :         l = hashmap_get(h, key);
     898         844 :         if (l) {
     899             :                 /* A list for this key already exists, let's append to it if it is not listed yet */
     900          98 :                 if (strv_contains(l, value))
     901          12 :                         return 0;
     902             : 
     903          86 :                 r = strv_extend(&l, value);
     904          86 :                 if (r < 0)
     905           0 :                         return r;
     906             : 
     907          86 :                 assert_se(hashmap_update(h, key, l) >= 0);
     908             :         } else {
     909             :                 /* No list for this key exists yet, create one */
     910         746 :                 _cleanup_strv_free_ char **l2 = NULL;
     911         746 :                 _cleanup_free_ char *t = NULL;
     912             : 
     913         746 :                 t = strdup(key);
     914         746 :                 if (!t)
     915           0 :                         return -ENOMEM;
     916             : 
     917         746 :                 r = strv_extend(&l2, value);
     918         746 :                 if (r < 0)
     919           0 :                         return r;
     920             : 
     921         746 :                 r = hashmap_put(h, t, l2);
     922         746 :                 if (r < 0)
     923           0 :                         return r;
     924         746 :                 TAKE_PTR(t);
     925         746 :                 TAKE_PTR(l2);
     926             :         }
     927             : 
     928         832 :         return 1;
     929             : }
     930             : 
     931         834 : int string_strv_hashmap_put(Hashmap **h, const char *key, const char *value) {
     932             :         int r;
     933             : 
     934         834 :         r = hashmap_ensure_allocated(h, &string_strv_hash_ops);
     935         834 :         if (r < 0)
     936           0 :                 return r;
     937             : 
     938         834 :         return string_strv_hashmap_put_internal(*h, key, value);
     939             : }
     940             : 
     941          10 : int string_strv_ordered_hashmap_put(OrderedHashmap **h, const char *key, const char *value) {
     942             :         int r;
     943             : 
     944          10 :         r = ordered_hashmap_ensure_allocated(h, &string_strv_hash_ops);
     945          10 :         if (r < 0)
     946           0 :                 return r;
     947             : 
     948          10 :         return string_strv_hashmap_put_internal(PLAIN_HASHMAP(*h), key, value);
     949             : }
     950             : 
     951        1492 : DEFINE_HASH_OPS_FULL(string_strv_hash_ops, char, string_hash_func, string_compare_func, free, char*, strv_free);

Generated by: LCOV version 1.14