diff options
author | Ben Pfaff <blp@nicira.com> | 2009-11-04 15:11:44 -0800 |
---|---|---|
committer | Ben Pfaff <blp@nicira.com> | 2009-11-04 17:12:10 -0800 |
commit | f85f8ebbfac946c19b3c6eb0f4170f579d0a4d25 (patch) | |
tree | 2111aee77751f2143773907f81c6adb9101afb6c /lib/ovsdb-parser.c | |
parent | f212909325be9bc7e296e1a32e2fc89694a0049f (diff) |
Initial implementation of OVSDB.
Diffstat (limited to 'lib/ovsdb-parser.c')
-rw-r--r-- | lib/ovsdb-parser.c | 167 |
1 files changed, 167 insertions, 0 deletions
diff --git a/lib/ovsdb-parser.c b/lib/ovsdb-parser.c new file mode 100644 index 00000000..d923d21a --- /dev/null +++ b/lib/ovsdb-parser.c @@ -0,0 +1,167 @@ +/* Copyright (c) 2009 Nicira Networks + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <config.h> + +#include "ovsdb-parser.h" + +#include <ctype.h> +#include <stdarg.h> + +#include "ovsdb-error.h" + +void +ovsdb_parser_init(struct ovsdb_parser *parser, const struct json *json, + const char *name, ...) +{ + va_list args; + + va_start(args, name); + parser->name = xvasprintf(name, args); + va_end(args); + + svec_init(&parser->used); + parser->error = NULL; + + parser->json = (json && json->type == JSON_OBJECT ? json : NULL); + if (!parser->json) { + ovsdb_parser_raise_error(parser, "Object expected."); + } +} + +static bool +is_id(const char *string) +{ + unsigned char c; + + c = *string; + if (!isalpha(c) && c != '_') { + return false; + } + + for (;;) { + c = *++string; + if (c == '\0') { + return true; + } else if (!isalpha(c) && !isdigit(c) && c != '_') { + return false; + } + } +} + +const struct json * +ovsdb_parser_member(struct ovsdb_parser *parser, const char *name, + enum ovsdb_parser_types types) +{ + struct json *value; + + if (!parser->json) { + return NULL; + } + + value = shash_find_data(json_object(parser->json), name); + if (!value) { + if (!(types & OP_OPTIONAL)) { + ovsdb_parser_raise_error(parser, + "Required '%s' member is missing.", name); + } + return NULL; + } + + if (value->type >= 0 && value->type < JSON_N_TYPES + && (types & (1u << value->type) + || (types & OP_ID + && value->type == JSON_STRING + && is_id(value->u.string)))) + { + svec_add(&parser->used, name); + return value; + } else { + ovsdb_parser_raise_error(parser, "Type mismatch for member '%s'.", + name); + return NULL; + } +} + +void +ovsdb_parser_raise_error(struct ovsdb_parser *parser, const char *format, ...) +{ + if (!parser->error) { + struct ovsdb_error *error; + va_list args; + char *message; + + va_start(args, format); + message = xvasprintf(format, args); + va_end(args); + + error = ovsdb_syntax_error(parser->json, NULL, "Parsing %s failed: %s", + parser->name, message); + free(message); + + parser->error = error; + } +} + +struct ovsdb_error * +ovsdb_parser_get_error(const struct ovsdb_parser *parser) +{ + return parser->error ? ovsdb_error_clone(parser->error) : NULL; +} + +bool +ovsdb_parser_has_error(const struct ovsdb_parser *parser) +{ + return parser->error != NULL; +} + +struct ovsdb_error * +ovsdb_parser_finish(struct ovsdb_parser *parser) +{ + if (!parser->error) { + const struct shash *object = json_object(parser->json); + size_t n_unused; + + /* XXX this method of detecting unused members can be made cheaper */ + svec_sort_unique(&parser->used); + n_unused = shash_count(object) - parser->used.n; + if (n_unused) { + struct shash_node *node; + + SHASH_FOR_EACH (node, object) { + if (!svec_contains(&parser->used, node->name)) { + if (n_unused > 1) { + ovsdb_parser_raise_error( + parser, + "Member '%s' and %zu other member%s " + "are present but not allowed here.", + node->name, n_unused - 1, n_unused > 2 ? "s" : ""); + } else { + ovsdb_parser_raise_error( + parser, + "Member '%s' is present but not allowed here.", + node->name); + } + break; + } + } + } + } + + free(parser->name); + svec_destroy(&parser->used); + + return parser->error; +} |