X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=lib%2Fjson.c;h=0a8bca27814ba692f817878dc2ccefca83e7e599;hb=0f50458b0a3054566c4f5cd70e0bc92ca7dafe49;hp=a7039ba55972a043a3d2d53a269e90f50855ca00;hpb=7d23a63aa4bc4479bf85b739e5be80ab12c5fc1b;p=sliver-openvswitch.git diff --git a/lib/json.c b/lib/json.c index a7039ba55..0a8bca278 100644 --- a/lib/json.c +++ b/lib/json.c @@ -277,7 +277,7 @@ json_real_create(double real) void json_object_put(struct json *json, const char *name, struct json *value) { - shash_add(json->u.object, name, value); + json_destroy(shash_replace(json->u.object, name, value)); } void @@ -607,7 +607,6 @@ json_lex_number(struct json_parser *p) const char *cp = ds_cstr(&p->buffer); unsigned long long int significand = 0; struct json_token token; - int sig_digits = 0; bool imprecise = false; bool negative = false; int pow10 = 0; @@ -621,7 +620,6 @@ json_lex_number(struct json_parser *p) /* At least one integer digit, but 0 may not be used as a leading digit for * a longer number. */ significand = 0; - sig_digits = 0; if (*cp == '0') { cp++; if (isdigit(*cp)) { @@ -632,7 +630,6 @@ json_lex_number(struct json_parser *p) do { if (significand <= ULLONG_MAX / 10) { significand = significand * 10 + (*cp - '0'); - sig_digits++; } else { pow10++; if (*cp != '0') { @@ -656,7 +653,6 @@ json_lex_number(struct json_parser *p) do { if (significand <= ULLONG_MAX / 10) { significand = significand * 10 + (*cp - '0'); - sig_digits++; pow10--; } else if (*cp != '0') { imprecise = true; @@ -709,7 +705,6 @@ json_lex_number(struct json_parser *p) * * We suppress negative zeros as a matter of policy. */ if (!significand) { - struct json_token token; token.type = T_INTEGER; token.u.integer = 0; json_parser_input(p, &token); @@ -719,12 +714,10 @@ json_lex_number(struct json_parser *p) if (!imprecise) { while (pow10 > 0 && significand < ULLONG_MAX / 10) { significand *= 10; - sig_digits++; pow10--; } while (pow10 < 0 && significand % 10 == 0) { significand /= 10; - sig_digits--; pow10++; } if (pow10 == 0 @@ -753,19 +746,15 @@ json_lex_number(struct json_parser *p) static const char * json_lex_4hex(const char *cp, const char *end, int *valuep) { - int value, i; + unsigned int value; if (cp + 4 > end) { return "quoted string ends within \\u escape"; } - value = 0; - for (i = 0; i < 4; i++) { - unsigned char c = *cp++; - if (!isxdigit(c)) { - return "malformed \\u escape"; - } - value = (value << 4) | hexit_value(c); + value = hexits_value(cp, 4, NULL); + if (value == UINT_MAX) { + return "malformed \\u escape"; } if (!value) { return "null bytes not supported in quoted strings"; @@ -832,7 +821,7 @@ json_string_unescape(const char *in, size_t in_len, char **outp) while (in < end) { if (*in == '"') { ds_clear(&out); - ds_put_cstr(&out, "quoted string may not include unescape \""); + ds_put_cstr(&out, "quoted string may not include unescaped \""); goto exit; } if (*in != '\\') { @@ -1192,7 +1181,7 @@ json_parser_put_value(struct json_parser *p, struct json *value) } } -static struct json_parser_node * +static void json_parser_push(struct json_parser *p, struct json *new_json, enum json_parse_state new_state) { @@ -1211,11 +1200,10 @@ json_parser_push(struct json_parser *p, node = &p->stack[p->height++]; node->json = new_json; p->parse_state = new_state; - return node; } else { + json_destroy(new_json); json_error(p, "input exceeds maximum nesting depth %d", JSON_MAX_HEIGHT); - return NULL; } } @@ -1428,17 +1416,17 @@ json_error(struct json_parser *p, const char *format, ...) #define SPACES_PER_LEVEL 2 struct json_serializer { - struct ds ds; + struct ds *ds; int depth; int flags; }; -static void json_to_ds(const struct json *, struct json_serializer *); -static void json_object_to_ds(const struct shash *object, - struct json_serializer *); -static void json_array_to_ds(const struct json_array *, - struct json_serializer *); -static void json_string_to_ds(const char *string, struct ds *); +static void json_serialize(const struct json *, struct json_serializer *); +static void json_serialize_object(const struct shash *object, + struct json_serializer *); +static void json_serialize_array(const struct json_array *, + struct json_serializer *); +static void json_serialize_string(const char *, struct ds *); /* Converts 'json' to a string in JSON format, encoded in UTF-8, and returns * that string. The caller is responsible for freeing the returned string, @@ -1456,19 +1444,30 @@ static void json_string_to_ds(const char *string, struct ds *); * object, since a bare literal does not satisfy the JSON grammar. */ char * json_to_string(const struct json *json, int flags) +{ + struct ds ds; + + ds_init(&ds); + json_to_ds(json, flags, &ds); + return ds_steal_cstr(&ds); +} + +/* Same as json_to_string(), but the output is appended to 'ds'. */ +void +json_to_ds(const struct json *json, int flags, struct ds *ds) { struct json_serializer s; - ds_init(&s.ds); + + s.ds = ds; s.depth = 0; s.flags = flags; - json_to_ds(json, &s); - return ds_steal_cstr(&s.ds); + json_serialize(json, &s); } static void -json_to_ds(const struct json *json, struct json_serializer *s) +json_serialize(const struct json *json, struct json_serializer *s) { - struct ds *ds = &s->ds; + struct ds *ds = s->ds; switch (json->type) { case JSON_NULL: @@ -1484,11 +1483,11 @@ json_to_ds(const struct json *json, struct json_serializer *s) break; case JSON_OBJECT: - json_object_to_ds(json->u.object, s); + json_serialize_object(json->u.object, s); break; case JSON_ARRAY: - json_array_to_ds(&json->u.array, s); + json_serialize_array(&json->u.array, s); break; case JSON_INTEGER: @@ -1500,7 +1499,7 @@ json_to_ds(const struct json *json, struct json_serializer *s) break; case JSON_STRING: - json_string_to_ds(json->u.string, ds); + json_serialize_string(json->u.string, ds); break; case JSON_N_TYPES: @@ -1513,34 +1512,34 @@ static void indent_line(struct json_serializer *s) { if (s->flags & JSSF_PRETTY) { - ds_put_char(&s->ds, '\n'); - ds_put_char_multiple(&s->ds, ' ', SPACES_PER_LEVEL * s->depth); + ds_put_char(s->ds, '\n'); + ds_put_char_multiple(s->ds, ' ', SPACES_PER_LEVEL * s->depth); } } static void -json_object_member_to_ds(size_t i, const struct shash_node *node, - struct json_serializer *s) +json_serialize_object_member(size_t i, const struct shash_node *node, + struct json_serializer *s) { - struct ds *ds = &s->ds; + struct ds *ds = s->ds; if (i) { ds_put_char(ds, ','); indent_line(s); } - json_string_to_ds(node->name, ds); + json_serialize_string(node->name, ds); ds_put_char(ds, ':'); if (s->flags & JSSF_PRETTY) { ds_put_char(ds, ' '); } - json_to_ds(node->data, s); + json_serialize(node->data, s); } static void -json_object_to_ds(const struct shash *object, struct json_serializer *s) +json_serialize_object(const struct shash *object, struct json_serializer *s) { - struct ds *ds = &s->ds; + struct ds *ds = s->ds; ds_put_char(ds, '{'); @@ -1554,7 +1553,7 @@ json_object_to_ds(const struct shash *object, struct json_serializer *s) nodes = shash_sort(object); n = shash_count(object); for (i = 0; i < n; i++) { - json_object_member_to_ds(i, nodes[i], s); + json_serialize_object_member(i, nodes[i], s); } free(nodes); } else { @@ -1563,7 +1562,7 @@ json_object_to_ds(const struct shash *object, struct json_serializer *s) i = 0; SHASH_FOR_EACH (node, object) { - json_object_member_to_ds(i++, node, s); + json_serialize_object_member(i++, node, s); } } @@ -1572,9 +1571,9 @@ json_object_to_ds(const struct shash *object, struct json_serializer *s) } static void -json_array_to_ds(const struct json_array *array, struct json_serializer *s) +json_serialize_array(const struct json_array *array, struct json_serializer *s) { - struct ds *ds = &s->ds; + struct ds *ds = s->ds; size_t i; ds_put_char(ds, '['); @@ -1588,7 +1587,7 @@ json_array_to_ds(const struct json_array *array, struct json_serializer *s) ds_put_char(ds, ','); indent_line(s); } - json_to_ds(array->elems[i], s); + json_serialize(array->elems[i], s); } } @@ -1597,7 +1596,7 @@ json_array_to_ds(const struct json_array *array, struct json_serializer *s) } static void -json_string_to_ds(const char *string, struct ds *ds) +json_serialize_string(const char *string, struct ds *ds) { uint8_t c;