#include "openvswitch/shash.h"
#include "unicode.h"
#include "util.h"
+#include "uuid.h"
/* The type of a JSON token. */
enum json_token_type {
double real;
long long int integer;
const char *string;
- } u;
+ };
};
enum json_lex_state {
json_string_create_nocopy(char *s)
{
struct json *json = json_create(JSON_STRING);
- json->u.string = s;
+ json->string = s;
return json;
}
json_array_create_empty(void)
{
struct json *json = json_create(JSON_ARRAY);
- json->u.array.elems = NULL;
- json->u.array.n = 0;
- json->u.array.n_allocated = 0;
+ json->array.elems = NULL;
+ json->array.n = 0;
+ json->array.n_allocated = 0;
return json;
}
json_array_create(struct json **elements, size_t n)
{
struct json *json = json_create(JSON_ARRAY);
- json->u.array.elems = elements;
- json->u.array.n = n;
- json->u.array.n_allocated = n;
+ json->array.elems = elements;
+ json->array.n = n;
+ json->array.n_allocated = n;
return json;
}
json_object_create(void)
{
struct json *json = json_create(JSON_OBJECT);
- json->u.object = xmalloc(sizeof *json->u.object);
- shash_init(json->u.object);
+ json->object = xmalloc(sizeof *json->object);
+ shash_init(json->object);
return json;
}
json_integer_create(long long int integer)
{
struct json *json = json_create(JSON_INTEGER);
- json->u.integer = integer;
+ json->integer = integer;
return json;
}
json_real_create(double real)
{
struct json *json = json_create(JSON_REAL);
- json->u.real = real;
+ json->real = real;
return json;
}
void
json_object_put(struct json *json, const char *name, struct json *value)
{
- json_destroy(shash_replace(json->u.object, name, value));
+ json_destroy(shash_replace(json->object, name, value));
+}
+
+void
+json_object_put_nocopy(struct json *json, char *name, struct json *value)
+{
+ json_destroy(shash_replace_nocopy(json->object, name, value));
}
void
json_object_put(json, name, json_string_create(value));
}
+void OVS_PRINTF_FORMAT(3, 4)
+json_object_put_format(struct json *json,
+ const char *name, const char *format, ...)
+{
+ va_list args;
+ va_start(args, format);
+ json_object_put(json, name,
+ json_string_create_nocopy(xvasprintf(format, args)));
+ va_end(args);
+}
+
const char *
json_string(const struct json *json)
{
ovs_assert(json->type == JSON_STRING);
- return json->u.string;
+ return json->string;
}
struct json_array *
json_array(const struct json *json)
{
ovs_assert(json->type == JSON_ARRAY);
- return CONST_CAST(struct json_array *, &json->u.array);
+ return CONST_CAST(struct json_array *, &json->array);
}
struct shash *
json_object(const struct json *json)
{
ovs_assert(json->type == JSON_OBJECT);
- return CONST_CAST(struct shash *, json->u.object);
+ return CONST_CAST(struct shash *, json->object);
}
bool
json_real(const struct json *json)
{
ovs_assert(json->type == JSON_REAL || json->type == JSON_INTEGER);
- return json->type == JSON_REAL ? json->u.real : json->u.integer;
+ return json->type == JSON_REAL ? json->real : json->integer;
}
int64_t
json_integer(const struct json *json)
{
ovs_assert(json->type == JSON_INTEGER);
- return json->u.integer;
+ return json->integer;
}
\f
static void json_destroy_object(struct shash *object);
if (json && !--json->count) {
switch (json->type) {
case JSON_OBJECT:
- json_destroy_object(json->u.object);
+ json_destroy_object(json->object);
break;
case JSON_ARRAY:
- json_destroy_array(&json->u.array);
+ json_destroy_array(&json->array);
break;
case JSON_STRING:
- free(json->u.string);
+ free(json->string);
break;
case JSON_NULL:
{
switch (json->type) {
case JSON_OBJECT:
- return json_clone_object(json->u.object);
+ return json_clone_object(json->object);
case JSON_ARRAY:
- return json_clone_array(&json->u.array);
+ return json_clone_array(&json->array);
case JSON_STRING:
- return json_string_create(json->u.string);
+ return json_string_create(json->string);
case JSON_NULL:
case JSON_FALSE:
return json_create(json->type);
case JSON_INTEGER:
- return json_integer_create(json->u.integer);
+ return json_integer_create(json->integer);
case JSON_REAL:
- return json_real_create(json->u.real);
+ return json_real_create(json->real);
case JSON_N_TYPES:
default:
{
switch (json->type) {
case JSON_OBJECT:
- return json_hash_object(json->u.object, basis);
+ return json_hash_object(json->object, basis);
case JSON_ARRAY:
- return json_hash_array(&json->u.array, basis);
+ return json_hash_array(&json->array, basis);
case JSON_STRING:
- return hash_string(json->u.string, basis);
+ return hash_string(json->string, basis);
case JSON_NULL:
case JSON_FALSE:
return hash_int(json->type << 8, basis);
case JSON_INTEGER:
- return hash_int(json->u.integer, basis);
+ return hash_int(json->integer, basis);
case JSON_REAL:
- return hash_double(json->u.real, basis);
+ return hash_double(json->real, basis);
case JSON_N_TYPES:
default:
{
if (a == b) {
return true;
- }
-
- if (a->type != b->type) {
+ } else if (!a || !b) {
+ return false;
+ } else if (a->type != b->type) {
return false;
}
switch (a->type) {
case JSON_OBJECT:
- return json_equal_object(a->u.object, b->u.object);
+ return json_equal_object(a->object, b->object);
case JSON_ARRAY:
- return json_equal_array(&a->u.array, &b->u.array);
+ return json_equal_array(&a->array, &b->array);
case JSON_STRING:
- return !strcmp(a->u.string, b->u.string);
+ return !strcmp(a->string, b->string);
case JSON_NULL:
case JSON_FALSE:
return true;
case JSON_INTEGER:
- return a->u.integer == b->u.integer;
+ return a->integer == b->integer;
case JSON_REAL:
- return a->u.real == b->u.real;
+ return a->real == b->real;
case JSON_N_TYPES:
default:
exponent = 0;
do {
if (exponent >= INT_MAX / 10) {
- json_error(p, "exponent outside valid range");
- return;
+ goto bad_exponent;
}
exponent = exponent * 10 + (*cp - '0');
cp++;
} while (isdigit((unsigned char) *cp));
if (negative_exponent) {
+ if (pow10 < INT_MIN + exponent) {
+ goto bad_exponent;
+ }
pow10 -= exponent;
} else {
+ if (pow10 > INT_MAX - exponent) {
+ goto bad_exponent;
+ }
pow10 += exponent;
}
}
* We suppress negative zeros as a matter of policy. */
if (!significand) {
token.type = T_INTEGER;
- token.u.integer = 0;
+ token.integer = 0;
json_parser_input(p, &token);
return;
}
? (unsigned long long int) LLONG_MAX + 1
: LLONG_MAX)) {
token.type = T_INTEGER;
- token.u.integer = negative ? -significand : significand;
+ token.integer = negative ? -significand : significand;
json_parser_input(p, &token);
return;
}
}
token.type = T_REAL;
- if (!str_to_double(ds_cstr(&p->buffer), &token.u.real)) {
+ if (!str_to_double(ds_cstr(&p->buffer), &token.real)) {
json_error(p, "number outside valid range");
return;
}
/* Suppress negative zero. */
- if (token.u.real == 0) {
- token.u.real = 0;
+ if (token.real == 0) {
+ token.real = 0;
}
json_parser_input(p, &token);
+ return;
+
+bad_exponent:
+ json_error(p, "exponent outside valid range");
}
static const char *
{
struct json json = {
.type = JSON_STRING,
- .u.string = CONST_CAST(char *, in),
+ .string = CONST_CAST(char *, in),
};
json_to_ds(&json, 0, out);
}
struct json_token token;
token.type = T_STRING;
- token.u.string = s;
+ token.string = s;
json_parser_input(p, &token);
}
{
struct json_parser_node *node = json_parser_top(p);
if (node->json->type == JSON_OBJECT) {
- json_object_put(node->json, p->member_name, value);
- free(p->member_name);
+ json_object_put_nocopy(node->json, p->member_name, value);
p->member_name = NULL;
} else if (node->json->type == JSON_ARRAY) {
json_array_add(node->json, value);
return;
case T_INTEGER:
- value = json_integer_create(token->u.integer);
+ value = json_integer_create(token->integer);
break;
case T_REAL:
- value = json_real_create(token->u.real);
+ value = json_real_create(token->real);
break;
case T_STRING:
- value = json_string_create(token->u.string);
+ value = json_string_create(token->string);
break;
case T_EOF:
/* Fall through. */
case JSON_PARSE_OBJECT_NAME:
if (token->type == T_STRING) {
- p->member_name = xstrdup(token->u.string);
+ p->member_name = xstrdup(token->string);
p->parse_state = JSON_PARSE_OBJECT_COLON;
} else {
json_error(p, "syntax error parsing object expecting string");
break;
case JSON_OBJECT:
- json_serialize_object(json->u.object, s);
+ json_serialize_object(json->object, s);
break;
case JSON_ARRAY:
- json_serialize_array(&json->u.array, s);
+ json_serialize_array(&json->array, s);
break;
case JSON_INTEGER:
- ds_put_format(ds, "%lld", json->u.integer);
+ ds_put_format(ds, "%lld", json->integer);
break;
case JSON_REAL:
- ds_put_format(ds, "%.*g", DBL_DIG, json->u.real);
+ ds_put_format(ds, "%.*g", DBL_DIG, json->real);
break;
case JSON_STRING:
- json_serialize_string(json->u.string, ds);
+ json_serialize_string(json->string, ds);
break;
case JSON_N_TYPES: