X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=lib%2Fjson.c;h=3acaa1964d3d5b2fe66291819dc423bb36d0a210;hb=4931f33ad9e25eb2df70ff20f1eeb4df813f8b2c;hp=d162fd5143bfc9e8cd3994007655c46ccca989f8;hpb=f6f8c3ba779e357801ebaefdf8ef8a426ab73ea4;p=openvswitch diff --git a/lib/json.c b/lib/json.c index d162fd51..3acaa196 100644 --- a/lib/json.c +++ b/lib/json.c @@ -606,6 +606,7 @@ 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; @@ -730,7 +731,6 @@ json_lex_number(struct json_parser *p) && significand <= (negative ? (unsigned long long int) LLONG_MAX + 1 : LLONG_MAX)) { - struct json_token token; token.type = T_INTEGER; token.u.integer = negative ? -significand : significand; json_parser_input(p, &token); @@ -738,19 +738,16 @@ json_lex_number(struct json_parser *p) } } - if (pow10 + sig_digits <= DBL_MAX_10_EXP) { - struct json_token token; - token.type = T_REAL; - token.u.real = significand * pow(10.0, pow10); - if (token.u.real <= DBL_MAX) { - if (negative && token.u.real) { - token.u.real = -token.u.real; - } - json_parser_input(p, &token); - return; - } + token.type = T_REAL; + if (!str_to_double(ds_cstr(&p->buffer), &token.u.real)) { + json_error(p, "number outside valid range"); + return; } - json_error(p, "number outside valid range"); + /* Suppress negative zero. */ + if (token.u.real == 0) { + token.u.real = 0; + } + json_parser_input(p, &token); } static bool @@ -1005,18 +1002,34 @@ json_from_string(const char *string) struct json * json_from_file(const char *file_name) { - struct json_parser *p; struct json *json; FILE *stream; - /* Open file. */ stream = fopen(file_name, "r"); if (!stream) { return json_string_create_nocopy( xasprintf("error opening \"%s\": %s", file_name, strerror(errno))); } + json = json_from_stream(stream); + fclose(stream); + + return json; +} + +/* Parses the contents of 'stream' as a JSON object or array, and returns a + * newly allocated 'struct json'. The caller must free the returned structure + * with json_destroy() when it is no longer needed. + * + * The file must be encoded in UTF-8. + * + * See json_from_string() for return value semantics. + */ +struct json * +json_from_stream(FILE *stream) +{ + struct json_parser *p; + struct json *json; - /* Read and parse file. */ p = json_parser_create(JSPF_TRAILER); for (;;) { char buffer[BUFSIZ]; @@ -1029,13 +1042,11 @@ json_from_file(const char *file_name) } json = json_parser_finish(p); - /* Close file and check for I/O errors. */ if (ferror(stream)) { json_destroy(json); json = json_string_create_nocopy( - xasprintf("error reading \"%s\": %s", file_name, strerror(errno))); + xasprintf("error reading JSON stream: %s", strerror(errno))); } - fclose(stream); return json; }