summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Haszlakiewicz <erh+git@nimenees.com>2014-03-22 17:28:40 -0400
committerEric Haszlakiewicz <erh+git@nimenees.com>2014-03-22 17:28:40 -0400
commit05da316b9ceee79fa98575133d9f4c9e2abe59d0 (patch)
treef42b8845dae79f8fddefdeb6504914f5cddc73cd
parent217bc29352de00e8cd24edb789784e1f30339414 (diff)
downloadjson-c-05da316b9ceee79fa98575133d9f4c9e2abe59d0.tar.gz
Issue #103: allow Infinity and -Infinity to be parsed.
-rw-r--r--config.h.in4
-rw-r--r--configure.ac1
-rw-r--r--json_tokener.c52
-rw-r--r--json_tokener.h3
-rw-r--r--math_compat.h4
-rw-r--r--tests/test_parse.c28
-rw-r--r--tests/test_parse.expected7
7 files changed, 97 insertions, 2 deletions
diff --git a/config.h.in b/config.h.in
index f24bfbc..7c8973f 100644
--- a/config.h.in
+++ b/config.h.in
@@ -3,6 +3,10 @@
/* Define if .gnu.warning accepts long strings. */
#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.
*/
#undef HAVE_DECL_ISINF
diff --git a/configure.ac b/configure.ac
index 96e2466..20ad715 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([INFINITY], [], [], [[#include <math.h>]])
AC_CHECK_DECLS([nan], [], [], [[#include <math.h>]])
AC_CHECK_DECLS([isnan], [], [], [[#include <math.h>]])
AC_CHECK_DECLS([isinf], [], [], [[#include <math.h>]])
diff --git a/json_tokener.c b/json_tokener.c
index 9862f9e..e4710e4 100644
--- a/json_tokener.c
+++ b/json_tokener.c
@@ -57,6 +57,8 @@
static const char json_null_str[] = "null";
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 int json_nan_str_len = sizeof(json_nan_str) - 1;
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;
current = json_object_new_array();
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':
state = json_tokener_state_null; // or NaN
@@ -332,7 +340,41 @@ struct json_object* json_tokener_parse_ex(struct json_tokener *tok,
tok->depth--;
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_nan;
@@ -628,6 +670,14 @@ struct json_object* json_tokener_parse_ex(struct json_tokener *tok,
}
if (case_len>0)
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;
diff --git a/json_tokener.h b/json_tokener.h
index 08e5ff7..61f73d2 100644
--- a/json_tokener.h
+++ b/json_tokener.h
@@ -60,7 +60,8 @@ enum json_tokener_state {
json_tokener_state_object_value_add,
json_tokener_state_object_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
diff --git a/math_compat.h b/math_compat.h
index d94a4da..f40b8fa 100644
--- a/math_compat.h
+++ b/math_compat.h
@@ -21,4 +21,8 @@
#error This platform does not have nan()
#endif
+#ifndef HAVE_DECL_INFINITY
+#error This platform does not have INFINITY
+#endif
+
#endif
diff --git a/tests/test_parse.c b/tests/test_parse.c
index f0f2550..8808d0f 100644
--- a/tests/test_parse.c
+++ b/tests/test_parse.c
@@ -51,6 +51,34 @@ 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"); /* 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");
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 378a82b..d49cbbb 100644
--- a/tests/test_parse.expected
+++ b/tests/test_parse.expected
@@ -4,6 +4,13 @@ new_obj.to_string()="foo"
new_obj.to_string()="ABC"
new_obj.to_string()=null
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()=12
new_obj.to_string()=12.3