[v8,9/9] kvargs: update parser to support lists
Checks
Commit Message
This patch updates kvargs parser to support lists on top of range, allow
multiple lists or range:
k1=a[1,2]b[3-5]
Signed-off-by: Xueming Li <xuemingl@nvidia.com>
Acked-by: Viacheslav Ovsiienko <viacheslavo@nvidia.com>
Acked-by: Thomas Monjalon <thomas@monjalon.net>
---
app/test/test_kvargs.c | 46 +++++++++++++--
lib/librte_kvargs/rte_kvargs.c | 101 +++++++++++++++++++++++----------
2 files changed, 112 insertions(+), 35 deletions(-)
Comments
On 3/4/2021 2:30 PM, Xueming Li wrote:
> This patch updates kvargs parser to support lists on top of range, allow
> multiple lists or range:
> k1=a[1,2]b[3-5]
>
> Signed-off-by: Xueming Li <xuemingl@nvidia.com>
> Acked-by: Viacheslav Ovsiienko <viacheslavo@nvidia.com>
> Acked-by: Thomas Monjalon <thomas@monjalon.net>
Is this update used at all in this set?
>-----Original Message-----
>From: Ferruh Yigit <ferruh.yigit@intel.com>
>Sent: Monday, March 8, 2021 10:45 PM
>To: Xueming(Steven) Li <xuemingl@nvidia.com>; Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
>Cc: dev@dpdk.org; Slava Ovsiienko <viacheslavo@nvidia.com>; Asaf Penso <asafp@nvidia.com>; Olivier Matz
><olivier.matz@6wind.com>
>Subject: Re: [dpdk-dev] [PATCH v8 9/9] kvargs: update parser to support lists
>
>On 3/4/2021 2:30 PM, Xueming Li wrote:
>> This patch updates kvargs parser to support lists on top of range,
>> allow multiple lists or range:
>> k1=a[1,2]b[3-5]
>>
>> Signed-off-by: Xueming Li <xuemingl@nvidia.com>
>> Acked-by: Viacheslav Ovsiienko <viacheslavo@nvidia.com>
>> Acked-by: Thomas Monjalon <thomas@monjalon.net>
>
>Is this update used at all in this set?
Yes, for example to support 'pf[0,1]sf[1,3,5]', this patch is a must.
On 3/8/2021 2:59 PM, Xueming(Steven) Li wrote:
>
>
>> -----Original Message-----
>> From: Ferruh Yigit <ferruh.yigit@intel.com>
>> Sent: Monday, March 8, 2021 10:45 PM
>> To: Xueming(Steven) Li <xuemingl@nvidia.com>; Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
>> Cc: dev@dpdk.org; Slava Ovsiienko <viacheslavo@nvidia.com>; Asaf Penso <asafp@nvidia.com>; Olivier Matz
>> <olivier.matz@6wind.com>
>> Subject: Re: [dpdk-dev] [PATCH v8 9/9] kvargs: update parser to support lists
>>
>> On 3/4/2021 2:30 PM, Xueming Li wrote:
>>> This patch updates kvargs parser to support lists on top of range,
>>> allow multiple lists or range:
>>> k1=a[1,2]b[3-5]
>>>
>>> Signed-off-by: Xueming Li <xuemingl@nvidia.com>
>>> Acked-by: Viacheslav Ovsiienko <viacheslavo@nvidia.com>
>>> Acked-by: Thomas Monjalon <thomas@monjalon.net>
>>
>> Is this update used at all in this set?
>
> Yes, for example to support 'pf[0,1]sf[1,3,5]', this patch is a must.
>
So should this patch be before where 'pf[0,1]sf[1,3,5]' syntax is required/used
in this set?
>-----Original Message-----
>From: Ferruh Yigit <ferruh.yigit@intel.com>
>Sent: Monday, March 8, 2021 11:55 PM
>To: Xueming(Steven) Li <xuemingl@nvidia.com>; Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
>Cc: dev@dpdk.org; Slava Ovsiienko <viacheslavo@nvidia.com>; Asaf Penso <asafp@nvidia.com>; Olivier Matz
><olivier.matz@6wind.com>
>Subject: Re: [dpdk-dev] [PATCH v8 9/9] kvargs: update parser to support lists
>
>On 3/8/2021 2:59 PM, Xueming(Steven) Li wrote:
>>
>>
>>> -----Original Message-----
>>> From: Ferruh Yigit <ferruh.yigit@intel.com>
>>> Sent: Monday, March 8, 2021 10:45 PM
>>> To: Xueming(Steven) Li <xuemingl@nvidia.com>; Andrew Rybchenko
>>> <andrew.rybchenko@oktetlabs.ru>
>>> Cc: dev@dpdk.org; Slava Ovsiienko <viacheslavo@nvidia.com>; Asaf
>>> Penso <asafp@nvidia.com>; Olivier Matz <olivier.matz@6wind.com>
>>> Subject: Re: [dpdk-dev] [PATCH v8 9/9] kvargs: update parser to
>>> support lists
>>>
>>> On 3/4/2021 2:30 PM, Xueming Li wrote:
>>>> This patch updates kvargs parser to support lists on top of range,
>>>> allow multiple lists or range:
>>>> k1=a[1,2]b[3-5]
>>>>
>>>> Signed-off-by: Xueming Li <xuemingl@nvidia.com>
>>>> Acked-by: Viacheslav Ovsiienko <viacheslavo@nvidia.com>
>>>> Acked-by: Thomas Monjalon <thomas@monjalon.net>
>>>
>>> Is this update used at all in this set?
>>
>> Yes, for example to support 'pf[0,1]sf[1,3,5]', this patch is a must.
>>
>
>So should this patch be before where 'pf[0,1]sf[1,3,5]' syntax is required/used in this set?
Good suggestion, I'll update in next version, thanks!
@@ -35,6 +35,25 @@ static int check_handler(const char *key, const char *value,
return 0;
}
+/* test parsing. */
+static int test_kvargs_parsing(const char *args, unsigned int n)
+{
+ struct rte_kvargs *kvlist;
+
+ kvlist = rte_kvargs_parse(args, NULL);
+ if (kvlist == NULL) {
+ printf("rte_kvargs_parse() error: %s\n", args);
+ return -1;
+ }
+ if (kvlist->count != n) {
+ printf("invalid count value %d: %s\n", kvlist->count, args);
+ rte_kvargs_free(kvlist);
+ return -1;
+ }
+ rte_kvargs_free(kvlist);
+ return 0;
+}
+
/* test a valid case */
static int test_valid_kvargs(void)
{
@@ -42,6 +61,19 @@ static int test_valid_kvargs(void)
const char *args;
const char *valid_keys_list[] = { "foo", "check", NULL };
const char **valid_keys;
+ static const struct {
+ unsigned int expected;
+ const char *input;
+ } valid_inputs[] = {
+ { 2, "foo=1,foo=" },
+ { 2, "foo=1,foo=" },
+ { 2, "foo=1,foo" },
+ { 2, "foo=1,=2" },
+ { 1, "foo=[1,2" },
+ { 1, ",=" },
+ { 1, "foo=[" },
+ };
+ unsigned int i;
/* empty args is valid */
args = "";
@@ -191,6 +223,14 @@ static int test_valid_kvargs(void)
}
rte_kvargs_free(kvlist);
+ valid_keys = NULL;
+
+ for (i = 0; i < RTE_DIM(valid_inputs); ++i) {
+ args = valid_inputs[i].input;
+ if (test_kvargs_parsing(args, valid_inputs[i].expected))
+ goto fail;
+ }
+
return 0;
fail:
@@ -212,12 +252,6 @@ static int test_invalid_kvargs(void)
/* list of argument that should fail */
const char *args_list[] = {
"wrong-key=x", /* key not in valid_keys_list */
- "foo=1,foo=", /* empty value */
- "foo=1,foo", /* no value */
- "foo=1,=2", /* no key */
- "foo=[1,2", /* no closing bracket in value */
- ",=", /* also test with a smiley */
- "foo=[", /* no value in list and no closing bracket */
NULL };
const char **args;
const char *valid_keys_list[] = { "foo", "check", NULL };
@@ -5,6 +5,7 @@
#include <string.h>
#include <stdlib.h>
+#include <stdbool.h>
#include <rte_string_fns.h>
@@ -13,15 +14,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
+ * k1
+ * 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;
+ bool in_list = false, end_key = false, end_value = false;
+ bool save = false, end_pair = false;
/* Copy the const char *params to a modifiable string
* to pass to rte_strsplit
@@ -32,36 +37,74 @@ 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_key = true;
+ save = true;
+ break;
+ case ',':
+ /* End of value, skip comma in middle of range */
+ if (!in_list) {
+ if (end_key)
+ end_value = true;
+ else
+ end_key = true;
+ save = true;
+ end_pair = true;
+ }
+ break;
+ case '[': /* Start of list. */
+ in_list = true;
+ break;
+ case ']': /* End of list. */
+ if (in_list)
+ in_list = false;
+ break;
+ case '\0': /* End of string */
+ if (end_key)
+ end_value = true;
+ else
+ end_key = true;
+ save = true;
+ end_pair = true;
+ break;
+ default:
+ break;
+ }
- i = kvlist->count;
- if (i >= RTE_KVARGS_MAX)
- return -1;
+ if (!save) {
+ /* Continue if not end of key or value. */
+ str++;
+ continue;
+ }
- 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)
+ if (kvlist->count >= RTE_KVARGS_MAX)
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 (end_value)
+ /* Value parsed */
+ kvlist->pairs[kvlist->count].value = start;
+ else if (end_key)
+ /* Key parsed. */
+ kvlist->pairs[kvlist->count].key = start;
+
+ if (end_pair) {
+ if (end_value || str != start)
+ /* Ignore empty pair. */
+ kvlist->count++;
+ end_key = false;
+ end_value = false;
+ end_pair = false;
}
- kvlist->count++;
- str = NULL;
+ if (*str == '\0') /* End of string. */
+ break;
+ *str = '\0';
+ str++;
+ start = str;
+ save = false;
}
return 0;