This patch updates kvargs parser to allow comma in list value:
  k1=a[1,2]b[3-5]

Signed-off-by: Xueming Li <xuemi...@nvidia.com>
---
 lib/librte_kvargs/rte_kvargs.c | 82 +++++++++++++++++++++++-----------
 1 file changed, 56 insertions(+), 26 deletions(-)

diff --git a/lib/librte_kvargs/rte_kvargs.c b/lib/librte_kvargs/rte_kvargs.c
index 285081c86c..6193109a17 100644
--- a/lib/librte_kvargs/rte_kvargs.c
+++ b/lib/librte_kvargs/rte_kvargs.c
@@ -13,15 +13,19 @@
 /*
  * Receive a string with a list of arguments following the pattern
  * key=value,key=value,... and insert them into the list.
- * strtok() is used so the params string will be copied to be modified.
+ * Params string will be copied to be modified.
+ * list "[]" and list element splitter ",", "-" is treated as value.
+ * Supported examples:
+ *   k1=v1,k2=v2
+ *   v1
+ *   k1=x[0-1]y[1,3-5,9]z
  */
 static int
 rte_kvargs_tokenize(struct rte_kvargs *kvlist, const char *params)
 {
        unsigned i;
-       char *str;
-       char *ctx1 = NULL;
-       char *ctx2 = NULL;
+       char *str, *start;
+       int in_list = 0, end_k = 0, end_v = 0;
 
        /* Copy the const char *params to a modifiable string
         * to pass to rte_strsplit
@@ -32,36 +36,62 @@ rte_kvargs_tokenize(struct rte_kvargs *kvlist, const char 
*params)
 
        /* browse each key/value pair and add it in kvlist */
        str = kvlist->str;
-       while ((str = strtok_r(str, RTE_KVARGS_PAIRS_DELIM, &ctx1)) != NULL) {
+       start = str; /* start of current key or value */
+       while (1) {
+               switch (*str) {
+               case '=': /* End of key. */
+                       end_k = 1;
+                       break;
+               case ',':
+                       /* End of value, skip comma in middle of range */
+                       if (!in_list)
+                               end_v = 1;
+                       break;
+               case '[': /* Start of list. */
+                       in_list++;
+                       break;
+               case ']': /* End of list.  */
+                       if (in_list)
+                               in_list--;
+                       break;
+               case 0: /* End of string */
+                       end_v = 1;
+                       break;
+               default:
+                       break;
+               }
+
+               if (!end_k && !end_v) {
+                       /* Continue if not end of key or value. */
+                       str++;
+                       continue;
+               }
 
                i = kvlist->count;
                if (i >= RTE_KVARGS_MAX)
                        return -1;
 
-               kvlist->pairs[i].key = strtok_r(str, RTE_KVARGS_KV_DELIM, 
&ctx2);
-               kvlist->pairs[i].value = strtok_r(NULL, RTE_KVARGS_KV_DELIM, 
&ctx2);
-               if (kvlist->pairs[i].key == NULL ||
-                   kvlist->pairs[i].value == NULL)
-                       return -1;
-
-               /* Detect list [a,b] to skip comma delimiter in list. */
-               str = kvlist->pairs[i].value;
-               if (str[0] == '[') {
-                       /* Find the end of the list. */
-                       while (str[strlen(str) - 1] != ']') {
-                               /* Restore the comma erased by strtok_r(). */
-                               if (ctx1 == NULL || ctx1[0] == '\0')
-                                       return -1; /* no closing bracket */
-                               str[strlen(str)] = ',';
-                               /* Parse until next comma. */
-                               str = strtok_r(NULL, RTE_KVARGS_PAIRS_DELIM, 
&ctx1);
-                               if (str == NULL)
-                                       return -1; /* no closing bracket */
+               if (start == str) /* Empty key  or value. */
+                       start = NULL;
+
+               if (end_k) {
+                       /* Key parsed. */
+                       kvlist->pairs[i].key = start;
+                       end_k = 0;
+               } else if (end_v) {
+                       /* Allow single key or single value. */
+                       if (kvlist->pairs[i].key || start) {
+                               kvlist->pairs[i].value = start;
+                               kvlist->count++;
                        }
+                       end_v = 0;
                }
 
-               kvlist->count++;
-               str = NULL;
+               if (!*str) /* End of string. */
+                       break;
+               *str = 0;
+               str++;
+               start = str;
        }
 
        return 0;
-- 
2.25.1

Reply via email to