[dpdk-dev] [RFC 5/7] kvargs: update parser for new representor syntax

Andrew Rybchenko andrew.rybchenko at oktetlabs.ru
Mon Dec 28 14:21:15 CET 2020


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 <xuemingl at 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;



More information about the dev mailing list