On 12/18/20 5:55 PM, Xueming Li wrote: > 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) {
DPDK coding style requires to compare integers vs 0 explicitly. Otherwise you can define it as bool and use as bool this way. > + /* 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) { same > + /* Key parsed. */ > + kvlist->pairs[i].key = start; > + end_k = 0; > + } else if (end_v) { same > + /* 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. */ Compare with '\0'. > + break; > + *str = 0; > + str++; > + start = str; > } > > return 0;