[ovs-dev] [PATCH 2/4] ovs-vsctl: Prepare for more flexible database argument parsing.
Ben Pfaff
blp at nicira.com
Thu Jun 24 11:41:28 PDT 2010
The wait-until command to be added in an upcoming commit needs to support
!=, <, >, <=, and >= operators in addition to =, so this commit adds that
infrastructure.
---
lib/ovsdb-data.c | 2 +-
tests/ovs-vsctl.at | 2 +-
utilities/ovs-vsctl.c | 77 +++++++++++++++++++++++++++++++++++++++++++------
3 files changed, 70 insertions(+), 11 deletions(-)
diff --git a/lib/ovsdb-data.c b/lib/ovsdb-data.c
index 39d10ed..fe7d8c4 100644
--- a/lib/ovsdb-data.c
+++ b/lib/ovsdb-data.c
@@ -1633,5 +1633,5 @@ error:
bool
ovsdb_token_is_delim(unsigned char c)
{
- return strchr(":=, []{}", c) != NULL;
+ return strchr(":=, []{}!<>", c) != NULL;
}
diff --git a/tests/ovs-vsctl.at b/tests/ovs-vsctl.at
index a8deb1a..89ef589 100644
--- a/tests/ovs-vsctl.at
+++ b/tests/ovs-vsctl.at
@@ -658,7 +658,7 @@ AT_CHECK([RUN_OVS_VSCTL([get b br0 :y=z])],
[1], [], [ovs-vsctl: :y=z: missing column name
], [OVS_VSCTL_CLEANUP])
AT_CHECK([RUN_OVS_VSCTL([get b br0 datapath_id:y=z])],
- [1], [], [ovs-vsctl: datapath_id:y=z: value not accepted here
+ [1], [], [ovs-vsctl: datapath_id:y=z: trailing garbage "=z" in argument
], [OVS_VSCTL_CLEANUP])
AT_CHECK([RUN_OVS_VSCTL([get b br0 datapath_id::])],
[1], [], [ovs-vsctl: datapath_id::: trailing garbage ":" in argument
diff --git a/utilities/ovs-vsctl.c b/utilities/ovs-vsctl.c
index 4aaebef..5b0e052 100644
--- a/utilities/ovs-vsctl.c
+++ b/utilities/ovs-vsctl.c
@@ -2104,15 +2104,40 @@ get_column(const struct vsctl_table_class *table, const char *column_name,
}
}
+/* Breaks 'arg' apart into a number of fields in the following order:
+ *
+ * - If 'columnp' is nonnull, the name of a column in 'table'. The column
+ * is stored into '*columnp'. The column name may be abbreviated.
+ *
+ * - If 'keyp' is nonnull, optionally a key string. (If both 'columnp'
+ * and 'keyp' are nonnull, then the column and key names are expected to
+ * be separated by ':'). The key is stored as a malloc()'d string into
+ * '*keyp', or NULL if no key is present in 'arg'.
+ *
+ * - If 'valuep' is nonnull, optionally an operator followed by a value
+ * string. The allowed operators are the 'n_allowed' string in
+ * 'allowed_operators', or just "=" if 'n_allowed' is 0. If
+ * 'operatorp' is nonnull, then the operator is stored into
+ * '*operatorp'. The value is stored as a malloc()'d string into
+ * '*valuep', or NULl if no value is present in 'arg'.
+ *
+ * At least 'columnp' or 'keyp' must be nonnull.
+ *
+ * On success, returns NULL. On failure, returned a malloc()'d string error
+ * message and stores NULL into all of the nonnull output arguments. */
static char * WARN_UNUSED_RESULT
-parse_column_key_value(const char *arg, const struct vsctl_table_class *table,
- const struct ovsdb_idl_column **columnp,
- char **keyp, char **valuep)
+parse_column_key_value(const char *arg,
+ const struct vsctl_table_class *table,
+ const struct ovsdb_idl_column **columnp, char **keyp,
+ const char **operatorp,
+ const char **allowed_operators, size_t n_allowed,
+ char **valuep)
{
const char *p = arg;
char *error;
assert(columnp || keyp);
+ assert(!(operatorp && !valuep));
if (keyp) {
*keyp = NULL;
}
@@ -2157,12 +2182,42 @@ parse_column_key_value(const char *arg, const struct vsctl_table_class *table,
}
/* Parse value string. */
- if (*p == '=') {
- if (!valuep) {
- error = xasprintf("%s: value not accepted here", arg);
+ if (valuep) {
+ const char *best;
+ size_t best_len;
+ size_t i;
+
+ if (*p == '\0') {
+ error = xasprintf("%s: missing value in argument", arg);
+ goto error;
+ }
+
+ if (!allowed_operators) {
+ static const char *equals = "=";
+ allowed_operators = =
+ n_allowed = 1;
+ }
+
+ best = NULL;
+ best_len = 0;
+ for (i = 0; i < n_allowed; i++) {
+ const char *op = allowed_operators[i];
+ size_t op_len = strlen(op);
+
+ if (op_len > best_len && !strncmp(op, p, op_len)) {
+ best_len = op_len;
+ best = op;
+ }
+ }
+ if (!best) {
+ error = xasprintf("%s: missing operator", arg);
goto error;
}
- *valuep = xstrdup(p + 1);
+
+ if (operatorp) {
+ *operatorp = best;
+ }
+ *valuep = xstrdup(p + best_len);
} else {
if (valuep) {
*valuep = NULL;
@@ -2186,6 +2241,9 @@ error:
if (valuep) {
free(*valuep);
*valuep = NULL;
+ if (operatorp) {
+ *operatorp = NULL;
+ }
}
return error;
}
@@ -2209,7 +2267,8 @@ cmd_get(struct vsctl_context *ctx)
char *key_string;
die_if_error(parse_column_key_value(ctx->argv[i], table,
- &column, &key_string, NULL));
+ &column, &key_string,
+ NULL, NULL, 0, NULL));
ovsdb_idl_txn_read(row, column, &datum);
if (key_string) {
@@ -2311,7 +2370,7 @@ set_column(const struct vsctl_table_class *table,
char *error;
error = parse_column_key_value(arg, table, &column, &key_string,
- &value_string);
+ NULL, NULL, 0, &value_string);
die_if_error(error);
if (!value_string) {
vsctl_fatal("%s: missing value", arg);
--
1.7.1
More information about the dev
mailing list