summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Haszlakiewicz <erh+git@nimenees.com>2014-03-09 16:41:33 -0400
committerEric Haszlakiewicz <erh+git@nimenees.com>2014-03-09 16:41:33 -0400
commit0eedf3802fad2d41e45eecd92af529440f0d7d3a (patch)
tree6149e87e18589634dece0add4d66417135a6bee1
parente6f1322b5e0fbbd5b8767b60c5fe34ff4468ec42 (diff)
downloadjson-c-0eedf3802fad2d41e45eecd92af529440f0d7d3a.tar.gz
Issue#102 - add support for parsing "NaN".
-rw-r--r--config.h.in3
-rw-r--r--configure.ac1
-rw-r--r--json_tokener.c41
-rw-r--r--math_compat.h4
-rw-r--r--tests/test_parse.c4
-rw-r--r--tests/test_parse.expected1
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