#include <string.h>
#include <stdlib.h>
+#include <stdbool.h>
#include <rte_string_fns.h>
/*
* 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
/* 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;
- kvlist->count++;
- str = NULL;
+ 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;
+ }
+
+ if (*str == '\0') /* End of string. */
+ break;
+ *str = '\0';
+ str++;
+ start = str;
+ save = false;
}
return 0;
const struct rte_kvargs_pair *pair;
unsigned i;
+ if (kvlist == NULL)
+ return 0;
+
for (i = 0; i < kvlist->count; i++) {
pair = &kvlist->pairs[i];
if (key_match == NULL || strcmp(pair->key, key_match) == 0) {
free(kvlist);
}
+/* Lookup a value in an rte_kvargs list by its key. */
+const char *
+rte_kvargs_get(const struct rte_kvargs *kvlist, const char *key)
+{
+ unsigned int i;
+
+ if (kvlist == NULL || key == NULL)
+ return NULL;
+ for (i = 0; i < kvlist->count; ++i) {
+ if (strcmp(kvlist->pairs[i].key, key) == 0)
+ return kvlist->pairs[i].value;
+ }
+ return NULL;
+}
+
/*
* Parse the arguments "key=value,key=value,..." string and return
* an allocated structure that contains a key/value list. Also
return kvlist;
}
-__rte_experimental
struct rte_kvargs *
rte_kvargs_parse_delim(const char *args, const char * const valid_keys[],
const char *valid_ends)
free(copy);
return kvlist;
}
+
+int
+rte_kvargs_strcmp(const char *key __rte_unused,
+ const char *value, void *opaque)
+{
+ const char *str = opaque;
+
+ return -abs(strcmp(str, value));
+}