ext/json/ext/parser/parser.rl in json_pure-1.1.0 vs ext/json/ext/parser/parser.rl in json_pure-1.1.1
- old
+ new
@@ -6,21 +6,26 @@
#include "unicode.h"
#define EVIL 0x666
static VALUE mJSON, mExt, cParser, eParserError, eNestingError;
+static VALUE CNaN, CInfinity, CMinusInfinity;
-static ID i_json_creatable_p, i_json_create, i_create_id, i_chr, i_max_nesting;
+static ID i_json_creatable_p, i_json_create, i_create_id, i_chr, i_max_nesting,
+ i_allow_nan;
+#define MinusInfinity "-Infinity"
+
typedef struct JSON_ParserStruct {
VALUE Vsource;
char *source;
long len;
char *memo;
VALUE create_id;
int max_nesting;
int current_nesting;
+ int allow_nan;
} JSON_Parser;
static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *result);
static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *result);
static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *result);
@@ -45,11 +50,14 @@
name_separator = ':';
value_separator = ',';
Vnull = 'null';
Vfalse = 'false';
Vtrue = 'true';
- begin_value = [nft"\-[{] | digit;
+ VNaN = 'NaN';
+ VInfinity = 'Infinity';
+ VMinusInfinity = '-Infinity';
+ begin_value = [nft"\-[{NI] | digit;
begin_object = '{';
end_object = '}';
begin_array = '[';
end_array = ']';
begin_string = '"';
@@ -131,17 +139,40 @@
*result = Qfalse;
}
action parse_true {
*result = Qtrue;
}
+ action parse_nan {
+ if (json->allow_nan) {
+ *result = CNaN;
+ } else {
+ rb_raise(eParserError, "unexpected token at '%s'", p - 2);
+ }
+ }
+ action parse_infinity {
+ if (json->allow_nan) {
+ *result = CInfinity;
+ } else {
+ rb_raise(eParserError, "unexpected token at '%s'", p - 8);
+ }
+ }
action parse_string {
char *np = JSON_parse_string(json, fpc, pe, result);
if (np == NULL) fbreak; else fexec np;
}
action parse_number {
char *np;
+ if(pe > fpc + 9 && !strncmp(MinusInfinity, fpc, 9)) {
+ if (json->allow_nan) {
+ *result = CMinusInfinity;
+ fexec p + 10;
+ fbreak;
+ } else {
+ rb_raise(eParserError, "unexpected token at '%s'", p);
+ }
+ }
np = JSON_parse_float(json, fpc, pe, result);
if (np != NULL) fexec np;
np = JSON_parse_integer(json, fpc, pe, result);
if (np != NULL) fexec np;
fbreak;
@@ -167,10 +198,12 @@
main := (
Vnull @parse_null |
Vfalse @parse_false |
Vtrue @parse_true |
+ VNaN @parse_nan |
+ VInfinity @parse_infinity |
begin_number >parse_number |
begin_string >parse_string |
begin_array >parse_array |
begin_object >parse_object
) %*exit;
@@ -433,11 +466,15 @@
* It will be configured by the _opts_ hash. _opts_ can have the following
* keys:
*
* _opts_ can have the following keys:
* * *max_nesting*: The maximum depth of nesting allowed in the parsed data
- * structures. Disable depth checking with :max_nesting => false.
+ * structures. Disable depth checking with :max_nesting => false|nil|0, it
+ * defaults to 19.
+ * * *allow_nan*: If set to true, allow NaN, Infinity and -Infinity in
+ * defiance of RFC 4627 to be parsed by the Parser. This option defaults to
+ * false.
*/
static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
{
char *ptr;
long len;
@@ -449,25 +486,31 @@
len = RSTRING_LEN(source);
if (len < 2) {
rb_raise(eParserError, "A JSON text must at least contain two octets!");
}
json->max_nesting = 19;
+ json->allow_nan = 0;
if (!NIL_P(opts)) {
opts = rb_convert_type(opts, T_HASH, "Hash", "to_hash");
if (NIL_P(opts)) {
rb_raise(rb_eArgError, "opts needs to be like a hash");
} else {
- VALUE s_max_nesting = ID2SYM(i_max_nesting);
- if (st_lookup(RHASH(opts)->tbl, s_max_nesting, 0)) {
- VALUE max_nesting = rb_hash_aref(opts, s_max_nesting);
+ VALUE tmp = ID2SYM(i_max_nesting);
+ if (st_lookup(RHASH(opts)->tbl, tmp, 0)) {
+ VALUE max_nesting = rb_hash_aref(opts, tmp);
if (RTEST(max_nesting)) {
Check_Type(max_nesting, T_FIXNUM);
json->max_nesting = FIX2INT(max_nesting);
} else {
json->max_nesting = 0;
}
}
+ tmp = ID2SYM(i_allow_nan);
+ if (st_lookup(RHASH(opts)->tbl, tmp, 0)) {
+ VALUE allow_nan = rb_hash_aref(opts, tmp);
+ if (RTEST(allow_nan)) json->allow_nan = 1;
+ }
}
}
json->current_nesting = 0;
/*
Convert these?
@@ -559,11 +602,16 @@
rb_define_alloc_func(cParser, cJSON_parser_s_allocate);
rb_define_method(cParser, "initialize", cParser_initialize, -1);
rb_define_method(cParser, "parse", cParser_parse, 0);
rb_define_method(cParser, "source", cParser_source, 0);
+ CNaN = rb_const_get(mJSON, rb_intern("NaN"));
+ CInfinity = rb_const_get(mJSON, rb_intern("Infinity"));
+ CMinusInfinity = rb_const_get(mJSON, rb_intern("MinusInfinity"));
+
i_json_creatable_p = rb_intern("json_creatable?");
i_json_create = rb_intern("json_create");
i_create_id = rb_intern("create_id");
i_chr = rb_intern("chr");
i_max_nesting = rb_intern("max_nesting");
+ i_allow_nan = rb_intern("allow_nan");
}