Skip to content

Commit

Permalink
Issue json-c#103: allow Infinity and -Infinity to be parsed.
Browse files Browse the repository at this point in the history
  • Loading branch information
hawicz committed Mar 22, 2014
1 parent 217bc29 commit 05da316
Show file tree
Hide file tree
Showing 7 changed files with 97 additions and 2 deletions.
4 changes: 4 additions & 0 deletions config.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -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>]])
Expand Down
52 changes: 51 additions & 1 deletion json_tokener.c
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
3 changes: 2 additions & 1 deletion json_tokener.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 4 additions & 0 deletions math_compat.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
28 changes: 28 additions & 0 deletions tests/test_parse.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
7 changes: 7 additions & 0 deletions tests/test_parse.expected
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 05da316

Please sign in to comment.