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;

Reply via email to