[PATCH 6/6] vshStringToArray: Rewrite using 'g_strsplit'

Peter Krempa pkrempa at redhat.com
Thu Aug 12 13:01:36 UTC 2021


Use 'g_strsplit' to split the strings and then concatenate back when the
escape sequence (',,') is used.

Signed-off-by: Peter Krempa <pkrempa at redhat.com>
---
 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




More information about the libvir-list mailing list