diff options
author | Eric Haszlakiewicz <erh+git@nimenees.com> | 2014-03-09 16:41:33 -0400 |
---|---|---|
committer | Eric Haszlakiewicz <erh+git@nimenees.com> | 2014-03-09 16:41:33 -0400 |
commit | 0eedf3802fad2d41e45eecd92af529440f0d7d3a (patch) | |
tree | 6149e87e18589634dece0add4d66417135a6bee1 | |
parent | e6f1322b5e0fbbd5b8767b60c5fe34ff4468ec42 (diff) | |
download | json-c-0eedf3802fad2d41e45eecd92af529440f0d7d3a.tar.gz |
Issue#102 - add support for parsing "NaN".
-rw-r--r-- | config.h.in | 3 | ||||
-rw-r--r-- | configure.ac | 1 | ||||
-rw-r--r-- | json_tokener.c | 41 | ||||
-rw-r--r-- | math_compat.h | 4 | ||||
-rw-r--r-- | tests/test_parse.c | 4 | ||||
-rw-r--r-- | tests/test_parse.expected | 1 |
6 files changed, 44 insertions, 10 deletions
diff --git a/config.h.in b/config.h.in index d612636..f24bfbc 100644 --- a/config.h.in +++ b/config.h.in @@ -11,6 +11,9 @@ */ #undef HAVE_DECL_ISNAN +/* Define to 1 if you have the declaration of `nan', and to 0 if you don't. */ +#undef HAVE_DECL_NAN + /* Define to 1 if you have the declaration of `_finite', and to 0 if you don't. */ #undef HAVE_DECL__FINITE diff --git a/configure.ac b/configure.ac index a7d2d7b..96e2466 100644 --- a/configure.ac +++ b/configure.ac @@ -29,6 +29,7 @@ AC_FUNC_MEMCMP AC_FUNC_MALLOC AC_FUNC_REALLOC AC_CHECK_FUNCS(strcasecmp strdup strerror snprintf vsnprintf vasprintf open vsyslog strncasecmp setlocale) +AC_CHECK_DECLS([nan], [], [], [[#include <math.h>]]) AC_CHECK_DECLS([isnan], [], [], [[#include <math.h>]]) AC_CHECK_DECLS([isinf], [], [], [[#include <math.h>]]) AC_CHECK_DECLS([_isnan], [], [], [[#include <float.h>]]) diff --git a/json_tokener.c b/json_tokener.c index 74fd27a..0c800d8 100644 --- a/json_tokener.c +++ b/json_tokener.c @@ -15,6 +15,7 @@ #include "config.h" +#include <math.h> #include <stdio.h> #include <stdlib.h> #include <stddef.h> @@ -49,9 +50,14 @@ # error You do not have strncasecmp on your system. #endif /* HAVE_STRNCASECMP */ -static const char* json_null_str = "null"; -static const char* json_true_str = "true"; -static const char* json_false_str = "false"; +static const char json_null_str[] = "null"; +static const int json_null_str_len = sizeof(json_null_str) - 1; +static const char json_nan_str[] = "NaN"; +static const int json_nan_str_len = sizeof(json_nan_str) - 1; +static const char json_true_str[] = "true"; +static const int json_true_str_len = sizeof(json_true_str) - 1; +static const char json_false_str[] = "false"; +static const int json_false_str_len = sizeof(json_false_str) - 1; // XXX after v0.10 this array will become static: const char* json_tokener_errors[] = { @@ -266,7 +272,7 @@ struct json_object* json_tokener_parse_ex(struct json_tokener *tok, break; case 'N': case 'n': - state = json_tokener_state_null; + state = json_tokener_state_null; // or NaN printbuf_reset(tok->pb); tok->st_pos = 0; goto redo_char; @@ -324,18 +330,33 @@ struct json_object* json_tokener_parse_ex(struct json_tokener *tok, case json_tokener_state_null: { int size; + int size_nan; printbuf_memappend_fast(tok->pb, &c, 1); - size = json_min(tok->st_pos+1, (int)strlen(json_null_str)); + size = json_min(tok->st_pos+1, json_null_str_len); + size_nan = json_min(tok->st_pos+1, json_nan_str_len); if((!(tok->flags & JSON_TOKENER_STRICT) && strncasecmp(json_null_str, tok->pb->buf, size) == 0) || (strncmp(json_null_str, tok->pb->buf, size) == 0) ) { - if(tok->st_pos == (int)strlen(json_null_str)) { + if (tok->st_pos == json_null_str_len) { current = NULL; saved_state = json_tokener_state_finish; state = json_tokener_state_eatws; goto redo_char; } + } + else if ((!(tok->flags & JSON_TOKENER_STRICT) && + strncasecmp(json_nan_str, tok->pb->buf, size_nan) == 0) || + (strncmp(json_nan_str, tok->pb->buf, size_nan) == 0) + ) + { + if (tok->st_pos == json_nan_str_len) + { + current = json_object_new_double(nan("")); + saved_state = json_tokener_state_finish; + state = json_tokener_state_eatws; + goto redo_char; + } } else { tok->err = json_tokener_error_parse_null; goto out; @@ -557,13 +578,13 @@ struct json_object* json_tokener_parse_ex(struct json_tokener *tok, { int size1, size2; printbuf_memappend_fast(tok->pb, &c, 1); - size1 = json_min(tok->st_pos+1, (int)strlen(json_true_str)); - size2 = json_min(tok->st_pos+1, (int)strlen(json_false_str)); + size1 = json_min(tok->st_pos+1, json_true_str_len); + size2 = json_min(tok->st_pos+1, json_false_str_len); if((!(tok->flags & JSON_TOKENER_STRICT) && strncasecmp(json_true_str, tok->pb->buf, size1) == 0) || (strncmp(json_true_str, tok->pb->buf, size1) == 0) ) { - if(tok->st_pos == (int)strlen(json_true_str)) { + if(tok->st_pos == json_true_str_len) { current = json_object_new_boolean(1); saved_state = json_tokener_state_finish; state = json_tokener_state_eatws; @@ -572,7 +593,7 @@ struct json_object* json_tokener_parse_ex(struct json_tokener *tok, } else if((!(tok->flags & JSON_TOKENER_STRICT) && strncasecmp(json_false_str, tok->pb->buf, size2) == 0) || (strncmp(json_false_str, tok->pb->buf, size2) == 0)) { - if(tok->st_pos == (int)strlen(json_false_str)) { + if(tok->st_pos == json_false_str_len) { current = json_object_new_boolean(0); saved_state = json_tokener_state_finish; state = json_tokener_state_eatws; diff --git a/math_compat.h b/math_compat.h index 4a2721e..d94a4da 100644 --- a/math_compat.h +++ b/math_compat.h @@ -17,4 +17,8 @@ # endif #endif +#ifndef HAVE_DECL_NAN +#error This platform does not have nan() +#endif + #endif diff --git a/tests/test_parse.c b/tests/test_parse.c index 1a59a6b..f0f2550 100644 --- a/tests/test_parse.c +++ b/tests/test_parse.c @@ -47,6 +47,10 @@ static void test_basic_parse() printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); json_object_put(new_obj); + new_obj = json_tokener_parse("NaN"); + 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"); printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); json_object_put(new_obj); diff --git a/tests/test_parse.expected b/tests/test_parse.expected index 5ea99d8..378a82b 100644 --- a/tests/test_parse.expected +++ b/tests/test_parse.expected @@ -3,6 +3,7 @@ new_obj.to_string()="foo" new_obj.to_string()="foo" new_obj.to_string()="ABC" new_obj.to_string()=null +new_obj.to_string()=NaN new_obj.to_string()=true new_obj.to_string()=12 new_obj.to_string()=12.3 |