Honor JSON_DECODE_INT_AS_REAL at lexical stage

This has the consequence that numbers are never converted to integers
when JSON_DECODE_INT_AS_REAL is set, and thus it works correctly all
integers that are representable as double.

Fixes #212.
This commit is contained in:
Petri Lehtinen
2014-12-18 15:16:14 +02:00
parent d799ee11b4
commit 5508ab403d
2 changed files with 25 additions and 16 deletions

View File

@@ -61,6 +61,7 @@ typedef struct {
typedef struct {
stream_t stream;
strbuffer_t saved_text;
size_t flags;
int token;
union {
struct {
@@ -507,7 +508,9 @@ static int lex_scan_number(lex_t *lex, int c, json_error_t *error)
goto out;
}
if(c != '.' && c != 'E' && c != 'e') {
if(!(lex->flags & JSON_DECODE_INT_AS_REAL) &&
c != '.' && c != 'E' && c != 'e')
{
json_int_t intval;
lex_unget_unsave(lex, c);
@@ -654,12 +657,13 @@ static char *lex_steal_string(lex_t *lex, size_t *out_len)
return result;
}
static int lex_init(lex_t *lex, get_func get, void *data)
static int lex_init(lex_t *lex, get_func get, size_t flags, void *data)
{
stream_init(&lex->stream, get, data);
if(strbuffer_init(&lex->saved_text))
return -1;
lex->flags = flags;
lex->token = TOKEN_INVALID;
return 0;
}
@@ -798,7 +802,6 @@ error:
static json_t *parse_value(lex_t *lex, size_t flags, json_error_t *error)
{
json_t *json;
double value;
switch(lex->token) {
case TOKEN_STRING: {
@@ -821,15 +824,7 @@ static json_t *parse_value(lex_t *lex, size_t flags, json_error_t *error)
}
case TOKEN_INTEGER: {
if (flags & JSON_DECODE_INT_AS_REAL) {
if(jsonp_strtod(&lex->saved_text, &value)) {
error_set(error, lex, "real number overflow");
return NULL;
}
json = json_real(value);
} else {
json = json_integer(lex->value.integer);
}
json = json_integer(lex->value.integer);
break;
}
@@ -942,7 +937,7 @@ json_t *json_loads(const char *string, size_t flags, json_error_t *error)
stream_data.data = string;
stream_data.pos = 0;
if(lex_init(&lex, string_get, (void *)&stream_data))
if(lex_init(&lex, string_get, flags, (void *)&stream_data))
return NULL;
result = parse_json(&lex, flags, error);
@@ -987,7 +982,7 @@ json_t *json_loadb(const char *buffer, size_t buflen, size_t flags, json_error_t
stream_data.pos = 0;
stream_data.len = buflen;
if(lex_init(&lex, buffer_get, (void *)&stream_data))
if(lex_init(&lex, buffer_get, flags, (void *)&stream_data))
return NULL;
result = parse_json(&lex, flags, error);
@@ -1014,7 +1009,7 @@ json_t *json_loadf(FILE *input, size_t flags, json_error_t *error)
return NULL;
}
if(lex_init(&lex, (get_func)fgetc, input))
if(lex_init(&lex, (get_func)fgetc, flags, input))
return NULL;
result = parse_json(&lex, flags, error);
@@ -1095,7 +1090,7 @@ json_t *json_load_callback(json_load_callback_t callback, void *arg, size_t flag
return NULL;
}
if(lex_init(&lex, (get_func)callback_get, &stream_data))
if(lex_init(&lex, (get_func)callback_get, flags, &stream_data))
return NULL;
result = parse_json(&lex, flags, error);

View File

@@ -97,6 +97,8 @@ static void decode_int_as_real()
json_int_t expected;
#endif
char big[311];
json = json_loads("42", JSON_DECODE_INT_AS_REAL | JSON_DECODE_ANY, &error);
if (!json || !json_is_real(json) || json_real_value(json) != 42.0)
fail("json_load decode int as real failed - int");
@@ -113,6 +115,18 @@ static void decode_int_as_real()
fail("json_load decode int as real failed - expected imprecision");
json_decref(json);
#endif
/* 1E309 overflows. Here we create 1E309 as a decimal number, i.e.
1000...(309 zeroes)...0. */
big[0] = '1';
memset(big + 1, '0', 309);
big[310] = '\0';
json = json_loads(big, JSON_DECODE_INT_AS_REAL | JSON_DECODE_ANY, &error);
if (json || strcmp(error.text, "real number overflow") != 0)
fail("json_load decode int as real failed - expected overflow");
json_decref(json);
}
static void allow_nul()