LCOV - code coverage report
Current view: top level - lib/util - string.c (source / functions) Hit Total Coverage
Test: ut_cov_unit.info Lines: 225 291 77.3 %
Date: 2024-12-06 08:20:53 Functions: 18 20 90.0 %

          Line data    Source code
       1             : /*   SPDX-License-Identifier: BSD-3-Clause
       2             :  *   Copyright (C) 2015 Intel Corporation.
       3             :  *   Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES.
       4             :  *   All rights reserved.
       5             :  */
       6             : 
       7             : #include "spdk/stdinc.h"
       8             : 
       9             : #include "spdk/string.h"
      10             : 
      11             : char *
      12         274 : spdk_vsprintf_append_realloc(char *buffer, const char *format, va_list args)
      13             : {
      14         274 :         va_list args_copy;
      15             :         char *new_buffer;
      16         274 :         int orig_size = 0, new_size;
      17             : 
      18             :         /* Original buffer size */
      19         274 :         if (buffer) {
      20           5 :                 orig_size = strlen(buffer);
      21             :         }
      22             : 
      23             :         /* Necessary buffer size */
      24         274 :         va_copy(args_copy, args);
      25         274 :         new_size = vsnprintf(NULL, 0, format, args_copy);
      26         274 :         va_end(args_copy);
      27             : 
      28         274 :         if (new_size < 0) {
      29           0 :                 return NULL;
      30             :         }
      31         274 :         new_size += orig_size + 1;
      32             : 
      33         274 :         new_buffer = realloc(buffer, new_size);
      34         274 :         if (new_buffer == NULL) {
      35           0 :                 return NULL;
      36             :         }
      37             : 
      38         274 :         vsnprintf(new_buffer + orig_size, new_size - orig_size, format, args);
      39             : 
      40         274 :         return new_buffer;
      41             : }
      42             : 
      43             : char *
      44           7 : spdk_sprintf_append_realloc(char *buffer, const char *format, ...)
      45             : {
      46           7 :         va_list args;
      47             :         char *ret;
      48             : 
      49           7 :         va_start(args, format);
      50           7 :         ret = spdk_vsprintf_append_realloc(buffer, format, args);
      51           7 :         va_end(args);
      52             : 
      53           7 :         return ret;
      54             : }
      55             : 
      56             : char *
      57         267 : spdk_vsprintf_alloc(const char *format, va_list args)
      58             : {
      59         267 :         return spdk_vsprintf_append_realloc(NULL, format, args);
      60             : }
      61             : 
      62             : char *
      63         253 : spdk_sprintf_alloc(const char *format, ...)
      64             : {
      65         253 :         va_list args;
      66             :         char *ret;
      67             : 
      68         253 :         va_start(args, format);
      69         253 :         ret = spdk_vsprintf_alloc(format, args);
      70         253 :         va_end(args);
      71             : 
      72         253 :         return ret;
      73             : }
      74             : 
      75             : char *
      76           0 : spdk_strlwr(char *s)
      77             : {
      78             :         char *p;
      79             : 
      80           0 :         if (s == NULL) {
      81           0 :                 return NULL;
      82             :         }
      83             : 
      84           0 :         p = s;
      85           0 :         while (*p != '\0') {
      86           0 :                 *p = tolower(*p);
      87           0 :                 p++;
      88             :         }
      89             : 
      90           0 :         return s;
      91             : }
      92             : 
      93             : char *
      94          24 : spdk_strsepq(char **stringp, const char *delim)
      95             : {
      96             :         char *p, *q, *r;
      97          24 :         int quoted = 0, bslash = 0;
      98             : 
      99          24 :         p = *stringp;
     100          24 :         if (p == NULL) {
     101           0 :                 return NULL;
     102             :         }
     103             : 
     104          24 :         r = q = p;
     105         156 :         while (*q != '\0' && *q != '\n') {
     106             :                 /* eat quoted characters */
     107         144 :                 if (bslash) {
     108           0 :                         bslash = 0;
     109           0 :                         *r++ = *q++;
     110           0 :                         continue;
     111         144 :                 } else if (quoted) {
     112           0 :                         if (quoted == '"' && *q == '\\') {
     113           0 :                                 bslash = 1;
     114           0 :                                 q++;
     115           0 :                                 continue;
     116           0 :                         } else if (*q == quoted) {
     117           0 :                                 quoted = 0;
     118           0 :                                 q++;
     119           0 :                                 continue;
     120             :                         }
     121           0 :                         *r++ = *q++;
     122           0 :                         continue;
     123         144 :                 } else if (*q == '\\') {
     124           0 :                         bslash = 1;
     125           0 :                         q++;
     126           0 :                         continue;
     127         144 :                 } else if (*q == '"' || *q == '\'') {
     128           0 :                         quoted = *q;
     129           0 :                         q++;
     130           0 :                         continue;
     131             :                 }
     132             : 
     133             :                 /* separator? */
     134         144 :                 if (strchr(delim, *q) == NULL) {
     135         132 :                         *r++ = *q++;
     136         132 :                         continue;
     137             :                 }
     138             : 
     139             :                 /* new string */
     140          12 :                 q++;
     141          12 :                 break;
     142             :         }
     143          24 :         *r = '\0';
     144             : 
     145             :         /* skip tailer */
     146          24 :         while (*q != '\0' && strchr(delim, *q) != NULL) {
     147           0 :                 q++;
     148             :         }
     149          24 :         if (*q != '\0') {
     150          12 :                 *stringp = q;
     151             :         } else {
     152          12 :                 *stringp = NULL;
     153             :         }
     154             : 
     155          24 :         return p;
     156             : }
     157             : 
     158             : char *
     159           0 : spdk_str_trim(char *s)
     160             : {
     161             :         char *p, *q;
     162             : 
     163           0 :         if (s == NULL) {
     164           0 :                 return NULL;
     165             :         }
     166             : 
     167             :         /* remove header */
     168           0 :         p = s;
     169           0 :         while (*p != '\0' && isspace(*p)) {
     170           0 :                 p++;
     171             :         }
     172             : 
     173             :         /* remove tailer */
     174           0 :         q = p + strlen(p);
     175           0 :         while (q - 1 >= p && isspace(*(q - 1))) {
     176           0 :                 q--;
     177           0 :                 *q = '\0';
     178             :         }
     179             : 
     180             :         /* if remove header, move */
     181           0 :         if (p != s) {
     182           0 :                 q = s;
     183           0 :                 while (*p != '\0') {
     184           0 :                         *q++ = *p++;
     185             :                 }
     186           0 :                 *q = '\0';
     187             :         }
     188             : 
     189           0 :         return s;
     190             : }
     191             : 
     192             : void
     193        1069 : spdk_strcpy_pad(void *dst, const char *src, size_t size, int pad)
     194             : {
     195             :         size_t len;
     196             : 
     197        1069 :         len = strlen(src);
     198        1069 :         if (len < size) {
     199         812 :                 memcpy(dst, src, len);
     200         812 :                 memset((char *)dst + len, pad, size - len);
     201             :         } else {
     202         257 :                 memcpy(dst, src, size);
     203             :         }
     204        1069 : }
     205             : 
     206             : size_t
     207           2 : spdk_strlen_pad(const void *str, size_t size, int pad)
     208             : {
     209             :         const uint8_t *start;
     210             :         const uint8_t *iter;
     211             :         uint8_t pad_byte;
     212             : 
     213           2 :         pad_byte = (uint8_t)pad;
     214           2 :         start = (const uint8_t *)str;
     215             : 
     216           2 :         if (size == 0) {
     217           0 :                 return 0;
     218             :         }
     219             : 
     220           2 :         iter = start + size - 1;
     221             :         while (1) {
     222           2 :                 if (*iter != pad_byte) {
     223           2 :                         return iter - start + 1;
     224             :                 }
     225             : 
     226           0 :                 if (iter == start) {
     227             :                         /* Hit the start of the string finding only pad_byte. */
     228           0 :                         return 0;
     229             :                 }
     230           0 :                 iter--;
     231             :         }
     232             : }
     233             : 
     234             : int
     235           5 : spdk_parse_ip_addr(char *ip, char **host, char **port)
     236             : {
     237             :         char *p;
     238             : 
     239           5 :         if (ip == NULL) {
     240           0 :                 return -EINVAL;
     241             :         }
     242             : 
     243           5 :         *host = NULL;
     244           5 :         *port = NULL;
     245             : 
     246           5 :         if (ip[0] == '[') {
     247             :                 /* IPv6 */
     248           3 :                 p = strchr(ip, ']');
     249           3 :                 if (p == NULL) {
     250           0 :                         return -EINVAL;
     251             :                 }
     252           3 :                 *host = &ip[1];
     253           3 :                 *p = '\0';
     254             : 
     255           3 :                 p++;
     256           3 :                 if (*p == '\0') {
     257           1 :                         return 0;
     258           2 :                 } else if (*p != ':') {
     259           0 :                         return -EINVAL;
     260             :                 }
     261             : 
     262           2 :                 p++;
     263           2 :                 if (*p == '\0') {
     264           1 :                         return 0;
     265             :                 }
     266             : 
     267           1 :                 *port = p;
     268             :         } else {
     269             :                 /* IPv4 */
     270           2 :                 p = strchr(ip, ':');
     271           2 :                 if (p == NULL) {
     272           1 :                         *host = ip;
     273           1 :                         return 0;
     274             :                 }
     275             : 
     276           1 :                 *host = ip;
     277           1 :                 *p = '\0';
     278             : 
     279           1 :                 p++;
     280           1 :                 if (*p == '\0') {
     281           0 :                         return 0;
     282             :                 }
     283             : 
     284           1 :                 *port = p;
     285             :         }
     286             : 
     287           2 :         return 0;
     288             : }
     289             : 
     290             : size_t
     291           9 : spdk_str_chomp(char *s)
     292             : {
     293           9 :         size_t len = strlen(s);
     294           9 :         size_t removed = 0;
     295             : 
     296          15 :         while (len > 0) {
     297          13 :                 if (s[len - 1] != '\r' && s[len - 1] != '\n') {
     298           7 :                         break;
     299             :                 }
     300             : 
     301           6 :                 s[len - 1] = '\0';
     302           6 :                 len--;
     303           6 :                 removed++;
     304             :         }
     305             : 
     306           9 :         return removed;
     307             : }
     308             : 
     309             : void
     310          44 : spdk_strerror_r(int errnum, char *buf, size_t buflen)
     311             : {
     312             :         int rc;
     313             : 
     314             : #if defined(__USE_GNU)
     315             :         char *new_buffer;
     316          44 :         new_buffer = strerror_r(errnum, buf, buflen);
     317          44 :         if (new_buffer == buf) {
     318          27 :                 rc = 0;
     319          17 :         } else if (new_buffer != NULL) {
     320          17 :                 snprintf(buf, buflen, "%s", new_buffer);
     321          17 :                 rc = 0;
     322             :         } else {
     323           0 :                 rc = 1;
     324             :         }
     325             : #else
     326             :         rc = strerror_r(errnum, buf, buflen);
     327             : #endif
     328             : 
     329          44 :         if (rc != 0) {
     330           0 :                 snprintf(buf, buflen, "Unknown error %d", errnum);
     331             :         }
     332          44 : }
     333             : 
     334             : int
     335          12 : spdk_parse_capacity(const char *cap_str, uint64_t *cap, bool *has_prefix)
     336             : {
     337             :         int rc;
     338          12 :         char bin_prefix;
     339             : 
     340          12 :         rc = sscanf(cap_str, "%"SCNu64"%c", cap, &bin_prefix);
     341          12 :         if (rc == 1) {
     342           2 :                 if (has_prefix != NULL) {
     343           2 :                         *has_prefix = false;
     344             :                 }
     345           2 :                 return 0;
     346          10 :         } else if (rc == 0) {
     347           2 :                 if (errno == 0) {
     348             :                         /* No scanf matches - the string does not start with a digit */
     349           2 :                         return -EINVAL;
     350             :                 } else {
     351             :                         /* Parsing error */
     352           0 :                         return -errno;
     353             :                 }
     354             :         }
     355             : 
     356           8 :         if (has_prefix != NULL) {
     357           8 :                 *has_prefix = true;
     358             :         }
     359             : 
     360           8 :         switch (bin_prefix) {
     361           4 :         case 'k':
     362             :         case 'K':
     363           4 :                 *cap *= 1024;
     364           4 :                 break;
     365           3 :         case 'm':
     366             :         case 'M':
     367           3 :                 *cap *= 1024 * 1024;
     368           3 :                 break;
     369           1 :         case 'g':
     370             :         case 'G':
     371           1 :                 *cap *= 1024 * 1024 * 1024;
     372           1 :                 break;
     373           0 :         default:
     374           0 :                 return -EINVAL;
     375             :         }
     376             : 
     377           8 :         return 0;
     378             : }
     379             : 
     380             : bool
     381        1185 : spdk_mem_all_zero(const void *data, size_t size)
     382             : {
     383        1185 :         const uint8_t *buf = data;
     384             : 
     385   105113006 :         while (size--) {
     386   105111869 :                 if (*buf++ != 0) {
     387          48 :                         return false;
     388             :                 }
     389             :         }
     390             : 
     391        1137 :         return true;
     392             : }
     393             : 
     394             : long int
     395          31 : spdk_strtol(const char *nptr, int base)
     396             : {
     397             :         long val;
     398          31 :         char *endptr;
     399             : 
     400             :         /* Since strtoll() can legitimately return 0, LONG_MAX, or LONG_MIN
     401             :          * on both success and failure, the calling program should set errno
     402             :          * to 0 before the call.
     403             :          */
     404          31 :         errno = 0;
     405             : 
     406          31 :         val = strtol(nptr, &endptr, base);
     407             : 
     408          31 :         if (!errno && *endptr != '\0') {
     409             :                 /* Non integer character was found. */
     410           4 :                 return -EINVAL;
     411          27 :         } else if (errno == ERANGE && (val == LONG_MAX || val == LONG_MIN)) {
     412             :                 /* Overflow occurred. */
     413           2 :                 return -ERANGE;
     414          25 :         } else if (errno != 0 && val == 0) {
     415             :                 /* Other error occurred. */
     416           1 :                 return -errno;
     417          24 :         } else if (val < 0) {
     418             :                 /* Input string was negative number. */
     419           2 :                 return -ERANGE;
     420             :         }
     421             : 
     422          22 :         return val;
     423             : }
     424             : 
     425             : long long int
     426          12 : spdk_strtoll(const char *nptr, int base)
     427             : {
     428             :         long long val;
     429          12 :         char *endptr;
     430             : 
     431             :         /* Since strtoll() can legitimately return 0, LLONG_MAX, or LLONG_MIN
     432             :          * on both success and failure, the calling program should set errno
     433             :          * to 0 before the call.
     434             :          */
     435          12 :         errno = 0;
     436             : 
     437          12 :         val = strtoll(nptr, &endptr, base);
     438             : 
     439          12 :         if (!errno && *endptr != '\0') {
     440             :                 /* Non integer character was found. */
     441           3 :                 return -EINVAL;
     442           9 :         } else if (errno == ERANGE && (val == LLONG_MAX || val == LLONG_MIN)) {
     443             :                 /* Overflow occurred. */
     444           2 :                 return -ERANGE;
     445           7 :         } else if (errno != 0 && val == 0) {
     446             :                 /* Other error occurred. */
     447           1 :                 return -errno;
     448           6 :         } else if (val < 0) {
     449             :                 /* Input string was negative number. */
     450           2 :                 return -ERANGE;
     451             :         }
     452             : 
     453           4 :         return val;
     454             : }
     455             : 
     456             : void
     457          14 : spdk_strarray_free(char **strarray)
     458             : {
     459             :         size_t i;
     460             : 
     461          14 :         if (strarray == NULL) {
     462           5 :                 return;
     463             :         }
     464             : 
     465          34 :         for (i = 0; strarray[i] != NULL; i++) {
     466          25 :                 free(strarray[i]);
     467             :         }
     468           9 :         free(strarray);
     469             : }
     470             : 
     471             : char **
     472           8 : spdk_strarray_from_string(const char *str, const char *delim)
     473             : {
     474           8 :         const char *c = str;
     475           8 :         size_t count = 0;
     476             :         char **result;
     477             :         size_t i;
     478             : 
     479           8 :         assert(str != NULL);
     480           8 :         assert(delim != NULL);
     481             : 
     482             :         /* Count number of entries. */
     483          12 :         for (;;) {
     484          20 :                 const char *next = strpbrk(c, delim);
     485             : 
     486          20 :                 count++;
     487             : 
     488          20 :                 if (next == NULL) {
     489           8 :                         break;
     490             :                 }
     491             : 
     492          12 :                 c = next + 1;
     493             :         }
     494             : 
     495             :         /* Account for the terminating NULL entry. */
     496           8 :         result = calloc(count + 1, sizeof(char *));
     497           8 :         if (result == NULL) {
     498           0 :                 return NULL;
     499             :         }
     500             : 
     501           8 :         c = str;
     502             : 
     503          28 :         for (i = 0; i < count; i++) {
     504          20 :                 const char *next = strpbrk(c, delim);
     505             : 
     506          20 :                 if (next == NULL) {
     507           8 :                         result[i] = strdup(c);
     508             :                 } else {
     509          12 :                         result[i] = strndup(c, next - c);
     510             :                 }
     511             : 
     512          20 :                 if (result[i] == NULL) {
     513           0 :                         spdk_strarray_free(result);
     514           0 :                         return NULL;
     515             :                 }
     516             : 
     517          20 :                 if (next != NULL) {
     518          12 :                         c = next + 1;
     519             :                 }
     520             :         }
     521             : 
     522           8 :         return result;
     523             : }
     524             : 
     525             : char **
     526           1 : spdk_strarray_dup(const char **strarray)
     527             : {
     528             :         size_t count, i;
     529             :         char **result;
     530             : 
     531           1 :         assert(strarray != NULL);
     532             : 
     533           6 :         for (count = 0; strarray[count] != NULL; count++)
     534             :                 ;
     535             : 
     536           1 :         result = calloc(count + 1, sizeof(char *));
     537           1 :         if (result == NULL) {
     538           0 :                 return NULL;
     539             :         }
     540             : 
     541           6 :         for (i = 0; i < count; i++) {
     542           5 :                 result[i] = strdup(strarray[i]);
     543           5 :                 if (result[i] == NULL) {
     544           0 :                         spdk_strarray_free(result);
     545           0 :                         return NULL;
     546             :                 }
     547             :         }
     548             : 
     549           1 :         return result;
     550             : }
     551             : 
     552             : int
     553           9 : spdk_strcpy_replace(char *dst, size_t size, const char *src, const char *search,
     554             :                     const char *replace)
     555             : {
     556             :         const char *p, *q;
     557             :         char *r;
     558             :         size_t c, search_size, replace_size, dst_size;
     559             : 
     560           9 :         if (dst == NULL || src == NULL || search == NULL || replace == NULL) {
     561           1 :                 return -EINVAL;
     562             :         }
     563             : 
     564           8 :         search_size = strlen(search);
     565           8 :         replace_size = strlen(replace);
     566             : 
     567           8 :         c = 0;
     568          19 :         for (p = strstr(src, search); p != NULL; p = strstr(p + search_size, search)) {
     569          11 :                 c++;
     570             :         }
     571             : 
     572           8 :         dst_size = strlen(src) + (replace_size - search_size) * c;
     573           8 :         if (dst_size >= size) {
     574           1 :                 return -EINVAL;
     575             :         }
     576             : 
     577           7 :         q = src;
     578           7 :         r = dst;
     579             : 
     580          17 :         for (p = strstr(src, search); p != NULL; p = strstr(p + search_size, search)) {
     581          10 :                 memcpy(r, q, p - q);
     582          10 :                 r += p - q;
     583             : 
     584          10 :                 memcpy(r, replace, replace_size);
     585          10 :                 r += replace_size;
     586             : 
     587          10 :                 q = p + search_size;
     588             :         }
     589             : 
     590           7 :         memcpy(r, q, strlen(q));
     591           7 :         r += strlen(q);
     592             : 
     593           7 :         *r = '\0';
     594             : 
     595           7 :         return 0;
     596             : }

Generated by: LCOV version 1.15