summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Frank <flori@ping.de>2011-08-29 21:31:33 +0200
committerFlorian Frank <flori@ping.de>2011-08-29 21:31:33 +0200
commit2b5de6d03750b113333eded00177b14f8719042e (patch)
treefeb73b6ed464249ef0f004d68ca5f6053ed5311c
parentfe046d68c5ed88b32b1cf3343babcf367b5cc79f (diff)
parent86bd839402eae91a1703fdfe6e1ae8267f39f030 (diff)
downloadjson-2b5de6d03750b113333eded00177b14f8719042e.tar.gz
Merge branch 'quirks-mode'
-rw-r--r--ext/json/ext/generator/generator.c47
-rw-r--r--ext/json/ext/generator/generator.h1
-rw-r--r--ext/json/ext/parser/parser.c513
-rw-r--r--ext/json/ext/parser/parser.h1
-rw-r--r--ext/json/ext/parser/parser.rl177
-rw-r--r--java/src/json/ext/Generator.java6
-rw-r--r--java/src/json/ext/GeneratorMethods.java4
-rw-r--r--java/src/json/ext/GeneratorService.java2
-rw-r--r--java/src/json/ext/GeneratorState.java53
-rw-r--r--java/src/json/ext/OptionsReader.java2
-rw-r--r--java/src/json/ext/Parser.java485
-rw-r--r--java/src/json/ext/Parser.rl121
-rw-r--r--java/src/json/ext/ParserService.java2
-rw-r--r--java/src/json/ext/Utils.java2
-rw-r--r--json.gemspec4
-rw-r--r--json_pure.gemspec4
-rw-r--r--lib/json/common.rb18
-rw-r--r--lib/json/pure/generator.rb17
-rw-r--r--lib/json/pure/parser.rb142
-rwxr-xr-xtests/test_json.rb36
-rwxr-xr-xtests/test_json_generate.rb22
21 files changed, 1223 insertions, 436 deletions
diff --git a/ext/json/ext/generator/generator.c b/ext/json/ext/generator/generator.c
index 4e44178..26b667b 100644
--- a/ext/json/ext/generator/generator.c
+++ b/ext/json/ext/generator/generator.c
@@ -13,8 +13,8 @@ static VALUE mJSON, mExt, mGenerator, cState, mGeneratorMethods, mObject,
static ID i_to_s, i_to_json, i_new, i_indent, i_space, i_space_before,
i_object_nl, i_array_nl, i_max_nesting, i_allow_nan, i_ascii_only,
- i_pack, i_unpack, i_create_id, i_extend, i_key_p, i_aref, i_send,
- i_respond_to_p, i_match, i_keys, i_depth, i_dup;
+ i_quirks_mode, i_pack, i_unpack, i_create_id, i_extend, i_key_p,
+ i_aref, i_send, i_respond_to_p, i_match, i_keys, i_depth, i_dup;
/*
* Copyright 2001-2004 Unicode, Inc.
@@ -688,6 +688,8 @@ static VALUE cState_configure(VALUE self, VALUE opts)
state->allow_nan = RTEST(tmp);
tmp = rb_hash_aref(opts, ID2SYM(i_ascii_only));
state->ascii_only = RTEST(tmp);
+ tmp = rb_hash_aref(opts, ID2SYM(i_quirks_mode));
+ state->quirks_mode = RTEST(tmp);
return self;
}
@@ -708,6 +710,7 @@ static VALUE cState_to_h(VALUE self)
rb_hash_aset(result, ID2SYM(i_array_nl), rb_str_new(state->array_nl, state->array_nl_len));
rb_hash_aset(result, ID2SYM(i_allow_nan), state->allow_nan ? Qtrue : Qfalse);
rb_hash_aset(result, ID2SYM(i_ascii_only), state->ascii_only ? Qtrue : Qfalse);
+ rb_hash_aset(result, ID2SYM(i_quirks_mode), state->quirks_mode ? Qtrue : Qfalse);
rb_hash_aset(result, ID2SYM(i_max_nesting), LONG2FIX(state->max_nesting));
rb_hash_aset(result, ID2SYM(i_depth), LONG2FIX(state->depth));
return result;
@@ -961,11 +964,14 @@ static VALUE cState_generate(VALUE self, VALUE obj)
{
VALUE result = cState_partial_generate(self, obj);
VALUE re, args[2];
- args[0] = rb_str_new2("\\A\\s*(?:\\[.*\\]|\\{.*\\})\\s*\\Z");
- args[1] = CRegexp_MULTILINE;
- re = rb_class_new_instance(2, args, rb_cRegexp);
- if (NIL_P(rb_funcall(re, i_match, 1, result))) {
- rb_raise(eGeneratorError, "only generation of JSON objects or arrays allowed");
+ GET_STATE(self);
+ if (!state->quirks_mode) {
+ args[0] = rb_str_new2("\\A\\s*(?:\\[.*\\]|\\{.*\\})\\s*\\Z");
+ args[1] = CRegexp_MULTILINE;
+ re = rb_class_new_instance(2, args, rb_cRegexp);
+ if (NIL_P(rb_funcall(re, i_match, 1, result))) {
+ rb_raise(eGeneratorError, "only generation of JSON objects or arrays allowed");
+ }
}
return result;
}
@@ -1288,6 +1294,29 @@ static VALUE cState_ascii_only_p(VALUE self)
}
/*
+ * call-seq: quirks_mode?
+ *
+ * Returns true, if quirks mode is enabled. Otherwise returns false.
+ */
+static VALUE cState_quirks_mode_p(VALUE self)
+{
+ GET_STATE(self);
+ return state->quirks_mode ? Qtrue : Qfalse;
+}
+
+/*
+ * call-seq: quirks_mode=(enable)
+ *
+ * If set to true, enables the quirks_mode mode.
+ */
+static VALUE cState_quirks_mode_set(VALUE self, VALUE enable)
+{
+ GET_STATE(self);
+ state->quirks_mode = RTEST(enable);
+ return Qnil;
+}
+
+/*
* call-seq: depth
*
* This integer returns the current depth of data structure nesting.
@@ -1345,6 +1374,9 @@ void Init_generator()
rb_define_method(cState, "check_circular?", cState_check_circular_p, 0);
rb_define_method(cState, "allow_nan?", cState_allow_nan_p, 0);
rb_define_method(cState, "ascii_only?", cState_ascii_only_p, 0);
+ rb_define_method(cState, "quirks_mode?", cState_quirks_mode_p, 0);
+ rb_define_method(cState, "quirks_mode", cState_quirks_mode_p, 0);
+ rb_define_method(cState, "quirks_mode=", cState_quirks_mode_set, 1);
rb_define_method(cState, "depth", cState_depth, 0);
rb_define_method(cState, "depth=", cState_depth_set, 1);
rb_define_method(cState, "configure", cState_configure, 1);
@@ -1392,6 +1424,7 @@ void Init_generator()
i_max_nesting = rb_intern("max_nesting");
i_allow_nan = rb_intern("allow_nan");
i_ascii_only = rb_intern("ascii_only");
+ i_quirks_mode = rb_intern("quirks_mode");
i_depth = rb_intern("depth");
i_pack = rb_intern("pack");
i_unpack = rb_intern("unpack");
diff --git a/ext/json/ext/generator/generator.h b/ext/json/ext/generator/generator.h
index ee496fe..6379f05 100644
--- a/ext/json/ext/generator/generator.h
+++ b/ext/json/ext/generator/generator.h
@@ -123,6 +123,7 @@ typedef struct JSON_Generator_StateStruct {
long max_nesting;
char allow_nan;
char ascii_only;
+ char quirks_mode;
long depth;
} JSON_Generator_State;
diff --git a/ext/json/ext/parser/parser.c b/ext/json/ext/parser/parser.c
index af57b81..4ea663c 100644
--- a/ext/json/ext/parser/parser.c
+++ b/ext/json/ext/parser/parser.c
@@ -78,15 +78,16 @@ 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_create_additions,
- i_chr, i_max_nesting, i_allow_nan, i_symbolize_names, i_object_class,
- i_array_class, i_key_p, i_deep_const_get, i_match, i_match_string, i_aset, i_leftshift;
+ i_chr, i_max_nesting, i_allow_nan, i_symbolize_names, i_quirks_mode,
+ i_object_class, i_array_class, i_key_p, i_deep_const_get, i_match,
+ i_match_string, i_aset, i_leftshift;
-#line 108 "parser.rl"
+#line 109 "parser.rl"
-#line 90 "parser.c"
+#line 91 "parser.c"
static const int JSON_object_start = 1;
static const int JSON_object_first_final = 27;
static const int JSON_object_error = 0;
@@ -94,7 +95,7 @@ static const int JSON_object_error = 0;
static const int JSON_object_en_main = 1;
-#line 148 "parser.rl"
+#line 150 "parser.rl"
static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *result)
@@ -110,14 +111,14 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu
*result = NIL_P(object_class) ? rb_hash_new() : rb_class_new_instance(0, 0, object_class);
-#line 114 "parser.c"
+#line 115 "parser.c"
{
cs = JSON_object_start;
}
-#line 163 "parser.rl"
+#line 165 "parser.rl"
-#line 121 "parser.c"
+#line 122 "parser.c"
{
if ( p == pe )
goto _test_eof;
@@ -145,7 +146,7 @@ case 2:
goto st2;
goto st0;
tr2:
-#line 131 "parser.rl"
+#line 132 "parser.rl"
{
char *np;
json->parsing_name = 1;
@@ -158,7 +159,7 @@ st3:
if ( ++p == pe )
goto _test_eof3;
case 3:
-#line 162 "parser.c"
+#line 163 "parser.c"
switch( (*p) ) {
case 13: goto st3;
case 32: goto st3;
@@ -225,7 +226,7 @@ case 8:
goto st8;
goto st0;
tr11:
-#line 116 "parser.rl"
+#line 117 "parser.rl"
{
VALUE v = Qnil;
char *np = JSON_parse_value(json, p, pe, &v);
@@ -245,7 +246,7 @@ st9:
if ( ++p == pe )
goto _test_eof9;
case 9:
-#line 249 "parser.c"
+#line 250 "parser.c"
switch( (*p) ) {
case 13: goto st9;
case 32: goto st9;
@@ -334,14 +335,14 @@ case 18:
goto st9;
goto st18;
tr4:
-#line 139 "parser.rl"
+#line 140 "parser.rl"
{ p--; {p++; cs = 27; goto _out;} }
goto st27;
st27:
if ( ++p == pe )
goto _test_eof27;
case 27:
-#line 345 "parser.c"
+#line 346 "parser.c"
goto st0;
st19:
if ( ++p == pe )
@@ -439,7 +440,7 @@ case 26:
_out: {}
}
-#line 164 "parser.rl"
+#line 166 "parser.rl"
if (cs >= JSON_object_first_final) {
if (json->create_additions) {
@@ -458,7 +459,8 @@ case 26:
}
-#line 462 "parser.c"
+
+#line 464 "parser.c"
static const int JSON_value_start = 1;
static const int JSON_value_first_final = 21;
static const int JSON_value_error = 0;
@@ -466,7 +468,7 @@ static const int JSON_value_error = 0;
static const int JSON_value_en_main = 1;
-#line 262 "parser.rl"
+#line 265 "parser.rl"
static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *result)
@@ -474,14 +476,14 @@ static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *resul
int cs = EVIL;
-#line 478 "parser.c"
+#line 480 "parser.c"
{
cs = JSON_value_start;
}
-#line 269 "parser.rl"
+#line 272 "parser.rl"
-#line 485 "parser.c"
+#line 487 "parser.c"
{
if ( p == pe )
goto _test_eof;
@@ -506,17 +508,17 @@ st0:
cs = 0;
goto _out;
tr0:
-#line 210 "parser.rl"
+#line 213 "parser.rl"
{
char *np = JSON_parse_string(json, p, pe, result);
if (np == NULL) { p--; {p++; cs = 21; goto _out;} } else {p = (( np))-1;}
}
goto st21;
tr2:
-#line 215 "parser.rl"
+#line 218 "parser.rl"
{
char *np;
- if(pe > p + 9 && !strncmp(MinusInfinity, p, 9)) {
+ if(pe > p + 9 - json->quirks_mode && !strncmp(MinusInfinity, p, 9)) {
if (json->allow_nan) {
*result = CMinusInfinity;
{p = (( p + 10))-1;}
@@ -533,7 +535,7 @@ tr2:
}
goto st21;
tr5:
-#line 233 "parser.rl"
+#line 236 "parser.rl"
{
char *np;
json->current_nesting++;
@@ -543,7 +545,7 @@ tr5:
}
goto st21;
tr9:
-#line 241 "parser.rl"
+#line 244 "parser.rl"
{
char *np;
json->current_nesting++;
@@ -553,7 +555,7 @@ tr9:
}
goto st21;
tr16:
-#line 203 "parser.rl"
+#line 206 "parser.rl"
{
if (json->allow_nan) {
*result = CInfinity;
@@ -563,7 +565,7 @@ tr16:
}
goto st21;
tr18:
-#line 196 "parser.rl"
+#line 199 "parser.rl"
{
if (json->allow_nan) {
*result = CNaN;
@@ -573,19 +575,19 @@ tr18:
}
goto st21;
tr22:
-#line 190 "parser.rl"
+#line 193 "parser.rl"
{
*result = Qfalse;
}
goto st21;
tr25:
-#line 187 "parser.rl"
+#line 190 "parser.rl"
{
*result = Qnil;
}
goto st21;
tr28:
-#line 193 "parser.rl"
+#line 196 "parser.rl"
{
*result = Qtrue;
}
@@ -594,9 +596,9 @@ st21:
if ( ++p == pe )
goto _test_eof21;
case 21:
-#line 249 "parser.rl"
+#line 252 "parser.rl"
{ p--; {p++; cs = 21; goto _out;} }
-#line 600 "parser.c"
+#line 602 "parser.c"
goto st0;
st2:
if ( ++p == pe )
@@ -757,7 +759,7 @@ case 20:
_out: {}
}
-#line 270 "parser.rl"
+#line 273 "parser.rl"
if (cs >= JSON_value_first_final) {
return p;
@@ -767,15 +769,15 @@ case 20:
}
-#line 771 "parser.c"
+#line 773 "parser.c"
static const int JSON_integer_start = 1;
-static const int JSON_integer_first_final = 5;
+static const int JSON_integer_first_final = 3;
static const int JSON_integer_error = 0;
static const int JSON_integer_en_main = 1;
-#line 286 "parser.rl"
+#line 289 "parser.rl"
static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *result)
@@ -783,15 +785,15 @@ static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *res
int cs = EVIL;
-#line 787 "parser.c"
+#line 789 "parser.c"
{
cs = JSON_integer_start;
}
-#line 293 "parser.rl"
+#line 296 "parser.rl"
json->memo = p;
-#line 795 "parser.c"
+#line 797 "parser.c"
{
if ( p == pe )
goto _test_eof;
@@ -803,7 +805,7 @@ case 1:
case 48: goto st3;
}
if ( 49 <= (*p) && (*p) <= 57 )
- goto st4;
+ goto st5;
goto st0;
st0:
cs = 0;
@@ -815,7 +817,7 @@ case 2:
if ( (*p) == 48 )
goto st3;
if ( 49 <= (*p) && (*p) <= 57 )
- goto st4;
+ goto st5;
goto st0;
st3:
if ( ++p == pe )
@@ -825,33 +827,33 @@ case 3:
goto st0;
goto tr4;
tr4:
-#line 283 "parser.rl"
- { p--; {p++; cs = 5; goto _out;} }
- goto st5;
-st5:
- if ( ++p == pe )
- goto _test_eof5;
-case 5:
-#line 836 "parser.c"
- goto st0;
+#line 286 "parser.rl"
+ { p--; {p++; cs = 4; goto _out;} }
+ goto st4;
st4:
if ( ++p == pe )
goto _test_eof4;
case 4:
+#line 838 "parser.c"
+ goto st0;
+st5:
+ if ( ++p == pe )
+ goto _test_eof5;
+case 5:
if ( 48 <= (*p) && (*p) <= 57 )
- goto st4;
+ goto st5;
goto tr4;
}
_test_eof2: cs = 2; goto _test_eof;
_test_eof3: cs = 3; goto _test_eof;
- _test_eof5: cs = 5; goto _test_eof;
_test_eof4: cs = 4; goto _test_eof;
+ _test_eof5: cs = 5; goto _test_eof;
_test_eof: {}
_out: {}
}
-#line 295 "parser.rl"
+#line 298 "parser.rl"
if (cs >= JSON_integer_first_final) {
long len = p - json->memo;
@@ -863,15 +865,15 @@ case 4:
}
-#line 867 "parser.c"
+#line 869 "parser.c"
static const int JSON_float_start = 1;
-static const int JSON_float_first_final = 10;
+static const int JSON_float_first_final = 8;
static const int JSON_float_error = 0;
static const int JSON_float_en_main = 1;
-#line 317 "parser.rl"
+#line 320 "parser.rl"
static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *result)
@@ -879,15 +881,15 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul
int cs = EVIL;
-#line 883 "parser.c"
+#line 885 "parser.c"
{
cs = JSON_float_start;
}
-#line 324 "parser.rl"
+#line 327 "parser.rl"
json->memo = p;
-#line 891 "parser.c"
+#line 893 "parser.c"
{
if ( p == pe )
goto _test_eof;
@@ -899,7 +901,7 @@ case 1:
case 48: goto st3;
}
if ( 49 <= (*p) && (*p) <= 57 )
- goto st9;
+ goto st7;
goto st0;
st0:
cs = 0;
@@ -911,7 +913,7 @@ case 2:
if ( (*p) == 48 )
goto st3;
if ( 49 <= (*p) && (*p) <= 57 )
- goto st9;
+ goto st7;
goto st0;
st3:
if ( ++p == pe )
@@ -919,8 +921,8 @@ st3:
case 3:
switch( (*p) ) {
case 46: goto st4;
- case 69: goto st6;
- case 101: goto st6;
+ case 69: goto st5;
+ case 101: goto st5;
}
goto st0;
st4:
@@ -928,92 +930,92 @@ st4:
goto _test_eof4;
case 4:
if ( 48 <= (*p) && (*p) <= 57 )
- goto st5;
+ goto st8;
goto st0;
-st5:
+st8:
if ( ++p == pe )
- goto _test_eof5;
-case 5:
+ goto _test_eof8;
+case 8:
switch( (*p) ) {
- case 69: goto st6;
- case 101: goto st6;
+ case 69: goto st5;
+ case 101: goto st5;
}
if ( (*p) > 46 ) {
if ( 48 <= (*p) && (*p) <= 57 )
- goto st5;
+ goto st8;
} else if ( (*p) >= 45 )
goto st0;
- goto tr7;
-tr7:
-#line 311 "parser.rl"
- { p--; {p++; cs = 10; goto _out;} }
- goto st10;
-st10:
+ goto tr9;
+tr9:
+#line 314 "parser.rl"
+ { p--; {p++; cs = 9; goto _out;} }
+ goto st9;
+st9:
if ( ++p == pe )
- goto _test_eof10;
-case 10:
-#line 956 "parser.c"
+ goto _test_eof9;
+case 9:
+#line 958 "parser.c"
goto st0;
-st6:
+st5:
if ( ++p == pe )
- goto _test_eof6;
-case 6:
+ goto _test_eof5;
+case 5:
switch( (*p) ) {
- case 43: goto st7;
- case 45: goto st7;
+ case 43: goto st6;
+ case 45: goto st6;
}
if ( 48 <= (*p) && (*p) <= 57 )
- goto st8;
+ goto st10;
goto st0;
-st7:
+st6:
if ( ++p == pe )
- goto _test_eof7;
-case 7:
+ goto _test_eof6;
+case 6:
if ( 48 <= (*p) && (*p) <= 57 )
- goto st8;
+ goto st10;
goto st0;
-st8:
+st10:
if ( ++p == pe )
- goto _test_eof8;
-case 8:
+ goto _test_eof10;
+case 10:
switch( (*p) ) {
case 69: goto st0;
case 101: goto st0;
}
if ( (*p) > 46 ) {
if ( 48 <= (*p) && (*p) <= 57 )
- goto st8;
+ goto st10;
} else if ( (*p) >= 45 )
goto st0;
- goto tr7;
-st9:
+ goto tr9;
+st7:
if ( ++p == pe )
- goto _test_eof9;
-case 9:
+ goto _test_eof7;
+case 7:
switch( (*p) ) {
case 46: goto st4;
- case 69: goto st6;
- case 101: goto st6;
+ case 69: goto st5;
+ case 101: goto st5;
}
if ( 48 <= (*p) && (*p) <= 57 )
- goto st9;
+ goto st7;
goto st0;
}
_test_eof2: cs = 2; goto _test_eof;
_test_eof3: cs = 3; goto _test_eof;
_test_eof4: cs = 4; goto _test_eof;
+ _test_eof8: cs = 8; goto _test_eof;
+ _test_eof9: cs = 9; goto _test_eof;
_test_eof5: cs = 5; goto _test_eof;
- _test_eof10: cs = 10; goto _test_eof;
_test_eof6: cs = 6; goto _test_eof;
+ _test_eof10: cs = 10; goto _test_eof;
_test_eof7: cs = 7; goto _test_eof;
- _test_eof8: cs = 8; goto _test_eof;
- _test_eof9: cs = 9; goto _test_eof;
_test_eof: {}
_out: {}
}
-#line 326 "parser.rl"
+#line 329 "parser.rl"
if (cs >= JSON_float_first_final) {
long len = p - json->memo;
@@ -1026,7 +1028,7 @@ case 9:
-#line 1030 "parser.c"
+#line 1032 "parser.c"
static const int JSON_array_start = 1;
static const int JSON_array_first_final = 17;
static const int JSON_array_error = 0;
@@ -1034,7 +1036,7 @@ static const int JSON_array_error = 0;
static const int JSON_array_en_main = 1;
-#line 366 "parser.rl"
+#line 369 "parser.rl"
static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *result)
@@ -1048,14 +1050,14 @@ static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *resul
*result = NIL_P(array_class) ? rb_ary_new() : rb_class_new_instance(0, 0, array_class);
-#line 1052 "parser.c"
+#line 1054 "parser.c"
{
cs = JSON_array_start;
}
-#line 379 "parser.rl"
+#line 382 "parser.rl"
-#line 1059 "parser.c"
+#line 1061 "parser.c"
{
if ( p == pe )
goto _test_eof;
@@ -1094,7 +1096,7 @@ case 2:
goto st2;
goto st0;
tr2:
-#line 343 "parser.rl"
+#line 346 "parser.rl"
{
VALUE v = Qnil;
char *np = JSON_parse_value(json, p, pe, &v);
@@ -1114,7 +1116,7 @@ st3:
if ( ++p == pe )
goto _test_eof3;
case 3:
-#line 1118 "parser.c"
+#line 1120 "parser.c"
switch( (*p) ) {
case 13: goto st3;
case 32: goto st3;
@@ -1214,14 +1216,14 @@ case 12:
goto st3;
goto st12;
tr4:
-#line 358 "parser.rl"
+#line 361 "parser.rl"
{ p--; {p++; cs = 17; goto _out;} }
goto st17;
st17:
if ( ++p == pe )
goto _test_eof17;
case 17:
-#line 1225 "parser.c"
+#line 1227 "parser.c"
goto st0;
st13:
if ( ++p == pe )
@@ -1277,7 +1279,7 @@ case 16:
_out: {}
}
-#line 380 "parser.rl"
+#line 383 "parser.rl"
if(cs >= JSON_array_first_final) {
return p + 1;
@@ -1358,7 +1360,7 @@ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd)
}
-#line 1362 "parser.c"
+#line 1364 "parser.c"
static const int JSON_string_start = 1;
static const int JSON_string_first_final = 8;
static const int JSON_string_error = 0;
@@ -1366,7 +1368,7 @@ static const int JSON_string_error = 0;
static const int JSON_string_en_main = 1;
-#line 479 "parser.rl"
+#line 482 "parser.rl"
static int
@@ -1388,15 +1390,15 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
*result = rb_str_buf_new(0);
-#line 1392 "parser.c"
+#line 1394 "parser.c"
{
cs = JSON_string_start;
}
-#line 500 "parser.rl"
+#line 503 "parser.rl"
json->memo = p;
-#line 1400 "parser.c"
+#line 1402 "parser.c"
{
if ( p == pe )
goto _test_eof;
@@ -1421,7 +1423,7 @@ case 2:
goto st0;
goto st2;
tr2:
-#line 465 "parser.rl"
+#line 468 "parser.rl"
{
*result = json_string_unescape(*result, json->memo + 1, p);
if (NIL_P(*result)) {
@@ -1432,14 +1434,14 @@ tr2:
{p = (( p + 1))-1;}
}
}
-#line 476 "parser.rl"
+#line 479 "parser.rl"
{ p--; {p++; cs = 8; goto _out;} }
goto st8;
st8:
if ( ++p == pe )
goto _test_eof8;
case 8:
-#line 1443 "parser.c"
+#line 1445 "parser.c"
goto st0;
st3:
if ( ++p == pe )
@@ -1515,7 +1517,7 @@ case 7:
_out: {}
}
-#line 502 "parser.rl"
+#line 505 "parser.rl"
if (json->create_additions && RTEST(match_string = json->match_string)) {
VALUE klass;
@@ -1538,19 +1540,6 @@ case 7:
}
}
-
-
-#line 1544 "parser.c"
-static const int JSON_start = 1;
-static const int JSON_first_final = 10;
-static const int JSON_error = 0;
-
-static const int JSON_en_main = 1;
-
-
-#line 550 "parser.rl"
-
-
/*
* Document-class: JSON::Ext::Parser
*
@@ -1632,8 +1621,6 @@ static VALUE convert_encoding(VALUE source)
*/
static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
{
- char *ptr;
- long len;
VALUE source, opts;
GET_PARSER_INIT;
@@ -1641,9 +1628,6 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
rb_raise(rb_eTypeError, "already initialized instance");
}
rb_scan_args(argc, argv, "11", &source, &opts);
- source = convert_encoding(StringValue(source));
- ptr = RSTRING_PTR(source);
- len = RSTRING_LEN(source);
if (!NIL_P(opts)) {
opts = rb_convert_type(opts, T_HASH, "Hash", "to_hash");
if (NIL_P(opts)) {
@@ -1673,6 +1657,13 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
} else {
json->symbolize_names = 0;
}
+ tmp = ID2SYM(i_quirks_mode);
+ if (option_given_p(opts, tmp)) {
+ VALUE quirks_mode = rb_hash_aref(opts, tmp);
+ json->quirks_mode = RTEST(quirks_mode) ? 1 : 0;
+ } else {
+ json->quirks_mode = 0;
+ }
tmp = ID2SYM(i_create_additions);
if (option_given_p(opts, tmp)) {
json->create_additions = RTEST(rb_hash_aref(opts, tmp));
@@ -1713,20 +1704,29 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
json->object_class = Qnil;
json->array_class = Qnil;
}
+ if (!json->quirks_mode) {
+ source = convert_encoding(StringValue(source));
+ }
json->current_nesting = 0;
- json->len = len;
- json->source = ptr;
+ json->len = RSTRING_LEN(source);
+ json->source = RSTRING_PTR(source);;
json->Vsource = source;
return self;
}
-/*
- * call-seq: parse()
- *
- * Parses the current JSON text _source_ and returns the complete data
- * structure as a result.
- */
-static VALUE cParser_parse(VALUE self)
+
+#line 1719 "parser.c"
+static const int JSON_start = 1;
+static const int JSON_first_final = 10;
+static const int JSON_error = 0;
+
+static const int JSON_en_main = 1;
+
+
+#line 726 "parser.rl"
+
+
+static VALUE cParser_parse_strict(VALUE self)
{
char *p, *pe;
int cs = EVIL;
@@ -1739,7 +1739,7 @@ static VALUE cParser_parse(VALUE self)
cs = JSON_start;
}
-#line 735 "parser.rl"
+#line 736 "parser.rl"
p = json->source;
pe = p + json->len;
@@ -1799,7 +1799,7 @@ case 5:
goto st1;
goto st5;
tr3:
-#line 539 "parser.rl"
+#line 715 "parser.rl"
{
char *np;
json->current_nesting = 1;
@@ -1808,7 +1808,7 @@ tr3:
}
goto st10;
tr4:
-#line 532 "parser.rl"
+#line 708 "parser.rl"
{
char *np;
json->current_nesting = 1;
@@ -1877,7 +1877,7 @@ case 9:
_out: {}
}
-#line 738 "parser.rl"
+#line 739 "parser.rl"
if (cs >= JSON_first_final && p == pe) {
return result;
@@ -1887,6 +1887,197 @@ case 9:
}
}
+
+
+#line 1893 "parser.c"
+static const int JSON_quirks_mode_start = 1;
+static const int JSON_quirks_mode_first_final = 10;
+static const int JSON_quirks_mode_error = 0;
+
+static const int JSON_quirks_mode_en_main = 1;
+
+
+#line 764 "parser.rl"
+
+
+static VALUE cParser_parse_quirks_mode(VALUE self)
+{
+ char *p, *pe;
+ int cs = EVIL;
+ VALUE result = Qnil;
+ GET_PARSER;
+
+
+#line 1912 "parser.c"
+ {
+ cs = JSON_quirks_mode_start;
+ }
+
+#line 774 "parser.rl"
+ p = json->source;
+ pe = p + json->len;
+
+#line 1921 "parser.c"
+ {
+ if ( p == pe )
+ goto _test_eof;
+ switch ( cs )
+ {
+st1:
+ if ( ++p == pe )
+ goto _test_eof1;
+case 1:
+ switch( (*p) ) {
+ case 13: goto st1;
+ case 32: goto st1;
+ case 34: goto tr2;
+ case 45: goto tr2;
+ case 47: goto st6;
+ case 73: goto tr2;
+ case 78: goto tr2;
+ case 91: goto tr2;
+ case 102: goto tr2;
+ case 110: goto tr2;
+ case 116: goto tr2;
+ case 123: goto tr2;
+ }
+ if ( (*p) > 10 ) {
+ if ( 48 <= (*p) && (*p) <= 57 )
+ goto tr2;
+ } else if ( (*p) >= 9 )
+ goto st1;
+ goto st0;
+st0:
+cs = 0;
+ goto _out;
+tr2:
+#line 756 "parser.rl"
+ {
+ char *np = JSON_parse_value(json, p, pe, &result);
+ if (np == NULL) { p--; {p++; cs = 10; goto _out;} } else {p = (( np))-1;}
+ }
+ goto st10;
+st10:
+ if ( ++p == pe )
+ goto _test_eof10;
+case 10:
+#line 1965 "parser.c"
+ switch( (*p) ) {
+ case 13: goto st10;
+ case 32: goto st10;
+ case 47: goto st2;
+ }
+ if ( 9 <= (*p) && (*p) <= 10 )
+ goto st10;
+ goto st0;
+st2:
+ if ( ++p == pe )
+ goto _test_eof2;
+case 2:
+ switch( (*p) ) {
+ case 42: goto st3;
+ case 47: goto st5;
+ }
+ goto st0;
+st3:
+ if ( ++p == pe )
+ goto _test_eof3;
+case 3:
+ if ( (*p) == 42 )
+ goto st4;
+ goto st3;
+st4:
+ if ( ++p == pe )
+ goto _test_eof4;
+case 4:
+ switch( (*p) ) {
+ case 42: goto st4;
+ case 47: goto st10;
+ }
+ goto st3;
+st5:
+ if ( ++p == pe )
+ goto _test_eof5;
+case 5:
+ if ( (*p) == 10 )
+ goto st10;
+ goto st5;
+st6:
+ if ( ++p == pe )
+ goto _test_eof6;
+case 6:
+ switch( (*p) ) {
+ case 42: goto st7;
+ case 47: goto st9;
+ }
+ goto st0;
+st7:
+ if ( ++p == pe )
+ goto _test_eof7;
+case 7:
+ if ( (*p) == 42 )
+ goto st8;
+ goto st7;
+st8:
+ if ( ++p == pe )
+ goto _test_eof8;
+case 8:
+ switch( (*p) ) {
+ case 42: goto st8;
+ case 47: goto st1;
+ }
+ goto st7;
+st9:
+ if ( ++p == pe )
+ goto _test_eof9;
+case 9:
+ if ( (*p) == 10 )
+ goto st1;
+ goto st9;
+ }
+ _test_eof1: cs = 1; goto _test_eof;
+ _test_eof10: cs = 10; goto _test_eof;
+ _test_eof2: cs = 2; goto _test_eof;
+ _test_eof3: cs = 3; goto _test_eof;
+ _test_eof4: cs = 4; goto _test_eof;
+ _test_eof5: cs = 5; goto _test_eof;
+ _test_eof6: cs = 6; goto _test_eof;
+ _test_eof7: cs = 7; goto _test_eof;
+ _test_eof8: cs = 8; goto _test_eof;
+ _test_eof9: cs = 9; goto _test_eof;
+
+ _test_eof: {}
+ _out: {}
+ }
+
+#line 777 "parser.rl"
+
+ if (cs >= JSON_quirks_mode_first_final && p == pe) {
+ return result;
+ } else {
+ rb_raise(eParserError, "%u: unexpected token at '%s'", __LINE__, p);
+ return Qnil;
+ }
+}
+
+/*
+ * call-seq: parse()
+ *
+ * Parses the current JSON text _source_ and returns the complete data
+ * structure as a result.
+ */
+static VALUE cParser_parse(VALUE self)
+{
+ GET_PARSER;
+
+ if (json->quirks_mode) {
+ return cParser_parse_quirks_mode(self);
+ } else {
+ return cParser_parse_strict(self);
+ }
+}
+
+
static JSON_Parser *JSON_allocate()
{
JSON_Parser *json = ALLOC(JSON_Parser);
@@ -1926,6 +2117,18 @@ static VALUE cParser_source(VALUE self)
return rb_str_dup(json->Vsource);
}
+/*
+ * call-seq: quirks_mode?()
+ *
+ * Returns a true, if this parser is in quirks_mode, false otherwise.
+ */
+static VALUE cParser_quirks_mode_p(VALUE self)
+{
+ GET_PARSER;
+ return json->quirks_mode ? Qtrue : Qfalse;
+}
+
+
void Init_parser()
{
rb_require("json/common");
@@ -1938,6 +2141,7 @@ void Init_parser()
rb_define_method(cParser, "initialize", cParser_initialize, -1);
rb_define_method(cParser, "parse", cParser_parse, 0);
rb_define_method(cParser, "source", cParser_source, 0);
+ rb_define_method(cParser, "quirks_mode?", cParser_quirks_mode_p, 0);
CNaN = rb_const_get(mJSON, rb_intern("NaN"));
CInfinity = rb_const_get(mJSON, rb_intern("Infinity"));
@@ -1951,6 +2155,7 @@ void Init_parser()
i_max_nesting = rb_intern("max_nesting");
i_allow_nan = rb_intern("allow_nan");
i_symbolize_names = rb_intern("symbolize_names");
+ i_quirks_mode = rb_intern("quirks_mode");
i_object_class = rb_intern("object_class");
i_array_class = rb_intern("array_class");
i_match = rb_intern("match");
diff --git a/ext/json/ext/parser/parser.h b/ext/json/ext/parser/parser.h
index f2ce5a4..fc73810 100644
--- a/ext/json/ext/parser/parser.h
+++ b/ext/json/ext/parser/parser.h
@@ -44,6 +44,7 @@ typedef struct JSON_ParserStruct {
int allow_nan;
int parsing_name;
int symbolize_names;
+ int quirks_mode;
VALUE object_class;
VALUE array_class;
int create_additions;
diff --git a/ext/json/ext/parser/parser.rl b/ext/json/ext/parser/parser.rl
index 21b445e..e7d47e1 100644
--- a/ext/json/ext/parser/parser.rl
+++ b/ext/json/ext/parser/parser.rl
@@ -76,8 +76,9 @@ 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_create_additions,
- i_chr, i_max_nesting, i_allow_nan, i_symbolize_names, i_object_class,
- i_array_class, i_key_p, i_deep_const_get, i_match, i_match_string, i_aset, i_leftshift;
+ i_chr, i_max_nesting, i_allow_nan, i_symbolize_names, i_quirks_mode,
+ i_object_class, i_array_class, i_key_p, i_deep_const_get, i_match,
+ i_match_string, i_aset, i_leftshift;
%%{
machine JSON_common;
@@ -138,13 +139,14 @@ static ID i_json_creatable_p, i_json_create, i_create_id, i_create_additions,
action exit { fhold; fbreak; }
- a_pair = ignore* begin_name >parse_name
- ignore* name_separator ignore*
- begin_value >parse_value;
+ pair = ignore* begin_name >parse_name ignore* name_separator ignore* begin_value >parse_value;
+ next_pair = ignore* value_separator pair;
- main := begin_object
- (a_pair (ignore* value_separator a_pair)*)?
- ignore* end_object @exit;
+ main := (
+ begin_object
+ (pair (next_pair)*)? ignore*
+ end_object
+ ) @exit;
}%%
static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *result)
@@ -178,6 +180,7 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu
}
}
+
%%{
machine JSON_value;
include JSON_common;
@@ -214,7 +217,7 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu
action parse_number {
char *np;
- if(pe > fpc + 9 && !strncmp(MinusInfinity, fpc, 9)) {
+ if(pe > fpc + 9 - json->quirks_mode && !strncmp(MinusInfinity, fpc, 9)) {
if (json->allow_nan) {
*result = CMinusInfinity;
fexec p + 10;
@@ -282,7 +285,7 @@ static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *resul
action exit { fhold; fbreak; }
- main := '-'? ('0' | [1-9][0-9]*) (^[0-9] @exit);
+ main := '-'? ('0' | [1-9][0-9]*) (^[0-9]? @exit);
}%%
static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *result)
@@ -313,7 +316,7 @@ static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *res
main := '-'? (
(('0' | [1-9][0-9]*) '.' [0-9]+ ([Ee] [+\-]?[0-9]+)?)
| (('0' | [1-9][0-9]*) ([Ee] [+\-]?[0-9]+))
- ) (^[0-9Ee.\-] @exit );
+ ) (^[0-9Ee.\-]? @exit );
}%%
static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *result)
@@ -521,34 +524,6 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
}
}
-
-%%{
- machine JSON;
-
- write data;
-
- include JSON_common;
-
- action parse_object {
- char *np;
- json->current_nesting = 1;
- np = JSON_parse_object(json, fpc, pe, &result);
- if (np == NULL) { fhold; fbreak; } else fexec np;
- }
-
- action parse_array {
- char *np;
- json->current_nesting = 1;
- np = JSON_parse_array(json, fpc, pe, &result);
- if (np == NULL) { fhold; fbreak; } else fexec np;
- }
-
- main := ignore* (
- begin_object >parse_object |
- begin_array >parse_array
- ) ignore*;
-}%%
-
/*
* Document-class: JSON::Ext::Parser
*
@@ -630,8 +605,6 @@ static VALUE convert_encoding(VALUE source)
*/
static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
{
- char *ptr;
- long len;
VALUE source, opts;
GET_PARSER_INIT;
@@ -639,9 +612,6 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
rb_raise(rb_eTypeError, "already initialized instance");
}
rb_scan_args(argc, argv, "11", &source, &opts);
- source = convert_encoding(StringValue(source));
- ptr = RSTRING_PTR(source);
- len = RSTRING_LEN(source);
if (!NIL_P(opts)) {
opts = rb_convert_type(opts, T_HASH, "Hash", "to_hash");
if (NIL_P(opts)) {
@@ -671,6 +641,13 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
} else {
json->symbolize_names = 0;
}
+ tmp = ID2SYM(i_quirks_mode);
+ if (option_given_p(opts, tmp)) {
+ VALUE quirks_mode = rb_hash_aref(opts, tmp);
+ json->quirks_mode = RTEST(quirks_mode) ? 1 : 0;
+ } else {
+ json->quirks_mode = 0;
+ }
tmp = ID2SYM(i_create_additions);
if (option_given_p(opts, tmp)) {
json->create_additions = RTEST(rb_hash_aref(opts, tmp));
@@ -711,20 +688,44 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
json->object_class = Qnil;
json->array_class = Qnil;
}
+ if (!json->quirks_mode) {
+ source = convert_encoding(StringValue(source));
+ }
json->current_nesting = 0;
- json->len = len;
- json->source = ptr;
+ json->len = RSTRING_LEN(source);
+ json->source = RSTRING_PTR(source);;
json->Vsource = source;
return self;
}
-/*
- * call-seq: parse()
- *
- * Parses the current JSON text _source_ and returns the complete data
- * structure as a result.
- */
-static VALUE cParser_parse(VALUE self)
+%%{
+ machine JSON;
+
+ write data;
+
+ include JSON_common;
+
+ action parse_object {
+ char *np;
+ json->current_nesting = 1;
+ np = JSON_parse_object(json, fpc, pe, &result);
+ if (np == NULL) { fhold; fbreak; } else fexec np;
+ }
+
+ action parse_array {
+ char *np;
+ json->current_nesting = 1;
+ np = JSON_parse_array(json, fpc, pe, &result);
+ if (np == NULL) { fhold; fbreak; } else fexec np;
+ }
+
+ main := ignore* (
+ begin_object >parse_object |
+ begin_array >parse_array
+ ) ignore*;
+}%%
+
+static VALUE cParser_parse_strict(VALUE self)
{
char *p, *pe;
int cs = EVIL;
@@ -744,6 +745,62 @@ static VALUE cParser_parse(VALUE self)
}
}
+
+%%{
+ machine JSON_quirks_mode;
+
+ write data;
+
+ include JSON_common;
+
+ action parse_value {
+ char *np = JSON_parse_value(json, fpc, pe, &result);
+ if (np == NULL) { fhold; fbreak; } else fexec np;
+ }
+
+ main := ignore* (
+ begin_value >parse_value
+ ) ignore*;
+}%%
+
+static VALUE cParser_parse_quirks_mode(VALUE self)
+{
+ char *p, *pe;
+ int cs = EVIL;
+ VALUE result = Qnil;
+ GET_PARSER;
+
+ %% write init;
+ p = json->source;
+ pe = p + json->len;
+ %% write exec;
+
+ if (cs >= JSON_quirks_mode_first_final && p == pe) {
+ return result;
+ } else {
+ rb_raise(eParserError, "%u: unexpected token at '%s'", __LINE__, p);
+ return Qnil;
+ }
+}
+
+/*
+ * call-seq: parse()
+ *
+ * Parses the current JSON text _source_ and returns the complete data
+ * structure as a result.
+ */
+static VALUE cParser_parse(VALUE self)
+{
+ GET_PARSER;
+
+ if (json->quirks_mode) {
+ return cParser_parse_quirks_mode(self);
+ } else {
+ return cParser_parse_strict(self);
+ }
+}
+
+
static JSON_Parser *JSON_allocate()
{
JSON_Parser *json = ALLOC(JSON_Parser);
@@ -783,6 +840,18 @@ static VALUE cParser_source(VALUE self)
return rb_str_dup(json->Vsource);
}
+/*
+ * call-seq: quirks_mode?()
+ *
+ * Returns a true, if this parser is in quirks_mode, false otherwise.
+ */
+static VALUE cParser_quirks_mode_p(VALUE self)
+{
+ GET_PARSER;
+ return json->quirks_mode ? Qtrue : Qfalse;
+}
+
+
void Init_parser()
{
rb_require("json/common");
@@ -795,6 +864,7 @@ void Init_parser()
rb_define_method(cParser, "initialize", cParser_initialize, -1);
rb_define_method(cParser, "parse", cParser_parse, 0);
rb_define_method(cParser, "source", cParser_source, 0);
+ rb_define_method(cParser, "quirks_mode?", cParser_quirks_mode_p, 0);
CNaN = rb_const_get(mJSON, rb_intern("NaN"));
CInfinity = rb_const_get(mJSON, rb_intern("Infinity"));
@@ -808,6 +878,7 @@ void Init_parser()
i_max_nesting = rb_intern("max_nesting");
i_allow_nan = rb_intern("allow_nan");
i_symbolize_names = rb_intern("symbolize_names");
+ i_quirks_mode = rb_intern("quirks_mode");
i_object_class = rb_intern("object_class");
i_array_class = rb_intern("array_class");
i_match = rb_intern("match");
diff --git a/java/src/json/ext/Generator.java b/java/src/json/ext/Generator.java
index fbc394f..78dc078 100644
--- a/java/src/json/ext/Generator.java
+++ b/java/src/json/ext/Generator.java
@@ -1,6 +1,6 @@
/*
* This code is copyrighted work by Daniel Luz <dev at mernen dot com>.
- *
+ *
* Distributed under the Ruby and GPLv2 licenses; see COPYING and GPL files
* for details.
*/
@@ -85,11 +85,11 @@ public final class Generator {
/**
* A class that concentrates all the information that is shared by
* generators working on a single session.
- *
+ *
* <p>A session is defined as the process of serializing a single root
* object; any handler directly called by container handlers (arrays and
* hashes/objects) shares this object with its caller.
- *
+ *
* <p>Note that anything called indirectly (via {@link GENERIC_HANDLER})
* won't be part of the session.
*/
diff --git a/java/src/json/ext/GeneratorMethods.java b/java/src/json/ext/GeneratorMethods.java
index 356f2d0..637b579 100644
--- a/java/src/json/ext/GeneratorMethods.java
+++ b/java/src/json/ext/GeneratorMethods.java
@@ -1,6 +1,6 @@
/*
* This code is copyrighted work by Daniel Luz <dev at mernen dot com>.
- *
+ *
* Distributed under the Ruby and GPLv2 licenses; see COPYING and GPL files
* for details.
*/
@@ -25,7 +25,7 @@ import org.jruby.util.ByteList;
/**
* A class that populates the
* <code>Json::Ext::Generator::GeneratorMethods</code> module.
- *
+ *
* @author mernen
*/
class GeneratorMethods {
diff --git a/java/src/json/ext/GeneratorService.java b/java/src/json/ext/GeneratorService.java
index 2f3b07e..ed33639 100644
--- a/java/src/json/ext/GeneratorService.java
+++ b/java/src/json/ext/GeneratorService.java
@@ -1,6 +1,6 @@
/*
* This code is copyrighted work by Daniel Luz <dev at mernen dot com>.
- *
+ *
* Distributed under the Ruby and GPLv2 licenses; see COPYING and GPL files
* for details.
*/
diff --git a/java/src/json/ext/GeneratorState.java b/java/src/json/ext/GeneratorState.java
index f04eda2..0536ac4 100644
--- a/java/src/json/ext/GeneratorState.java
+++ b/java/src/json/ext/GeneratorState.java
@@ -1,6 +1,6 @@
/*
* This code is copyrighted work by Daniel Luz <dev at mernen dot com>.
- *
+ *
* Distributed under the Ruby and GPLv2 licenses; see COPYING and GPL files
* for details.
*/
@@ -24,10 +24,10 @@ import org.jruby.util.ByteList;
/**
* The <code>JSON::Ext::Generator::State</code> class.
- *
+ *
* <p>This class is used to create State instances, that are use to hold data
* while generating a JSON text from a a Ruby data structure.
- *
+ *
* @author mernen
*/
public class GeneratorState extends RubyObject {
@@ -72,10 +72,16 @@ public class GeneratorState extends RubyObject {
private boolean allowNaN = DEFAULT_ALLOW_NAN;
static final boolean DEFAULT_ALLOW_NAN = false;
/**
- * XXX
+ * If set to <code>true</code> all JSON documents generated do not contain
+ * any other characters than ASCII characters.
*/
private boolean asciiOnly = DEFAULT_ASCII_ONLY;
static final boolean DEFAULT_ASCII_ONLY = false;
+ /**
+ * XXX
+ */
+ private boolean quirksMode = DEFAULT_QUIRKS_MODE;
+ static final boolean DEFAULT_QUIRKS_MODE = false;
/**
* The current depth (inside a #to_json call)
@@ -94,7 +100,7 @@ public class GeneratorState extends RubyObject {
/**
* <code>State.from_state(opts)</code>
- *
+ *
* <p>Creates a State object from <code>opts</code>, which ought to be
* {@link RubyHash Hash} to create a new <code>State</code> instance
* configured by <codes>opts</code>, something else to create an
@@ -136,11 +142,11 @@ public class GeneratorState extends RubyObject {
/**
* <code>State#initialize(opts = {})</code>
- *
+ *
* Instantiates a new <code>State</code> object, configured by <code>opts</code>.
- *
+ *
* <code>opts</code> can have the following keys:
- *
+ *
* <dl>
* <dt><code>:indent</code>
* <dd>a {@link RubyString String} used to indent levels (default: <code>""</code>)
@@ -151,7 +157,7 @@ public class GeneratorState extends RubyObject {
* <dd>a String that is put before a <code>":"</code> pair delimiter
* (default: <code>""</code>)
* <dt><code>:object_nl</code>
- * <dd>a String that is put at the end of a JSON object (default: <code>""</code>)
+ * <dd>a String that is put at the end of a JSON object (default: <code>""</code>)
* <dt><code>:array_nl</code>
* <dd>a String that is put at the end of a JSON array (default: <code>""</code>)
* <dt><code>:allow_nan</code>
@@ -181,17 +187,20 @@ public class GeneratorState extends RubyObject {
this.maxNesting = orig.maxNesting;
this.allowNaN = orig.allowNaN;
this.asciiOnly = orig.asciiOnly;
+ this.quirksMode = orig.quirksMode;
this.depth = orig.depth;
return this;
}
/**
- * XXX
+ * Generates a valid JSON document from object <code>obj</code> and returns
+ * the result. If no valid JSON document can be created this method raises
+ * a GeneratorError exception.
*/
@JRubyMethod
public IRubyObject generate(ThreadContext context, IRubyObject obj) {
RubyString result = Generator.generateJson(context, obj, this);
- if (!objectOrArrayLiteral(result)) {
+ if (!quirksMode && !objectOrArrayLiteral(result)) {
throw Utils.newException(context, Utils.M_GENERATOR_ERROR,
"only generation of JSON objects or arrays allowed");
}
@@ -364,6 +373,22 @@ public class GeneratorState extends RubyObject {
return context.getRuntime().newBoolean(asciiOnly);
}
+ @JRubyMethod(name="quirks_mode")
+ public RubyBoolean quirks_mode_get(ThreadContext context) {
+ return context.getRuntime().newBoolean(quirksMode);
+ }
+
+ @JRubyMethod(name="quirks_mode=")
+ public IRubyObject quirks_mode_set(IRubyObject quirks_mode) {
+ quirksMode = quirks_mode.isTrue();
+ return quirks_mode.getRuntime().newBoolean(quirksMode);
+ }
+
+ @JRubyMethod(name="quirks_mode?")
+ public RubyBoolean quirks_mode_p(ThreadContext context) {
+ return context.getRuntime().newBoolean(quirksMode);
+ }
+
public int getDepth() {
return depth;
}
@@ -390,7 +415,7 @@ public class GeneratorState extends RubyObject {
/**
* <code>State#configure(opts)</code>
- *
+ *
* <p>Configures this State instance with the {@link RubyHash Hash}
* <code>opts</code>, and returns itself.
* @param vOpts The options hash
@@ -418,6 +443,7 @@ public class GeneratorState extends RubyObject {
maxNesting = opts.getInt("max_nesting", DEFAULT_MAX_NESTING);
allowNaN = opts.getBool("allow_nan", DEFAULT_ALLOW_NAN);
asciiOnly = opts.getBool("ascii_only", DEFAULT_ASCII_ONLY);
+ quirksMode = opts.getBool("quirks_mode", DEFAULT_QUIRKS_MODE);
depth = opts.getInt("depth", 0);
@@ -426,7 +452,7 @@ public class GeneratorState extends RubyObject {
/**
* <code>State#to_h()</code>
- *
+ *
* <p>Returns the configuration instance variables as a hash, that can be
* passed to the configure method.
* @return
@@ -443,6 +469,7 @@ public class GeneratorState extends RubyObject {
result.op_aset(context, runtime.newSymbol("array_nl"), array_nl_get(context));
result.op_aset(context, runtime.newSymbol("allow_nan"), allow_nan_p(context));
result.op_aset(context, runtime.newSymbol("ascii_only"), ascii_only_p(context));
+ result.op_aset(context, runtime.newSymbol("quirks_mode"), quirks_mode_p(context));
result.op_aset(context, runtime.newSymbol("max_nesting"), max_nesting_get(context));
result.op_aset(context, runtime.newSymbol("depth"), depth_get(context));
return result;
diff --git a/java/src/json/ext/OptionsReader.java b/java/src/json/ext/OptionsReader.java
index c9c9c94..a0b76b1 100644
--- a/java/src/json/ext/OptionsReader.java
+++ b/java/src/json/ext/OptionsReader.java
@@ -1,6 +1,6 @@
/*
* This code is copyrighted work by Daniel Luz <dev at mernen dot com>.
- *
+ *
* Distributed under the Ruby and GPLv2 licenses; see COPYING and GPL files
* for details.
*/
diff --git a/java/src/json/ext/Parser.java b/java/src/json/ext/Parser.java
index cea42d4..1240922 100644
--- a/java/src/json/ext/Parser.java
+++ b/java/src/json/ext/Parser.java
@@ -2,7 +2,7 @@
// line 1 "Parser.rl"
/*
* This code is copyrighted work by Daniel Luz <dev at mernen dot com>.
- *
+ *
* Distributed under the Ruby and GPLv2 licenses; see COPYING and GPL files
* for details.
*/
@@ -31,16 +31,16 @@ import org.jruby.util.ByteList;
/**
* The <code>JSON::Ext::Parser</code> class.
- *
+ *
* <p>This is the JSON parser implemented as a Java class. To use it as the
* standard parser, set
* <pre>JSON.parser = JSON::Ext::Parser</pre>
* This is performed for you when you <code>include "json/ext"</code>.
- *
+ *
* <p>This class does not perform the actual parsing, just acts as an interface
* to Ruby code. When the {@link #parse()} method is invoked, a
* Parser.ParserSession object is instantiated, which handles the process.
- *
+ *
* @author mernen
*/
public class Parser extends RubyObject {
@@ -51,6 +51,7 @@ public class Parser extends RubyObject {
private int maxNesting;
private boolean allowNaN;
private boolean symbolizeNames;
+ private boolean quirksMode;
private RubyClass objectClass;
private RubyClass arrayClass;
private RubyHash match_string;
@@ -71,7 +72,7 @@ public class Parser extends RubyObject {
/**
* Multiple-value return for internal parser methods.
- *
+ *
* <p>All the <code>parse<var>Stuff</var></code> methods return instances of
* <code>ParserResult</code> when successful, or <code>null</code> when
* there's a problem with the input data.
@@ -100,18 +101,18 @@ public class Parser extends RubyObject {
/**
* <code>Parser.new(source, opts = {})</code>
- *
+ *
* <p>Creates a new <code>JSON::Ext::Parser</code> instance for the string
* <code>source</code>.
* It will be configured by the <code>opts</code> Hash.
* <code>opts</code> can have the following keys:
- *
+ *
* <dl>
* <dt><code>:max_nesting</code>
* <dd>The maximum depth of nesting allowed in the parsed data
* structures. Disable depth checking with <code>:max_nesting => false|nil|0</code>,
* it defaults to 19.
- *
+ *
* <dt><code>:allow_nan</code>
* <dd>If set to <code>true</code>, allow <code>NaN</code>,
* <code>Infinity</code> and <code>-Infinity</code> in defiance of RFC 4627
@@ -120,15 +121,19 @@ public class Parser extends RubyObject {
* <dt><code>:symbolize_names</code>
* <dd>If set to <code>true</code>, returns symbols for the names (keys) in
* a JSON object. Otherwise strings are returned, which is also the default.
+ *
+ * <dt><code>:quirks_mode?</code>
+ * <dd>If set to <code>true</code>, if the parse is in quirks_mode, false
+ * otherwise.
*
* <dt><code>:create_additions</code>
* <dd>If set to <code>false</code>, the Parser doesn't create additions
* even if a matchin class and <code>create_id</code> was found. This option
* defaults to <code>true</code>.
- *
+ *
* <dt><code>:object_class</code>
* <dd>Defaults to Hash.
- *
+ *
* <dt><code>:array_class</code>
* <dd>Defaults to Array.
* </dl>
@@ -148,19 +153,21 @@ public class Parser extends RubyObject {
if (this.vSource != null) {
throw runtime.newTypeError("already initialized instance");
}
- RubyString source = convertEncoding(context, args[0].convertToString());
OptionsReader opts = new OptionsReader(context, args.length > 1 ? args[1] : null);
this.maxNesting = opts.getInt("max_nesting", DEFAULT_MAX_NESTING);
this.allowNaN = opts.getBool("allow_nan", false);
this.symbolizeNames = opts.getBool("symbolize_names", false);
+ this.quirksMode = opts.getBool("quirks_mode", false);
this.createId = opts.getString("create_id", getCreateId(context));
this.createAdditions = opts.getBool("create_additions", true);
this.objectClass = opts.getClass("object_class", runtime.getHash());
this.arrayClass = opts.getClass("array_class", runtime.getArray());
this.match_string = opts.getHash("match_string");
- this.vSource = source;
+ this.vSource = args[0].convertToString();
+ if (!quirksMode) this.vSource = convertEncoding(context, vSource);
+
return this;
}
@@ -229,7 +236,7 @@ public class Parser extends RubyObject {
/**
* <code>Parser#parse()</code>
- *
+ *
* <p>Parses the current JSON text <code>source</code> and returns the
* complete data structure as a result.
*/
@@ -240,7 +247,7 @@ public class Parser extends RubyObject {
/**
* <code>Parser#source()</code>
- *
+ *
* <p>Returns a copy of the current <code>source</code> string, that was
* used to construct this Parser.
*/
@@ -249,6 +256,17 @@ public class Parser extends RubyObject {
return checkAndGetSource().dup();
}
+ /**
+ * <code>Parser#quirks_mode?()</code>
+ *
+ * <p>If set to <code>true</code>, if the parse is in quirks_mode, false
+ * otherwise.
+ */
+ @JRubyMethod(name = "quirks_mode?")
+ public IRubyObject quirks_mode_p(ThreadContext context) {
+ return context.getRuntime().newBoolean(quirksMode);
+ }
+
public RubyString checkAndGetSource() {
if (vSource != null) {
return vSource;
@@ -268,7 +286,7 @@ public class Parser extends RubyObject {
/**
* A string parsing session.
- *
+ *
* <p>Once a ParserSession is instantiated, the source string should not
* change until the parsing is complete. The ParserSession object assumes
* the source {@link RubyString} is still associated to its original
@@ -309,11 +327,11 @@ public class Parser extends RubyObject {
}
-// line 335 "Parser.rl"
+// line 353 "Parser.rl"
-// line 317 "Parser.java"
+// line 335 "Parser.java"
private static byte[] init__JSON_value_actions_0()
{
return new byte [] {
@@ -427,7 +445,7 @@ static final int JSON_value_error = 0;
static final int JSON_value_en_main = 1;
-// line 441 "Parser.rl"
+// line 459 "Parser.rl"
ParserResult parseValue(int p, int pe) {
@@ -435,14 +453,14 @@ static final int JSON_value_en_main = 1;
IRubyObject result = null;
-// line 439 "Parser.java"
+// line 457 "Parser.java"
{
cs = JSON_value_start;
}
-// line 448 "Parser.rl"
+// line 466 "Parser.rl"
-// line 446 "Parser.java"
+// line 464 "Parser.java"
{
int _klen;
int _trans = 0;
@@ -468,13 +486,13 @@ case 1:
while ( _nacts-- > 0 ) {
switch ( _JSON_value_actions[_acts++] ) {
case 9:
-// line 426 "Parser.rl"
+// line 444 "Parser.rl"
{
p--;
{ p += 1; _goto_targ = 5; if (true) continue _goto;}
}
break;
-// line 478 "Parser.java"
+// line 496 "Parser.java"
}
}
@@ -537,25 +555,25 @@ case 1:
switch ( _JSON_value_actions[_acts++] )
{
case 0:
-// line 343 "Parser.rl"
+// line 361 "Parser.rl"
{
result = getRuntime().getNil();
}
break;
case 1:
-// line 346 "Parser.rl"
+// line 364 "Parser.rl"
{
result = getRuntime().getFalse();
}
break;
case 2:
-// line 349 "Parser.rl"
+// line 367 "Parser.rl"
{
result = getRuntime().getTrue();
}
break;
case 3:
-// line 352 "Parser.rl"
+// line 370 "Parser.rl"
{
if (parser.allowNaN) {
result = getConstant(CONST_NAN);
@@ -565,7 +583,7 @@ case 1:
}
break;
case 4:
-// line 359 "Parser.rl"
+// line 377 "Parser.rl"
{
if (parser.allowNaN) {
result = getConstant(CONST_INFINITY);
@@ -575,9 +593,9 @@ case 1:
}
break;
case 5:
-// line 366 "Parser.rl"
+// line 384 "Parser.rl"
{
- if (pe > p + 9 &&
+ if (pe > p + 9 - (parser.quirksMode ? 1 : 0) &&
absSubSequence(p, p + 9).toString().equals(JSON_MINUS_INFINITY)) {
if (parser.allowNaN) {
@@ -604,7 +622,7 @@ case 1:
}
break;
case 6:
-// line 392 "Parser.rl"
+// line 410 "Parser.rl"
{
ParserResult res = parseString(p, pe);
if (res == null) {
@@ -617,7 +635,7 @@ case 1:
}
break;
case 7:
-// line 402 "Parser.rl"
+// line 420 "Parser.rl"
{
currentNesting++;
ParserResult res = parseArray(p, pe);
@@ -632,7 +650,7 @@ case 1:
}
break;
case 8:
-// line 414 "Parser.rl"
+// line 432 "Parser.rl"
{
currentNesting++;
ParserResult res = parseObject(p, pe);
@@ -646,7 +664,7 @@ case 1:
}
}
break;
-// line 650 "Parser.java"
+// line 668 "Parser.java"
}
}
}
@@ -666,7 +684,7 @@ case 5:
break; }
}
-// line 449 "Parser.rl"
+// line 467 "Parser.rl"
if (cs >= JSON_value_first_final && result != null) {
return new ParserResult(result, p);
@@ -676,7 +694,7 @@ case 5:
}
-// line 680 "Parser.java"
+// line 698 "Parser.java"
private static byte[] init__JSON_integer_actions_0()
{
return new byte [] {
@@ -690,7 +708,7 @@ private static final byte _JSON_integer_actions[] = init__JSON_integer_actions_0
private static byte[] init__JSON_integer_key_offsets_0()
{
return new byte [] {
- 0, 0, 4, 7, 9, 11
+ 0, 0, 4, 7, 9, 9
};
}
@@ -720,7 +738,7 @@ private static final byte _JSON_integer_single_lengths[] = init__JSON_integer_si
private static byte[] init__JSON_integer_range_lengths_0()
{
return new byte [] {
- 0, 1, 1, 1, 1, 0
+ 0, 1, 1, 1, 0, 1
};
}
@@ -730,7 +748,7 @@ private static final byte _JSON_integer_range_lengths[] = init__JSON_integer_ran
private static byte[] init__JSON_integer_index_offsets_0()
{
return new byte [] {
- 0, 0, 4, 7, 9, 11
+ 0, 0, 4, 7, 9, 10
};
}
@@ -740,7 +758,7 @@ private static final byte _JSON_integer_index_offsets[] = init__JSON_integer_ind
private static byte[] init__JSON_integer_indicies_0()
{
return new byte [] {
- 0, 2, 3, 1, 2, 3, 1, 1, 4, 3, 4, 1,
+ 0, 2, 3, 1, 2, 3, 1, 1, 4, 1, 3, 4,
0
};
}
@@ -751,7 +769,7 @@ private static final byte _JSON_integer_indicies[] = init__JSON_integer_indicies
private static byte[] init__JSON_integer_trans_targs_0()
{
return new byte [] {
- 2, 0, 3, 4, 5
+ 2, 0, 3, 5, 4
};
}
@@ -769,28 +787,28 @@ private static final byte _JSON_integer_trans_actions[] = init__JSON_integer_tra
static final int JSON_integer_start = 1;
-static final int JSON_integer_first_final = 5;
+static final int JSON_integer_first_final = 3;
static final int JSON_integer_error = 0;
static final int JSON_integer_en_main = 1;
-// line 468 "Parser.rl"
+// line 486 "Parser.rl"
ParserResult parseInteger(int p, int pe) {
int cs = EVIL;
-// line 786 "Parser.java"
+// line 804 "Parser.java"
{
cs = JSON_integer_start;
}
-// line 474 "Parser.rl"
+// line 492 "Parser.rl"
int memo = p;
-// line 794 "Parser.java"
+// line 812 "Parser.java"
{
int _klen;
int _trans = 0;
@@ -871,13 +889,13 @@ case 1:
switch ( _JSON_integer_actions[_acts++] )
{
case 0:
-// line 462 "Parser.rl"
+// line 480 "Parser.rl"
{
p--;
{ p += 1; _goto_targ = 5; if (true) continue _goto;}
}
break;
-// line 881 "Parser.java"
+// line 899 "Parser.java"
}
}
}
@@ -897,7 +915,7 @@ case 5:
break; }
}
-// line 476 "Parser.rl"
+// line 494 "Parser.rl"
if (cs < JSON_integer_first_final) {
return null;
@@ -912,7 +930,7 @@ case 5:
}
-// line 916 "Parser.java"
+// line 934 "Parser.java"
private static byte[] init__JSON_float_actions_0()
{
return new byte [] {
@@ -926,7 +944,7 @@ private static final byte _JSON_float_actions[] = init__JSON_float_actions_0();
private static byte[] init__JSON_float_key_offsets_0()
{
return new byte [] {
- 0, 0, 4, 7, 10, 12, 18, 22, 24, 30, 35
+ 0, 0, 4, 7, 10, 12, 16, 18, 23, 29, 29
};
}
@@ -937,8 +955,8 @@ private static char[] init__JSON_float_trans_keys_0()
{
return new char [] {
45, 48, 49, 57, 48, 49, 57, 46, 69, 101, 48, 57,
- 69, 101, 45, 46, 48, 57, 43, 45, 48, 57, 48, 57,
- 69, 101, 45, 46, 48, 57, 46, 69, 101, 48, 57, 0
+ 43, 45, 48, 57, 48, 57, 46, 69, 101, 48, 57, 69,
+ 101, 45, 46, 48, 57, 69, 101, 45, 46, 48, 57, 0
};
}
@@ -948,7 +966,7 @@ private static final char _JSON_float_trans_keys[] = init__JSON_float_trans_keys
private static byte[] init__JSON_float_single_lengths_0()
{
return new byte [] {
- 0, 2, 1, 3, 0, 2, 2, 0, 2, 3, 0
+ 0, 2, 1, 3, 0, 2, 0, 3, 2, 0, 2
};
}
@@ -958,7 +976,7 @@ private static final byte _JSON_float_single_lengths[] = init__JSON_float_single
private static byte[] init__JSON_float_range_lengths_0()
{
return new byte [] {
- 0, 1, 1, 0, 1, 2, 1, 1, 2, 1, 0
+ 0, 1, 1, 0, 1, 1, 1, 1, 2, 0, 2
};
}
@@ -968,7 +986,7 @@ private static final byte _JSON_float_range_lengths[] = init__JSON_float_range_l
private static byte[] init__JSON_float_index_offsets_0()
{
return new byte [] {
- 0, 0, 4, 7, 11, 13, 18, 22, 24, 29, 34
+ 0, 0, 4, 7, 11, 13, 17, 19, 24, 29, 30
};
}
@@ -979,8 +997,8 @@ private static byte[] init__JSON_float_indicies_0()
{
return new byte [] {
0, 2, 3, 1, 2, 3, 1, 4, 5, 5, 1, 6,
- 1, 5, 5, 1, 6, 7, 8, 8, 9, 1, 9, 1,
- 1, 1, 1, 9, 7, 4, 5, 5, 3, 1, 1, 0
+ 1, 7, 7, 8, 1, 8, 1, 4, 5, 5, 3, 1,
+ 5, 5, 1, 6, 9, 1, 1, 1, 1, 8, 9, 0
};
}
@@ -990,7 +1008,7 @@ private static final byte _JSON_float_indicies[] = init__JSON_float_indicies_0()
private static byte[] init__JSON_float_trans_targs_0()
{
return new byte [] {
- 2, 0, 3, 9, 4, 6, 5, 10, 7, 8
+ 2, 0, 3, 7, 4, 5, 8, 6, 10, 9
};
}
@@ -1000,7 +1018,7 @@ private static final byte _JSON_float_trans_targs[] = init__JSON_float_trans_tar
private static byte[] init__JSON_float_trans_actions_0()
{
return new byte [] {
- 0, 0, 0, 0, 0, 0, 0, 1, 0, 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
};
}
@@ -1008,28 +1026,28 @@ private static final byte _JSON_float_trans_actions[] = init__JSON_float_trans_a
static final int JSON_float_start = 1;
-static final int JSON_float_first_final = 10;
+static final int JSON_float_first_final = 8;
static final int JSON_float_error = 0;
static final int JSON_float_en_main = 1;
-// line 504 "Parser.rl"
+// line 522 "Parser.rl"
ParserResult parseFloat(int p, int pe) {
int cs = EVIL;
-// line 1025 "Parser.java"
+// line 1043 "Parser.java"
{
cs = JSON_float_start;
}
-// line 510 "Parser.rl"
+// line 528 "Parser.rl"
int memo = p;
-// line 1033 "Parser.java"
+// line 1051 "Parser.java"
{
int _klen;
int _trans = 0;
@@ -1110,13 +1128,13 @@ case 1:
switch ( _JSON_float_actions[_acts++] )
{
case 0:
-// line 495 "Parser.rl"
+// line 513 "Parser.rl"
{
p--;
{ p += 1; _goto_targ = 5; if (true) continue _goto;}
}
break;
-// line 1120 "Parser.java"
+// line 1138 "Parser.java"
}
}
}
@@ -1136,7 +1154,7 @@ case 5:
break; }
}
-// line 512 "Parser.rl"
+// line 530 "Parser.rl"
if (cs < JSON_float_first_final) {
return null;
@@ -1151,7 +1169,7 @@ case 5:
}
-// line 1155 "Parser.java"
+// line 1173 "Parser.java"
private static byte[] init__JSON_string_actions_0()
{
return new byte [] {
@@ -1253,7 +1271,7 @@ static final int JSON_string_error = 0;
static final int JSON_string_en_main = 1;
-// line 556 "Parser.rl"
+// line 574 "Parser.rl"
ParserResult parseString(int p, int pe) {
@@ -1261,15 +1279,15 @@ static final int JSON_string_en_main = 1;
IRubyObject result = null;
-// line 1265 "Parser.java"
+// line 1283 "Parser.java"
{
cs = JSON_string_start;
}
-// line 563 "Parser.rl"
+// line 581 "Parser.rl"
int memo = p;
-// line 1273 "Parser.java"
+// line 1291 "Parser.java"
{
int _klen;
int _trans = 0;
@@ -1350,7 +1368,7 @@ case 1:
switch ( _JSON_string_actions[_acts++] )
{
case 0:
-// line 531 "Parser.rl"
+// line 549 "Parser.rl"
{
int offset = byteList.begin();
ByteList decoded = decoder.decode(byteList, memo + 1 - offset,
@@ -1365,13 +1383,13 @@ case 1:
}
break;
case 1:
-// line 544 "Parser.rl"
+// line 562 "Parser.rl"
{
p--;
{ p += 1; _goto_targ = 5; if (true) continue _goto;}
}
break;
-// line 1375 "Parser.java"
+// line 1393 "Parser.java"
}
}
}
@@ -1391,7 +1409,7 @@ case 5:
break; }
}
-// line 565 "Parser.rl"
+// line 583 "Parser.rl"
if (parser.createAdditions) {
RubyHash match_string = parser.match_string;
@@ -1408,7 +1426,7 @@ case 5:
}
});
} catch (JumpException e) { }
- if (memoArray[1] != null) {
+ if (memoArray[1] != null) {
RubyClass klass = (RubyClass) memoArray[1];
if (klass.respondsTo("json_creatable?") &&
klass.callMethod(context, "json_creatable?").isTrue()) {
@@ -1426,7 +1444,7 @@ case 5:
}
-// line 1430 "Parser.java"
+// line 1448 "Parser.java"
private static byte[] init__JSON_array_actions_0()
{
return new byte [] {
@@ -1539,7 +1557,7 @@ static final int JSON_array_error = 0;
static final int JSON_array_en_main = 1;
-// line 635 "Parser.rl"
+// line 653 "Parser.rl"
ParserResult parseArray(int p, int pe) {
@@ -1557,14 +1575,14 @@ static final int JSON_array_en_main = 1;
IRubyObject.NULL_ARRAY, Block.NULL_BLOCK);
-// line 1561 "Parser.java"
+// line 1579 "Parser.java"
{
cs = JSON_array_start;
}
-// line 652 "Parser.rl"
+// line 670 "Parser.rl"
-// line 1568 "Parser.java"
+// line 1586 "Parser.java"
{
int _klen;
int _trans = 0;
@@ -1645,7 +1663,7 @@ case 1:
switch ( _JSON_array_actions[_acts++] )
{
case 0:
-// line 604 "Parser.rl"
+// line 622 "Parser.rl"
{
ParserResult res = parseValue(p, pe);
if (res == null) {
@@ -1662,13 +1680,13 @@ case 1:
}
break;
case 1:
-// line 619 "Parser.rl"
+// line 637 "Parser.rl"
{
p--;
{ p += 1; _goto_targ = 5; if (true) continue _goto;}
}
break;
-// line 1672 "Parser.java"
+// line 1690 "Parser.java"
}
}
}
@@ -1688,7 +1706,7 @@ case 5:
break; }
}
-// line 653 "Parser.rl"
+// line 671 "Parser.rl"
if (cs >= JSON_array_first_final) {
return new ParserResult(result, p + 1);
@@ -1698,7 +1716,7 @@ case 5:
}
-// line 1702 "Parser.java"
+// line 1720 "Parser.java"
private static byte[] init__JSON_object_actions_0()
{
return new byte [] {
@@ -1821,7 +1839,7 @@ static final int JSON_object_error = 0;
static final int JSON_object_en_main = 1;
-// line 713 "Parser.rl"
+// line 730 "Parser.rl"
ParserResult parseObject(int p, int pe) {
@@ -1840,14 +1858,14 @@ static final int JSON_object_en_main = 1;
IRubyObject.NULL_ARRAY, Block.NULL_BLOCK);
-// line 1844 "Parser.java"
+// line 1862 "Parser.java"
{
cs = JSON_object_start;
}
-// line 731 "Parser.rl"
+// line 748 "Parser.rl"
-// line 1851 "Parser.java"
+// line 1869 "Parser.java"
{
int _klen;
int _trans = 0;
@@ -1928,7 +1946,7 @@ case 1:
switch ( _JSON_object_actions[_acts++] )
{
case 0:
-// line 667 "Parser.rl"
+// line 685 "Parser.rl"
{
ParserResult res = parseValue(p, pe);
if (res == null) {
@@ -1945,7 +1963,7 @@ case 1:
}
break;
case 1:
-// line 682 "Parser.rl"
+// line 700 "Parser.rl"
{
ParserResult res = parseString(p, pe);
if (res == null) {
@@ -1965,13 +1983,13 @@ case 1:
}
break;
case 2:
-// line 700 "Parser.rl"
+// line 718 "Parser.rl"
{
p--;
{ p += 1; _goto_targ = 5; if (true) continue _goto;}
}
break;
-// line 1975 "Parser.java"
+// line 1993 "Parser.java"
}
}
}
@@ -1991,7 +2009,7 @@ case 5:
break; }
}
-// line 732 "Parser.rl"
+// line 749 "Parser.rl"
if (cs < JSON_object_first_final) {
return null;
@@ -2017,7 +2035,7 @@ case 5:
}
-// line 2021 "Parser.java"
+// line 2039 "Parser.java"
private static byte[] init__JSON_actions_0()
{
return new byte [] {
@@ -2121,25 +2139,25 @@ static final int JSON_error = 0;
static final int JSON_en_main = 1;
-// line 790 "Parser.rl"
+// line 807 "Parser.rl"
- public IRubyObject parse() {
+ public IRubyObject parseStrict() {
int cs = EVIL;
int p, pe;
IRubyObject result = null;
-// line 2134 "Parser.java"
+// line 2152 "Parser.java"
{
cs = JSON_start;
}
-// line 798 "Parser.rl"
+// line 815 "Parser.rl"
p = byteList.begin();
pe = p + byteList.length();
-// line 2143 "Parser.java"
+// line 2161 "Parser.java"
{
int _klen;
int _trans = 0;
@@ -2220,7 +2238,7 @@ case 1:
switch ( _JSON_actions[_acts++] )
{
case 0:
-// line 762 "Parser.rl"
+// line 779 "Parser.rl"
{
currentNesting = 1;
ParserResult res = parseObject(p, pe);
@@ -2234,7 +2252,7 @@ case 1:
}
break;
case 1:
-// line 774 "Parser.rl"
+// line 791 "Parser.rl"
{
currentNesting = 1;
ParserResult res = parseArray(p, pe);
@@ -2247,7 +2265,7 @@ case 1:
}
}
break;
-// line 2251 "Parser.java"
+// line 2269 "Parser.java"
}
}
}
@@ -2267,7 +2285,7 @@ case 5:
break; }
}
-// line 801 "Parser.rl"
+// line 818 "Parser.rl"
if (cs >= JSON_first_final && p == pe) {
return result;
@@ -2276,6 +2294,259 @@ case 5:
}
}
+
+// line 2299 "Parser.java"
+private static byte[] init__JSON_quirks_mode_actions_0()
+{
+ return new byte [] {
+ 0, 1, 0
+ };
+}
+
+private static final byte _JSON_quirks_mode_actions[] = init__JSON_quirks_mode_actions_0();
+
+
+private static byte[] init__JSON_quirks_mode_key_offsets_0()
+{
+ return new byte [] {
+ 0, 0, 16, 18, 19, 21, 22, 24, 25, 27, 28
+ };
+}
+
+private static final byte _JSON_quirks_mode_key_offsets[] = init__JSON_quirks_mode_key_offsets_0();
+
+
+private static char[] init__JSON_quirks_mode_trans_keys_0()
+{
+ return new char [] {
+ 13, 32, 34, 45, 47, 73, 78, 91, 102, 110, 116, 123,
+ 9, 10, 48, 57, 42, 47, 42, 42, 47, 10, 42, 47,
+ 42, 42, 47, 10, 13, 32, 47, 9, 10, 0
+ };
+}
+
+private static final char _JSON_quirks_mode_trans_keys[] = init__JSON_quirks_mode_trans_keys_0();
+
+
+private static byte[] init__JSON_quirks_mode_single_lengths_0()
+{
+ return new byte [] {
+ 0, 12, 2, 1, 2, 1, 2, 1, 2, 1, 3
+ };
+}
+
+private static final byte _JSON_quirks_mode_single_lengths[] = init__JSON_quirks_mode_single_lengths_0();
+
+
+private static byte[] init__JSON_quirks_mode_range_lengths_0()
+{
+ return new byte [] {
+ 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 1
+ };
+}
+
+private static final byte _JSON_quirks_mode_range_lengths[] = init__JSON_quirks_mode_range_lengths_0();
+
+
+private static byte[] init__JSON_quirks_mode_index_offsets_0()
+{
+ return new byte [] {
+ 0, 0, 15, 18, 20, 23, 25, 28, 30, 33, 35
+ };
+}
+
+private static final byte _JSON_quirks_mode_index_offsets[] = init__JSON_quirks_mode_index_offsets_0();
+
+
+private static byte[] init__JSON_quirks_mode_indicies_0()
+{
+ return new byte [] {
+ 0, 0, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2,
+ 0, 2, 1, 4, 5, 1, 6, 4, 6, 7, 4, 7,
+ 5, 8, 9, 1, 10, 8, 10, 0, 8, 0, 9, 7,
+ 7, 11, 7, 1, 0
+ };
+}
+
+private static final byte _JSON_quirks_mode_indicies[] = init__JSON_quirks_mode_indicies_0();
+
+
+private static byte[] init__JSON_quirks_mode_trans_targs_0()
+{
+ return new byte [] {
+ 1, 0, 10, 6, 3, 5, 4, 10, 7, 9, 8, 2
+ };
+}
+
+private static final byte _JSON_quirks_mode_trans_targs[] = init__JSON_quirks_mode_trans_targs_0();
+
+
+private static byte[] init__JSON_quirks_mode_trans_actions_0()
+{
+ return new byte [] {
+ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ };
+}
+
+private static final byte _JSON_quirks_mode_trans_actions[] = init__JSON_quirks_mode_trans_actions_0();
+
+
+static final int JSON_quirks_mode_start = 1;
+static final int JSON_quirks_mode_first_final = 10;
+static final int JSON_quirks_mode_error = 0;
+
+static final int JSON_quirks_mode_en_main = 1;
+
+
+// line 846 "Parser.rl"
+
+
+ public IRubyObject parseQuirksMode() {
+ int cs = EVIL;
+ int p, pe;
+ IRubyObject result = null;
+
+
+// line 2411 "Parser.java"
+ {
+ cs = JSON_quirks_mode_start;
+ }
+
+// line 854 "Parser.rl"
+ p = byteList.begin();
+ pe = p + byteList.length();
+
+// line 2420 "Parser.java"
+ {
+ int _klen;
+ int _trans = 0;
+ int _acts;
+ int _nacts;
+ int _keys;
+ int _goto_targ = 0;
+
+ _goto: while (true) {
+ switch ( _goto_targ ) {
+ case 0:
+ if ( p == pe ) {
+ _goto_targ = 4;
+ continue _goto;
+ }
+ if ( cs == 0 ) {
+ _goto_targ = 5;
+ continue _goto;
+ }
+case 1:
+ _match: do {
+ _keys = _JSON_quirks_mode_key_offsets[cs];
+ _trans = _JSON_quirks_mode_index_offsets[cs];
+ _klen = _JSON_quirks_mode_single_lengths[cs];
+ if ( _klen > 0 ) {
+ int _lower = _keys;
+ int _mid;
+ int _upper = _keys + _klen - 1;
+ while (true) {
+ if ( _upper < _lower )
+ break;
+
+ _mid = _lower + ((_upper-_lower) >> 1);
+ if ( data[p] < _JSON_quirks_mode_trans_keys[_mid] )
+ _upper = _mid - 1;
+ else if ( data[p] > _JSON_quirks_mode_trans_keys[_mid] )
+ _lower = _mid + 1;
+ else {
+ _trans += (_mid - _keys);
+ break _match;
+ }
+ }
+ _keys += _klen;
+ _trans += _klen;
+ }
+
+ _klen = _JSON_quirks_mode_range_lengths[cs];
+ if ( _klen > 0 ) {
+ int _lower = _keys;
+ int _mid;
+ int _upper = _keys + (_klen<<1) - 2;
+ while (true) {
+ if ( _upper < _lower )
+ break;
+
+ _mid = _lower + (((_upper-_lower) >> 1) & ~1);
+ if ( data[p] < _JSON_quirks_mode_trans_keys[_mid] )
+ _upper = _mid - 2;
+ else if ( data[p] > _JSON_quirks_mode_trans_keys[_mid+1] )
+ _lower = _mid + 2;
+ else {
+ _trans += ((_mid - _keys)>>1);
+ break _match;
+ }
+ }
+ _trans += _klen;
+ }
+ } while (false);
+
+ _trans = _JSON_quirks_mode_indicies[_trans];
+ cs = _JSON_quirks_mode_trans_targs[_trans];
+
+ if ( _JSON_quirks_mode_trans_actions[_trans] != 0 ) {
+ _acts = _JSON_quirks_mode_trans_actions[_trans];
+ _nacts = (int) _JSON_quirks_mode_actions[_acts++];
+ while ( _nacts-- > 0 )
+ {
+ switch ( _JSON_quirks_mode_actions[_acts++] )
+ {
+ case 0:
+// line 832 "Parser.rl"
+ {
+ ParserResult res = parseValue(p, pe);
+ if (res == null) {
+ p--;
+ { p += 1; _goto_targ = 5; if (true) continue _goto;}
+ } else {
+ result = res.result;
+ {p = (( res.p))-1;}
+ }
+ }
+ break;
+// line 2513 "Parser.java"
+ }
+ }
+ }
+
+case 2:
+ if ( cs == 0 ) {
+ _goto_targ = 5;
+ continue _goto;
+ }
+ if ( ++p != pe ) {
+ _goto_targ = 1;
+ continue _goto;
+ }
+case 4:
+case 5:
+ }
+ break; }
+ }
+
+// line 857 "Parser.rl"
+
+ if (cs >= JSON_quirks_mode_first_final && p == pe) {
+ return result;
+ } else {
+ throw unexpectedToken(p, pe);
+ }
+ }
+
+ public IRubyObject parse() {
+ if (parser.quirksMode) {
+ return parseQuirksMode();
+ } else {
+ return parseStrict();
+ }
+
+ }
+
/**
* Returns a subsequence of the source ByteList, based on source
* array byte offsets (i.e., the ByteList's own begin offset is not
diff --git a/java/src/json/ext/Parser.rl b/java/src/json/ext/Parser.rl
index 779d3f3..b037359 100644
--- a/java/src/json/ext/Parser.rl
+++ b/java/src/json/ext/Parser.rl
@@ -1,6 +1,6 @@
/*
* This code is copyrighted work by Daniel Luz <dev at mernen dot com>.
- *
+ *
* Distributed under the Ruby and GPLv2 licenses; see COPYING and GPL files
* for details.
*/
@@ -29,16 +29,16 @@ import org.jruby.util.ByteList;
/**
* The <code>JSON::Ext::Parser</code> class.
- *
+ *
* <p>This is the JSON parser implemented as a Java class. To use it as the
* standard parser, set
* <pre>JSON.parser = JSON::Ext::Parser</pre>
* This is performed for you when you <code>include "json/ext"</code>.
- *
+ *
* <p>This class does not perform the actual parsing, just acts as an interface
* to Ruby code. When the {@link #parse()} method is invoked, a
* Parser.ParserSession object is instantiated, which handles the process.
- *
+ *
* @author mernen
*/
public class Parser extends RubyObject {
@@ -49,6 +49,7 @@ public class Parser extends RubyObject {
private int maxNesting;
private boolean allowNaN;
private boolean symbolizeNames;
+ private boolean quirksMode;
private RubyClass objectClass;
private RubyClass arrayClass;
private RubyHash match_string;
@@ -69,7 +70,7 @@ public class Parser extends RubyObject {
/**
* Multiple-value return for internal parser methods.
- *
+ *
* <p>All the <code>parse<var>Stuff</var></code> methods return instances of
* <code>ParserResult</code> when successful, or <code>null</code> when
* there's a problem with the input data.
@@ -98,18 +99,18 @@ public class Parser extends RubyObject {
/**
* <code>Parser.new(source, opts = {})</code>
- *
+ *
* <p>Creates a new <code>JSON::Ext::Parser</code> instance for the string
* <code>source</code>.
* It will be configured by the <code>opts</code> Hash.
* <code>opts</code> can have the following keys:
- *
+ *
* <dl>
* <dt><code>:max_nesting</code>
* <dd>The maximum depth of nesting allowed in the parsed data
* structures. Disable depth checking with <code>:max_nesting => false|nil|0</code>,
* it defaults to 19.
- *
+ *
* <dt><code>:allow_nan</code>
* <dd>If set to <code>true</code>, allow <code>NaN</code>,
* <code>Infinity</code> and <code>-Infinity</code> in defiance of RFC 4627
@@ -118,15 +119,19 @@ public class Parser extends RubyObject {
* <dt><code>:symbolize_names</code>
* <dd>If set to <code>true</code>, returns symbols for the names (keys) in
* a JSON object. Otherwise strings are returned, which is also the default.
+ *
+ * <dt><code>:quirks_mode?</code>
+ * <dd>If set to <code>true</code>, if the parse is in quirks_mode, false
+ * otherwise.
*
* <dt><code>:create_additions</code>
* <dd>If set to <code>false</code>, the Parser doesn't create additions
* even if a matchin class and <code>create_id</code> was found. This option
* defaults to <code>true</code>.
- *
+ *
* <dt><code>:object_class</code>
* <dd>Defaults to Hash.
- *
+ *
* <dt><code>:array_class</code>
* <dd>Defaults to Array.
* </dl>
@@ -146,19 +151,21 @@ public class Parser extends RubyObject {
if (this.vSource != null) {
throw runtime.newTypeError("already initialized instance");
}
- RubyString source = convertEncoding(context, args[0].convertToString());
OptionsReader opts = new OptionsReader(context, args.length > 1 ? args[1] : null);
this.maxNesting = opts.getInt("max_nesting", DEFAULT_MAX_NESTING);
this.allowNaN = opts.getBool("allow_nan", false);
this.symbolizeNames = opts.getBool("symbolize_names", false);
+ this.quirksMode = opts.getBool("quirks_mode", false);
this.createId = opts.getString("create_id", getCreateId(context));
this.createAdditions = opts.getBool("create_additions", true);
this.objectClass = opts.getClass("object_class", runtime.getHash());
this.arrayClass = opts.getClass("array_class", runtime.getArray());
this.match_string = opts.getHash("match_string");
- this.vSource = source;
+ this.vSource = args[0].convertToString();
+ if (!quirksMode) this.vSource = convertEncoding(context, vSource);
+
return this;
}
@@ -227,7 +234,7 @@ public class Parser extends RubyObject {
/**
* <code>Parser#parse()</code>
- *
+ *
* <p>Parses the current JSON text <code>source</code> and returns the
* complete data structure as a result.
*/
@@ -238,7 +245,7 @@ public class Parser extends RubyObject {
/**
* <code>Parser#source()</code>
- *
+ *
* <p>Returns a copy of the current <code>source</code> string, that was
* used to construct this Parser.
*/
@@ -247,6 +254,17 @@ public class Parser extends RubyObject {
return checkAndGetSource().dup();
}
+ /**
+ * <code>Parser#quirks_mode?()</code>
+ *
+ * <p>If set to <code>true</code>, if the parse is in quirks_mode, false
+ * otherwise.
+ */
+ @JRubyMethod(name = "quirks_mode?")
+ public IRubyObject quirks_mode_p(ThreadContext context) {
+ return context.getRuntime().newBoolean(quirksMode);
+ }
+
public RubyString checkAndGetSource() {
if (vSource != null) {
return vSource;
@@ -266,7 +284,7 @@ public class Parser extends RubyObject {
/**
* A string parsing session.
- *
+ *
* <p>Once a ParserSession is instantiated, the source string should not
* change until the parsing is complete. The ParserSession object assumes
* the source {@link RubyString} is still associated to its original
@@ -364,7 +382,7 @@ public class Parser extends RubyObject {
}
}
action parse_number {
- if (pe > fpc + 9 &&
+ if (pe > fpc + 9 - (parser.quirksMode ? 1 : 0) &&
absSubSequence(fpc, fpc + 9).toString().equals(JSON_MINUS_INFINITY)) {
if (parser.allowNaN) {
@@ -464,7 +482,7 @@ public class Parser extends RubyObject {
fbreak;
}
- main := '-'? ( '0' | [1-9][0-9]* ) ( ^[0-9] @exit );
+ main := '-'? ( '0' | [1-9][0-9]* ) ( ^[0-9]? @exit );
}%%
ParserResult parseInteger(int p, int pe) {
@@ -500,7 +518,7 @@ public class Parser extends RubyObject {
main := '-'?
( ( ( '0' | [1-9][0-9]* ) '.' [0-9]+ ( [Ee] [+\-]?[0-9]+ )? )
| ( ( '0' | [1-9][0-9]* ) ( [Ee] [+\-]? [0-9]+ ) ) )
- ( ^[0-9Ee.\-] @exit );
+ ( ^[0-9Ee.\-]? @exit );
}%%
ParserResult parseFloat(int p, int pe) {
@@ -578,7 +596,7 @@ public class Parser extends RubyObject {
}
});
} catch (JumpException e) { }
- if (memoArray[1] != null) {
+ if (memoArray[1] != null) {
RubyClass klass = (RubyClass) memoArray[1];
if (klass.respondsTo("json_creatable?") &&
klass.callMethod(context, "json_creatable?").isTrue()) {
@@ -701,15 +719,14 @@ public class Parser extends RubyObject {
fhold;
fbreak;
}
+
+ pair = ignore* begin_name >parse_name ignore* name_separator
+ ignore* begin_value >parse_value;
+ next_pair = ignore* value_separator pair;
- a_pair = ignore*
- begin_name >parse_name
- ignore* name_separator ignore*
- begin_value >parse_value;
-
- main := begin_object
- (a_pair (ignore* value_separator a_pair)*)?
- ignore* end_object @exit;
+ main := (
+ begin_object (pair (next_pair)*)? ignore* end_object
+ ) @exit;
}%%
ParserResult parseObject(int p, int pe) {
@@ -789,7 +806,7 @@ public class Parser extends RubyObject {
ignore*;
}%%
- public IRubyObject parse() {
+ public IRubyObject parseStrict() {
int cs = EVIL;
int p, pe;
IRubyObject result = null;
@@ -806,6 +823,54 @@ public class Parser extends RubyObject {
}
}
+ %%{
+ machine JSON_quirks_mode;
+ include JSON_common;
+
+ write data;
+
+ action parse_value {
+ ParserResult res = parseValue(fpc, pe);
+ if (res == null) {
+ fhold;
+ fbreak;
+ } else {
+ result = res.result;
+ fexec res.p;
+ }
+ }
+
+ main := ignore*
+ ( begin_value >parse_value)
+ ignore*;
+ }%%
+
+ public IRubyObject parseQuirksMode() {
+ int cs = EVIL;
+ int p, pe;
+ IRubyObject result = null;
+
+ %% write init;
+ p = byteList.begin();
+ pe = p + byteList.length();
+ %% write exec;
+
+ if (cs >= JSON_quirks_mode_first_final && p == pe) {
+ return result;
+ } else {
+ throw unexpectedToken(p, pe);
+ }
+ }
+
+ public IRubyObject parse() {
+ if (parser.quirksMode) {
+ return parseQuirksMode();
+ } else {
+ return parseStrict();
+ }
+
+ }
+
/**
* Returns a subsequence of the source ByteList, based on source
* array byte offsets (i.e., the ByteList's own begin offset is not
diff --git a/java/src/json/ext/ParserService.java b/java/src/json/ext/ParserService.java
index f2ecae1..dde8834 100644
--- a/java/src/json/ext/ParserService.java
+++ b/java/src/json/ext/ParserService.java
@@ -1,6 +1,6 @@
/*
* This code is copyrighted work by Daniel Luz <dev at mernen dot com>.
- *
+ *
* Distributed under the Ruby and GPLv2 licenses; see COPYING and GPL files
* for details.
*/
diff --git a/java/src/json/ext/Utils.java b/java/src/json/ext/Utils.java
index f52ac8d..44d6a55 100644
--- a/java/src/json/ext/Utils.java
+++ b/java/src/json/ext/Utils.java
@@ -1,6 +1,6 @@
/*
* This code is copyrighted work by Daniel Luz <dev at mernen dot com>.
- *
+ *
* Distributed under the Ruby and GPLv2 licenses; see COPYING and GPL files
* for details.
*/
diff --git a/json.gemspec b/json.gemspec
index 456715d..b47b18e 100644
--- a/json.gemspec
+++ b/json.gemspec
@@ -6,13 +6,13 @@ Gem::Specification.new do |s|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
s.authors = [%q{Florian Frank}]
- s.date = %q{2011-07-24}
+ s.date = %q{2011-07-30}
s.description = %q{This is a JSON implementation as a Ruby extension in C.}
s.email = %q{flori@ping.de}
s.executables = [%q{edit_json.rb}, %q{prettify_json.rb}]
s.extensions = [%q{ext/json/ext/parser/extconf.rb}, %q{ext/json/ext/generator/extconf.rb}]
s.extra_rdoc_files = [%q{README.rdoc}]
- s.files = [%q{Gemfile.lock}, %q{tests}, %q{tests/test_json_string_matching.rb}, %q{tests/test_json_fixtures.rb}, %q{tests/setup_variant.rb}, %q{tests/fixtures}, %q{tests/fixtures/fail6.json}, %q{tests/fixtures/fail9.json}, %q{tests/fixtures/fail10.json}, %q{tests/fixtures/fail24.json}, %q{tests/fixtures/fail28.json}, %q{tests/fixtures/fail13.json}, %q{tests/fixtures/fail4.json}, %q{tests/fixtures/pass3.json}, %q{tests/fixtures/fail11.json}, %q{tests/fixtures/fail14.json}, %q{tests/fixtures/fail3.json}, %q{tests/fixtures/fail12.json}, %q{tests/fixtures/pass16.json}, %q{tests/fixtures/pass15.json}, %q{tests/fixtures/fail20.json}, %q{tests/fixtures/fail8.json}, %q{tests/fixtures/pass2.json}, %q{tests/fixtures/fail5.json}, %q{tests/fixtures/fail1.json}, %q{tests/fixtures/fail25.json}, %q{tests/fixtures/pass17.json}, %q{tests/fixtures/fail7.json}, %q{tests/fixtures/pass26.json}, %q{tests/fixtures/fail21.json}, %q{tests/fixtures/pass1.json}, %q{tests/fixtures/fail23.json}, %q{tests/fixtures/fail18.json}, %q{tests/fixtures/fail2.json}, %q{tests/fixtures/fail22.json}, %q{tests/fixtures/fail27.json}, %q{tests/fixtures/fail19.json}, %q{tests/test_json_unicode.rb}, %q{tests/test_json_addition.rb}, %q{tests/test_json_generate.rb}, %q{tests/test_json_encoding.rb}, %q{tests/test_json.rb}, %q{COPYING}, %q{TODO}, %q{Rakefile}, %q{benchmarks}, %q{benchmarks/data-p4-3GHz-ruby18}, %q{benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkExt#parser.dat}, %q{benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkPure.log}, %q{benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkYAML.log}, %q{benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkRails.log}, %q{benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkRails.log}, %q{benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_safe.dat}, %q{benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkYAML#parser.dat}, %q{benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkRails#generator.dat}, %q{benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure.log}, %q{benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_pretty-autocorrelation.dat}, %q{benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkPure#parser-autocorrelation.dat}, %q{benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkExt#parser-autocorrelation.dat}, %q{benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkPure#parser.dat}, %q{benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkRails#parser-autocorrelation.dat}, %q{benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkExt.log}, %q{benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_fast.dat}, %q{benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_safe.dat}, %q{benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_pretty.dat}, %q{benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkComparison.log}, %q{benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkRails#parser.dat}, %q{benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt.log}, %q{benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_safe-autocorrelation.dat}, %q{benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkRails#generator-autocorrelation.dat}, %q{benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_fast-autocorrelation.dat}, %q{benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_pretty.dat}, %q{benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_fast-autocorrelation.dat}, %q{benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_fast.dat}, %q{benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkComparison.log}, %q{benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_pretty-autocorrelation.dat}, %q{benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkYAML#parser-autocorrelation.dat}, %q{benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_safe-autocorrelation.dat}, %q{benchmarks/parser2_benchmark.rb}, %q{benchmarks/parser_benchmark.rb}, %q{benchmarks/generator2_benchmark.rb}, %q{benchmarks/generator_benchmark.rb}, %q{benchmarks/ohai.ruby}, %q{benchmarks/data}, %q{benchmarks/ohai.json}, %q{lib}, %q{lib/json}, %q{lib/json/json.xpm}, %q{lib/json/TrueClass.xpm}, %q{lib/json/version.rb}, %q{lib/json/Array.xpm}, %q{lib/json/add}, %q{lib/json/add/core.rb}, %q{lib/json/add/rails.rb}, %q{lib/json/common.rb}, %q{lib/json/pure}, %q{lib/json/pure/generator.rb}, %q{lib/json/pure/parser.rb}, %q{lib/json/ext.rb}, %q{lib/json/pure.rb}, %q{lib/json/Key.xpm}, %q{lib/json/FalseClass.xpm}, %q{lib/json/editor.rb}, %q{lib/json/Numeric.xpm}, %q{lib/json/ext}, %q{lib/json/NilClass.xpm}, %q{lib/json/String.xpm}, %q{lib/json/Hash.xpm}, %q{lib/json.rb}, %q{Gemfile}, %q{README.rdoc}, %q{json_pure.gemspec}, %q{GPL}, %q{CHANGES}, %q{bin}, %q{bin/prettify_json.rb}, %q{bin/edit_json.rb}, %q{COPYING-json-jruby}, %q{ext}, %q{ext/json}, %q{ext/json/ext}, %q{ext/json/ext/parser}, %q{ext/json/ext/parser/parser.h}, %q{ext/json/ext/parser/extconf.rb}, %q{ext/json/ext/parser/parser.rl}, %q{ext/json/ext/parser/parser.c}, %q{ext/json/ext/generator}, %q{ext/json/ext/generator/generator.c}, %q{ext/json/ext/generator/extconf.rb}, %q{ext/json/ext/generator/generator.h}, %q{VERSION}, %q{data}, %q{data/prototype.js}, %q{data/index.html}, %q{data/example.json}, %q{json.gemspec}, %q{java}, %q{java/src}, %q{java/src/json}, %q{java/src/json/ext}, %q{java/src/json/ext/Parser.java}, %q{java/src/json/ext/RuntimeInfo.java}, %q{java/src/json/ext/GeneratorState.java}, %q{java/src/json/ext/OptionsReader.java}, %q{java/src/json/ext/ParserService.java}, %q{java/src/json/ext/Parser.rl}, %q{java/src/json/ext/StringEncoder.java}, %q{java/src/json/ext/GeneratorService.java}, %q{java/src/json/ext/Utils.java}, %q{java/src/json/ext/StringDecoder.java}, %q{java/src/json/ext/Generator.java}, %q{java/src/json/ext/ByteListTranscoder.java}, %q{java/src/json/ext/GeneratorMethods.java}, %q{java/lib}, %q{java/lib/bytelist-1.0.6.jar}, %q{java/lib/jcodings.jar}, %q{diagrams}, %q{README-json-jruby.markdown}, %q{install.rb}, %q{json-java.gemspec}, %q{tools}, %q{tools/fuzz.rb}, %q{tools/server.rb}, %q{./tests/test_json_string_matching.rb}, %q{./tests/test_json_fixtures.rb}, %q{./tests/test_json_unicode.rb}, %q{./tests/test_json_addition.rb}, %q{./tests/test_json_generate.rb}, %q{./tests/test_json_encoding.rb}, %q{./tests/test_json.rb}]
+ s.files = [%q{tests}, %q{tests/test_json_string_matching.rb}, %q{tests/test_json_fixtures.rb}, %q{tests/setup_variant.rb}, %q{tests/fixtures}, %q{tests/fixtures/fail6.json}, %q{tests/fixtures/fail9.json}, %q{tests/fixtures/fail10.json}, %q{tests/fixtures/fail24.json}, %q{tests/fixtures/fail28.json}, %q{tests/fixtures/fail13.json}, %q{tests/fixtures/fail4.json}, %q{tests/fixtures/pass3.json}, %q{tests/fixtures/fail11.json}, %q{tests/fixtures/fail14.json}, %q{tests/fixtures/fail3.json}, %q{tests/fixtures/fail12.json}, %q{tests/fixtures/pass16.json}, %q{tests/fixtures/pass15.json}, %q{tests/fixtures/fail20.json}, %q{tests/fixtures/fail8.json}, %q{tests/fixtures/pass2.json}, %q{tests/fixtures/fail5.json}, %q{tests/fixtures/fail1.json}, %q{tests/fixtures/fail25.json}, %q{tests/fixtures/pass17.json}, %q{tests/fixtures/fail7.json}, %q{tests/fixtures/pass26.json}, %q{tests/fixtures/fail21.json}, %q{tests/fixtures/pass1.json}, %q{tests/fixtures/fail23.json}, %q{tests/fixtures/fail18.json}, %q{tests/fixtures/fail2.json}, %q{tests/fixtures/fail22.json}, %q{tests/fixtures/fail27.json}, %q{tests/fixtures/fail19.json}, %q{tests/test_json_unicode.rb}, %q{tests/test_json_addition.rb}, %q{tests/test_json_generate.rb}, %q{tests/test_json_encoding.rb}, %q{tests/test_json.rb}, %q{COPYING}, %q{TODO}, %q{Rakefile}, %q{benchmarks}, %q{benchmarks/data-p4-3GHz-ruby18}, %q{benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkExt#parser.dat}, %q{benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkPure.log}, %q{benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkYAML.log}, %q{benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkRails.log}, %q{benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkRails.log}, %q{benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_safe.dat}, %q{benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkYAML#parser.dat}, %q{benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkRails#generator.dat}, %q{benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure.log}, %q{benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_pretty-autocorrelation.dat}, %q{benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkPure#parser-autocorrelation.dat}, %q{benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkExt#parser-autocorrelation.dat}, %q{benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkPure#parser.dat}, %q{benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkRails#parser-autocorrelation.dat}, %q{benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkExt.log}, %q{benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_fast.dat}, %q{benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_safe.dat}, %q{benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_pretty.dat}, %q{benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkComparison.log}, %q{benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkRails#parser.dat}, %q{benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt.log}, %q{benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_safe-autocorrelation.dat}, %q{benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkRails#generator-autocorrelation.dat}, %q{benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_fast-autocorrelation.dat}, %q{benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_pretty.dat}, %q{benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_fast-autocorrelation.dat}, %q{benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_fast.dat}, %q{benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkComparison.log}, %q{benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_pretty-autocorrelation.dat}, %q{benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkYAML#parser-autocorrelation.dat}, %q{benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_safe-autocorrelation.dat}, %q{benchmarks/parser2_benchmark.rb}, %q{benchmarks/parser_benchmark.rb}, %q{benchmarks/generator2_benchmark.rb}, %q{benchmarks/generator_benchmark.rb}, %q{benchmarks/ohai.ruby}, %q{benchmarks/data}, %q{benchmarks/ohai.json}, %q{lib}, %q{lib/json}, %q{lib/json/json.xpm}, %q{lib/json/TrueClass.xpm}, %q{lib/json/version.rb}, %q{lib/json/Array.xpm}, %q{lib/json/add}, %q{lib/json/add/core.rb}, %q{lib/json/common.rb}, %q{lib/json/pure}, %q{lib/json/pure/generator.rb}, %q{lib/json/pure/parser.rb}, %q{lib/json/ext.rb}, %q{lib/json/pure.rb}, %q{lib/json/Key.xpm}, %q{lib/json/FalseClass.xpm}, %q{lib/json/editor.rb}, %q{lib/json/Numeric.xpm}, %q{lib/json/ext}, %q{lib/json/NilClass.xpm}, %q{lib/json/String.xpm}, %q{lib/json/Hash.xpm}, %q{lib/json.rb}, %q{Gemfile}, %q{README.rdoc}, %q{json_pure.gemspec}, %q{GPL}, %q{CHANGES}, %q{bin}, %q{bin/prettify_json.rb}, %q{bin/edit_json.rb}, %q{COPYING-json-jruby}, %q{ext}, %q{ext/json}, %q{ext/json/ext}, %q{ext/json/ext/parser}, %q{ext/json/ext/parser/parser.h}, %q{ext/json/ext/parser/extconf.rb}, %q{ext/json/ext/parser/parser.rl}, %q{ext/json/ext/parser/parser.c}, %q{ext/json/ext/generator}, %q{ext/json/ext/generator/generator.c}, %q{ext/json/ext/generator/extconf.rb}, %q{ext/json/ext/generator/generator.h}, %q{VERSION}, %q{data}, %q{data/prototype.js}, %q{data/index.html}, %q{data/example.json}, %q{json.gemspec}, %q{java}, %q{java/src}, %q{java/src/json}, %q{java/src/json/ext}, %q{java/src/json/ext/Parser.java}, %q{java/src/json/ext/RuntimeInfo.java}, %q{java/src/json/ext/GeneratorState.java}, %q{java/src/json/ext/OptionsReader.java}, %q{java/src/json/ext/ParserService.java}, %q{java/src/json/ext/Parser.rl}, %q{java/src/json/ext/StringEncoder.java}, %q{java/src/json/ext/GeneratorService.java}, %q{java/src/json/ext/Utils.java}, %q{java/src/json/ext/StringDecoder.java}, %q{java/src/json/ext/Generator.java}, %q{java/src/json/ext/ByteListTranscoder.java}, %q{java/src/json/ext/GeneratorMethods.java}, %q{java/lib}, %q{java/lib/bytelist-1.0.6.jar}, %q{java/lib/jcodings.jar}, %q{diagrams}, %q{README-json-jruby.markdown}, %q{install.rb}, %q{json-java.gemspec}, %q{tools}, %q{tools/fuzz.rb}, %q{tools/server.rb}, %q{./tests/test_json_string_matching.rb}, %q{./tests/test_json_fixtures.rb}, %q{./tests/test_json_unicode.rb}, %q{./tests/test_json_addition.rb}, %q{./tests/test_json_generate.rb}, %q{./tests/test_json_encoding.rb}, %q{./tests/test_json.rb}]
s.homepage = %q{http://flori.github.com/json}
s.rdoc_options = [%q{--title}, %q{JSON implemention for Ruby}, %q{--main}, %q{README.rdoc}]
s.require_paths = [%q{ext/json/ext}, %q{ext}, %q{lib}]
diff --git a/json_pure.gemspec b/json_pure.gemspec
index 9e4c082..ab8b0bc 100644
--- a/json_pure.gemspec
+++ b/json_pure.gemspec
@@ -6,12 +6,12 @@ Gem::Specification.new do |s|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
s.authors = [%q{Florian Frank}]
- s.date = %q{2011-07-24}
+ s.date = %q{2011-07-30}
s.description = %q{This is a JSON implementation in pure Ruby.}
s.email = %q{flori@ping.de}
s.executables = [%q{edit_json.rb}, %q{prettify_json.rb}]
s.extra_rdoc_files = [%q{README.rdoc}]
- s.files = [%q{Gemfile.lock}, %q{tests}, %q{tests/test_json_string_matching.rb}, %q{tests/test_json_fixtures.rb}, %q{tests/setup_variant.rb}, %q{tests/fixtures}, %q{tests/fixtures/fail6.json}, %q{tests/fixtures/fail9.json}, %q{tests/fixtures/fail10.json}, %q{tests/fixtures/fail24.json}, %q{tests/fixtures/fail28.json}, %q{tests/fixtures/fail13.json}, %q{tests/fixtures/fail4.json}, %q{tests/fixtures/pass3.json}, %q{tests/fixtures/fail11.json}, %q{tests/fixtures/fail14.json}, %q{tests/fixtures/fail3.json}, %q{tests/fixtures/fail12.json}, %q{tests/fixtures/pass16.json}, %q{tests/fixtures/pass15.json}, %q{tests/fixtures/fail20.json}, %q{tests/fixtures/fail8.json}, %q{tests/fixtures/pass2.json}, %q{tests/fixtures/fail5.json}, %q{tests/fixtures/fail1.json}, %q{tests/fixtures/fail25.json}, %q{tests/fixtures/pass17.json}, %q{tests/fixtures/fail7.json}, %q{tests/fixtures/pass26.json}, %q{tests/fixtures/fail21.json}, %q{tests/fixtures/pass1.json}, %q{tests/fixtures/fail23.json}, %q{tests/fixtures/fail18.json}, %q{tests/fixtures/fail2.json}, %q{tests/fixtures/fail22.json}, %q{tests/fixtures/fail27.json}, %q{tests/fixtures/fail19.json}, %q{tests/test_json_unicode.rb}, %q{tests/test_json_addition.rb}, %q{tests/test_json_generate.rb}, %q{tests/test_json_encoding.rb}, %q{tests/test_json.rb}, %q{COPYING}, %q{TODO}, %q{Rakefile}, %q{benchmarks}, %q{benchmarks/data-p4-3GHz-ruby18}, %q{benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkExt#parser.dat}, %q{benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkPure.log}, %q{benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkYAML.log}, %q{benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkRails.log}, %q{benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkRails.log}, %q{benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_safe.dat}, %q{benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkYAML#parser.dat}, %q{benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkRails#generator.dat}, %q{benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure.log}, %q{benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_pretty-autocorrelation.dat}, %q{benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkPure#parser-autocorrelation.dat}, %q{benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkExt#parser-autocorrelation.dat}, %q{benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkPure#parser.dat}, %q{benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkRails#parser-autocorrelation.dat}, %q{benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkExt.log}, %q{benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_fast.dat}, %q{benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_safe.dat}, %q{benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_pretty.dat}, %q{benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkComparison.log}, %q{benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkRails#parser.dat}, %q{benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt.log}, %q{benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_safe-autocorrelation.dat}, %q{benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkRails#generator-autocorrelation.dat}, %q{benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_fast-autocorrelation.dat}, %q{benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_pretty.dat}, %q{benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_fast-autocorrelation.dat}, %q{benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_fast.dat}, %q{benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkComparison.log}, %q{benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_pretty-autocorrelation.dat}, %q{benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkYAML#parser-autocorrelation.dat}, %q{benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_safe-autocorrelation.dat}, %q{benchmarks/parser2_benchmark.rb}, %q{benchmarks/parser_benchmark.rb}, %q{benchmarks/generator2_benchmark.rb}, %q{benchmarks/generator_benchmark.rb}, %q{benchmarks/ohai.ruby}, %q{benchmarks/data}, %q{benchmarks/ohai.json}, %q{lib}, %q{lib/json}, %q{lib/json/json.xpm}, %q{lib/json/TrueClass.xpm}, %q{lib/json/version.rb}, %q{lib/json/Array.xpm}, %q{lib/json/add}, %q{lib/json/add/core.rb}, %q{lib/json/add/rails.rb}, %q{lib/json/common.rb}, %q{lib/json/pure}, %q{lib/json/pure/generator.rb}, %q{lib/json/pure/parser.rb}, %q{lib/json/ext.rb}, %q{lib/json/pure.rb}, %q{lib/json/Key.xpm}, %q{lib/json/FalseClass.xpm}, %q{lib/json/editor.rb}, %q{lib/json/Numeric.xpm}, %q{lib/json/ext}, %q{lib/json/NilClass.xpm}, %q{lib/json/String.xpm}, %q{lib/json/Hash.xpm}, %q{lib/json.rb}, %q{Gemfile}, %q{README.rdoc}, %q{json_pure.gemspec}, %q{GPL}, %q{CHANGES}, %q{bin}, %q{bin/prettify_json.rb}, %q{bin/edit_json.rb}, %q{COPYING-json-jruby}, %q{ext}, %q{ext/json}, %q{ext/json/ext}, %q{ext/json/ext/parser}, %q{ext/json/ext/parser/parser.h}, %q{ext/json/ext/parser/extconf.rb}, %q{ext/json/ext/parser/parser.rl}, %q{ext/json/ext/parser/parser.c}, %q{ext/json/ext/generator}, %q{ext/json/ext/generator/generator.c}, %q{ext/json/ext/generator/extconf.rb}, %q{ext/json/ext/generator/generator.h}, %q{VERSION}, %q{data}, %q{data/prototype.js}, %q{data/index.html}, %q{data/example.json}, %q{json.gemspec}, %q{java}, %q{java/src}, %q{java/src/json}, %q{java/src/json/ext}, %q{java/src/json/ext/Parser.java}, %q{java/src/json/ext/RuntimeInfo.java}, %q{java/src/json/ext/GeneratorState.java}, %q{java/src/json/ext/OptionsReader.java}, %q{java/src/json/ext/ParserService.java}, %q{java/src/json/ext/Parser.rl}, %q{java/src/json/ext/StringEncoder.java}, %q{java/src/json/ext/GeneratorService.java}, %q{java/src/json/ext/Utils.java}, %q{java/src/json/ext/StringDecoder.java}, %q{java/src/json/ext/Generator.java}, %q{java/src/json/ext/ByteListTranscoder.java}, %q{java/src/json/ext/GeneratorMethods.java}, %q{java/lib}, %q{java/lib/bytelist-1.0.6.jar}, %q{java/lib/jcodings.jar}, %q{diagrams}, %q{README-json-jruby.markdown}, %q{install.rb}, %q{json-java.gemspec}, %q{tools}, %q{tools/fuzz.rb}, %q{tools/server.rb}, %q{./tests/test_json_string_matching.rb}, %q{./tests/test_json_fixtures.rb}, %q{./tests/test_json_unicode.rb}, %q{./tests/test_json_addition.rb}, %q{./tests/test_json_generate.rb}, %q{./tests/test_json_encoding.rb}, %q{./tests/test_json.rb}]
+ s.files = [%q{tests}, %q{tests/test_json_string_matching.rb}, %q{tests/test_json_fixtures.rb}, %q{tests/setup_variant.rb}, %q{tests/fixtures}, %q{tests/fixtures/fail6.json}, %q{tests/fixtures/fail9.json}, %q{tests/fixtures/fail10.json}, %q{tests/fixtures/fail24.json}, %q{tests/fixtures/fail28.json}, %q{tests/fixtures/fail13.json}, %q{tests/fixtures/fail4.json}, %q{tests/fixtures/pass3.json}, %q{tests/fixtures/fail11.json}, %q{tests/fixtures/fail14.json}, %q{tests/fixtures/fail3.json}, %q{tests/fixtures/fail12.json}, %q{tests/fixtures/pass16.json}, %q{tests/fixtures/pass15.json}, %q{tests/fixtures/fail20.json}, %q{tests/fixtures/fail8.json}, %q{tests/fixtures/pass2.json}, %q{tests/fixtures/fail5.json}, %q{tests/fixtures/fail1.json}, %q{tests/fixtures/fail25.json}, %q{tests/fixtures/pass17.json}, %q{tests/fixtures/fail7.json}, %q{tests/fixtures/pass26.json}, %q{tests/fixtures/fail21.json}, %q{tests/fixtures/pass1.json}, %q{tests/fixtures/fail23.json}, %q{tests/fixtures/fail18.json}, %q{tests/fixtures/fail2.json}, %q{tests/fixtures/fail22.json}, %q{tests/fixtures/fail27.json}, %q{tests/fixtures/fail19.json}, %q{tests/test_json_unicode.rb}, %q{tests/test_json_addition.rb}, %q{tests/test_json_generate.rb}, %q{tests/test_json_encoding.rb}, %q{tests/test_json.rb}, %q{COPYING}, %q{TODO}, %q{Rakefile}, %q{benchmarks}, %q{benchmarks/data-p4-3GHz-ruby18}, %q{benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkExt#parser.dat}, %q{benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkPure.log}, %q{benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkYAML.log}, %q{benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkRails.log}, %q{benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkRails.log}, %q{benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_safe.dat}, %q{benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkYAML#parser.dat}, %q{benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkRails#generator.dat}, %q{benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure.log}, %q{benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_pretty-autocorrelation.dat}, %q{benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkPure#parser-autocorrelation.dat}, %q{benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkExt#parser-autocorrelation.dat}, %q{benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkPure#parser.dat}, %q{benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkRails#parser-autocorrelation.dat}, %q{benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkExt.log}, %q{benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_fast.dat}, %q{benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_safe.dat}, %q{benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_pretty.dat}, %q{benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkComparison.log}, %q{benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkRails#parser.dat}, %q{benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt.log}, %q{benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_safe-autocorrelation.dat}, %q{benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkRails#generator-autocorrelation.dat}, %q{benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_fast-autocorrelation.dat}, %q{benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_pretty.dat}, %q{benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_fast-autocorrelation.dat}, %q{benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_fast.dat}, %q{benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkComparison.log}, %q{benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_pretty-autocorrelation.dat}, %q{benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkYAML#parser-autocorrelation.dat}, %q{benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_safe-autocorrelation.dat}, %q{benchmarks/parser2_benchmark.rb}, %q{benchmarks/parser_benchmark.rb}, %q{benchmarks/generator2_benchmark.rb}, %q{benchmarks/generator_benchmark.rb}, %q{benchmarks/ohai.ruby}, %q{benchmarks/data}, %q{benchmarks/ohai.json}, %q{lib}, %q{lib/json}, %q{lib/json/json.xpm}, %q{lib/json/TrueClass.xpm}, %q{lib/json/version.rb}, %q{lib/json/Array.xpm}, %q{lib/json/add}, %q{lib/json/add/core.rb}, %q{lib/json/common.rb}, %q{lib/json/pure}, %q{lib/json/pure/generator.rb}, %q{lib/json/pure/parser.rb}, %q{lib/json/ext.rb}, %q{lib/json/pure.rb}, %q{lib/json/Key.xpm}, %q{lib/json/FalseClass.xpm}, %q{lib/json/editor.rb}, %q{lib/json/Numeric.xpm}, %q{lib/json/ext}, %q{lib/json/NilClass.xpm}, %q{lib/json/String.xpm}, %q{lib/json/Hash.xpm}, %q{lib/json.rb}, %q{Gemfile}, %q{README.rdoc}, %q{json_pure.gemspec}, %q{GPL}, %q{CHANGES}, %q{bin}, %q{bin/prettify_json.rb}, %q{bin/edit_json.rb}, %q{COPYING-json-jruby}, %q{ext}, %q{ext/json}, %q{ext/json/ext}, %q{ext/json/ext/parser}, %q{ext/json/ext/parser/parser.h}, %q{ext/json/ext/parser/extconf.rb}, %q{ext/json/ext/parser/parser.rl}, %q{ext/json/ext/parser/parser.c}, %q{ext/json/ext/generator}, %q{ext/json/ext/generator/generator.c}, %q{ext/json/ext/generator/extconf.rb}, %q{ext/json/ext/generator/generator.h}, %q{VERSION}, %q{data}, %q{data/prototype.js}, %q{data/index.html}, %q{data/example.json}, %q{json.gemspec}, %q{java}, %q{java/src}, %q{java/src/json}, %q{java/src/json/ext}, %q{java/src/json/ext/Parser.java}, %q{java/src/json/ext/RuntimeInfo.java}, %q{java/src/json/ext/GeneratorState.java}, %q{java/src/json/ext/OptionsReader.java}, %q{java/src/json/ext/ParserService.java}, %q{java/src/json/ext/Parser.rl}, %q{java/src/json/ext/StringEncoder.java}, %q{java/src/json/ext/GeneratorService.java}, %q{java/src/json/ext/Utils.java}, %q{java/src/json/ext/StringDecoder.java}, %q{java/src/json/ext/Generator.java}, %q{java/src/json/ext/ByteListTranscoder.java}, %q{java/src/json/ext/GeneratorMethods.java}, %q{java/lib}, %q{java/lib/bytelist-1.0.6.jar}, %q{java/lib/jcodings.jar}, %q{diagrams}, %q{README-json-jruby.markdown}, %q{install.rb}, %q{json-java.gemspec}, %q{tools}, %q{tools/fuzz.rb}, %q{tools/server.rb}, %q{./tests/test_json_string_matching.rb}, %q{./tests/test_json_fixtures.rb}, %q{./tests/test_json_unicode.rb}, %q{./tests/test_json_addition.rb}, %q{./tests/test_json_generate.rb}, %q{./tests/test_json_encoding.rb}, %q{./tests/test_json.rb}]
s.homepage = %q{http://flori.github.com/json}
s.rdoc_options = [%q{--title}, %q{JSON implemention for ruby}, %q{--main}, %q{README.rdoc}]
s.require_paths = [%q{lib}]
diff --git a/lib/json/common.rb b/lib/json/common.rb
index bc8c952..43e249c 100644
--- a/lib/json/common.rb
+++ b/lib/json/common.rb
@@ -198,7 +198,11 @@ module JSON
# amount of sanity checks, and the pretty_generate method for some
# defaults for pretty output.
def generate(obj, opts = nil)
- state = SAFE_STATE_PROTOTYPE.dup
+ if State === opts
+ state, opts = opts, nil
+ else
+ state = SAFE_STATE_PROTOTYPE.dup
+ end
if opts
if opts.respond_to? :to_hash
opts = opts.to_hash
@@ -225,7 +229,11 @@ module JSON
# *WARNING*: Be careful not to pass any Ruby data structures with circles as
# _obj_ argument because this will cause JSON to go into an infinite loop.
def fast_generate(obj, opts = nil)
- state = FAST_STATE_PROTOTYPE.dup
+ if State === opts
+ state, opts = opts, nil
+ else
+ state = FAST_STATE_PROTOTYPE.dup
+ end
if opts
if opts.respond_to? :to_hash
opts = opts.to_hash
@@ -252,7 +260,11 @@ module JSON
# The _opts_ argument can be used to configure the generator. See the
# generate method for a more detailed explanation.
def pretty_generate(obj, opts = nil)
- state = PRETTY_STATE_PROTOTYPE.dup
+ if State === opts
+ state, opts = opts, nil
+ else
+ state = PRETTY_STATE_PROTOTYPE.dup
+ end
if opts
if opts.respond_to? :to_hash
opts = opts.to_hash
diff --git a/lib/json/pure/generator.rb b/lib/json/pure/generator.rb
index 3687e30..59df74d 100644
--- a/lib/json/pure/generator.rb
+++ b/lib/json/pure/generator.rb
@@ -141,6 +141,7 @@ module JSON
@array_nl = ''
@allow_nan = false
@ascii_only = false
+ @quirks_mode = false
configure opts
end
@@ -165,6 +166,10 @@ module JSON
# the generated JSON, max_nesting = 0 if no maximum is checked.
attr_accessor :max_nesting
+ # If this attribute is set to true, quirks mode is enabled, otherwise
+ # it's disabled.
+ attr_accessor :quirks_mode
+
# This integer returns the current depth data structure nesting in the
# generated JSON.
attr_accessor :depth
@@ -188,10 +193,17 @@ module JSON
@allow_nan
end
+ # Returns true, if only ASCII characters should be generated. Otherwise
+ # returns false.
def ascii_only?
@ascii_only
end
+ # Returns true, if quirks mode is enabled. Otherwise returns false.
+ def quirks_mode?
+ @quirks_mode
+ end
+
# Configure this State instance with the Hash _opts_, and return
# itself.
def configure(opts)
@@ -203,6 +215,7 @@ module JSON
@allow_nan = !!opts[:allow_nan] if opts.key?(:allow_nan)
@ascii_only = opts[:ascii_only] if opts.key?(:ascii_only)
@depth = opts[:depth] || 0
+ @quirks_mode = opts[:quirks_mode] if opts.key?(:quirks_mode)
if !opts.key?(:max_nesting) # defaults to 19
@max_nesting = 19
elsif opts[:max_nesting]
@@ -218,7 +231,7 @@ module JSON
# passed to the configure method.
def to_h
result = {}
- for iv in %w[indent space space_before object_nl array_nl allow_nan max_nesting ascii_only depth]
+ for iv in %w[indent space space_before object_nl array_nl allow_nan max_nesting ascii_only quirks_mode depth]
result[iv.intern] = instance_variable_get("@#{iv}")
end
result
@@ -229,7 +242,7 @@ module JSON
# GeneratorError exception.
def generate(obj)
result = obj.to_json(self)
- if result !~ /\A\s*(?:\[.*\]|\{.*\})\s*\Z/m
+ if !@quirks_mode && result !~ /\A\s*(?:\[.*\]|\{.*\})\s*\Z/m
raise GeneratorError, "only generation of JSON objects or arrays allowed"
end
result
diff --git a/lib/json/pure/parser.rb b/lib/json/pure/parser.rb
index d612018..5ef1b78 100644
--- a/lib/json/pure/parser.rb
+++ b/lib/json/pure/parser.rb
@@ -70,40 +70,8 @@ module JSON
# * *array_class*: Defaults to Array
def initialize(source, opts = {})
opts ||= {}
- if defined?(::Encoding)
- if source.encoding == ::Encoding::ASCII_8BIT
- b = source[0, 4].bytes.to_a
- source = case
- when b.size >= 4 && b[0] == 0 && b[1] == 0 && b[2] == 0
- source.dup.force_encoding(::Encoding::UTF_32BE).encode!(::Encoding::UTF_8)
- when b.size >= 4 && b[0] == 0 && b[2] == 0
- source.dup.force_encoding(::Encoding::UTF_16BE).encode!(::Encoding::UTF_8)
- when b.size >= 4 && b[1] == 0 && b[2] == 0 && b[3] == 0
- source.dup.force_encoding(::Encoding::UTF_32LE).encode!(::Encoding::UTF_8)
-
- when b.size >= 4 && b[1] == 0 && b[3] == 0
- source.dup.force_encoding(::Encoding::UTF_16LE).encode!(::Encoding::UTF_8)
- else
- source.dup
- end
- else
- source = source.encode(::Encoding::UTF_8)
- end
- source.force_encoding(::Encoding::ASCII_8BIT)
- else
- b = source
- source = case
- when b.size >= 4 && b[0] == 0 && b[1] == 0 && b[2] == 0
- JSON.iconv('utf-8', 'utf-32be', b)
- when b.size >= 4 && b[0] == 0 && b[2] == 0
- JSON.iconv('utf-8', 'utf-16be', b)
- when b.size >= 4 && b[1] == 0 && b[2] == 0 && b[3] == 0
- JSON.iconv('utf-8', 'utf-32le', b)
- when b.size >= 4 && b[1] == 0 && b[3] == 0
- JSON.iconv('utf-8', 'utf-16le', b)
- else
- b
- end
+ unless @quirks_mode = opts[:quirks_mode]
+ source = determine_encoding source
end
super source
if !opts.key?(:max_nesting) # defaults to 19
@@ -113,44 +81,108 @@ module JSON
else
@max_nesting = 0
end
- @allow_nan = !!opts[:allow_nan]
- @symbolize_names = !!opts[:symbolize_names]
- @create_additions = opts.key?(:create_additions) ? !!opts[:create_additions] : true
- @create_id = opts[:create_id] || JSON.create_id
- @object_class = opts[:object_class] || Hash
- @array_class = opts[:array_class] || Array
- @match_string = opts[:match_string]
+ @allow_nan = !!opts[:allow_nan]
+ @symbolize_names = !!opts[:symbolize_names]
+ if opts.key?(:create_additions)
+ @create_additions = !!opts[:create_additions]
+ else
+ @create_additions = true
+ end
+ @create_id = @create_additions ? JSON.create_id : nil
+ @object_class = opts[:object_class] || Hash
+ @array_class = opts[:array_class] || Array
+ @match_string = opts[:match_string]
end
alias source string
+ def quirks_mode?
+ !!@quirks_mode
+ end
+
+ def reset
+ super
+ @current_nesting = 0
+ end
+
# Parses the current JSON string _source_ and returns the complete data
# structure as a result.
def parse
reset
obj = nil
- until eos?
- case
- when scan(OBJECT_OPEN)
- obj and raise ParserError, "source '#{peek(20)}' not in JSON!"
- @current_nesting = 1
- obj = parse_object
- when scan(ARRAY_OPEN)
- obj and raise ParserError, "source '#{peek(20)}' not in JSON!"
- @current_nesting = 1
- obj = parse_array
- when skip(IGNORE)
- ;
+ if @quirks_mode
+ while !eos? && skip(IGNORE)
+ end
+ if eos?
+ raise ParserError, "source did not contain any JSON!"
else
- raise ParserError, "source '#{peek(20)}' not in JSON!"
+ obj = parse_value
+ obj == UNPARSED and raise ParserError, "source did not contain any JSON!"
end
+ else
+ until eos?
+ case
+ when scan(OBJECT_OPEN)
+ obj and raise ParserError, "source '#{peek(20)}' not in JSON!"
+ @current_nesting = 1
+ obj = parse_object
+ when scan(ARRAY_OPEN)
+ obj and raise ParserError, "source '#{peek(20)}' not in JSON!"
+ @current_nesting = 1
+ obj = parse_array
+ when skip(IGNORE)
+ ;
+ else
+ raise ParserError, "source '#{peek(20)}' not in JSON!"
+ end
+ end
+ obj or raise ParserError, "source did not contain any JSON!"
end
- obj or raise ParserError, "source did not contain any JSON!"
obj
end
private
+ def determine_encoding(source)
+ if defined?(::Encoding)
+ if source.encoding == ::Encoding::ASCII_8BIT
+ b = source[0, 4].bytes.to_a
+ source =
+ case
+ when b.size >= 4 && b[0] == 0 && b[1] == 0 && b[2] == 0
+ source.dup.force_encoding(::Encoding::UTF_32BE).encode!(::Encoding::UTF_8)
+ when b.size >= 4 && b[0] == 0 && b[2] == 0
+ source.dup.force_encoding(::Encoding::UTF_16BE).encode!(::Encoding::UTF_8)
+ when b.size >= 4 && b[1] == 0 && b[2] == 0 && b[3] == 0
+ source.dup.force_encoding(::Encoding::UTF_32LE).encode!(::Encoding::UTF_8)
+ when b.size >= 4 && b[1] == 0 && b[3] == 0
+ source.dup.force_encoding(::Encoding::UTF_16LE).encode!(::Encoding::UTF_8)
+ else
+ source.dup
+ end
+ else
+ source = source.encode(::Encoding::UTF_8)
+ end
+ source.force_encoding(::Encoding::ASCII_8BIT)
+ else
+ b = source
+ source =
+ case
+ when b.size >= 4 && b[0] == 0 && b[1] == 0 && b[2] == 0
+ JSON.iconv('utf-8', 'utf-32be', b)
+ when b.size >= 4 && b[0] == 0 && b[2] == 0
+ JSON.iconv('utf-8', 'utf-16be', b)
+ when b.size >= 4 && b[1] == 0 && b[2] == 0 && b[3] == 0
+ JSON.iconv('utf-8', 'utf-32le', b)
+ when b.size >= 4 && b[1] == 0 && b[3] == 0
+ JSON.iconv('utf-8', 'utf-16le', b)
+ else
+ b
+ end
+ end
+ source
+ end
+
# Unescape characters in strings.
UNESCAPE_MAP = Hash.new { |h, k| h[k] = k.chr }
UNESCAPE_MAP.update({
diff --git a/tests/test_json.rb b/tests/test_json.rb
index b367e90..eafd758 100755
--- a/tests/test_json.rb
+++ b/tests/test_json.rb
@@ -104,6 +104,42 @@ class TC_JSON < Test::Unit::TestCase
assert_equal({ "a" => 0.23 }, parse(' { "a" : 0.23 } '))
end
+ def test_parse_json_primitive_values
+ assert_raise(JSON::ParserError) { JSON.parse('') }
+ assert_raise(JSON::ParserError) { JSON.parse('', :quirks_mode => true) }
+ assert_raise(JSON::ParserError) { JSON.parse(' /* foo */ ') }
+ assert_raise(JSON::ParserError) { JSON.parse(' /* foo */ ', :quirks_mode => true) }
+ parser = JSON::Parser.new('null')
+ assert_equal false, parser.quirks_mode?
+ assert_raise(JSON::ParserError) { parser.parse }
+ assert_raise(JSON::ParserError) { JSON.parse('null') }
+ assert_equal nil, JSON.parse('null', :quirks_mode => true)
+ parser = JSON::Parser.new('null', :quirks_mode => true)
+ assert_equal true, parser.quirks_mode?
+ assert_equal nil, parser.parse
+ assert_raise(JSON::ParserError) { JSON.parse('false') }
+ assert_equal false, JSON.parse('false', :quirks_mode => true)
+ assert_raise(JSON::ParserError) { JSON.parse('true') }
+ assert_equal true, JSON.parse('true', :quirks_mode => true)
+ assert_raise(JSON::ParserError) { JSON.parse('23') }
+ assert_equal 23, JSON.parse('23', :quirks_mode => true)
+ assert_raise(JSON::ParserError) { JSON.parse('1') }
+ assert_equal 1, JSON.parse('1', :quirks_mode => true)
+ assert_raise(JSON::ParserError) { JSON.parse('3.141') }
+ assert_in_delta 3.141, JSON.parse('3.141', :quirks_mode => true), 1E-3
+ assert_raise(JSON::ParserError) { JSON.parse('18446744073709551616') }
+ assert_equal 2 ** 64, JSON.parse('18446744073709551616', :quirks_mode => true)
+ assert_raise(JSON::ParserError) { JSON.parse('"foo"') }
+ assert_equal 'foo', JSON.parse('"foo"', :quirks_mode => true)
+ assert_raise(JSON::ParserError) { JSON.parse('NaN', :allow_nan => true) }
+ assert JSON.parse('NaN', :quirks_mode => true, :allow_nan => true).nan?
+ assert_raise(JSON::ParserError) { JSON.parse('Infinity', :allow_nan => true) }
+ assert JSON.parse('Infinity', :quirks_mode => true, :allow_nan => true).infinite?
+ assert_raise(JSON::ParserError) { JSON.parse('-Infinity', :allow_nan => true) }
+ assert JSON.parse('-Infinity', :quirks_mode => true, :allow_nan => true).infinite?
+ assert_raise(JSON::ParserError) { JSON.parse('[ 1, ]', :quirks_mode => true) }
+ end
+
if Array.method_defined?(:permutation)
def test_parse_more_complex_arrays
a = [ nil, false, true, "foßbar", [ "n€st€d", true ], { "nested" => true, "n€ßt€ð2" => {} }]
diff --git a/tests/test_json_generate.rb b/tests/test_json_generate.rb
index 9b0cff4..dc1450a 100755
--- a/tests/test_json_generate.rb
+++ b/tests/test_json_generate.rb
@@ -50,6 +50,7 @@ EOT
parsed_json = parse(json)
assert_equal({"1"=>2}, parsed_json)
assert_raise(GeneratorError) { generate(666) }
+ assert_equal '666', generate(666, :quirks_mode => true)
end
def test_generate_pretty
@@ -67,6 +68,7 @@ EOT
parsed_json = parse(json)
assert_equal({"1"=>2}, parsed_json)
assert_raise(GeneratorError) { pretty_generate(666) }
+ assert_equal '666', pretty_generate(666, :quirks_mode => true)
end
def test_fast_generate
@@ -79,9 +81,24 @@ EOT
parsed_json = parse(json)
assert_equal({"1"=>2}, parsed_json)
assert_raise(GeneratorError) { fast_generate(666) }
+ assert_equal '666', fast_generate(666, :quirks_mode => true)
end
-
+ def test_own_state
+ state = State.new
+ json = generate(@hash, state)
+ assert_equal(JSON.parse(@json2), JSON.parse(json))
+ parsed_json = parse(json)
+ assert_equal(@hash, parsed_json)
+ json = generate({1=>2}, state)
+ assert_equal('{"1":2}', json)
+ parsed_json = parse(json)
+ assert_equal({"1"=>2}, parsed_json)
+ assert_raise(GeneratorError) { generate(666, state) }
+ state.quirks_mode = true
+ assert state.quirks_mode?
+ assert_equal '666', generate(666, state)
+ end
def test_states
json = generate({1=>2}, nil)
@@ -107,6 +124,7 @@ EOT
:allow_nan => false,
:array_nl => "\n",
:ascii_only => false,
+ :quirks_mode => false,
:depth => 0,
:indent => " ",
:max_nesting => 19,
@@ -122,6 +140,7 @@ EOT
:allow_nan => false,
:array_nl => "",
:ascii_only => false,
+ :quirks_mode => false,
:depth => 0,
:indent => "",
:max_nesting => 19,
@@ -137,6 +156,7 @@ EOT
:allow_nan => false,
:array_nl => "",
:ascii_only => false,
+ :quirks_mode => false,
:depth => 0,
:indent => "",
:max_nesting => 0,