/*
- * Copyright (c) 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
+ * Copyright (c) 2009, 2010, 2011, 2012, 2014, 2015 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
static void json_parser_input(struct json_parser *, struct json_token *);
static void json_error(struct json_parser *p, const char *format, ...)
- PRINTF_FORMAT(2, 3);
+ OVS_PRINTF_FORMAT(2, 3);
\f
const char *
json_type_to_string(enum json_type type)
break;
case JSON_N_TYPES:
- NOT_REACHED();
+ OVS_NOT_REACHED();
}
free(json);
}
case JSON_N_TYPES:
default:
- NOT_REACHED();
+ OVS_NOT_REACHED();
}
}
basis = hash_string(node->name, basis);
basis = json_hash(node->data, basis);
}
+ free(nodes);
return basis;
}
case JSON_N_TYPES:
default:
- NOT_REACHED();
+ OVS_NOT_REACHED();
}
}
case JSON_N_TYPES:
default:
- NOT_REACHED();
+ OVS_NOT_REACHED();
}
}
\f
json_lex_4hex(const char *cp, const char *end, int *valuep)
{
unsigned int value;
+ bool ok;
if (cp + 4 > end) {
return "quoted string ends within \\u escape";
}
- value = hexits_value(cp, 4, NULL);
- if (value == UINT_MAX) {
+ value = hexits_value(cp, 4, &ok);
+ if (!ok) {
return "malformed \\u escape";
}
if (!value) {
ds_init(&out);
ds_reserve(&out, in_len);
- if (in_len > 0 && in[in_len - 1] == '\\') {
- ds_put_cstr(&out, "quoted string may not end with backslash");
- goto exit;
- }
while (in < end) {
if (*in == '"') {
ds_clear(&out);
}
in++;
+ if (in >= end) {
+ /* The JSON parser will never trigger this message, because its
+ * lexer will never pass in a string that ends in a single
+ * backslash, but json_string_unescape() has other callers that
+ * are not as careful.*/
+ ds_clear(&out);
+ ds_put_cstr(&out, "quoted string may not end with backslash");
+ goto exit;
+ }
switch (*in++) {
case '"': case '\\': case '/':
ds_put_char(&out, in[-1]);
return ok;
}
+void
+json_string_escape(const char *in, struct ds *out)
+{
+ struct json json = {
+ .type = JSON_STRING,
+ .u.string = CONST_CAST(char *, in),
+ };
+ json_to_ds(&json, 0, out);
+}
+
static void
json_parser_input_string(struct json_parser *p, const char *s)
{
} else if (node->json->type == JSON_ARRAY) {
json_array_add(node->json, value);
} else {
- NOT_REACHED();
+ OVS_NOT_REACHED();
}
}
} else if (node->json->type == JSON_OBJECT) {
p->parse_state = JSON_PARSE_OBJECT_NEXT;
} else {
- NOT_REACHED();
+ OVS_NOT_REACHED();
}
}
}
case JSON_N_TYPES:
default:
- NOT_REACHED();
+ OVS_NOT_REACHED();
}
}
}
ds_put_char(ds, '"');
}
-\f
-static size_t
-json_string_serialized_length(const char *string)
-{
- size_t length;
- uint8_t c;
-
- length = strlen("\"\"");
-
- while ((c = *string++) != '\0') {
- switch (c) {
- case '"':
- case '\\':
- case '\b':
- case '\f':
- case '\n':
- case '\r':
- case '\t':
- length += 2;
- break;
-
- default:
- if (c >= 32) {
- length++;
- } else {
- /* \uXXXX */
- length += 6;
- }
- break;
- }
- }
-
- return length;
-}
-
-static size_t
-json_object_serialized_length(const struct shash *object)
-{
- size_t length = strlen("{}");
-
- if (!shash_is_empty(object)) {
- struct shash_node *node;
-
- /* Commas and colons. */
- length += 2 * shash_count(object) - 1;
-
- SHASH_FOR_EACH (node, object) {
- const struct json *value = node->data;
-
- length += json_string_serialized_length(node->name);
- length += json_serialized_length(value);
- }
- }
-
- return length;
-}
-
-static size_t
-json_array_serialized_length(const struct json_array *array)
-{
- size_t length = strlen("[]");
-
- if (array->n) {
- size_t i;
-
- /* Commas. */
- length += array->n - 1;
-
- for (i = 0; i < array->n; i++) {
- length += json_serialized_length(array->elems[i]);
- }
- }
-
- return length;
-}
-
-/* Returns strlen(json_to_string(json, 0)), that is, the number of bytes in the
- * JSON output by json_to_string() for 'json' when JSSF_PRETTY is not
- * requested. (JSSF_SORT does not affect the length of json_to_string()'s
- * output.) */
-size_t
-json_serialized_length(const struct json *json)
-{
- switch (json->type) {
- case JSON_NULL:
- return strlen("null");
-
- case JSON_FALSE:
- return strlen("false");
-
- case JSON_TRUE:
- return strlen("true");
-
- case JSON_OBJECT:
- return json_object_serialized_length(json->u.object);
-
- case JSON_ARRAY:
- return json_array_serialized_length(&json->u.array);
-
- case JSON_INTEGER:
- return snprintf(NULL, 0, "%lld", json->u.integer);
-
- case JSON_REAL:
- return snprintf(NULL, 0, "%.*g", DBL_DIG, json->u.real);
-
- case JSON_STRING:
- return json_string_serialized_length(json->u.string);
-
- case JSON_N_TYPES:
- default:
- NOT_REACHED();
- }
-}