| @@ -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 | ||||