LCOV - code coverage report
Current view: top level - basic - string-util.c (source / functions) Hit Total Coverage
Test: systemd_full.info Lines: 471 556 84.7 %
Date: 2019-08-23 13:36:53 Functions: 33 35 94.3 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 301 423 71.2 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: LGPL-2.1+ */
       2                 :            : 
       3                 :            : #include <errno.h>
       4                 :            : #include <stdarg.h>
       5                 :            : #include <stdint.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 "fileio.h"
      13                 :            : #include "gunicode.h"
      14                 :            : #include "locale-util.h"
      15                 :            : #include "macro.h"
      16                 :            : #include "memory-util.h"
      17                 :            : #include "string-util.h"
      18                 :            : #include "terminal-util.h"
      19                 :            : #include "utf8.h"
      20                 :            : #include "util.h"
      21                 :            : 
      22                 :    4910137 : int strcmp_ptr(const char *a, const char *b) {
      23                 :            : 
      24                 :            :         /* Like strcmp(), but tries to make sense of NULL pointers */
      25   [ +  +  +  + ]:    4910137 :         if (a && b)
      26                 :    4761407 :                 return strcmp(a, b);
      27                 :            : 
      28   [ +  +  +  + ]:     148730 :         if (!a && b)
      29                 :     111422 :                 return -1;
      30                 :            : 
      31   [ +  +  +  - ]:      37308 :         if (a && !b)
      32                 :      36360 :                 return 1;
      33                 :            : 
      34                 :        948 :         return 0;
      35                 :            : }
      36                 :            : 
      37                 :    5089043 : char* endswith(const char *s, const char *postfix) {
      38                 :            :         size_t sl, pl;
      39                 :            : 
      40         [ -  + ]:    5089043 :         assert(s);
      41         [ -  + ]:    5089043 :         assert(postfix);
      42                 :            : 
      43                 :    5089043 :         sl = strlen(s);
      44                 :    5089043 :         pl = strlen(postfix);
      45                 :            : 
      46         [ +  + ]:    5089043 :         if (pl == 0)
      47                 :          8 :                 return (char*) s + sl;
      48                 :            : 
      49         [ +  + ]:    5089035 :         if (sl < pl)
      50                 :        372 :                 return NULL;
      51                 :            : 
      52         [ +  + ]:    5088663 :         if (memcmp(s + sl - pl, postfix, pl) != 0)
      53                 :    4973907 :                 return NULL;
      54                 :            : 
      55                 :     114756 :         return (char*) s + sl - pl;
      56                 :            : }
      57                 :            : 
      58                 :       6652 : char* endswith_no_case(const char *s, const char *postfix) {
      59                 :            :         size_t sl, pl;
      60                 :            : 
      61         [ -  + ]:       6652 :         assert(s);
      62         [ -  + ]:       6652 :         assert(postfix);
      63                 :            : 
      64                 :       6652 :         sl = strlen(s);
      65                 :       6652 :         pl = strlen(postfix);
      66                 :            : 
      67         [ +  + ]:       6652 :         if (pl == 0)
      68                 :          8 :                 return (char*) s + sl;
      69                 :            : 
      70         [ +  + ]:       6644 :         if (sl < pl)
      71                 :        504 :                 return NULL;
      72                 :            : 
      73         [ +  + ]:       6140 :         if (strcasecmp(s + sl - pl, postfix) != 0)
      74                 :       3682 :                 return NULL;
      75                 :            : 
      76                 :       2458 :         return (char*) s + sl - pl;
      77                 :            : }
      78                 :            : 
      79                 :      28912 : char* first_word(const char *s, const char *word) {
      80                 :            :         size_t sl, wl;
      81                 :            :         const char *p;
      82                 :            : 
      83         [ -  + ]:      28912 :         assert(s);
      84         [ -  + ]:      28912 :         assert(word);
      85                 :            : 
      86                 :            :         /* Checks if the string starts with the specified word, either
      87                 :            :          * followed by NUL or by whitespace. Returns a pointer to the
      88                 :            :          * NUL or the first character after the whitespace. */
      89                 :            : 
      90                 :      28912 :         sl = strlen(s);
      91                 :      28912 :         wl = strlen(word);
      92                 :            : 
      93         [ +  + ]:      28912 :         if (sl < wl)
      94                 :       2656 :                 return NULL;
      95                 :            : 
      96         [ +  + ]:      26256 :         if (wl == 0)
      97                 :          4 :                 return (char*) s;
      98                 :            : 
      99         [ +  + ]:      26252 :         if (memcmp(s, word, wl) != 0)
     100                 :      26140 :                 return NULL;
     101                 :            : 
     102                 :        112 :         p = s + wl;
     103         [ +  + ]:        112 :         if (*p == 0)
     104                 :          4 :                 return (char*) p;
     105                 :            : 
     106         [ +  + ]:        108 :         if (!strchr(WHITESPACE, *p))
     107                 :          4 :                 return NULL;
     108                 :            : 
     109                 :        104 :         p += strspn(p, WHITESPACE);
     110                 :        104 :         return (char*) p;
     111                 :            : }
     112                 :            : 
     113                 :        128 : static size_t strcspn_escaped(const char *s, const char *reject) {
     114                 :        128 :         bool escaped = false;
     115                 :            :         int n;
     116                 :            : 
     117         [ +  + ]:       1344 :         for (n=0; s[n]; n++) {
     118         [ -  + ]:       1320 :                 if (escaped)
     119                 :          0 :                         escaped = false;
     120         [ -  + ]:       1320 :                 else if (s[n] == '\\')
     121                 :          0 :                         escaped = true;
     122         [ +  + ]:       1320 :                 else if (strchr(reject, s[n]))
     123                 :        104 :                         break;
     124                 :            :         }
     125                 :            : 
     126                 :            :         /* if s ends in \, return index of previous char */
     127                 :        128 :         return n - escaped;
     128                 :            : }
     129                 :            : 
     130                 :            : /* Split a string into words. */
     131                 :       9080 : const char* split(const char **state, size_t *l, const char *separator, SplitFlags flags) {
     132                 :            :         const char *current;
     133                 :            : 
     134                 :       9080 :         current = *state;
     135                 :            : 
     136         [ +  + ]:       9080 :         if (!*current) {
     137         [ -  + ]:       2384 :                 assert(**state == '\0');
     138                 :       2384 :                 return NULL;
     139                 :            :         }
     140                 :            : 
     141                 :       6696 :         current += strspn(current, separator);
     142         [ +  + ]:       6696 :         if (!*current) {
     143                 :         60 :                 *state = current;
     144                 :         60 :                 return NULL;
     145                 :            :         }
     146                 :            : 
     147   [ +  +  +  - ]:       6636 :         if (flags & SPLIT_QUOTES && strchr("\'\"", *current)) {
     148                 :        128 :                 char quotechars[2] = {*current, '\0'};
     149                 :            : 
     150                 :        128 :                 *l = strcspn_escaped(current + 1, quotechars);
     151   [ +  +  +  - ]:        128 :                 if (current[*l + 1] == '\0' || current[*l + 1] != quotechars[0] ||
     152   [ +  +  +  + ]:        104 :                     (current[*l + 2] && !strchr(separator, current[*l + 2]))) {
     153                 :            :                         /* right quote missing or garbage at the end */
     154         [ +  + ]:         40 :                         if (flags & SPLIT_RELAX) {
     155                 :         32 :                                 *state = current + *l + 1 + (current[*l + 1] != '\0');
     156                 :         40 :                                 return current + 1;
     157                 :            :                         }
     158                 :          8 :                         *state = current;
     159                 :          8 :                         return NULL;
     160                 :            :                 }
     161                 :         88 :                 *state = current++ + *l + 2;
     162         [ -  + ]:       6508 :         } else if (flags & SPLIT_QUOTES) {
     163                 :          0 :                 *l = strcspn_escaped(current, separator);
     164   [ #  #  #  #  :          0 :                 if (current[*l] && !strchr(separator, current[*l]) && !(flags & SPLIT_RELAX)) {
                   #  # ]
     165                 :            :                         /* unfinished escape */
     166                 :          0 :                         *state = current;
     167                 :          0 :                         return NULL;
     168                 :            :                 }
     169                 :          0 :                 *state = current + *l;
     170                 :            :         } else {
     171                 :       6508 :                 *l = strcspn(current, separator);
     172                 :       6508 :                 *state = current + *l;
     173                 :            :         }
     174                 :            : 
     175                 :       6596 :         return current;
     176                 :            : }
     177                 :            : 
     178                 :        588 : char *strnappend(const char *s, const char *suffix, size_t b) {
     179                 :            :         size_t a;
     180                 :            :         char *r;
     181                 :            : 
     182   [ +  +  -  + ]:        588 :         if (!s && !suffix)
     183                 :          0 :                 return strdup("");
     184                 :            : 
     185         [ +  + ]:        588 :         if (!s)
     186                 :        260 :                 return strndup(suffix, b);
     187                 :            : 
     188         [ -  + ]:        328 :         if (!suffix)
     189                 :          0 :                 return strdup(s);
     190                 :            : 
     191         [ -  + ]:        328 :         assert(s);
     192         [ -  + ]:        328 :         assert(suffix);
     193                 :            : 
     194                 :        328 :         a = strlen(s);
     195         [ -  + ]:        328 :         if (b > ((size_t) -1) - a)
     196                 :          0 :                 return NULL;
     197                 :            : 
     198                 :        328 :         r = new(char, a+b+1);
     199         [ -  + ]:        328 :         if (!r)
     200                 :          0 :                 return NULL;
     201                 :            : 
     202                 :        328 :         memcpy(r, s, a);
     203                 :        328 :         memcpy(r+a, suffix, b);
     204                 :        328 :         r[a+b] = 0;
     205                 :            : 
     206                 :        328 :         return r;
     207                 :            : }
     208                 :            : 
     209                 :      93444 : char *strjoin_real(const char *x, ...) {
     210                 :            :         va_list ap;
     211                 :            :         size_t l;
     212                 :            :         char *r, *p;
     213                 :            : 
     214                 :      93444 :         va_start(ap, x);
     215                 :            : 
     216         [ +  + ]:      93444 :         if (x) {
     217                 :      93364 :                 l = strlen(x);
     218                 :            : 
     219                 :     172544 :                 for (;;) {
     220                 :            :                         const char *t;
     221                 :            :                         size_t n;
     222                 :            : 
     223                 :     265908 :                         t = va_arg(ap, const char *);
     224         [ +  + ]:     265908 :                         if (!t)
     225                 :      93364 :                                 break;
     226                 :            : 
     227                 :     172544 :                         n = strlen(t);
     228         [ -  + ]:     172544 :                         if (n > ((size_t) -1) - l) {
     229                 :          0 :                                 va_end(ap);
     230                 :          0 :                                 return NULL;
     231                 :            :                         }
     232                 :            : 
     233                 :     172544 :                         l += n;
     234                 :            :                 }
     235                 :            :         } else
     236                 :         80 :                 l = 0;
     237                 :            : 
     238                 :      93444 :         va_end(ap);
     239                 :            : 
     240                 :      93444 :         r = new(char, l+1);
     241         [ -  + ]:      93444 :         if (!r)
     242                 :          0 :                 return NULL;
     243                 :            : 
     244         [ +  + ]:      93444 :         if (x) {
     245                 :      93364 :                 p = stpcpy(r, x);
     246                 :            : 
     247                 :      93364 :                 va_start(ap, x);
     248                 :            : 
     249                 :     172544 :                 for (;;) {
     250                 :            :                         const char *t;
     251                 :            : 
     252                 :     265908 :                         t = va_arg(ap, const char *);
     253         [ +  + ]:     265908 :                         if (!t)
     254                 :      93364 :                                 break;
     255                 :            : 
     256                 :     172544 :                         p = stpcpy(p, t);
     257                 :            :                 }
     258                 :            : 
     259                 :      93364 :                 va_end(ap);
     260                 :            :         } else
     261                 :         80 :                 r[0] = 0;
     262                 :            : 
     263                 :      93444 :         return r;
     264                 :            : }
     265                 :            : 
     266                 :      85024 : char *strstrip(char *s) {
     267         [ -  + ]:      85024 :         if (!s)
     268                 :          0 :                 return NULL;
     269                 :            : 
     270                 :            :         /* Drops trailing whitespace. Modifies the string in place. Returns pointer to first non-space character */
     271                 :            : 
     272                 :      85024 :         return delete_trailing_chars(skip_leading_chars(s, WHITESPACE), WHITESPACE);
     273                 :            : }
     274                 :            : 
     275                 :         36 : char *delete_chars(char *s, const char *bad) {
     276                 :            :         char *f, *t;
     277                 :            : 
     278                 :            :         /* Drops all specified bad characters, regardless where in the string */
     279                 :            : 
     280         [ -  + ]:         36 :         if (!s)
     281                 :          0 :                 return NULL;
     282                 :            : 
     283         [ -  + ]:         36 :         if (!bad)
     284                 :          0 :                 bad = WHITESPACE;
     285                 :            : 
     286         [ +  + ]:        524 :         for (f = s, t = s; *f; f++) {
     287         [ +  + ]:        488 :                 if (strchr(bad, *f))
     288                 :        268 :                         continue;
     289                 :            : 
     290                 :        220 :                 *(t++) = *f;
     291                 :            :         }
     292                 :            : 
     293                 :         36 :         *t = 0;
     294                 :            : 
     295                 :         36 :         return s;
     296                 :            : }
     297                 :            : 
     298                 :      95616 : char *delete_trailing_chars(char *s, const char *bad) {
     299                 :      95616 :         char *p, *c = s;
     300                 :            : 
     301                 :            :         /* Drops all specified bad characters, at the end of the string */
     302                 :            : 
     303         [ -  + ]:      95616 :         if (!s)
     304                 :          0 :                 return NULL;
     305                 :            : 
     306         [ -  + ]:      95616 :         if (!bad)
     307                 :          0 :                 bad = WHITESPACE;
     308                 :            : 
     309         [ +  + ]:   18987212 :         for (p = s; *p; p++)
     310         [ +  + ]:   18891596 :                 if (!strchr(bad, *p))
     311                 :   18784960 :                         c = p + 1;
     312                 :            : 
     313                 :      95616 :         *c = 0;
     314                 :            : 
     315                 :      95616 :         return s;
     316                 :            : }
     317                 :            : 
     318                 :          8 : char *truncate_nl(char *s) {
     319         [ -  + ]:          8 :         assert(s);
     320                 :            : 
     321                 :          8 :         s[strcspn(s, NEWLINE)] = 0;
     322                 :          8 :         return s;
     323                 :            : }
     324                 :            : 
     325                 :     110550 : char ascii_tolower(char x) {
     326                 :            : 
     327   [ +  +  +  + ]:     110550 :         if (x >= 'A' && x <= 'Z')
     328                 :       1632 :                 return x - 'A' + 'a';
     329                 :            : 
     330                 :     108918 :         return x;
     331                 :            : }
     332                 :            : 
     333                 :          0 : char ascii_toupper(char x) {
     334                 :            : 
     335   [ #  #  #  # ]:          0 :         if (x >= 'a' && x <= 'z')
     336                 :          0 :                 return x - 'a' + 'A';
     337                 :            : 
     338                 :          0 :         return x;
     339                 :            : }
     340                 :            : 
     341                 :         72 : char *ascii_strlower(char *t) {
     342                 :            :         char *p;
     343                 :            : 
     344         [ -  + ]:         72 :         assert(t);
     345                 :            : 
     346         [ +  + ]:        440 :         for (p = t; *p; p++)
     347                 :        368 :                 *p = ascii_tolower(*p);
     348                 :            : 
     349                 :         72 :         return t;
     350                 :            : }
     351                 :            : 
     352                 :          0 : char *ascii_strupper(char *t) {
     353                 :            :         char *p;
     354                 :            : 
     355         [ #  # ]:          0 :         assert(t);
     356                 :            : 
     357         [ #  # ]:          0 :         for (p = t; *p; p++)
     358                 :          0 :                 *p = ascii_toupper(*p);
     359                 :            : 
     360                 :          0 :         return t;
     361                 :            : }
     362                 :            : 
     363                 :       8272 : char *ascii_strlower_n(char *t, size_t n) {
     364                 :            :         size_t i;
     365                 :            : 
     366         [ +  + ]:       8272 :         if (n <= 0)
     367                 :         44 :                 return t;
     368                 :            : 
     369         [ +  + ]:      57040 :         for (i = 0; i < n; i++)
     370                 :      48812 :                 t[i] = ascii_tolower(t[i]);
     371                 :            : 
     372                 :       8228 :         return t;
     373                 :            : }
     374                 :            : 
     375                 :       5635 : int ascii_strcasecmp_n(const char *a, const char *b, size_t n) {
     376                 :            : 
     377         [ +  + ]:      32825 :         for (; n > 0; a++, b++, n--) {
     378                 :            :                 int x, y;
     379                 :            : 
     380                 :      27655 :                 x = (int) (uint8_t) ascii_tolower(*a);
     381                 :      27655 :                 y = (int) (uint8_t) ascii_tolower(*b);
     382                 :            : 
     383         [ +  + ]:      27655 :                 if (x != y)
     384                 :        465 :                         return x - y;
     385                 :            :         }
     386                 :            : 
     387                 :       5170 :         return 0;
     388                 :            : }
     389                 :            : 
     390                 :       1151 : int ascii_strcasecmp_nn(const char *a, size_t n, const char *b, size_t m) {
     391                 :            :         int r;
     392                 :            : 
     393                 :       1151 :         r = ascii_strcasecmp_n(a, b, MIN(n, m));
     394         [ +  + ]:       1151 :         if (r != 0)
     395                 :        277 :                 return r;
     396                 :            : 
     397         [ +  + ]:        874 :         return CMP(n, m);
     398                 :            : }
     399                 :            : 
     400                 :         44 : bool chars_intersect(const char *a, const char *b) {
     401                 :            :         const char *p;
     402                 :            : 
     403                 :            :         /* Returns true if any of the chars in a are in b. */
     404         [ +  + ]:        224 :         for (p = a; *p; p++)
     405         [ +  + ]:        204 :                 if (strchr(b, *p))
     406                 :         24 :                         return true;
     407                 :            : 
     408                 :         20 :         return false;
     409                 :            : }
     410                 :            : 
     411                 :        400 : bool string_has_cc(const char *p, const char *ok) {
     412                 :            :         const char *t;
     413                 :            : 
     414         [ -  + ]:        400 :         assert(p);
     415                 :            : 
     416                 :            :         /*
     417                 :            :          * Check if a string contains control characters. If 'ok' is
     418                 :            :          * non-NULL it may be a string containing additional CCs to be
     419                 :            :          * considered OK.
     420                 :            :          */
     421                 :            : 
     422         [ +  + ]:       3508 :         for (t = p; *t; t++) {
     423   [ +  +  +  + ]:       3164 :                 if (ok && strchr(ok, *t))
     424                 :         64 :                         continue;
     425                 :            : 
     426   [ +  +  +  + ]:       3100 :                 if (*t > 0 && *t < ' ')
     427                 :         32 :                         return true;
     428                 :            : 
     429         [ +  + ]:       3068 :                 if (*t == 127)
     430                 :         24 :                         return true;
     431                 :            :         }
     432                 :            : 
     433                 :        344 :         return false;
     434                 :            : }
     435                 :            : 
     436                 :       3196 : static int write_ellipsis(char *buf, bool unicode) {
     437   [ +  +  +  - ]:       3196 :         if (unicode || is_locale_utf8()) {
     438                 :       3196 :                 buf[0] = 0xe2; /* tri-dot ellipsis: … */
     439                 :       3196 :                 buf[1] = 0x80;
     440                 :       3196 :                 buf[2] = 0xa6;
     441                 :            :         } else {
     442                 :          0 :                 buf[0] = '.';
     443                 :          0 :                 buf[1] = '.';
     444                 :          0 :                 buf[2] = '.';
     445                 :            :         }
     446                 :            : 
     447                 :       3196 :         return 3;
     448                 :            : }
     449                 :            : 
     450                 :       4108 : static char *ascii_ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigned percent) {
     451                 :            :         size_t x, need_space, suffix_len;
     452                 :            :         char *t;
     453                 :            : 
     454         [ -  + ]:       4108 :         assert(s);
     455         [ -  + ]:       4108 :         assert(percent <= 100);
     456         [ -  + ]:       4108 :         assert(new_length != (size_t) -1);
     457                 :            : 
     458         [ +  + ]:       4108 :         if (old_length <= new_length)
     459                 :       3000 :                 return strndup(s, old_length);
     460                 :            : 
     461                 :            :         /* Special case short ellipsations */
     462   [ -  +  +  + ]:       1108 :         switch (new_length) {
     463                 :            : 
     464                 :          0 :         case 0:
     465                 :          0 :                 return strdup("");
     466                 :            : 
     467                 :        236 :         case 1:
     468         [ +  - ]:        236 :                 if (is_locale_utf8())
     469                 :        236 :                         return strdup("…");
     470                 :            :                 else
     471                 :          0 :                         return strdup(".");
     472                 :            : 
     473                 :        140 :         case 2:
     474         [ -  + ]:        140 :                 if (!is_locale_utf8())
     475                 :          0 :                         return strdup("..");
     476                 :            : 
     477                 :        140 :                 break;
     478                 :            : 
     479                 :        732 :         default:
     480                 :        732 :                 break;
     481                 :            :         }
     482                 :            : 
     483                 :            :         /* Calculate how much space the ellipsis will take up. If we are in UTF-8 mode we only need space for one
     484                 :            :          * character ("…"), otherwise for three characters ("..."). Note that in both cases we need 3 bytes of storage,
     485                 :            :          * either for the UTF-8 encoded character or for three ASCII characters. */
     486         [ +  - ]:        872 :         need_space = is_locale_utf8() ? 1 : 3;
     487                 :            : 
     488                 :        872 :         t = new(char, new_length+3);
     489         [ -  + ]:        872 :         if (!t)
     490                 :          0 :                 return NULL;
     491                 :            : 
     492         [ -  + ]:        872 :         assert(new_length >= need_space);
     493                 :            : 
     494                 :        872 :         x = ((new_length - need_space) * percent + 50) / 100;
     495         [ -  + ]:        872 :         assert(x <= new_length - need_space);
     496                 :            : 
     497                 :        872 :         memcpy(t, s, x);
     498                 :        872 :         write_ellipsis(t + x, false);
     499                 :        872 :         suffix_len = new_length - x - need_space;
     500                 :        872 :         memcpy(t + x + 3, s + old_length - suffix_len, suffix_len);
     501                 :        872 :         *(t + x + 3 + suffix_len) = '\0';
     502                 :            : 
     503                 :        872 :         return t;
     504                 :            : }
     505                 :            : 
     506                 :      13692 : char *ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigned percent) {
     507                 :            :         size_t x, k, len, len2;
     508                 :            :         const char *i, *j;
     509                 :            :         char *e;
     510                 :            :         int r;
     511                 :            : 
     512                 :            :         /* Note that 'old_length' refers to bytes in the string, while 'new_length' refers to character cells taken up
     513                 :            :          * on screen. This distinction doesn't matter for ASCII strings, but it does matter for non-ASCII UTF-8
     514                 :            :          * strings.
     515                 :            :          *
     516                 :            :          * Ellipsation is done in a locale-dependent way:
     517                 :            :          * 1. If the string passed in is fully ASCII and the current locale is not UTF-8, three dots are used ("...")
     518                 :            :          * 2. Otherwise, a unicode ellipsis is used ("…")
     519                 :            :          *
     520                 :            :          * In other words: you'll get a unicode ellipsis as soon as either the string contains non-ASCII characters or
     521                 :            :          * the current locale is UTF-8.
     522                 :            :          */
     523                 :            : 
     524         [ -  + ]:      13692 :         assert(s);
     525         [ -  + ]:      13692 :         assert(percent <= 100);
     526                 :            : 
     527         [ -  + ]:      13692 :         if (new_length == (size_t) -1)
     528                 :          0 :                 return strndup(s, old_length);
     529                 :            : 
     530         [ +  + ]:      13692 :         if (new_length == 0)
     531                 :        656 :                 return strdup("");
     532                 :            : 
     533                 :            :         /* If no multibyte characters use ascii_ellipsize_mem for speed */
     534         [ +  + ]:      13036 :         if (ascii_is_valid_n(s, old_length))
     535                 :       4108 :                 return ascii_ellipsize_mem(s, old_length, new_length, percent);
     536                 :            : 
     537                 :       8928 :         x = ((new_length - 1) * percent) / 100;
     538         [ -  + ]:       8928 :         assert(x <= new_length - 1);
     539                 :            : 
     540                 :       8928 :         k = 0;
     541         [ +  + ]:      43756 :         for (i = s; i < s + old_length; i = utf8_next_char(i)) {
     542                 :            :                 char32_t c;
     543                 :            :                 int w;
     544                 :            : 
     545                 :      39012 :                 r = utf8_encoded_to_unichar(i, &c);
     546         [ -  + ]:      39012 :                 if (r < 0)
     547                 :          0 :                         return NULL;
     548                 :            : 
     549         [ +  + ]:      39012 :                 w = unichar_iswide(c) ? 2 : 1;
     550         [ +  + ]:      39012 :                 if (k + w <= x)
     551                 :      34828 :                         k += w;
     552                 :            :                 else
     553                 :       4184 :                         break;
     554                 :            :         }
     555                 :            : 
     556         [ +  + ]:      20256 :         for (j = s + old_length; j > i; ) {
     557                 :            :                 char32_t c;
     558                 :            :                 int w;
     559                 :            :                 const char *jj;
     560                 :            : 
     561                 :      13556 :                 jj = utf8_prev_char(j);
     562                 :      13556 :                 r = utf8_encoded_to_unichar(jj, &c);
     563         [ -  + ]:      13556 :                 if (r < 0)
     564                 :          0 :                         return NULL;
     565                 :            : 
     566         [ +  + ]:      13556 :                 w = unichar_iswide(c) ? 2 : 1;
     567         [ +  + ]:      13556 :                 if (k + w <= new_length) {
     568                 :      11328 :                         k += w;
     569                 :      11328 :                         j = jj;
     570                 :            :                 } else
     571                 :       2228 :                         break;
     572                 :            :         }
     573         [ -  + ]:       8928 :         assert(i <= j);
     574                 :            : 
     575                 :            :         /* we don't actually need to ellipsize */
     576         [ +  + ]:       8928 :         if (i == j)
     577                 :       6700 :                 return memdup_suffix0(s, old_length);
     578                 :            : 
     579                 :            :         /* make space for ellipsis, if possible */
     580         [ +  + ]:       2228 :         if (j < s + old_length)
     581                 :       2060 :                 j = utf8_next_char(j);
     582         [ +  + ]:        168 :         else if (i > s)
     583                 :         68 :                 i = utf8_prev_char(i);
     584                 :            : 
     585                 :       2228 :         len = i - s;
     586                 :       2228 :         len2 = s + old_length - j;
     587                 :       2228 :         e = new(char, len + 3 + len2 + 1);
     588         [ -  + ]:       2228 :         if (!e)
     589                 :          0 :                 return NULL;
     590                 :            : 
     591                 :            :         /*
     592                 :            :         printf("old_length=%zu new_length=%zu x=%zu len=%u len2=%u k=%u\n",
     593                 :            :                old_length, new_length, x, len, len2, k);
     594                 :            :         */
     595                 :            : 
     596                 :       2228 :         memcpy(e, s, len);
     597                 :       2228 :         write_ellipsis(e + len, true);
     598                 :       2228 :         memcpy(e + len + 3, j, len2);
     599                 :       2228 :         *(e + len + 3 + len2) = '\0';
     600                 :            : 
     601                 :       2228 :         return e;
     602                 :            : }
     603                 :            : 
     604                 :       4775 : char *cellescape(char *buf, size_t len, const char *s) {
     605                 :            :         /* Escape and ellipsize s into buffer buf of size len. Only non-control ASCII
     606                 :            :          * characters are copied as they are, everything else is escaped. The result
     607                 :            :          * is different then if escaping and ellipsization was performed in two
     608                 :            :          * separate steps, because each sequence is either stored in full or skipped.
     609                 :            :          *
     610                 :            :          * This function should be used for logging about strings which expected to
     611                 :            :          * be plain ASCII in a safe way.
     612                 :            :          *
     613                 :            :          * An ellipsis will be used if s is too long. It was always placed at the
     614                 :            :          * very end.
     615                 :            :          */
     616                 :            : 
     617                 :       4775 :         size_t i = 0, last_char_width[4] = {}, k = 0, j;
     618                 :            : 
     619         [ -  + ]:       4775 :         assert(len > 0); /* at least a terminating NUL */
     620                 :            : 
     621                 :      47262 :         for (;;) {
     622                 :            :                 char four[4];
     623                 :            :                 int w;
     624                 :            : 
     625         [ +  + ]:      52037 :                 if (*s == 0) /* terminating NUL detected? then we are done! */
     626                 :       4631 :                         goto done;
     627                 :            : 
     628                 :      47406 :                 w = cescape_char(*s, four);
     629         [ +  + ]:      47406 :                 if (i + w + 1 > len) /* This character doesn't fit into the buffer anymore? In that case let's
     630                 :            :                                       * ellipsize at the previous location */
     631                 :        144 :                         break;
     632                 :            : 
     633                 :            :                 /* OK, there was space, let's add this escaped character to the buffer */
     634                 :      47262 :                 memcpy(buf + i, four, w);
     635                 :      47262 :                 i += w;
     636                 :            : 
     637                 :            :                 /* And remember its width in the ring buffer */
     638                 :      47262 :                 last_char_width[k] = w;
     639                 :      47262 :                 k = (k + 1) % 4;
     640                 :            : 
     641                 :      47262 :                 s++;
     642                 :            :         }
     643                 :            : 
     644                 :            :         /* Ellipsation is necessary. This means we might need to truncate the string again to make space for 4
     645                 :            :          * characters ideally, but the buffer is shorter than that in the first place take what we can get */
     646         [ +  - ]:        324 :         for (j = 0; j < ELEMENTSOF(last_char_width); j++) {
     647                 :            : 
     648         [ +  + ]:        324 :                 if (i + 4 <= len) /* nice, we reached our space goal */
     649                 :         96 :                         break;
     650                 :            : 
     651         [ +  + ]:        228 :                 k = k == 0 ? 3 : k - 1;
     652         [ +  + ]:        228 :                 if (last_char_width[k] == 0) /* bummer, we reached the beginning of the strings */
     653                 :         48 :                         break;
     654                 :            : 
     655         [ -  + ]:        180 :                 assert(i >= last_char_width[k]);
     656                 :        180 :                 i -= last_char_width[k];
     657                 :            :         }
     658                 :            : 
     659         [ +  + ]:        144 :         if (i + 4 <= len) /* yay, enough space */
     660                 :         96 :                 i += write_ellipsis(buf + i, false);
     661         [ +  + ]:         48 :         else if (i + 3 <= len) { /* only space for ".." */
     662                 :         16 :                 buf[i++] = '.';
     663                 :         16 :                 buf[i++] = '.';
     664         [ +  + ]:         32 :         } else if (i + 2 <= len) /* only space for a single "." */
     665                 :         16 :                 buf[i++] = '.';
     666                 :            :         else
     667         [ -  + ]:         16 :                 assert(i + 1 <= len);
     668                 :            : 
     669                 :         16 :  done:
     670                 :       4775 :         buf[i] = '\0';
     671                 :       4775 :         return buf;
     672                 :            : }
     673                 :            : 
     674                 :         32 : char* strshorten(char *s, size_t l) {
     675         [ -  + ]:         32 :         assert(s);
     676                 :            : 
     677         [ +  + ]:         32 :         if (strnlen(s, l+1) > l)
     678                 :         16 :                 s[l] = 0;
     679                 :            : 
     680                 :         32 :         return s;
     681                 :            : }
     682                 :            : 
     683                 :        272 : char *strreplace(const char *text, const char *old_string, const char *new_string) {
     684                 :        272 :         size_t l, old_len, new_len, allocated = 0;
     685                 :        272 :         char *t, *ret = NULL;
     686                 :            :         const char *f;
     687                 :            : 
     688         [ -  + ]:        272 :         assert(old_string);
     689         [ -  + ]:        272 :         assert(new_string);
     690                 :            : 
     691         [ +  + ]:        272 :         if (!text)
     692                 :          4 :                 return NULL;
     693                 :            : 
     694                 :        268 :         old_len = strlen(old_string);
     695                 :        268 :         new_len = strlen(new_string);
     696                 :            : 
     697                 :        268 :         l = strlen(text);
     698         [ -  + ]:        268 :         if (!GREEDY_REALLOC(ret, allocated, l+1))
     699                 :          0 :                 return NULL;
     700                 :            : 
     701                 :        268 :         f = text;
     702                 :        268 :         t = ret;
     703         [ +  + ]:       6496 :         while (*f) {
     704                 :            :                 size_t d, nl;
     705                 :            : 
     706         [ +  + ]:       6228 :                 if (!startswith(f, old_string)) {
     707                 :       6136 :                         *(t++) = *(f++);
     708                 :       6136 :                         continue;
     709                 :            :                 }
     710                 :            : 
     711                 :         92 :                 d = t - ret;
     712                 :         92 :                 nl = l - old_len + new_len;
     713                 :            : 
     714         [ -  + ]:         92 :                 if (!GREEDY_REALLOC(ret, allocated, nl + 1))
     715                 :          0 :                         return mfree(ret);
     716                 :            : 
     717                 :         92 :                 l = nl;
     718                 :         92 :                 t = ret + d;
     719                 :            : 
     720                 :         92 :                 t = stpcpy(t, new_string);
     721                 :         92 :                 f += old_len;
     722                 :            :         }
     723                 :            : 
     724                 :        268 :         *t = 0;
     725                 :        268 :         return ret;
     726                 :            : }
     727                 :            : 
     728                 :         40 : static void advance_offsets(
     729                 :            :                 ssize_t diff,
     730                 :            :                 size_t offsets[2], /* note: we can't use [static 2] here, since this may be NULL */
     731                 :            :                 size_t shift[static 2],
     732                 :            :                 size_t size) {
     733                 :            : 
     734         [ +  - ]:         40 :         if (!offsets)
     735                 :         40 :                 return;
     736                 :            : 
     737         [ #  # ]:          0 :         assert(shift);
     738                 :            : 
     739         [ #  # ]:          0 :         if ((size_t) diff < offsets[0])
     740                 :          0 :                 shift[0] += size;
     741         [ #  # ]:          0 :         if ((size_t) diff < offsets[1])
     742                 :          0 :                 shift[1] += size;
     743                 :            : }
     744                 :            : 
     745                 :         20 : char *strip_tab_ansi(char **ibuf, size_t *_isz, size_t highlight[2]) {
     746                 :         20 :         const char *i, *begin = NULL;
     747                 :            :         enum {
     748                 :            :                 STATE_OTHER,
     749                 :            :                 STATE_ESCAPE,
     750                 :            :                 STATE_CSI,
     751                 :            :                 STATE_CSO,
     752                 :         20 :         } state = STATE_OTHER;
     753                 :         20 :         char *obuf = NULL;
     754                 :         20 :         size_t osz = 0, isz, shift[2] = {};
     755                 :            :         FILE *f;
     756                 :            : 
     757         [ -  + ]:         20 :         assert(ibuf);
     758         [ -  + ]:         20 :         assert(*ibuf);
     759                 :            : 
     760                 :            :         /* This does three things:
     761                 :            :          *
     762                 :            :          * 1. Replaces TABs by 8 spaces
     763                 :            :          * 2. Strips ANSI color sequences (a subset of CSI), i.e. ESC '[' … 'm' sequences
     764                 :            :          * 3. Strips ANSI operating system sequences (CSO), i.e. ESC ']' … BEL sequences
     765                 :            :          *
     766                 :            :          * Everything else will be left as it is. In particular other ANSI sequences are left as they are, as
     767                 :            :          * are any other special characters. Truncated ANSI sequences are left-as is too. This call is
     768                 :            :          * supposed to suppress the most basic formatting noise, but nothing else.
     769                 :            :          *
     770                 :            :          * Why care for CSO sequences? Well, to undo what terminal_urlify() and friends generate. */
     771                 :            : 
     772         [ -  + ]:         20 :         isz = _isz ? *_isz : strlen(*ibuf);
     773                 :            : 
     774                 :            :         /* Note we turn off internal locking on f for performance reasons. It's safe to do so since we
     775                 :            :          * created f here and it doesn't leave our scope. */
     776                 :         20 :         f = open_memstream_unlocked(&obuf, &osz);
     777         [ -  + ]:         20 :         if (!f)
     778                 :          0 :                 return NULL;
     779                 :            : 
     780         [ +  + ]:        680 :         for (i = *ibuf; i < *ibuf + isz + 1; i++) {
     781                 :            : 
     782   [ +  +  +  -  :        660 :                 switch (state) {
                      - ]
     783                 :            : 
     784                 :        444 :                 case STATE_OTHER:
     785         [ +  + ]:        444 :                         if (i >= *ibuf + isz) /* EOT */
     786                 :         20 :                                 break;
     787         [ +  + ]:        424 :                         else if (*i == '\x1B')
     788                 :         52 :                                 state = STATE_ESCAPE;
     789         [ +  + ]:        372 :                         else if (*i == '\t') {
     790                 :         20 :                                 fputs("        ", f);
     791                 :         20 :                                 advance_offsets(i - *ibuf, highlight, shift, 7);
     792                 :            :                         } else
     793                 :        352 :                                 fputc(*i, f);
     794                 :            : 
     795                 :        424 :                         break;
     796                 :            : 
     797                 :         52 :                 case STATE_ESCAPE:
     798         [ -  + ]:         52 :                         if (i >= *ibuf + isz) { /* EOT */
     799                 :          0 :                                 fputc('\x1B', f);
     800                 :          0 :                                 advance_offsets(i - *ibuf, highlight, shift, 1);
     801                 :          0 :                                 break;
     802         [ +  - ]:         52 :                         } else if (*i == '[') { /* ANSI CSI */
     803                 :         52 :                                 state = STATE_CSI;
     804                 :         52 :                                 begin = i + 1;
     805         [ #  # ]:          0 :                         } else if (*i == ']') { /* ANSI CSO */
     806                 :          0 :                                 state = STATE_CSO;
     807                 :          0 :                                 begin = i + 1;
     808                 :            :                         } else {
     809                 :          0 :                                 fputc('\x1B', f);
     810                 :          0 :                                 fputc(*i, f);
     811                 :          0 :                                 advance_offsets(i - *ibuf, highlight, shift, 1);
     812                 :          0 :                                 state = STATE_OTHER;
     813                 :            :                         }
     814                 :            : 
     815                 :         52 :                         break;
     816                 :            : 
     817                 :        164 :                 case STATE_CSI:
     818                 :            : 
     819         [ +  - ]:        164 :                         if (i >= *ibuf + isz || /* EOT … */
     820         [ +  + ]:        164 :                             !strchr("01234567890;m", *i)) { /* … or invalid chars in sequence */
     821                 :         20 :                                 fputc('\x1B', f);
     822                 :         20 :                                 fputc('[', f);
     823                 :         20 :                                 advance_offsets(i - *ibuf, highlight, shift, 2);
     824                 :         20 :                                 state = STATE_OTHER;
     825                 :         20 :                                 i = begin-1;
     826         [ +  + ]:        144 :                         } else if (*i == 'm')
     827                 :         32 :                                 state = STATE_OTHER;
     828                 :            : 
     829                 :        164 :                         break;
     830                 :            : 
     831                 :          0 :                 case STATE_CSO:
     832                 :            : 
     833         [ #  # ]:          0 :                         if (i >= *ibuf + isz || /* EOT … */
     834   [ #  #  #  #  :          0 :                             (*i != '\a' && (uint8_t) *i < 32U) || (uint8_t) *i > 126U) { /* … or invalid chars in sequence */
                   #  # ]
     835                 :          0 :                                 fputc('\x1B', f);
     836                 :          0 :                                 fputc(']', f);
     837                 :          0 :                                 advance_offsets(i - *ibuf, highlight, shift, 2);
     838                 :          0 :                                 state = STATE_OTHER;
     839                 :          0 :                                 i = begin-1;
     840         [ #  # ]:          0 :                         } else if (*i == '\a')
     841                 :          0 :                                 state = STATE_OTHER;
     842                 :            : 
     843                 :          0 :                         break;
     844                 :            :                 }
     845                 :        660 :         }
     846                 :            : 
     847         [ -  + ]:         20 :         if (fflush_and_check(f) < 0) {
     848                 :          0 :                 fclose(f);
     849                 :          0 :                 return mfree(obuf);
     850                 :            :         }
     851                 :            : 
     852                 :         20 :         fclose(f);
     853                 :            : 
     854                 :         20 :         free_and_replace(*ibuf, obuf);
     855                 :            : 
     856         [ -  + ]:         20 :         if (_isz)
     857                 :          0 :                 *_isz = osz;
     858                 :            : 
     859         [ -  + ]:         20 :         if (highlight) {
     860                 :          0 :                 highlight[0] += shift[0];
     861                 :          0 :                 highlight[1] += shift[1];
     862                 :            :         }
     863                 :            : 
     864                 :         20 :         return *ibuf;
     865                 :            : }
     866                 :            : 
     867                 :     319188 : char *strextend_with_separator(char **x, const char *separator, ...) {
     868                 :            :         bool need_separator;
     869                 :            :         size_t f, l, l_separator;
     870                 :            :         char *r, *p;
     871                 :            :         va_list ap;
     872                 :            : 
     873         [ -  + ]:     319188 :         assert(x);
     874                 :            : 
     875                 :     319188 :         l = f = strlen_ptr(*x);
     876                 :            : 
     877                 :     319188 :         need_separator = !isempty(*x);
     878                 :     319188 :         l_separator = strlen_ptr(separator);
     879                 :            : 
     880                 :     319188 :         va_start(ap, separator);
     881                 :     319440 :         for (;;) {
     882                 :            :                 const char *t;
     883                 :            :                 size_t n;
     884                 :            : 
     885                 :     638628 :                 t = va_arg(ap, const char *);
     886         [ +  + ]:     638628 :                 if (!t)
     887                 :     319188 :                         break;
     888                 :            : 
     889                 :     319440 :                 n = strlen(t);
     890                 :            : 
     891         [ +  + ]:     319440 :                 if (need_separator)
     892                 :     315464 :                         n += l_separator;
     893                 :            : 
     894         [ -  + ]:     319440 :                 if (n > ((size_t) -1) - l) {
     895                 :          0 :                         va_end(ap);
     896                 :          0 :                         return NULL;
     897                 :            :                 }
     898                 :            : 
     899                 :     319440 :                 l += n;
     900                 :     319440 :                 need_separator = true;
     901                 :            :         }
     902                 :     319188 :         va_end(ap);
     903                 :            : 
     904                 :     319188 :         need_separator = !isempty(*x);
     905                 :            : 
     906                 :     319188 :         r = realloc(*x, l+1);
     907         [ -  + ]:     319188 :         if (!r)
     908                 :          0 :                 return NULL;
     909                 :            : 
     910                 :     319188 :         p = r + f;
     911                 :            : 
     912                 :     319188 :         va_start(ap, separator);
     913                 :     319440 :         for (;;) {
     914                 :            :                 const char *t;
     915                 :            : 
     916                 :     638628 :                 t = va_arg(ap, const char *);
     917         [ +  + ]:     638628 :                 if (!t)
     918                 :     319188 :                         break;
     919                 :            : 
     920   [ +  +  +  + ]:     319440 :                 if (need_separator && separator)
     921                 :        576 :                         p = stpcpy(p, separator);
     922                 :            : 
     923                 :     319440 :                 p = stpcpy(p, t);
     924                 :            : 
     925                 :     319440 :                 need_separator = true;
     926                 :            :         }
     927                 :     319188 :         va_end(ap);
     928                 :            : 
     929         [ -  + ]:     319188 :         assert(p == r + l);
     930                 :            : 
     931                 :     319188 :         *p = 0;
     932                 :     319188 :         *x = r;
     933                 :            : 
     934                 :     319188 :         return r + l;
     935                 :            : }
     936                 :            : 
     937                 :        516 : char *strrep(const char *s, unsigned n) {
     938                 :            :         size_t l;
     939                 :            :         char *r, *p;
     940                 :            :         unsigned i;
     941                 :            : 
     942         [ -  + ]:        516 :         assert(s);
     943                 :            : 
     944                 :        516 :         l = strlen(s);
     945                 :        516 :         p = r = malloc(l * n + 1);
     946         [ -  + ]:        516 :         if (!r)
     947                 :          0 :                 return NULL;
     948                 :            : 
     949         [ +  + ]:       2480 :         for (i = 0; i < n; i++)
     950                 :       1964 :                 p = stpcpy(p, s);
     951                 :            : 
     952                 :        516 :         *p = 0;
     953                 :        516 :         return r;
     954                 :            : }
     955                 :            : 
     956                 :        192 : int split_pair(const char *s, const char *sep, char **l, char **r) {
     957                 :            :         char *x, *a, *b;
     958                 :            : 
     959         [ -  + ]:        192 :         assert(s);
     960         [ -  + ]:        192 :         assert(sep);
     961         [ -  + ]:        192 :         assert(l);
     962         [ -  + ]:        192 :         assert(r);
     963                 :            : 
     964         [ +  + ]:        192 :         if (isempty(sep))
     965                 :          8 :                 return -EINVAL;
     966                 :            : 
     967                 :        184 :         x = strstr(s, sep);
     968         [ +  + ]:        184 :         if (!x)
     969                 :          4 :                 return -EINVAL;
     970                 :            : 
     971                 :        180 :         a = strndup(s, x - s);
     972         [ -  + ]:        180 :         if (!a)
     973                 :          0 :                 return -ENOMEM;
     974                 :            : 
     975                 :        180 :         b = strdup(x + strlen(sep));
     976         [ -  + ]:        180 :         if (!b) {
     977                 :          0 :                 free(a);
     978                 :          0 :                 return -ENOMEM;
     979                 :            :         }
     980                 :            : 
     981                 :        180 :         *l = a;
     982                 :        180 :         *r = b;
     983                 :            : 
     984                 :        180 :         return 0;
     985                 :            : }
     986                 :            : 
     987                 :      22008 : int free_and_strdup(char **p, const char *s) {
     988                 :            :         char *t;
     989                 :            : 
     990         [ -  + ]:      22008 :         assert(p);
     991                 :            : 
     992                 :            :         /* Replaces a string pointer with a strdup()ed new string,
     993                 :            :          * possibly freeing the old one. */
     994                 :            : 
     995         [ +  + ]:      22008 :         if (streq_ptr(*p, s))
     996                 :        392 :                 return 0;
     997                 :            : 
     998         [ +  + ]:      21616 :         if (s) {
     999                 :      21600 :                 t = strdup(s);
    1000         [ -  + ]:      21600 :                 if (!t)
    1001                 :          0 :                         return -ENOMEM;
    1002                 :            :         } else
    1003                 :         16 :                 t = NULL;
    1004                 :            : 
    1005                 :      21616 :         free(*p);
    1006                 :      21616 :         *p = t;
    1007                 :            : 
    1008                 :      21616 :         return 1;
    1009                 :            : }
    1010                 :            : 
    1011                 :        964 : int free_and_strndup(char **p, const char *s, size_t l) {
    1012                 :            :         char *t;
    1013                 :            : 
    1014         [ -  + ]:        964 :         assert(p);
    1015   [ +  +  -  + ]:        964 :         assert(s || l == 0);
    1016                 :            : 
    1017                 :            :         /* Replaces a string pointer with a strndup()ed new string,
    1018                 :            :          * freeing the old one. */
    1019                 :            : 
    1020   [ +  +  -  + ]:        964 :         if (!*p && !s)
    1021                 :          0 :                 return 0;
    1022                 :            : 
    1023   [ +  +  +  +  :        964 :         if (*p && s && strneq(*p, s, l) && (l > strlen(*p) || (*p)[l] == '\0'))
          +  +  +  +  +  
                      + ]
    1024                 :        348 :                 return 0;
    1025                 :            : 
    1026         [ +  + ]:        616 :         if (s) {
    1027                 :        612 :                 t = strndup(s, l);
    1028         [ -  + ]:        612 :                 if (!t)
    1029                 :          0 :                         return -ENOMEM;
    1030                 :            :         } else
    1031                 :          4 :                 t = NULL;
    1032                 :            : 
    1033                 :        616 :         free_and_replace(*p, t);
    1034                 :        616 :         return 1;
    1035                 :            : }
    1036                 :            : 
    1037                 :       5972 : bool string_is_safe(const char *p) {
    1038                 :            :         const char *t;
    1039                 :            : 
    1040         [ -  + ]:       5972 :         if (!p)
    1041                 :          0 :                 return false;
    1042                 :            : 
    1043         [ +  + ]:      64308 :         for (t = p; *t; t++) {
    1044   [ +  -  +  + ]:      58392 :                 if (*t > 0 && *t < ' ') /* no control characters */
    1045                 :         36 :                         return false;
    1046                 :            : 
    1047         [ +  + ]:      58356 :                 if (strchr(QUOTES "\\\x7f", *t))
    1048                 :         20 :                         return false;
    1049                 :            :         }
    1050                 :            : 
    1051                 :       5916 :         return true;
    1052                 :            : }

Generated by: LCOV version 1.14