Branch data Line data Source code
1 : : /* Copyright (c) 2009, 2011, 2013, 2015 Nicira, Inc.
2 : : *
3 : : * Licensed under the Apache License, Version 2.0 (the "License");
4 : : * you may not use this file except in compliance with the License.
5 : : * You may obtain a copy of the License at:
6 : : *
7 : : * http://www.apache.org/licenses/LICENSE-2.0
8 : : *
9 : : * Unless required by applicable law or agreed to in writing, software
10 : : * distributed under the License is distributed on an "AS IS" BASIS,
11 : : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : : * See the License for the specific language governing permissions and
13 : : * limitations under the License.
14 : : */
15 : :
16 : : #include <config.h>
17 : :
18 : : #include "ovsdb-parser.h"
19 : :
20 : : #include <ctype.h>
21 : : #include <stdarg.h>
22 : :
23 : : #include "ovsdb-error.h"
24 : :
25 : : void
26 : 884397 : ovsdb_parser_init(struct ovsdb_parser *parser, const struct json *json,
27 : : const char *name, ...)
28 : : {
29 : : va_list args;
30 : :
31 : 884397 : va_start(args, name);
32 : 884397 : parser->name = xvasprintf(name, args);
33 : 884397 : va_end(args);
34 : :
35 : 884397 : sset_init(&parser->used);
36 : 884397 : parser->error = NULL;
37 : :
38 [ + - ][ + - ]: 884397 : parser->json = (json && json->type == JSON_OBJECT ? json : NULL);
39 [ - + ]: 884397 : if (!parser->json) {
40 : 0 : ovsdb_parser_raise_error(parser, "Object expected.");
41 : : }
42 : 884397 : }
43 : :
44 : : bool
45 : 529605 : ovsdb_parser_is_id(const char *string)
46 : : {
47 : : unsigned char c;
48 : :
49 : 529605 : c = *string;
50 [ + + ][ + - ]: 529605 : if (!isalpha(c) && c != '_') {
51 : 2 : return false;
52 : : }
53 : :
54 : : for (;;) {
55 : 5357064 : c = *++string;
56 [ + + ]: 5357064 : if (c == '\0') {
57 : 529602 : return true;
58 [ + + ][ + + ]: 4827462 : } else if (!isalpha(c) && !isdigit(c) && c != '_') {
[ + + ]
59 : 1 : return false;
60 : : }
61 : 4827461 : }
62 : : }
63 : :
64 : : const struct json *
65 : 2918549 : ovsdb_parser_member(struct ovsdb_parser *parser, const char *name,
66 : : enum ovsdb_parser_types types)
67 : : {
68 : : struct json *value;
69 : :
70 [ - + ]: 2918549 : if (!parser->json) {
71 : 0 : return NULL;
72 : : }
73 : :
74 : 2918549 : value = shash_find_data(json_object(parser->json), name);
75 [ + + ]: 2918549 : if (!value) {
76 [ + + ]: 1090251 : if (!(types & OP_OPTIONAL)) {
77 : 4 : ovsdb_parser_raise_error(parser,
78 : : "Required '%s' member is missing.", name);
79 : : }
80 : 1090251 : return NULL;
81 : : }
82 : :
83 [ + - ][ + - ]: 1828298 : if (((int) value->type >= 0 && value->type < JSON_N_TYPES
84 [ + + ]: 1828298 : && types & (1u << value->type))
85 [ + - ][ + - ]: 211737 : || (types & OP_ID && value->type == JSON_STRING
86 [ + + ]: 211737 : && ovsdb_parser_is_id(value->u.string)))
87 : : {
88 : 1828296 : sset_add(&parser->used, name);
89 : 1828296 : return value;
90 : : } else {
91 : 2 : ovsdb_parser_raise_error(parser, "Type mismatch for member '%s'.",
92 : : name);
93 : 2 : return NULL;
94 : : }
95 : : }
96 : :
97 : : void
98 : 6 : ovsdb_parser_raise_error(struct ovsdb_parser *parser, const char *format, ...)
99 : : {
100 [ + - ]: 6 : if (!parser->error) {
101 : : struct ovsdb_error *error;
102 : : va_list args;
103 : : char *message;
104 : :
105 : 6 : va_start(args, format);
106 : 6 : message = xvasprintf(format, args);
107 : 6 : va_end(args);
108 : :
109 : 6 : error = ovsdb_syntax_error(parser->json, NULL, "Parsing %s failed: %s",
110 : : parser->name, message);
111 : 6 : free(message);
112 : :
113 : 6 : parser->error = error;
114 : : }
115 : 6 : }
116 : :
117 : : struct ovsdb_error *
118 : 68451 : ovsdb_parser_get_error(const struct ovsdb_parser *parser)
119 : : {
120 [ + + ]: 68451 : return parser->error ? ovsdb_error_clone(parser->error) : NULL;
121 : : }
122 : :
123 : : bool
124 : 116394 : ovsdb_parser_has_error(const struct ovsdb_parser *parser)
125 : : {
126 : 116394 : return parser->error != NULL;
127 : : }
128 : :
129 : : struct ovsdb_error *
130 : 884397 : ovsdb_parser_destroy(struct ovsdb_parser *parser)
131 : : {
132 : 884397 : free(parser->name);
133 : 884397 : sset_destroy(&parser->used);
134 : :
135 : 884397 : return parser->error;
136 : : }
137 : :
138 : : struct ovsdb_error *
139 : 767556 : ovsdb_parser_finish(struct ovsdb_parser *parser)
140 : : {
141 [ + + ]: 767556 : if (!parser->error) {
142 : 767550 : const struct shash *object = json_object(parser->json);
143 : : size_t n_unused;
144 : :
145 : 767550 : n_unused = shash_count(object) - sset_count(&parser->used);
146 [ - + ]: 767550 : if (n_unused) {
147 : : struct shash_node *node;
148 : :
149 [ # # ][ # # ]: 0 : SHASH_FOR_EACH (node, object) {
150 [ # # ]: 0 : if (!sset_contains(&parser->used, node->name)) {
151 [ # # ]: 0 : if (n_unused > 1) {
152 [ # # ]: 0 : ovsdb_parser_raise_error(
153 : : parser,
154 : : "Member '%s' and %"PRIuSIZE" other member%s "
155 : : "are present but not allowed here.",
156 : : node->name, n_unused - 1, n_unused > 2 ? "s" : "");
157 : : } else {
158 : 0 : ovsdb_parser_raise_error(
159 : : parser,
160 : : "Member '%s' is present but not allowed here.",
161 : : node->name);
162 : : }
163 : 0 : break;
164 : : }
165 : : }
166 : : }
167 : : }
168 : :
169 : 767556 : return ovsdb_parser_destroy(parser);
170 : : }
|