diff --git a/include/spdk/string.h b/include/spdk/string.h index 172a3dcb2..67512ba34 100644 --- a/include/spdk/string.h +++ b/include/spdk/string.h @@ -54,6 +54,19 @@ char *spdk_sprintf_alloc(const char *format, ...) __attribute__((format(printf, */ char *spdk_strlwr(char *s); +/** + * Parse a delimited string with quote handling. + * + * \param stringp Pointer to starting location in string. *stringp will be updated to point to the + * start of the next field, or NULL if the end of the string has been reached. + * \param delim Null-terminated string containing the list of accepted delimiters. + * + * \return Pointer to beginning of the current field. + * + * Note that the string will be modified in place to add the string terminator to each field. + */ +char *spdk_strsepq(char **stringp, const char *delim); + #ifdef __cplusplus } #endif diff --git a/lib/util/string.c b/lib/util/string.c index 56e124aa1..5355ffa2e 100644 --- a/lib/util/string.c +++ b/lib/util/string.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include "spdk/string.h" @@ -100,3 +101,68 @@ spdk_strlwr(char *s) return s; } + +char * +spdk_strsepq(char **stringp, const char *delim) +{ + char *p, *q, *r; + int quoted = 0, bslash = 0; + + p = *stringp; + if (p == NULL) { + return NULL; + } + + r = q = p; + while (*q != '\0' && *q != '\n') { + /* eat quoted characters */ + if (bslash) { + bslash = 0; + *r++ = *q++; + continue; + } else if (quoted) { + if (quoted == '"' && *q == '\\') { + bslash = 1; + q++; + continue; + } else if (*q == quoted) { + quoted = 0; + q++; + continue; + } + *r++ = *q++; + continue; + } else if (*q == '\\') { + bslash = 1; + q++; + continue; + } else if (*q == '"' || *q == '\'') { + quoted = *q; + q++; + continue; + } + + /* separator? */ + if (strchr(delim, *q) == NULL) { + *r++ = *q++; + continue; + } + + /* new string */ + q++; + break; + } + *r = '\0'; + + /* skip tailer */ + while (*q != '\0' && strchr(delim, *q) != NULL) { + q++; + } + if (*q != '\0') { + *stringp = q; + } else { + *stringp = NULL; + } + + return p; +}