1488570ebSJim Harris /* SPDX-License-Identifier: BSD-3-Clause
2a6dbe372Spaul luse * Copyright (C) 2015 Intel Corporation.
3d6e57b53SShuhei Matsumoto * Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES.
492da7447SDaniel Verkamp * All rights reserved.
592da7447SDaniel Verkamp */
692da7447SDaniel Verkamp
7b961d9ccSBen Walker #include "spdk/stdinc.h"
892da7447SDaniel Verkamp
992da7447SDaniel Verkamp #include "spdk/string.h"
1092da7447SDaniel Verkamp
1192da7447SDaniel Verkamp char *
spdk_vsprintf_append_realloc(char * buffer,const char * format,va_list args)128adbd909SShuhei Matsumoto spdk_vsprintf_append_realloc(char *buffer, const char *format, va_list args)
1392da7447SDaniel Verkamp {
14b4bd76bcSDaniel Verkamp va_list args_copy;
158adbd909SShuhei Matsumoto char *new_buffer;
168adbd909SShuhei Matsumoto int orig_size = 0, new_size;
1792da7447SDaniel Verkamp
188adbd909SShuhei Matsumoto /* Original buffer size */
198adbd909SShuhei Matsumoto if (buffer) {
208adbd909SShuhei Matsumoto orig_size = strlen(buffer);
2192da7447SDaniel Verkamp }
2292da7447SDaniel Verkamp
238adbd909SShuhei Matsumoto /* Necessary buffer size */
24b4bd76bcSDaniel Verkamp va_copy(args_copy, args);
258adbd909SShuhei Matsumoto new_size = vsnprintf(NULL, 0, format, args_copy);
26b4bd76bcSDaniel Verkamp va_end(args_copy);
2792da7447SDaniel Verkamp
288adbd909SShuhei Matsumoto if (new_size < 0) {
2992da7447SDaniel Verkamp return NULL;
3092da7447SDaniel Verkamp }
318adbd909SShuhei Matsumoto new_size += orig_size + 1;
328adbd909SShuhei Matsumoto
338adbd909SShuhei Matsumoto new_buffer = realloc(buffer, new_size);
348adbd909SShuhei Matsumoto if (new_buffer == NULL) {
358adbd909SShuhei Matsumoto return NULL;
368adbd909SShuhei Matsumoto }
378adbd909SShuhei Matsumoto
388adbd909SShuhei Matsumoto vsnprintf(new_buffer + orig_size, new_size - orig_size, format, args);
398adbd909SShuhei Matsumoto
408adbd909SShuhei Matsumoto return new_buffer;
418adbd909SShuhei Matsumoto }
428adbd909SShuhei Matsumoto
438adbd909SShuhei Matsumoto char *
spdk_sprintf_append_realloc(char * buffer,const char * format,...)448adbd909SShuhei Matsumoto spdk_sprintf_append_realloc(char *buffer, const char *format, ...)
458adbd909SShuhei Matsumoto {
468adbd909SShuhei Matsumoto va_list args;
478adbd909SShuhei Matsumoto char *ret;
488adbd909SShuhei Matsumoto
498adbd909SShuhei Matsumoto va_start(args, format);
508adbd909SShuhei Matsumoto ret = spdk_vsprintf_append_realloc(buffer, format, args);
518adbd909SShuhei Matsumoto va_end(args);
528adbd909SShuhei Matsumoto
538adbd909SShuhei Matsumoto return ret;
548adbd909SShuhei Matsumoto }
558adbd909SShuhei Matsumoto
568adbd909SShuhei Matsumoto char *
spdk_vsprintf_alloc(const char * format,va_list args)578adbd909SShuhei Matsumoto spdk_vsprintf_alloc(const char *format, va_list args)
588adbd909SShuhei Matsumoto {
598adbd909SShuhei Matsumoto return spdk_vsprintf_append_realloc(NULL, format, args);
608adbd909SShuhei Matsumoto }
61c5611b26SDaniel Verkamp
62c5611b26SDaniel Verkamp char *
spdk_sprintf_alloc(const char * format,...)63b4bd76bcSDaniel Verkamp spdk_sprintf_alloc(const char *format, ...)
64b4bd76bcSDaniel Verkamp {
65b4bd76bcSDaniel Verkamp va_list args;
66b4bd76bcSDaniel Verkamp char *ret;
67b4bd76bcSDaniel Verkamp
68b4bd76bcSDaniel Verkamp va_start(args, format);
69b4bd76bcSDaniel Verkamp ret = spdk_vsprintf_alloc(format, args);
70b4bd76bcSDaniel Verkamp va_end(args);
71b4bd76bcSDaniel Verkamp
72b4bd76bcSDaniel Verkamp return ret;
73b4bd76bcSDaniel Verkamp }
74b4bd76bcSDaniel Verkamp
75b4bd76bcSDaniel Verkamp char *
spdk_strlwr(char * s)76c5611b26SDaniel Verkamp spdk_strlwr(char *s)
77c5611b26SDaniel Verkamp {
78c5611b26SDaniel Verkamp char *p;
79c5611b26SDaniel Verkamp
80c5611b26SDaniel Verkamp if (s == NULL) {
81c5611b26SDaniel Verkamp return NULL;
82c5611b26SDaniel Verkamp }
83c5611b26SDaniel Verkamp
84c5611b26SDaniel Verkamp p = s;
85c5611b26SDaniel Verkamp while (*p != '\0') {
86c5611b26SDaniel Verkamp *p = tolower(*p);
87c5611b26SDaniel Verkamp p++;
88c5611b26SDaniel Verkamp }
89c5611b26SDaniel Verkamp
90c5611b26SDaniel Verkamp return s;
91c5611b26SDaniel Verkamp }
92e56aab98SDaniel Verkamp
93e56aab98SDaniel Verkamp char *
spdk_strsepq(char ** stringp,const char * delim)94e56aab98SDaniel Verkamp spdk_strsepq(char **stringp, const char *delim)
95e56aab98SDaniel Verkamp {
96e56aab98SDaniel Verkamp char *p, *q, *r;
97e56aab98SDaniel Verkamp int quoted = 0, bslash = 0;
98e56aab98SDaniel Verkamp
99e56aab98SDaniel Verkamp p = *stringp;
100e56aab98SDaniel Verkamp if (p == NULL) {
101e56aab98SDaniel Verkamp return NULL;
102e56aab98SDaniel Verkamp }
103e56aab98SDaniel Verkamp
104e56aab98SDaniel Verkamp r = q = p;
105e56aab98SDaniel Verkamp while (*q != '\0' && *q != '\n') {
106e56aab98SDaniel Verkamp /* eat quoted characters */
107e56aab98SDaniel Verkamp if (bslash) {
108e56aab98SDaniel Verkamp bslash = 0;
109e56aab98SDaniel Verkamp *r++ = *q++;
110e56aab98SDaniel Verkamp continue;
111e56aab98SDaniel Verkamp } else if (quoted) {
112e56aab98SDaniel Verkamp if (quoted == '"' && *q == '\\') {
113e56aab98SDaniel Verkamp bslash = 1;
114e56aab98SDaniel Verkamp q++;
115e56aab98SDaniel Verkamp continue;
116e56aab98SDaniel Verkamp } else if (*q == quoted) {
117e56aab98SDaniel Verkamp quoted = 0;
118e56aab98SDaniel Verkamp q++;
119e56aab98SDaniel Verkamp continue;
120e56aab98SDaniel Verkamp }
121e56aab98SDaniel Verkamp *r++ = *q++;
122e56aab98SDaniel Verkamp continue;
123e56aab98SDaniel Verkamp } else if (*q == '\\') {
124e56aab98SDaniel Verkamp bslash = 1;
125e56aab98SDaniel Verkamp q++;
126e56aab98SDaniel Verkamp continue;
127e56aab98SDaniel Verkamp } else if (*q == '"' || *q == '\'') {
128e56aab98SDaniel Verkamp quoted = *q;
129e56aab98SDaniel Verkamp q++;
130e56aab98SDaniel Verkamp continue;
131e56aab98SDaniel Verkamp }
132e56aab98SDaniel Verkamp
133e56aab98SDaniel Verkamp /* separator? */
134e56aab98SDaniel Verkamp if (strchr(delim, *q) == NULL) {
135e56aab98SDaniel Verkamp *r++ = *q++;
136e56aab98SDaniel Verkamp continue;
137e56aab98SDaniel Verkamp }
138e56aab98SDaniel Verkamp
139e56aab98SDaniel Verkamp /* new string */
140e56aab98SDaniel Verkamp q++;
141e56aab98SDaniel Verkamp break;
142e56aab98SDaniel Verkamp }
143e56aab98SDaniel Verkamp *r = '\0';
144e56aab98SDaniel Verkamp
145e56aab98SDaniel Verkamp /* skip tailer */
146e56aab98SDaniel Verkamp while (*q != '\0' && strchr(delim, *q) != NULL) {
147e56aab98SDaniel Verkamp q++;
148e56aab98SDaniel Verkamp }
149e56aab98SDaniel Verkamp if (*q != '\0') {
150e56aab98SDaniel Verkamp *stringp = q;
151e56aab98SDaniel Verkamp } else {
152e56aab98SDaniel Verkamp *stringp = NULL;
153e56aab98SDaniel Verkamp }
154e56aab98SDaniel Verkamp
155e56aab98SDaniel Verkamp return p;
156e56aab98SDaniel Verkamp }
157d0cbec4aSDaniel Verkamp
158d0cbec4aSDaniel Verkamp char *
spdk_str_trim(char * s)159d0cbec4aSDaniel Verkamp spdk_str_trim(char *s)
160d0cbec4aSDaniel Verkamp {
161d0cbec4aSDaniel Verkamp char *p, *q;
162d0cbec4aSDaniel Verkamp
163d0cbec4aSDaniel Verkamp if (s == NULL) {
164d0cbec4aSDaniel Verkamp return NULL;
165d0cbec4aSDaniel Verkamp }
166d0cbec4aSDaniel Verkamp
167d0cbec4aSDaniel Verkamp /* remove header */
168d0cbec4aSDaniel Verkamp p = s;
169d0cbec4aSDaniel Verkamp while (*p != '\0' && isspace(*p)) {
170d0cbec4aSDaniel Verkamp p++;
171d0cbec4aSDaniel Verkamp }
172d0cbec4aSDaniel Verkamp
173d0cbec4aSDaniel Verkamp /* remove tailer */
174d0cbec4aSDaniel Verkamp q = p + strlen(p);
175d0cbec4aSDaniel Verkamp while (q - 1 >= p && isspace(*(q - 1))) {
176d0cbec4aSDaniel Verkamp q--;
177d0cbec4aSDaniel Verkamp *q = '\0';
178d0cbec4aSDaniel Verkamp }
179d0cbec4aSDaniel Verkamp
180d0cbec4aSDaniel Verkamp /* if remove header, move */
181d0cbec4aSDaniel Verkamp if (p != s) {
182d0cbec4aSDaniel Verkamp q = s;
183d0cbec4aSDaniel Verkamp while (*p != '\0') {
184d0cbec4aSDaniel Verkamp *q++ = *p++;
185d0cbec4aSDaniel Verkamp }
186d0cbec4aSDaniel Verkamp *q = '\0';
187d0cbec4aSDaniel Verkamp }
188d0cbec4aSDaniel Verkamp
189d0cbec4aSDaniel Verkamp return s;
190d0cbec4aSDaniel Verkamp }
19198c8867eSDaniel Verkamp
19298c8867eSDaniel Verkamp void
spdk_strcpy_pad(void * dst,const char * src,size_t size,int pad)19398c8867eSDaniel Verkamp spdk_strcpy_pad(void *dst, const char *src, size_t size, int pad)
19498c8867eSDaniel Verkamp {
19598c8867eSDaniel Verkamp size_t len;
19698c8867eSDaniel Verkamp
19798c8867eSDaniel Verkamp len = strlen(src);
19898c8867eSDaniel Verkamp if (len < size) {
19998c8867eSDaniel Verkamp memcpy(dst, src, len);
20098c8867eSDaniel Verkamp memset((char *)dst + len, pad, size - len);
20198c8867eSDaniel Verkamp } else {
20298c8867eSDaniel Verkamp memcpy(dst, src, size);
20398c8867eSDaniel Verkamp }
20498c8867eSDaniel Verkamp }
205ae6fbf1dSDaniel Verkamp
206ae6fbf1dSDaniel Verkamp size_t
spdk_strlen_pad(const void * str,size_t size,int pad)207ae6fbf1dSDaniel Verkamp spdk_strlen_pad(const void *str, size_t size, int pad)
208ae6fbf1dSDaniel Verkamp {
209ae6fbf1dSDaniel Verkamp const uint8_t *start;
210ae6fbf1dSDaniel Verkamp const uint8_t *iter;
211ae6fbf1dSDaniel Verkamp uint8_t pad_byte;
212ae6fbf1dSDaniel Verkamp
213ae6fbf1dSDaniel Verkamp pad_byte = (uint8_t)pad;
214ae6fbf1dSDaniel Verkamp start = (const uint8_t *)str;
215ae6fbf1dSDaniel Verkamp
216ae6fbf1dSDaniel Verkamp if (size == 0) {
217ae6fbf1dSDaniel Verkamp return 0;
218ae6fbf1dSDaniel Verkamp }
219ae6fbf1dSDaniel Verkamp
220ae6fbf1dSDaniel Verkamp iter = start + size - 1;
221ae6fbf1dSDaniel Verkamp while (1) {
222ae6fbf1dSDaniel Verkamp if (*iter != pad_byte) {
223ae6fbf1dSDaniel Verkamp return iter - start + 1;
224ae6fbf1dSDaniel Verkamp }
225ae6fbf1dSDaniel Verkamp
226ae6fbf1dSDaniel Verkamp if (iter == start) {
227ae6fbf1dSDaniel Verkamp /* Hit the start of the string finding only pad_byte. */
228ae6fbf1dSDaniel Verkamp return 0;
229ae6fbf1dSDaniel Verkamp }
230ae6fbf1dSDaniel Verkamp iter--;
231ae6fbf1dSDaniel Verkamp }
232ae6fbf1dSDaniel Verkamp }
23308238af7SBen Walker
23408238af7SBen Walker int
spdk_parse_ip_addr(char * ip,char ** host,char ** port)2354404793dSDaniel Verkamp spdk_parse_ip_addr(char *ip, char **host, char **port)
23608238af7SBen Walker {
23708238af7SBen Walker char *p;
23808238af7SBen Walker
23908238af7SBen Walker if (ip == NULL) {
2407818939cSPawel Wodkowski return -EINVAL;
24108238af7SBen Walker }
24208238af7SBen Walker
24308238af7SBen Walker *host = NULL;
24408238af7SBen Walker *port = NULL;
24508238af7SBen Walker
24608238af7SBen Walker if (ip[0] == '[') {
24708238af7SBen Walker /* IPv6 */
24808238af7SBen Walker p = strchr(ip, ']');
24908238af7SBen Walker if (p == NULL) {
2507818939cSPawel Wodkowski return -EINVAL;
25108238af7SBen Walker }
25208238af7SBen Walker *host = &ip[1];
25308238af7SBen Walker *p = '\0';
25408238af7SBen Walker
25508238af7SBen Walker p++;
25608238af7SBen Walker if (*p == '\0') {
25708238af7SBen Walker return 0;
25808238af7SBen Walker } else if (*p != ':') {
2597818939cSPawel Wodkowski return -EINVAL;
26008238af7SBen Walker }
26108238af7SBen Walker
26208238af7SBen Walker p++;
26308238af7SBen Walker if (*p == '\0') {
26408238af7SBen Walker return 0;
26508238af7SBen Walker }
26608238af7SBen Walker
26708238af7SBen Walker *port = p;
26808238af7SBen Walker } else {
26908238af7SBen Walker /* IPv4 */
27008238af7SBen Walker p = strchr(ip, ':');
27108238af7SBen Walker if (p == NULL) {
27208238af7SBen Walker *host = ip;
27308238af7SBen Walker return 0;
27408238af7SBen Walker }
27508238af7SBen Walker
27608238af7SBen Walker *host = ip;
27708238af7SBen Walker *p = '\0';
27808238af7SBen Walker
27908238af7SBen Walker p++;
28008238af7SBen Walker if (*p == '\0') {
28108238af7SBen Walker return 0;
28208238af7SBen Walker }
28308238af7SBen Walker
28408238af7SBen Walker *port = p;
28508238af7SBen Walker }
28608238af7SBen Walker
28708238af7SBen Walker return 0;
28808238af7SBen Walker }
28916c362a8SDaniel Verkamp
29016c362a8SDaniel Verkamp size_t
spdk_str_chomp(char * s)29116c362a8SDaniel Verkamp spdk_str_chomp(char *s)
29216c362a8SDaniel Verkamp {
29316c362a8SDaniel Verkamp size_t len = strlen(s);
29416c362a8SDaniel Verkamp size_t removed = 0;
29516c362a8SDaniel Verkamp
29616c362a8SDaniel Verkamp while (len > 0) {
29716c362a8SDaniel Verkamp if (s[len - 1] != '\r' && s[len - 1] != '\n') {
29816c362a8SDaniel Verkamp break;
29916c362a8SDaniel Verkamp }
30016c362a8SDaniel Verkamp
30116c362a8SDaniel Verkamp s[len - 1] = '\0';
30216c362a8SDaniel Verkamp len--;
30316c362a8SDaniel Verkamp removed++;
30416c362a8SDaniel Verkamp }
30516c362a8SDaniel Verkamp
30616c362a8SDaniel Verkamp return removed;
30716c362a8SDaniel Verkamp }
3084d43844fSSeth Howell
30971db3a08SDaniel Verkamp void
spdk_strerror_r(int errnum,char * buf,size_t buflen)3104d43844fSSeth Howell spdk_strerror_r(int errnum, char *buf, size_t buflen)
3114d43844fSSeth Howell {
31271db3a08SDaniel Verkamp int rc;
31371db3a08SDaniel Verkamp
3144d43844fSSeth Howell #if defined(__USE_GNU)
3154d43844fSSeth Howell char *new_buffer;
3164d43844fSSeth Howell new_buffer = strerror_r(errnum, buf, buflen);
317772db556SVitaliy Mysak if (new_buffer == buf) {
318772db556SVitaliy Mysak rc = 0;
319772db556SVitaliy Mysak } else if (new_buffer != NULL) {
3204d43844fSSeth Howell snprintf(buf, buflen, "%s", new_buffer);
32171db3a08SDaniel Verkamp rc = 0;
32271db3a08SDaniel Verkamp } else {
32371db3a08SDaniel Verkamp rc = 1;
3244d43844fSSeth Howell }
3254d43844fSSeth Howell #else
32671db3a08SDaniel Verkamp rc = strerror_r(errnum, buf, buflen);
3274d43844fSSeth Howell #endif
32871db3a08SDaniel Verkamp
32971db3a08SDaniel Verkamp if (rc != 0) {
33071db3a08SDaniel Verkamp snprintf(buf, buflen, "Unknown error %d", errnum);
33171db3a08SDaniel Verkamp }
3324d43844fSSeth Howell }
333ec6a1afbSDariusz Stojaczyk
334ec6a1afbSDariusz Stojaczyk int
spdk_parse_capacity(const char * cap_str,uint64_t * cap,bool * has_prefix)335ec6a1afbSDariusz Stojaczyk spdk_parse_capacity(const char *cap_str, uint64_t *cap, bool *has_prefix)
336ec6a1afbSDariusz Stojaczyk {
337ec6a1afbSDariusz Stojaczyk int rc;
338ec6a1afbSDariusz Stojaczyk char bin_prefix;
339ec6a1afbSDariusz Stojaczyk
340ec6a1afbSDariusz Stojaczyk rc = sscanf(cap_str, "%"SCNu64"%c", cap, &bin_prefix);
341ec6a1afbSDariusz Stojaczyk if (rc == 1) {
342*856388d8SKonrad Sztyber if (has_prefix != NULL) {
343ec6a1afbSDariusz Stojaczyk *has_prefix = false;
344*856388d8SKonrad Sztyber }
345ec6a1afbSDariusz Stojaczyk return 0;
346ec6a1afbSDariusz Stojaczyk } else if (rc == 0) {
347ec6a1afbSDariusz Stojaczyk if (errno == 0) {
348ec6a1afbSDariusz Stojaczyk /* No scanf matches - the string does not start with a digit */
349ec6a1afbSDariusz Stojaczyk return -EINVAL;
350ec6a1afbSDariusz Stojaczyk } else {
351ec6a1afbSDariusz Stojaczyk /* Parsing error */
352ec6a1afbSDariusz Stojaczyk return -errno;
353ec6a1afbSDariusz Stojaczyk }
354ec6a1afbSDariusz Stojaczyk }
355ec6a1afbSDariusz Stojaczyk
356*856388d8SKonrad Sztyber if (has_prefix != NULL) {
357ec6a1afbSDariusz Stojaczyk *has_prefix = true;
358*856388d8SKonrad Sztyber }
359*856388d8SKonrad Sztyber
360ec6a1afbSDariusz Stojaczyk switch (bin_prefix) {
361ec6a1afbSDariusz Stojaczyk case 'k':
362ec6a1afbSDariusz Stojaczyk case 'K':
363ec6a1afbSDariusz Stojaczyk *cap *= 1024;
364ec6a1afbSDariusz Stojaczyk break;
365ec6a1afbSDariusz Stojaczyk case 'm':
366ec6a1afbSDariusz Stojaczyk case 'M':
367ec6a1afbSDariusz Stojaczyk *cap *= 1024 * 1024;
368ec6a1afbSDariusz Stojaczyk break;
369ec6a1afbSDariusz Stojaczyk case 'g':
370ec6a1afbSDariusz Stojaczyk case 'G':
371ec6a1afbSDariusz Stojaczyk *cap *= 1024 * 1024 * 1024;
372ec6a1afbSDariusz Stojaczyk break;
373ec6a1afbSDariusz Stojaczyk default:
374ec6a1afbSDariusz Stojaczyk return -EINVAL;
375ec6a1afbSDariusz Stojaczyk }
376ec6a1afbSDariusz Stojaczyk
377ec6a1afbSDariusz Stojaczyk return 0;
378ec6a1afbSDariusz Stojaczyk }
379d81f3dfdSDaniel Verkamp
380d81f3dfdSDaniel Verkamp bool
spdk_mem_all_zero(const void * data,size_t size)381d81f3dfdSDaniel Verkamp spdk_mem_all_zero(const void *data, size_t size)
382d81f3dfdSDaniel Verkamp {
383d81f3dfdSDaniel Verkamp const uint8_t *buf = data;
384d81f3dfdSDaniel Verkamp
385d81f3dfdSDaniel Verkamp while (size--) {
386d81f3dfdSDaniel Verkamp if (*buf++ != 0) {
387d81f3dfdSDaniel Verkamp return false;
388d81f3dfdSDaniel Verkamp }
389d81f3dfdSDaniel Verkamp }
390d81f3dfdSDaniel Verkamp
391d81f3dfdSDaniel Verkamp return true;
392d81f3dfdSDaniel Verkamp }
393b78e763cSShuhei Matsumoto
394b78e763cSShuhei Matsumoto long int
spdk_strtol(const char * nptr,int base)395b78e763cSShuhei Matsumoto spdk_strtol(const char *nptr, int base)
396b78e763cSShuhei Matsumoto {
397b78e763cSShuhei Matsumoto long val;
398b78e763cSShuhei Matsumoto char *endptr;
399b78e763cSShuhei Matsumoto
400b78e763cSShuhei Matsumoto /* Since strtoll() can legitimately return 0, LONG_MAX, or LONG_MIN
401b78e763cSShuhei Matsumoto * on both success and failure, the calling program should set errno
402b78e763cSShuhei Matsumoto * to 0 before the call.
403b78e763cSShuhei Matsumoto */
404b78e763cSShuhei Matsumoto errno = 0;
405b78e763cSShuhei Matsumoto
406b78e763cSShuhei Matsumoto val = strtol(nptr, &endptr, base);
407b78e763cSShuhei Matsumoto
408f0e6bbeaSWojciech Malikowski if (!errno && *endptr != '\0') {
409b78e763cSShuhei Matsumoto /* Non integer character was found. */
410b78e763cSShuhei Matsumoto return -EINVAL;
411b78e763cSShuhei Matsumoto } else if (errno == ERANGE && (val == LONG_MAX || val == LONG_MIN)) {
412b78e763cSShuhei Matsumoto /* Overflow occurred. */
413b78e763cSShuhei Matsumoto return -ERANGE;
414b78e763cSShuhei Matsumoto } else if (errno != 0 && val == 0) {
415b78e763cSShuhei Matsumoto /* Other error occurred. */
416b78e763cSShuhei Matsumoto return -errno;
417b78e763cSShuhei Matsumoto } else if (val < 0) {
418b78e763cSShuhei Matsumoto /* Input string was negative number. */
419b78e763cSShuhei Matsumoto return -ERANGE;
420b78e763cSShuhei Matsumoto }
421b78e763cSShuhei Matsumoto
422b78e763cSShuhei Matsumoto return val;
423b78e763cSShuhei Matsumoto }
424b78e763cSShuhei Matsumoto
425b78e763cSShuhei Matsumoto long long int
spdk_strtoll(const char * nptr,int base)426b78e763cSShuhei Matsumoto spdk_strtoll(const char *nptr, int base)
427b78e763cSShuhei Matsumoto {
428b78e763cSShuhei Matsumoto long long val;
429b78e763cSShuhei Matsumoto char *endptr;
430b78e763cSShuhei Matsumoto
431b78e763cSShuhei Matsumoto /* Since strtoll() can legitimately return 0, LLONG_MAX, or LLONG_MIN
432b78e763cSShuhei Matsumoto * on both success and failure, the calling program should set errno
433b78e763cSShuhei Matsumoto * to 0 before the call.
434b78e763cSShuhei Matsumoto */
435b78e763cSShuhei Matsumoto errno = 0;
436b78e763cSShuhei Matsumoto
437b78e763cSShuhei Matsumoto val = strtoll(nptr, &endptr, base);
438b78e763cSShuhei Matsumoto
439f0e6bbeaSWojciech Malikowski if (!errno && *endptr != '\0') {
440b78e763cSShuhei Matsumoto /* Non integer character was found. */
441b78e763cSShuhei Matsumoto return -EINVAL;
442b78e763cSShuhei Matsumoto } else if (errno == ERANGE && (val == LLONG_MAX || val == LLONG_MIN)) {
443b78e763cSShuhei Matsumoto /* Overflow occurred. */
444b78e763cSShuhei Matsumoto return -ERANGE;
445b78e763cSShuhei Matsumoto } else if (errno != 0 && val == 0) {
446b78e763cSShuhei Matsumoto /* Other error occurred. */
447b78e763cSShuhei Matsumoto return -errno;
448b78e763cSShuhei Matsumoto } else if (val < 0) {
449b78e763cSShuhei Matsumoto /* Input string was negative number. */
450b78e763cSShuhei Matsumoto return -ERANGE;
451b78e763cSShuhei Matsumoto }
452b78e763cSShuhei Matsumoto
453b78e763cSShuhei Matsumoto return val;
454b78e763cSShuhei Matsumoto }
4551139cb14SJohn Levon
4561139cb14SJohn Levon void
spdk_strarray_free(char ** strarray)4571139cb14SJohn Levon spdk_strarray_free(char **strarray)
4581139cb14SJohn Levon {
4591139cb14SJohn Levon size_t i;
4601139cb14SJohn Levon
4611139cb14SJohn Levon if (strarray == NULL) {
4621139cb14SJohn Levon return;
4631139cb14SJohn Levon }
4641139cb14SJohn Levon
4651139cb14SJohn Levon for (i = 0; strarray[i] != NULL; i++) {
4661139cb14SJohn Levon free(strarray[i]);
4671139cb14SJohn Levon }
4681139cb14SJohn Levon free(strarray);
4691139cb14SJohn Levon }
4701139cb14SJohn Levon
4711139cb14SJohn Levon char **
spdk_strarray_from_string(const char * str,const char * delim)4721139cb14SJohn Levon spdk_strarray_from_string(const char *str, const char *delim)
4731139cb14SJohn Levon {
4741139cb14SJohn Levon const char *c = str;
4751139cb14SJohn Levon size_t count = 0;
4761139cb14SJohn Levon char **result;
4771139cb14SJohn Levon size_t i;
4781139cb14SJohn Levon
4791139cb14SJohn Levon assert(str != NULL);
4801139cb14SJohn Levon assert(delim != NULL);
4811139cb14SJohn Levon
4821139cb14SJohn Levon /* Count number of entries. */
4831139cb14SJohn Levon for (;;) {
4841139cb14SJohn Levon const char *next = strpbrk(c, delim);
4851139cb14SJohn Levon
4861139cb14SJohn Levon count++;
4871139cb14SJohn Levon
4881139cb14SJohn Levon if (next == NULL) {
4891139cb14SJohn Levon break;
4901139cb14SJohn Levon }
4911139cb14SJohn Levon
4921139cb14SJohn Levon c = next + 1;
4931139cb14SJohn Levon }
4941139cb14SJohn Levon
4951139cb14SJohn Levon /* Account for the terminating NULL entry. */
4961139cb14SJohn Levon result = calloc(count + 1, sizeof(char *));
4971139cb14SJohn Levon if (result == NULL) {
4981139cb14SJohn Levon return NULL;
4991139cb14SJohn Levon }
5001139cb14SJohn Levon
5011139cb14SJohn Levon c = str;
5021139cb14SJohn Levon
5031139cb14SJohn Levon for (i = 0; i < count; i++) {
5041139cb14SJohn Levon const char *next = strpbrk(c, delim);
5051139cb14SJohn Levon
5061139cb14SJohn Levon if (next == NULL) {
5071139cb14SJohn Levon result[i] = strdup(c);
5081139cb14SJohn Levon } else {
5091139cb14SJohn Levon result[i] = strndup(c, next - c);
5101139cb14SJohn Levon }
5111139cb14SJohn Levon
5121139cb14SJohn Levon if (result[i] == NULL) {
5131139cb14SJohn Levon spdk_strarray_free(result);
5141139cb14SJohn Levon return NULL;
5151139cb14SJohn Levon }
5161139cb14SJohn Levon
5171139cb14SJohn Levon if (next != NULL) {
5181139cb14SJohn Levon c = next + 1;
5191139cb14SJohn Levon }
5201139cb14SJohn Levon }
5211139cb14SJohn Levon
5221139cb14SJohn Levon return result;
5231139cb14SJohn Levon }
5241139cb14SJohn Levon
5251139cb14SJohn Levon char **
spdk_strarray_dup(const char ** strarray)5261139cb14SJohn Levon spdk_strarray_dup(const char **strarray)
5271139cb14SJohn Levon {
5281139cb14SJohn Levon size_t count, i;
5291139cb14SJohn Levon char **result;
5301139cb14SJohn Levon
5311139cb14SJohn Levon assert(strarray != NULL);
5321139cb14SJohn Levon
5331139cb14SJohn Levon for (count = 0; strarray[count] != NULL; count++)
5341139cb14SJohn Levon ;
5351139cb14SJohn Levon
5361139cb14SJohn Levon result = calloc(count + 1, sizeof(char *));
5371139cb14SJohn Levon if (result == NULL) {
5381139cb14SJohn Levon return NULL;
5391139cb14SJohn Levon }
5401139cb14SJohn Levon
5411139cb14SJohn Levon for (i = 0; i < count; i++) {
5421139cb14SJohn Levon result[i] = strdup(strarray[i]);
5431139cb14SJohn Levon if (result[i] == NULL) {
5441139cb14SJohn Levon spdk_strarray_free(result);
5451139cb14SJohn Levon return NULL;
5461139cb14SJohn Levon }
5471139cb14SJohn Levon }
5481139cb14SJohn Levon
5491139cb14SJohn Levon return result;
5501139cb14SJohn Levon }
551d6e57b53SShuhei Matsumoto
552d6e57b53SShuhei Matsumoto int
spdk_strcpy_replace(char * dst,size_t size,const char * src,const char * search,const char * replace)553d6e57b53SShuhei Matsumoto spdk_strcpy_replace(char *dst, size_t size, const char *src, const char *search,
554d6e57b53SShuhei Matsumoto const char *replace)
555d6e57b53SShuhei Matsumoto {
556d6e57b53SShuhei Matsumoto const char *p, *q;
557d6e57b53SShuhei Matsumoto char *r;
558d6e57b53SShuhei Matsumoto size_t c, search_size, replace_size, dst_size;
559d6e57b53SShuhei Matsumoto
560d6e57b53SShuhei Matsumoto if (dst == NULL || src == NULL || search == NULL || replace == NULL) {
561d6e57b53SShuhei Matsumoto return -EINVAL;
562d6e57b53SShuhei Matsumoto }
563d6e57b53SShuhei Matsumoto
564d6e57b53SShuhei Matsumoto search_size = strlen(search);
565d6e57b53SShuhei Matsumoto replace_size = strlen(replace);
566d6e57b53SShuhei Matsumoto
567d6e57b53SShuhei Matsumoto c = 0;
568d6e57b53SShuhei Matsumoto for (p = strstr(src, search); p != NULL; p = strstr(p + search_size, search)) {
569d6e57b53SShuhei Matsumoto c++;
570d6e57b53SShuhei Matsumoto }
571d6e57b53SShuhei Matsumoto
572d6e57b53SShuhei Matsumoto dst_size = strlen(src) + (replace_size - search_size) * c;
573d6e57b53SShuhei Matsumoto if (dst_size >= size) {
574d6e57b53SShuhei Matsumoto return -EINVAL;
575d6e57b53SShuhei Matsumoto }
576d6e57b53SShuhei Matsumoto
577d6e57b53SShuhei Matsumoto q = src;
578d6e57b53SShuhei Matsumoto r = dst;
579d6e57b53SShuhei Matsumoto
580d6e57b53SShuhei Matsumoto for (p = strstr(src, search); p != NULL; p = strstr(p + search_size, search)) {
581d6e57b53SShuhei Matsumoto memcpy(r, q, p - q);
582d6e57b53SShuhei Matsumoto r += p - q;
583d6e57b53SShuhei Matsumoto
584d6e57b53SShuhei Matsumoto memcpy(r, replace, replace_size);
585d6e57b53SShuhei Matsumoto r += replace_size;
586d6e57b53SShuhei Matsumoto
587d6e57b53SShuhei Matsumoto q = p + search_size;
588d6e57b53SShuhei Matsumoto }
589d6e57b53SShuhei Matsumoto
590d6e57b53SShuhei Matsumoto memcpy(r, q, strlen(q));
591d6e57b53SShuhei Matsumoto r += strlen(q);
592d6e57b53SShuhei Matsumoto
593d6e57b53SShuhei Matsumoto *r = '\0';
594d6e57b53SShuhei Matsumoto
595d6e57b53SShuhei Matsumoto return 0;
596d6e57b53SShuhei Matsumoto }
597