LCOV - code coverage report
Current view: top level - basic - strv.c (source / functions) Hit Total Coverage
Test: systemd_full.info Lines: 399 496 80.4 %
Date: 2019-08-23 13:36:53 Functions: 45 48 93.8 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 248 355 69.9 %

           Branch data     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                 :    2330779 : char *strv_find(char **l, const char *name) {
      21                 :            :         char **i;
      22                 :            : 
      23         [ -  + ]:    2330779 :         assert(name);
      24                 :            : 
      25   [ +  +  +  + ]:   41730576 :         STRV_FOREACH(i, l)
      26         [ +  + ]:   39402981 :                 if (streq(*i, name))
      27                 :       3184 :                         return *i;
      28                 :            : 
      29                 :    2327595 :         return NULL;
      30                 :            : }
      31                 :            : 
      32                 :         20 : char *strv_find_prefix(char **l, const char *name) {
      33                 :            :         char **i;
      34                 :            : 
      35         [ -  + ]:         20 :         assert(name);
      36                 :            : 
      37   [ +  -  +  + ]:         44 :         STRV_FOREACH(i, l)
      38         [ +  + ]:         36 :                 if (startswith(*i, name))
      39                 :         12 :                         return *i;
      40                 :            : 
      41                 :          8 :         return NULL;
      42                 :            : }
      43                 :            : 
      44                 :         20 : char *strv_find_startswith(char **l, const char *name) {
      45                 :            :         char **i, *e;
      46                 :            : 
      47         [ -  + ]:         20 :         assert(name);
      48                 :            : 
      49                 :            :         /* Like strv_find_prefix, but actually returns only the
      50                 :            :          * suffix, not the whole item */
      51                 :            : 
      52   [ +  -  +  + ]:         44 :         STRV_FOREACH(i, l) {
      53                 :         36 :                 e = startswith(*i, name);
      54         [ +  + ]:         36 :                 if (e)
      55                 :         12 :                         return e;
      56                 :            :         }
      57                 :            : 
      58                 :          8 :         return NULL;
      59                 :            : }
      60                 :            : 
      61                 :     475123 : void strv_clear(char **l) {
      62                 :            :         char **k;
      63                 :            : 
      64         [ +  + ]:     475123 :         if (!l)
      65                 :      98293 :                 return;
      66                 :            : 
      67         [ +  + ]:     879505 :         for (k = l; *k; k++)
      68                 :     502675 :                 free(*k);
      69                 :            : 
      70                 :     376830 :         *l = NULL;
      71                 :            : }
      72                 :            : 
      73                 :     121451 : char **strv_free(char **l) {
      74                 :     121451 :         strv_clear(l);
      75                 :     121451 :         return mfree(l);
      76                 :            : }
      77                 :            : 
      78                 :         36 : char **strv_free_erase(char **l) {
      79                 :            :         char **i;
      80                 :            : 
      81   [ +  -  +  + ]:        144 :         STRV_FOREACH(i, l)
      82                 :        108 :                 erase_and_freep(i);
      83                 :            : 
      84                 :         36 :         return mfree(l);
      85                 :            : }
      86                 :            : 
      87                 :       3828 : char **strv_copy(char * const *l) {
      88                 :            :         char **r, **k;
      89                 :            : 
      90                 :       3828 :         k = r = new(char*, strv_length(l) + 1);
      91         [ -  + ]:       3828 :         if (!r)
      92                 :          0 :                 return NULL;
      93                 :            : 
      94         [ +  + ]:       3828 :         if (l)
      95         [ +  + ]:      55544 :                 for (; *l; k++, l++) {
      96                 :      51720 :                         *k = strdup(*l);
      97         [ -  + ]:      51720 :                         if (!*k) {
      98                 :          0 :                                 strv_free(r);
      99                 :          0 :                                 return NULL;
     100                 :            :                         }
     101                 :            :                 }
     102                 :            : 
     103                 :       3828 :         *k = NULL;
     104                 :       3828 :         return r;
     105                 :            : }
     106                 :            : 
     107                 :     429655 : size_t strv_length(char * const *l) {
     108                 :     429655 :         size_t n = 0;
     109                 :            : 
     110         [ +  + ]:     429655 :         if (!l)
     111                 :      17212 :                 return 0;
     112                 :            : 
     113         [ +  + ]:     817115 :         for (; *l; l++)
     114                 :     404672 :                 n++;
     115                 :            : 
     116                 :     412443 :         return n;
     117                 :            : }
     118                 :            : 
     119                 :       1328 : char **strv_new_ap(const char *x, va_list ap) {
     120                 :            :         const char *s;
     121                 :       1328 :         _cleanup_strv_free_ char **a = NULL;
     122                 :       1328 :         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         [ +  + ]:       1328 :         if (x) {
     131                 :       1320 :                 n = x == STRV_IGNORE ? 0 : 1;
     132                 :            : 
     133                 :       1320 :                 va_copy(aq, ap);
     134         [ +  + ]:      16968 :                 while ((s = va_arg(aq, const char*))) {
     135         [ +  + ]:      15648 :                         if (s == STRV_IGNORE)
     136                 :        980 :                                 continue;
     137                 :            : 
     138                 :      14668 :                         n++;
     139                 :            :                 }
     140                 :            : 
     141                 :       1320 :                 va_end(aq);
     142                 :            :         }
     143                 :            : 
     144                 :       1328 :         a = new(char*, n+1);
     145         [ -  + ]:       1328 :         if (!a)
     146                 :          0 :                 return NULL;
     147                 :            : 
     148         [ +  + ]:       1328 :         if (x) {
     149         [ +  + ]:       1320 :                 if (x != STRV_IGNORE) {
     150                 :       1312 :                         a[i] = strdup(x);
     151         [ -  + ]:       1312 :                         if (!a[i])
     152                 :          0 :                                 return NULL;
     153                 :       1312 :                         i++;
     154                 :            :                 }
     155                 :            : 
     156         [ +  + ]:      16968 :                 while ((s = va_arg(ap, const char*))) {
     157                 :            : 
     158         [ +  + ]:      15648 :                         if (s == STRV_IGNORE)
     159                 :        980 :                                 continue;
     160                 :            : 
     161                 :      14668 :                         a[i] = strdup(s);
     162         [ -  + ]:      14668 :                         if (!a[i])
     163                 :          0 :                                 return NULL;
     164                 :            : 
     165                 :      14668 :                         i++;
     166                 :            :                 }
     167                 :            :         }
     168                 :            : 
     169                 :       1328 :         a[i] = NULL;
     170                 :            : 
     171                 :       1328 :         return TAKE_PTR(a);
     172                 :            : }
     173                 :            : 
     174                 :       1312 : char **strv_new_internal(const char *x, ...) {
     175                 :            :         char **r;
     176                 :            :         va_list ap;
     177                 :            : 
     178                 :       1312 :         va_start(ap, x);
     179                 :       1312 :         r = strv_new_ap(x, ap);
     180                 :       1312 :         va_end(ap);
     181                 :            : 
     182                 :       1312 :         return r;
     183                 :            : }
     184                 :            : 
     185                 :         64 : int strv_extend_strv(char ***a, char **b, bool filter_duplicates) {
     186                 :            :         char **s, **t;
     187                 :         64 :         size_t p, q, i = 0, j;
     188                 :            : 
     189         [ -  + ]:         64 :         assert(a);
     190                 :            : 
     191         [ +  + ]:         64 :         if (strv_isempty(b))
     192                 :          8 :                 return 0;
     193                 :            : 
     194                 :         56 :         p = strv_length(*a);
     195                 :         56 :         q = strv_length(b);
     196                 :            : 
     197                 :         56 :         t = reallocarray(*a, p + q + 1, sizeof(char *));
     198         [ -  + ]:         56 :         if (!t)
     199                 :          0 :                 return -ENOMEM;
     200                 :            : 
     201                 :         56 :         t[p] = NULL;
     202                 :         56 :         *a = t;
     203                 :            : 
     204   [ +  -  +  + ]:        220 :         STRV_FOREACH(s, b) {
     205                 :            : 
     206   [ +  +  +  + ]:        164 :                 if (filter_duplicates && strv_contains(t, *s))
     207                 :          4 :                         continue;
     208                 :            : 
     209                 :        160 :                 t[p+i] = strdup(*s);
     210         [ -  + ]:        160 :                 if (!t[p+i])
     211                 :          0 :                         goto rollback;
     212                 :            : 
     213                 :        160 :                 i++;
     214                 :        160 :                 t[p+i] = NULL;
     215                 :            :         }
     216                 :            : 
     217         [ -  + ]:         56 :         assert(i <= q);
     218                 :            : 
     219                 :         56 :         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                 :        368 : int strv_extend_strv_concat(char ***a, char **b, const char *suffix) {
     230                 :            :         int r;
     231                 :            :         char **s;
     232                 :            : 
     233   [ +  +  +  + ]:       1112 :         STRV_FOREACH(s, b) {
     234                 :            :                 char *v;
     235                 :            : 
     236                 :        744 :                 v = strjoin(*s, suffix);
     237         [ -  + ]:        744 :                 if (!v)
     238                 :          0 :                         return -ENOMEM;
     239                 :            : 
     240                 :        744 :                 r = strv_push(a, v);
     241         [ -  + ]:        744 :                 if (r < 0) {
     242                 :          0 :                         free(v);
     243                 :          0 :                         return r;
     244                 :            :                 }
     245                 :            :         }
     246                 :            : 
     247                 :        368 :         return 0;
     248                 :            : }
     249                 :            : 
     250                 :        736 : 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         [ -  + ]:        736 :         assert(s);
     257                 :            : 
     258         [ +  + ]:        736 :         if (!separator)
     259                 :         56 :                 separator = WHITESPACE;
     260                 :            : 
     261                 :        736 :         s += strspn(s, separator);
     262         [ +  + ]:        736 :         if (isempty(s))
     263                 :         52 :                 return new0(char*, 1);
     264                 :            : 
     265                 :        684 :         n = 0;
     266         [ +  + ]:       2092 :         _FOREACH_WORD(word, l, s, separator, flags, state)
     267                 :       1408 :                 n++;
     268                 :            : 
     269                 :        684 :         r = new(char*, n+1);
     270         [ -  + ]:        684 :         if (!r)
     271                 :          0 :                 return NULL;
     272                 :            : 
     273                 :        684 :         i = 0;
     274         [ +  + ]:       2092 :         _FOREACH_WORD(word, l, s, separator, flags, state) {
     275                 :       1408 :                 r[i] = strndup(word, l);
     276         [ -  + ]:       1408 :                 if (!r[i]) {
     277                 :          0 :                         strv_free(r);
     278                 :          0 :                         return NULL;
     279                 :            :                 }
     280                 :            : 
     281                 :       1408 :                 i++;
     282                 :            :         }
     283                 :            : 
     284                 :        684 :         r[i] = NULL;
     285                 :        684 :         return r;
     286                 :            : }
     287                 :            : 
     288                 :         32 : char **strv_split_newlines(const char *s) {
     289                 :            :         char **l;
     290                 :            :         size_t n;
     291                 :            : 
     292         [ -  + ]:         32 :         assert(s);
     293                 :            : 
     294                 :            :         /* Special version of strv_split() that splits on newlines and
     295                 :            :          * suppresses an empty string at the end */
     296                 :            : 
     297                 :         32 :         l = strv_split(s, NEWLINE);
     298         [ -  + ]:         32 :         if (!l)
     299                 :          0 :                 return NULL;
     300                 :            : 
     301                 :         32 :         n = strv_length(l);
     302         [ -  + ]:         32 :         if (n <= 0)
     303                 :          0 :                 return l;
     304                 :            : 
     305         [ -  + ]:         32 :         if (isempty(l[n - 1]))
     306                 :          0 :                 l[n - 1] = mfree(l[n - 1]);
     307                 :            : 
     308                 :         32 :         return l;
     309                 :            : }
     310                 :            : 
     311                 :       2984 : int strv_split_extract(char ***t, const char *s, const char *separators, ExtractFlags flags) {
     312                 :       2984 :         _cleanup_strv_free_ char **l = NULL;
     313                 :       2984 :         size_t n = 0, allocated = 0;
     314                 :            :         int r;
     315                 :            : 
     316         [ -  + ]:       2984 :         assert(t);
     317         [ -  + ]:       2984 :         assert(s);
     318                 :            : 
     319                 :      14092 :         for (;;) {
     320      [ +  +  + ]:      17076 :                 _cleanup_free_ char *word = NULL;
     321                 :            : 
     322                 :      17076 :                 r = extract_first_word(&s, &word, separators, flags);
     323         [ +  + ]:      17076 :                 if (r < 0)
     324                 :         28 :                         return r;
     325         [ +  + ]:      17048 :                 if (r == 0)
     326                 :       2956 :                         break;
     327                 :            : 
     328         [ -  + ]:      14092 :                 if (!GREEDY_REALLOC(l, allocated, n + 2))
     329                 :          0 :                         return -ENOMEM;
     330                 :            : 
     331                 :      14092 :                 l[n++] = TAKE_PTR(word);
     332                 :            : 
     333                 :      14092 :                 l[n] = NULL;
     334                 :            :         }
     335                 :            : 
     336         [ +  + ]:       2956 :         if (!l) {
     337                 :         12 :                 l = new0(char*, 1);
     338         [ -  + ]:         12 :                 if (!l)
     339                 :          0 :                         return -ENOMEM;
     340                 :            :         }
     341                 :            : 
     342                 :       2956 :         *t = TAKE_PTR(l);
     343                 :            : 
     344                 :       2956 :         return (int) n;
     345                 :            : }
     346                 :            : 
     347                 :       2408 : 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         [ +  + ]:       2408 :         if (!separator)
     353                 :          8 :                 separator = " ";
     354                 :            : 
     355                 :       2408 :         k = strlen(separator);
     356                 :       2408 :         m = strlen_ptr(prefix);
     357                 :            : 
     358                 :       2408 :         n = 0;
     359   [ +  +  +  + ]:       5804 :         STRV_FOREACH(s, l) {
     360         [ +  + ]:       3396 :                 if (s != l)
     361                 :       1064 :                         n += k;
     362                 :       3396 :                 n += m + strlen(*s);
     363                 :            :         }
     364                 :            : 
     365                 :       2408 :         r = new(char, n+1);
     366         [ -  + ]:       2408 :         if (!r)
     367                 :          0 :                 return NULL;
     368                 :            : 
     369                 :       2408 :         e = r;
     370   [ +  +  +  + ]:       5804 :         STRV_FOREACH(s, l) {
     371         [ +  + ]:       3396 :                 if (s != l)
     372                 :       1064 :                         e = stpcpy(e, separator);
     373                 :            : 
     374         [ +  + ]:       3396 :                 if (prefix)
     375                 :         52 :                         e = stpcpy(e, prefix);
     376                 :            : 
     377                 :       3396 :                 e = stpcpy(e, *s);
     378                 :            :         }
     379                 :            : 
     380                 :       2408 :         *e = 0;
     381                 :            : 
     382                 :       2408 :         return r;
     383                 :            : }
     384                 :            : 
     385                 :     412372 : int strv_push(char ***l, char *value) {
     386                 :            :         char **c;
     387                 :            :         size_t n, m;
     388                 :            : 
     389         [ -  + ]:     412372 :         if (!value)
     390                 :          0 :                 return 0;
     391                 :            : 
     392                 :     412372 :         n = strv_length(*l);
     393                 :            : 
     394                 :            :         /* Increase and check for overflow */
     395                 :     412372 :         m = n + 2;
     396         [ -  + ]:     412372 :         if (m < n)
     397                 :          0 :                 return -ENOMEM;
     398                 :            : 
     399                 :     412372 :         c = reallocarray(*l, m, sizeof(char*));
     400         [ -  + ]:     412372 :         if (!c)
     401                 :          0 :                 return -ENOMEM;
     402                 :            : 
     403                 :     412372 :         c[n] = value;
     404                 :     412372 :         c[n+1] = NULL;
     405                 :            : 
     406                 :     412372 :         *l = c;
     407                 :     412372 :         return 0;
     408                 :            : }
     409                 :            : 
     410                 :         48 : int strv_push_pair(char ***l, char *a, char *b) {
     411                 :            :         char **c;
     412                 :            :         size_t n, m;
     413                 :            : 
     414   [ -  +  #  # ]:         48 :         if (!a && !b)
     415                 :          0 :                 return 0;
     416                 :            : 
     417                 :         48 :         n = strv_length(*l);
     418                 :            : 
     419                 :            :         /* increase and check for overflow */
     420                 :         48 :         m = n + !!a + !!b + 1;
     421         [ -  + ]:         48 :         if (m < n)
     422                 :          0 :                 return -ENOMEM;
     423                 :            : 
     424                 :         48 :         c = reallocarray(*l, m, sizeof(char*));
     425         [ -  + ]:         48 :         if (!c)
     426                 :          0 :                 return -ENOMEM;
     427                 :            : 
     428         [ +  - ]:         48 :         if (a)
     429                 :         48 :                 c[n++] = a;
     430         [ +  - ]:         48 :         if (b)
     431                 :         48 :                 c[n++] = b;
     432                 :         48 :         c[n] = NULL;
     433                 :            : 
     434                 :         48 :         *l = c;
     435                 :         48 :         return 0;
     436                 :            : }
     437                 :            : 
     438                 :         76 : int strv_insert(char ***l, size_t position, char *value) {
     439                 :            :         char **c;
     440                 :            :         size_t n, m, i;
     441                 :            : 
     442         [ +  + ]:         76 :         if (!value)
     443                 :          4 :                 return 0;
     444                 :            : 
     445                 :         72 :         n = strv_length(*l);
     446                 :         72 :         position = MIN(position, n);
     447                 :            : 
     448                 :            :         /* increase and check for overflow */
     449                 :         72 :         m = n + 2;
     450         [ -  + ]:         72 :         if (m < n)
     451                 :          0 :                 return -ENOMEM;
     452                 :            : 
     453                 :         72 :         c = new(char*, m);
     454         [ -  + ]:         72 :         if (!c)
     455                 :          0 :                 return -ENOMEM;
     456                 :            : 
     457         [ +  + ]:        136 :         for (i = 0; i < position; i++)
     458                 :         64 :                 c[i] = (*l)[i];
     459                 :         72 :         c[position] = value;
     460         [ +  + ]:        132 :         for (i = position; i < n; i++)
     461                 :         60 :                 c[i+1] = (*l)[i];
     462                 :            : 
     463                 :         72 :         c[n+1] = NULL;
     464                 :            : 
     465                 :         72 :         free(*l);
     466                 :         72 :         *l = c;
     467                 :            : 
     468                 :         72 :         return 0;
     469                 :            : }
     470                 :            : 
     471                 :     410992 : int strv_consume(char ***l, char *value) {
     472                 :            :         int r;
     473                 :            : 
     474                 :     410992 :         r = strv_push(l, value);
     475         [ -  + ]:     410992 :         if (r < 0)
     476                 :          0 :                 free(value);
     477                 :            : 
     478                 :     410992 :         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                 :          4 : int strv_consume_prepend(char ***l, char *value) {
     494                 :            :         int r;
     495                 :            : 
     496                 :          4 :         r = strv_push_prepend(l, value);
     497         [ -  + ]:          4 :         if (r < 0)
     498                 :          0 :                 free(value);
     499                 :            : 
     500                 :          4 :         return r;
     501                 :            : }
     502                 :            : 
     503                 :       6732 : int strv_extend(char ***l, const char *value) {
     504                 :            :         char *v;
     505                 :            : 
     506         [ +  + ]:       6732 :         if (!value)
     507                 :          4 :                 return 0;
     508                 :            : 
     509                 :       6728 :         v = strdup(value);
     510         [ -  + ]:       6728 :         if (!v)
     511                 :          0 :                 return -ENOMEM;
     512                 :            : 
     513                 :       6728 :         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                 :       5132 : 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   [ +  +  +  + ]:      65084 :         STRV_FOREACH(i, l)
     559                 :      59952 :                 strv_remove(i+1, *i);
     560                 :            : 
     561                 :       5132 :         return l;
     562                 :            : }
     563                 :            : 
     564                 :         16 : bool strv_is_uniq(char **l) {
     565                 :            :         char **i;
     566                 :            : 
     567   [ +  -  +  + ]:         32 :         STRV_FOREACH(i, l)
     568         [ +  + ]:         20 :                 if (strv_find(i+1, *i))
     569                 :          4 :                         return false;
     570                 :            : 
     571                 :         12 :         return true;
     572                 :            : }
     573                 :            : 
     574                 :      59952 : char **strv_remove(char **l, const char *s) {
     575                 :            :         char **f, **t;
     576                 :            : 
     577         [ -  + ]:      59952 :         if (!l)
     578                 :          0 :                 return NULL;
     579                 :            : 
     580         [ -  + ]:      59952 :         assert(s);
     581                 :            : 
     582                 :            :         /* Drops every occurrence of s in the string list, edits
     583                 :            :          * in-place. */
     584                 :            : 
     585         [ +  + ]:     456980 :         for (f = t = l; *f; f++)
     586         [ +  + ]:     397028 :                 if (streq(*f, s))
     587                 :       3872 :                         free(*f);
     588                 :            :                 else
     589                 :     393156 :                         *(t++) = *f;
     590                 :            : 
     591                 :      59952 :         *t = NULL;
     592                 :      59952 :         return l;
     593                 :            : }
     594                 :            : 
     595                 :         36 : 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                 :         36 :         size_t c = 0, i = 0;
     609                 :            :         char **v;
     610                 :            : 
     611   [ -  +  #  # ]:         36 :         assert(s || l <= 0);
     612                 :            : 
     613         [ +  + ]:         36 :         if (l <= 0)
     614                 :          8 :                 return new0(char*, 1);
     615                 :            : 
     616         [ +  + ]:        788 :         for (p = s; p < s + l; p++)
     617         [ +  + ]:        760 :                 if (*p == 0)
     618                 :         80 :                         c++;
     619                 :            : 
     620         [ +  + ]:         28 :         if (s[l-1] != 0)
     621                 :         16 :                 c++;
     622                 :            : 
     623         [ +  - ]:         28 :         v = new0(char*, c+1);
     624         [ -  + ]:         28 :         if (!v)
     625                 :          0 :                 return NULL;
     626                 :            : 
     627                 :         28 :         p = s;
     628         [ +  + ]:        108 :         while (p < s + l) {
     629                 :            :                 const char *e;
     630                 :            : 
     631                 :         96 :                 e = memchr(p, 0, s + l - p);
     632                 :            : 
     633         [ +  + ]:         96 :                 v[i] = strndup(p, e ? e - p : s + l - p);
     634         [ -  + ]:         96 :                 if (!v[i]) {
     635                 :          0 :                         strv_free(v);
     636                 :          0 :                         return NULL;
     637                 :            :                 }
     638                 :            : 
     639                 :         96 :                 i++;
     640                 :            : 
     641         [ +  + ]:         96 :                 if (!e)
     642                 :         16 :                         break;
     643                 :            : 
     644                 :         80 :                 p = e + 1;
     645                 :            :         }
     646                 :            : 
     647         [ -  + ]:         28 :         assert(i == c);
     648                 :            : 
     649                 :         28 :         return v;
     650                 :            : }
     651                 :            : 
     652                 :        236 : char **strv_split_nulstr(const char *s) {
     653                 :            :         const char *i;
     654                 :        236 :         char **r = NULL;
     655                 :            : 
     656   [ +  -  +  + ]:       1156 :         NULSTR_FOREACH(i, s)
     657         [ -  + ]:        920 :                 if (strv_extend(&r, i) < 0) {
     658                 :          0 :                         strv_free(r);
     659                 :          0 :                         return NULL;
     660                 :            :                 }
     661                 :            : 
     662         [ -  + ]:        236 :         if (!r)
     663                 :          0 :                 return strv_new(NULL);
     664                 :            : 
     665                 :        236 :         return r;
     666                 :            : }
     667                 :            : 
     668                 :         40 : 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                 :         40 :         size_t n_allocated = 0, n = 0;
     677                 :         40 :         _cleanup_free_ char *m = NULL;
     678                 :            :         char **i;
     679                 :            : 
     680         [ -  + ]:         40 :         assert(p);
     681         [ -  + ]:         40 :         assert(q);
     682                 :            : 
     683   [ +  +  +  + ]:         88 :         STRV_FOREACH(i, l) {
     684                 :            :                 size_t z;
     685                 :            : 
     686                 :         48 :                 z = strlen(*i);
     687                 :            : 
     688         [ -  + ]:         48 :                 if (!GREEDY_REALLOC(m, n_allocated, n + z + 2))
     689                 :          0 :                         return -ENOMEM;
     690                 :            : 
     691                 :         48 :                 memcpy(m + n, *i, z + 1);
     692                 :         48 :                 n += z + 1;
     693                 :            :         }
     694                 :            : 
     695         [ +  + ]:         40 :         if (!m) {
     696                 :         16 :                 m = new0(char, 1);
     697         [ -  + ]:         16 :                 if (!m)
     698                 :          0 :                         return -ENOMEM;
     699                 :         16 :                 n = 1;
     700                 :            :         } else
     701                 :            :                 /* make sure there is a second extra NUL at the end of resulting nulstr */
     702                 :         24 :                 m[n] = '\0';
     703                 :            : 
     704         [ -  + ]:         40 :         assert(n > 0);
     705                 :         40 :         *p = m;
     706                 :         40 :         *q = n - 1;
     707                 :            : 
     708                 :         40 :         m = NULL;
     709                 :            : 
     710                 :         40 :         return 0;
     711                 :            : }
     712                 :            : 
     713                 :          8 : bool strv_overlap(char **a, char **b) {
     714                 :            :         char **i;
     715                 :            : 
     716   [ +  -  +  + ]:         24 :         STRV_FOREACH(i, a)
     717         [ +  + ]:         20 :                 if (strv_contains(b, *i))
     718                 :          4 :                         return true;
     719                 :            : 
     720                 :          4 :         return false;
     721                 :            : }
     722                 :            : 
     723                 :      54096 : static int str_compare(char * const *a, char * const *b) {
     724                 :      54096 :         return strcmp(*a, *b);
     725                 :            : }
     726                 :            : 
     727                 :         83 : char **strv_sort(char **l) {
     728                 :         83 :         typesafe_qsort(l, strv_length(l), str_compare);
     729                 :         83 :         return l;
     730                 :            : }
     731                 :            : 
     732                 :       5140 : bool strv_equal(char **a, char **b) {
     733                 :            : 
     734         [ +  + ]:       5140 :         if (strv_isempty(a))
     735                 :       4868 :                 return strv_isempty(b);
     736                 :            : 
     737         [ +  + ]:        272 :         if (strv_isempty(b))
     738                 :          4 :                 return false;
     739                 :            : 
     740   [ +  +  +  + ]:        972 :         for ( ; *a || *b; ++a, ++b)
     741         [ +  + ]:        712 :                 if (!streq_ptr(*a, *b))
     742                 :          8 :                         return false;
     743                 :            : 
     744                 :        260 :         return true;
     745                 :            : }
     746                 :            : 
     747                 :         20 : void strv_print(char **l) {
     748                 :            :         char **s;
     749                 :            : 
     750   [ +  -  +  + ]:         88 :         STRV_FOREACH(s, l)
     751                 :         68 :                 puts(*s);
     752                 :         20 : }
     753                 :            : 
     754                 :          8 : int strv_extendf(char ***l, const char *format, ...) {
     755                 :            :         va_list ap;
     756                 :            :         char *x;
     757                 :            :         int r;
     758                 :            : 
     759                 :          8 :         va_start(ap, format);
     760                 :          8 :         r = vasprintf(&x, format, ap);
     761                 :          8 :         va_end(ap);
     762                 :            : 
     763         [ -  + ]:          8 :         if (r < 0)
     764                 :          0 :                 return -ENOMEM;
     765                 :            : 
     766                 :          8 :         return strv_consume(l, x);
     767                 :            : }
     768                 :            : 
     769                 :         16 : char **strv_reverse(char **l) {
     770                 :            :         size_t n, i;
     771                 :            : 
     772                 :         16 :         n = strv_length(l);
     773         [ +  + ]:         16 :         if (n <= 1)
     774                 :          8 :                 return l;
     775                 :            : 
     776         [ +  + ]:         16 :         for (i = 0; i < n / 2; i++)
     777                 :          8 :                 SWAP_TWO(l[i], l[n-1-i]);
     778                 :            : 
     779                 :          8 :         return l;
     780                 :            : }
     781                 :            : 
     782                 :          4 : 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   [ +  -  +  + ]:         16 :         STRV_FOREACH(s, l) {
     789                 :            :                 char *v;
     790                 :            : 
     791                 :         12 :                 v = shell_escape(*s, bad);
     792         [ -  + ]:         12 :                 if (!v)
     793                 :          0 :                         return NULL;
     794                 :            : 
     795                 :         12 :                 free(*s);
     796                 :         12 :                 *s = v;
     797                 :            :         }
     798                 :            : 
     799                 :          4 :         return l;
     800                 :            : }
     801                 :            : 
     802                 :         12 : bool strv_fnmatch(char* const* patterns, const char *s, int flags) {
     803                 :            :         char* const* p;
     804                 :            : 
     805   [ +  -  +  + ]:         16 :         STRV_FOREACH(p, patterns)
     806         [ +  + ]:          8 :                 if (fnmatch(*p, s, flags) == 0)
     807                 :          4 :                         return true;
     808                 :            : 
     809                 :          8 :         return false;
     810                 :            : }
     811                 :            : 
     812                 :          4 : char ***strv_free_free(char ***l) {
     813                 :            :         char ***i;
     814                 :            : 
     815         [ -  + ]:          4 :         if (!l)
     816                 :          0 :                 return NULL;
     817                 :            : 
     818         [ +  + ]:         12 :         for (i = l; *i; i++)
     819                 :          8 :                 strv_free(*i);
     820                 :            : 
     821                 :          4 :         return mfree(l);
     822                 :            : }
     823                 :            : 
     824                 :         52 : char **strv_skip(char **l, size_t n) {
     825                 :            : 
     826         [ +  + ]:        112 :         while (n > 0) {
     827         [ +  + ]:         80 :                 if (strv_isempty(l))
     828                 :         20 :                         return l;
     829                 :            : 
     830                 :         60 :                 l++, n--;
     831                 :            :         }
     832                 :            : 
     833                 :         32 :         return l;
     834                 :            : }
     835                 :            : 
     836                 :         16 : int strv_extend_n(char ***l, const char *value, size_t n) {
     837                 :            :         size_t i, j, k;
     838                 :            :         char **nl;
     839                 :            : 
     840         [ -  + ]:         16 :         assert(l);
     841                 :            : 
     842         [ -  + ]:         16 :         if (!value)
     843                 :          0 :                 return 0;
     844         [ +  + ]:         16 :         if (n == 0)
     845                 :          4 :                 return 0;
     846                 :            : 
     847                 :            :         /* Adds the value n times to l */
     848                 :            : 
     849                 :         12 :         k = strv_length(*l);
     850                 :            : 
     851                 :         12 :         nl = reallocarray(*l, k + n + 1, sizeof(char *));
     852         [ -  + ]:         12 :         if (!nl)
     853                 :          0 :                 return -ENOMEM;
     854                 :            : 
     855                 :         12 :         *l = nl;
     856                 :            : 
     857         [ +  + ]:         36 :         for (i = k; i < k + n; i++) {
     858                 :         24 :                 nl[i] = strdup(value);
     859         [ -  + ]:         24 :                 if (!nl[i])
     860                 :          0 :                         goto rollback;
     861                 :            :         }
     862                 :            : 
     863                 :         12 :         nl[i] = NULL;
     864                 :         12 :         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                 :       3356 : static int string_strv_hashmap_put_internal(Hashmap *h, const char *key, const char *value) {
     894                 :            :         char **l;
     895                 :            :         int r;
     896                 :            : 
     897                 :       3356 :         l = hashmap_get(h, key);
     898         [ +  + ]:       3356 :         if (l) {
     899                 :            :                 /* A list for this key already exists, let's append to it if it is not listed yet */
     900         [ +  + ]:        376 :                 if (strv_contains(l, value))
     901                 :         36 :                         return 0;
     902                 :            : 
     903                 :        340 :                 r = strv_extend(&l, value);
     904         [ -  + ]:        340 :                 if (r < 0)
     905                 :          0 :                         return r;
     906                 :            : 
     907         [ -  + ]:        340 :                 assert_se(hashmap_update(h, key, l) >= 0);
     908                 :            :         } else {
     909                 :            :                 /* No list for this key exists yet, create one */
     910         [ +  - ]:       2980 :                 _cleanup_strv_free_ char **l2 = NULL;
     911         [ +  - ]:       2980 :                 _cleanup_free_ char *t = NULL;
     912                 :            : 
     913                 :       2980 :                 t = strdup(key);
     914         [ -  + ]:       2980 :                 if (!t)
     915                 :          0 :                         return -ENOMEM;
     916                 :            : 
     917                 :       2980 :                 r = strv_extend(&l2, value);
     918         [ -  + ]:       2980 :                 if (r < 0)
     919                 :          0 :                         return r;
     920                 :            : 
     921                 :       2980 :                 r = hashmap_put(h, t, l2);
     922         [ -  + ]:       2980 :                 if (r < 0)
     923                 :          0 :                         return r;
     924                 :       2980 :                 TAKE_PTR(t);
     925                 :       2980 :                 TAKE_PTR(l2);
     926                 :            :         }
     927                 :            : 
     928                 :       3320 :         return 1;
     929                 :            : }
     930                 :            : 
     931                 :       3326 : int string_strv_hashmap_put(Hashmap **h, const char *key, const char *value) {
     932                 :            :         int r;
     933                 :            : 
     934                 :       3326 :         r = hashmap_ensure_allocated(h, &string_strv_hash_ops);
     935         [ -  + ]:       3326 :         if (r < 0)
     936                 :          0 :                 return r;
     937                 :            : 
     938                 :       3326 :         return string_strv_hashmap_put_internal(*h, key, value);
     939                 :            : }
     940                 :            : 
     941                 :         30 : int string_strv_ordered_hashmap_put(OrderedHashmap **h, const char *key, const char *value) {
     942                 :            :         int r;
     943                 :            : 
     944                 :         30 :         r = ordered_hashmap_ensure_allocated(h, &string_strv_hash_ops);
     945         [ -  + ]:         30 :         if (r < 0)
     946                 :          0 :                 return r;
     947                 :            : 
     948                 :         30 :         return string_strv_hashmap_put_internal(PLAIN_HASHMAP(*h), key, value);
     949                 :            : }
     950                 :            : 
     951                 :       5960 : 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