Browse Source

Issue #103: allow Infinity and -Infinity to be parsed.

tags/json-c-0.12-20140410
Eric Haszlakiewicz 11 years ago
parent
commit
05da316b9c
7 changed files with 97 additions and 2 deletions
  1. +4
    -0
      config.h.in
  2. +1
    -0
      configure.ac
  3. +51
    -1
      json_tokener.c
  4. +2
    -1
      json_tokener.h
  5. +4
    -0
      math_compat.h
  6. +28
    -0
      tests/test_parse.c
  7. +7
    -0
      tests/test_parse.expected

+ 4
- 0
config.h.in View File

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


+ 1
- 0
configure.ac View File

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


+ 51
- 1
json_tokener.c View File

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


+ 2
- 1
json_tokener.h View File

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


+ 4
- 0
math_compat.h View File

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

+ 28
- 0
tests/test_parse.c View File

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


+ 7
- 0
tests/test_parse.expected View File

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


Loading…
Cancel
Save