Use 'g_strsplit' to split the strings and then concatenate back when the escape sequence (',,') is used. Signed-off-by: Peter Krempa <pkrempa@xxxxxxxxxx> --- tools/vsh.c | 62 ++++++++++++++++++++++------------------------------- 1 file changed, 26 insertions(+), 36 deletions(-) diff --git a/tools/vsh.c b/tools/vsh.c index cdcf67684e..202a507f2e 100644 --- a/tools/vsh.c +++ b/tools/vsh.c @@ -122,48 +122,38 @@ int vshStringToArray(const char *str, char ***array) { - g_autofree char *str_copied = g_strdup(str); - char *str_tok = NULL; - char *tmp; - unsigned int nstr_tokens = 0; - char **arr = NULL; - size_t len = strlen(str_copied); - - /* tokenize the string from user and save its parts into an array */ - nstr_tokens = 1; - - /* count the delimiters, recognizing ,, as an escape for a - * literal comma */ - str_tok = str_copied; - while ((str_tok = strchr(str_tok, ','))) { - if (str_tok[1] == ',') - str_tok++; - else - nstr_tokens++; - str_tok++; - } + g_auto(GStrv) tmp = NULL; + GStrv n; + size_t ntoks = 0; + bool concat = false; + + tmp = g_strsplit(str, ",", 0); + + *array = g_new0(char *, g_strv_length(tmp) + 1); + (*array)[ntoks++] = g_strdup(tmp[0]); - /* reserve the NULL element at the end */ - arr = g_new0(char *, nstr_tokens + 1); + /* undo splitting of comma escape (',,') by concatenating back on empty strings */ + for (n = tmp + 1; n[0]; n++) { + if (concat) { + g_autofree char *old = (*array)[ntoks - 1]; - /* tokenize the input string, while treating ,, as a literal comma */ - nstr_tokens = 0; - tmp = str_tok = str_copied; - while ((tmp = strchr(tmp, ','))) { - if (tmp[1] == ',') { - memmove(&tmp[1], &tmp[2], len - (tmp - str_copied) - 2 + 1); - len--; - tmp++; + (*array)[ntoks - 1] = g_strconcat(old, ",", n[0], NULL); + concat = false; continue; } - *tmp++ = '\0'; - arr[nstr_tokens++] = g_strdup(str_tok); - str_tok = tmp; + + if (strlen(n[0]) == 0) { + concat = true; + } else { + (*array)[ntoks++] = g_strdup(n[0]); + } } - arr[nstr_tokens++] = g_strdup(str_tok); - *array = arr; - return nstr_tokens; + /* corner case of ending with a single comma */ + if (concat) + (*array)[ntoks++] = g_strdup(""); + + return ntoks; } virErrorPtr last_error; -- 2.31.1