1 /* Copyright (c) 2009, 2010 Nicira Networks
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:
7 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 #include "ovsdb-types.h"
22 #include "dynamic-string.h"
24 #include "ovsdb-error.h"
25 #include "ovsdb-parser.h"
27 const struct ovsdb_type ovsdb_type_integer =
28 OVSDB_TYPE_SCALAR_INITIALIZER(OVSDB_TYPE_INTEGER);
29 const struct ovsdb_type ovsdb_type_real =
30 OVSDB_TYPE_SCALAR_INITIALIZER(OVSDB_TYPE_REAL);
31 const struct ovsdb_type ovsdb_type_boolean =
32 OVSDB_TYPE_SCALAR_INITIALIZER(OVSDB_TYPE_BOOLEAN);
33 const struct ovsdb_type ovsdb_type_string =
34 OVSDB_TYPE_SCALAR_INITIALIZER(OVSDB_TYPE_STRING);
35 const struct ovsdb_type ovsdb_type_uuid =
36 OVSDB_TYPE_SCALAR_INITIALIZER(OVSDB_TYPE_UUID);
39 ovsdb_atomic_type_to_string(enum ovsdb_atomic_type type)
45 case OVSDB_TYPE_INTEGER:
51 case OVSDB_TYPE_BOOLEAN:
54 case OVSDB_TYPE_STRING:
67 ovsdb_atomic_type_to_json(enum ovsdb_atomic_type type)
69 return json_string_create(ovsdb_atomic_type_to_string(type));
73 ovsdb_type_is_valid(const struct ovsdb_type *type)
75 return (type->key_type != OVSDB_TYPE_VOID
76 && ovsdb_atomic_type_is_valid(type->key_type)
77 && ovsdb_atomic_type_is_valid(type->value_type)
79 && type->n_min <= type->n_max
80 && (type->value_type == OVSDB_TYPE_VOID
81 || ovsdb_atomic_type_is_valid_key(type->key_type)));
85 ovsdb_atomic_type_from_string(const char *string, enum ovsdb_atomic_type *type)
87 if (!strcmp(string, "integer")) {
88 *type = OVSDB_TYPE_INTEGER;
89 } else if (!strcmp(string, "real")) {
90 *type = OVSDB_TYPE_REAL;
91 } else if (!strcmp(string, "boolean")) {
92 *type = OVSDB_TYPE_BOOLEAN;
93 } else if (!strcmp(string, "string")) {
94 *type = OVSDB_TYPE_STRING;
95 } else if (!strcmp(string, "uuid")) {
96 *type = OVSDB_TYPE_UUID;
104 ovsdb_atomic_type_from_json(enum ovsdb_atomic_type *type,
105 const struct json *json)
107 if (json->type == JSON_STRING) {
108 if (ovsdb_atomic_type_from_string(json_string(json), type)) {
111 *type = OVSDB_TYPE_VOID;
112 return ovsdb_syntax_error(json, NULL,
113 "\"%s\" is not an atomic-type",
117 *type = OVSDB_TYPE_VOID;
118 return ovsdb_syntax_error(json, NULL, "atomic-type expected");
122 static struct ovsdb_error *
123 n_from_json(const struct json *json, unsigned int *n)
127 } else if (json->type == JSON_INTEGER
128 && json->u.integer >= 0 && json->u.integer < UINT_MAX) {
129 *n = json->u.integer;
132 return ovsdb_syntax_error(json, NULL, "bad min or max value");
137 ovsdb_type_to_english(const struct ovsdb_type *type)
139 const char *key = ovsdb_atomic_type_to_string(type->key_type);
140 const char *value = ovsdb_atomic_type_to_string(type->value_type);
141 if (ovsdb_type_is_scalar(type)) {
144 struct ds s = DS_EMPTY_INITIALIZER;
145 ds_put_cstr(&s, ovsdb_type_is_set(type) ? "set" : "map");
146 if (type->n_max == UINT_MAX) {
148 ds_put_format(&s, " of %u or more", type->n_min);
150 ds_put_cstr(&s, " of");
152 } else if (type->n_min) {
153 ds_put_format(&s, " of %u to %u", type->n_min, type->n_max);
155 ds_put_format(&s, " of up to %u", type->n_max);
157 if (ovsdb_type_is_set(type)) {
158 ds_put_format(&s, " %ss", key);
160 ds_put_format(&s, " (%s, %s) pairs", key, value);
167 ovsdb_type_from_json(struct ovsdb_type *type, const struct json *json)
169 type->value_type = OVSDB_TYPE_VOID;
173 if (json->type == JSON_STRING) {
174 return ovsdb_atomic_type_from_json(&type->key_type, json);
175 } else if (json->type == JSON_OBJECT) {
176 const struct json *key, *value, *min, *max;
177 struct ovsdb_error *error;
178 struct ovsdb_parser parser;
180 ovsdb_parser_init(&parser, json, "ovsdb type");
181 key = ovsdb_parser_member(&parser, "key", OP_STRING);
182 value = ovsdb_parser_member(&parser, "value", OP_STRING | OP_OPTIONAL);
183 min = ovsdb_parser_member(&parser, "min", OP_INTEGER | OP_OPTIONAL);
184 max = ovsdb_parser_member(&parser, "max",
185 OP_INTEGER | OP_STRING | OP_OPTIONAL);
186 error = ovsdb_parser_finish(&parser);
191 error = ovsdb_atomic_type_from_json(&type->key_type, key);
197 error = ovsdb_atomic_type_from_json(&type->value_type, value);
203 error = n_from_json(min, &type->n_min);
208 if (max && max->type == JSON_STRING
209 && !strcmp(max->u.string, "unlimited")) {
210 type->n_max = UINT_MAX;
212 error = n_from_json(max, &type->n_max);
218 if (!ovsdb_type_is_valid(type)) {
219 return ovsdb_syntax_error(json, NULL,
220 "ovsdb type fails constraint checks");
225 return ovsdb_syntax_error(json, NULL, "ovsdb type expected");
230 ovsdb_type_to_json(const struct ovsdb_type *type)
232 if (ovsdb_type_is_scalar(type)) {
233 return ovsdb_atomic_type_to_json(type->key_type);
235 struct json *json = json_object_create();
236 json_object_put(json, "key",
237 ovsdb_atomic_type_to_json(type->key_type));
238 if (type->value_type != OVSDB_TYPE_VOID) {
239 json_object_put(json, "value",
240 ovsdb_atomic_type_to_json(type->value_type));
242 if (type->n_min != 1) {
243 json_object_put(json, "min", json_integer_create(type->n_min));
245 if (type->n_max == UINT_MAX) {
246 json_object_put_string(json, "max", "unlimited");
247 } else if (type->n_max != 1) {
248 json_object_put(json, "max", json_integer_create(type->n_max));