@@ -3,6 +3,10 @@ | |||||
/* Define if .gnu.warning accepts long strings. */ | /* Define if .gnu.warning accepts long strings. */ | ||||
#undef HAS_GNU_WARNING_LONG | #undef HAS_GNU_WARNING_LONG | ||||
/* Define to 1 if you have the declaration of `INFINITY', and to 0 if you | |||||
don't. */ | |||||
#undef HAVE_DECL_INFINITY | |||||
/* Define to 1 if you have the declaration of `isinf', and to 0 if you don't. | /* Define to 1 if you have the declaration of `isinf', and to 0 if you don't. | ||||
*/ | */ | ||||
#undef HAVE_DECL_ISINF | #undef HAVE_DECL_ISINF | ||||
@@ -29,6 +29,7 @@ AC_FUNC_MEMCMP | |||||
AC_FUNC_MALLOC | AC_FUNC_MALLOC | ||||
AC_FUNC_REALLOC | AC_FUNC_REALLOC | ||||
AC_CHECK_FUNCS(strcasecmp strdup strerror snprintf vsnprintf vasprintf open vsyslog strncasecmp setlocale) | AC_CHECK_FUNCS(strcasecmp strdup strerror snprintf vsnprintf vasprintf open vsyslog strncasecmp setlocale) | ||||
AC_CHECK_DECLS([INFINITY], [], [], [[#include <math.h>]]) | |||||
AC_CHECK_DECLS([nan], [], [], [[#include <math.h>]]) | AC_CHECK_DECLS([nan], [], [], [[#include <math.h>]]) | ||||
AC_CHECK_DECLS([isnan], [], [], [[#include <math.h>]]) | AC_CHECK_DECLS([isnan], [], [], [[#include <math.h>]]) | ||||
AC_CHECK_DECLS([isinf], [], [], [[#include <math.h>]]) | AC_CHECK_DECLS([isinf], [], [], [[#include <math.h>]]) | ||||
@@ -57,6 +57,8 @@ | |||||
static const char json_null_str[] = "null"; | static const char json_null_str[] = "null"; | ||||
static const int json_null_str_len = sizeof(json_null_str) - 1; | static const int json_null_str_len = sizeof(json_null_str) - 1; | ||||
static const char json_inf_str[] = "Infinity"; | |||||
static const int json_inf_str_len = sizeof(json_inf_str) - 1; | |||||
static const char json_nan_str[] = "NaN"; | static const char json_nan_str[] = "NaN"; | ||||
static const int json_nan_str_len = sizeof(json_nan_str) - 1; | static const int json_nan_str_len = sizeof(json_nan_str) - 1; | ||||
static const char json_true_str[] = "true"; | static const char json_true_str[] = "true"; | ||||
@@ -275,6 +277,12 @@ struct json_object* json_tokener_parse_ex(struct json_tokener *tok, | |||||
saved_state = json_tokener_state_array; | saved_state = json_tokener_state_array; | ||||
current = json_object_new_array(); | current = json_object_new_array(); | ||||
break; | break; | ||||
case 'I': | |||||
case 'i': | |||||
state = json_tokener_state_inf; | |||||
printbuf_reset(tok->pb); | |||||
tok->st_pos = 0; | |||||
goto redo_char; | |||||
case 'N': | case 'N': | ||||
case 'n': | case 'n': | ||||
state = json_tokener_state_null; // or NaN | state = json_tokener_state_null; // or NaN | ||||
@@ -332,7 +340,41 @@ struct json_object* json_tokener_parse_ex(struct json_tokener *tok, | |||||
tok->depth--; | tok->depth--; | ||||
goto redo_char; | goto redo_char; | ||||
case json_tokener_state_null: | |||||
case json_tokener_state_inf: /* aka starts with 'i' */ | |||||
{ | |||||
int size; | |||||
int size_inf; | |||||
int is_negative = 0; | |||||
printbuf_memappend_fast(tok->pb, &c, 1); | |||||
size = json_min(tok->st_pos+1, json_null_str_len); | |||||
size_inf = json_min(tok->st_pos+1, json_inf_str_len); | |||||
char *infbuf = tok->pb->buf; | |||||
if (*infbuf == '-') | |||||
{ | |||||
infbuf++; | |||||
is_negative = 1; | |||||
} | |||||
if ((!(tok->flags & JSON_TOKENER_STRICT) && | |||||
strncasecmp(json_inf_str, infbuf, size_inf) == 0) || | |||||
(strncmp(json_inf_str, infbuf, size_inf) == 0) | |||||
) | |||||
{ | |||||
if (tok->st_pos == json_inf_str_len) | |||||
{ | |||||
current = json_object_new_double(is_negative ? -INFINITY : INFINITY); | |||||
saved_state = json_tokener_state_finish; | |||||
state = json_tokener_state_eatws; | |||||
goto redo_char; | |||||
} | |||||
} else { | |||||
tok->err = json_tokener_error_parse_unexpected; | |||||
goto out; | |||||
} | |||||
tok->st_pos++; | |||||
} | |||||
break; | |||||
case json_tokener_state_null: /* aka starts with 'n' */ | |||||
{ | { | ||||
int size; | int size; | ||||
int size_nan; | int size_nan; | ||||
@@ -628,6 +670,14 @@ struct json_object* json_tokener_parse_ex(struct json_tokener *tok, | |||||
} | } | ||||
if (case_len>0) | if (case_len>0) | ||||
printbuf_memappend_fast(tok->pb, case_start, case_len); | printbuf_memappend_fast(tok->pb, case_start, case_len); | ||||
// Check for -Infinity | |||||
if (tok->pb->buf[0] == '-' && case_len == 1 && | |||||
(c == 'i' || c == 'I')) | |||||
{ | |||||
state = json_tokener_state_inf; | |||||
goto redo_char; | |||||
} | |||||
} | } | ||||
{ | { | ||||
int64_t num64; | int64_t num64; | ||||
@@ -60,7 +60,8 @@ enum json_tokener_state { | |||||
json_tokener_state_object_value_add, | json_tokener_state_object_value_add, | ||||
json_tokener_state_object_sep, | json_tokener_state_object_sep, | ||||
json_tokener_state_array_after_sep, | json_tokener_state_array_after_sep, | ||||
json_tokener_state_object_field_start_after_sep | |||||
json_tokener_state_object_field_start_after_sep, | |||||
json_tokener_state_inf | |||||
}; | }; | ||||
struct json_tokener_srec | struct json_tokener_srec | ||||
@@ -21,4 +21,8 @@ | |||||
#error This platform does not have nan() | #error This platform does not have nan() | ||||
#endif | #endif | ||||
#ifndef HAVE_DECL_INFINITY | |||||
#error This platform does not have INFINITY | |||||
#endif | |||||
#endif | #endif |
@@ -51,6 +51,34 @@ static void test_basic_parse() | |||||
printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); | printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); | ||||
json_object_put(new_obj); | json_object_put(new_obj); | ||||
new_obj = json_tokener_parse("-NaN"); /* non-sensical, returns null */ | |||||
printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); | |||||
json_object_put(new_obj); | |||||
new_obj = json_tokener_parse("Inf"); /* must use full string, returns null */ | |||||
printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); | |||||
json_object_put(new_obj); | |||||
new_obj = json_tokener_parse("inf"); /* must use full string, returns null */ | |||||
printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); | |||||
json_object_put(new_obj); | |||||
new_obj = json_tokener_parse("Infinity"); | |||||
printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); | |||||
json_object_put(new_obj); | |||||
new_obj = json_tokener_parse("infinity"); | |||||
printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); | |||||
json_object_put(new_obj); | |||||
new_obj = json_tokener_parse("-Infinity"); | |||||
printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); | |||||
json_object_put(new_obj); | |||||
new_obj = json_tokener_parse("-infinity"); | |||||
printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); | |||||
json_object_put(new_obj); | |||||
new_obj = json_tokener_parse("True"); | new_obj = json_tokener_parse("True"); | ||||
printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); | printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); | ||||
json_object_put(new_obj); | json_object_put(new_obj); | ||||
@@ -4,6 +4,13 @@ new_obj.to_string()="foo" | |||||
new_obj.to_string()="ABC" | new_obj.to_string()="ABC" | ||||
new_obj.to_string()=null | new_obj.to_string()=null | ||||
new_obj.to_string()=NaN | new_obj.to_string()=NaN | ||||
new_obj.to_string()=null | |||||
new_obj.to_string()=null | |||||
new_obj.to_string()=null | |||||
new_obj.to_string()=Infinity | |||||
new_obj.to_string()=Infinity | |||||
new_obj.to_string()=-Infinity | |||||
new_obj.to_string()=-Infinity | |||||
new_obj.to_string()=true | new_obj.to_string()=true | ||||
new_obj.to_string()=12 | new_obj.to_string()=12 | ||||
new_obj.to_string()=12.3 | new_obj.to_string()=12.3 | ||||