diff options
author | Florian Frank <flori@ping.de> | 2011-07-27 02:46:10 +0200 |
---|---|---|
committer | Florian Frank <flori@ping.de> | 2011-07-31 00:55:16 +0200 |
commit | 9d0b1ca629f6f5bc558a4b3f887f0f8cf154fe78 (patch) | |
tree | bdfcebfd65e40f591514515bad3106ad1dadcf92 | |
parent | 9320a2a18a4d09f8e8a83129db793057968928b1 (diff) | |
download | json-9d0b1ca629f6f5bc558a4b3f887f0f8cf154fe78.tar.gz |
Implement quirks_mode
This allows parsing of primitive values
-rw-r--r-- | ext/json/ext/parser/parser.c | 513 | ||||
-rw-r--r-- | ext/json/ext/parser/parser.h | 1 | ||||
-rw-r--r-- | ext/json/ext/parser/parser.rl | 177 | ||||
-rw-r--r-- | java/src/json/ext/GeneratorState.java | 7 | ||||
-rw-r--r-- | java/src/json/ext/Parser.java | 457 | ||||
-rw-r--r-- | java/src/json/ext/Parser.rl | 93 | ||||
-rw-r--r-- | json.gemspec | 4 | ||||
-rw-r--r-- | json_pure.gemspec | 4 | ||||
-rw-r--r-- | lib/json/pure/parser.rb | 142 | ||||
-rwxr-xr-x | tests/test_json.rb | 36 |
10 files changed, 1059 insertions, 375 deletions
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/GeneratorState.java b/java/src/json/ext/GeneratorState.java index f04eda2..6ea269a 100644 --- a/java/src/json/ext/GeneratorState.java +++ b/java/src/json/ext/GeneratorState.java @@ -72,7 +72,8 @@ 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; @@ -186,7 +187,9 @@ public class GeneratorState extends RubyObject { } /** - * 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) { diff --git a/java/src/json/ext/Parser.java b/java/src/json/ext/Parser.java index cea42d4..84a36ac 100644 --- a/java/src/json/ext/Parser.java +++ b/java/src/json/ext/Parser.java @@ -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; @@ -120,6 +121,10 @@ 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 @@ -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; } @@ -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; @@ -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; @@ -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..9cd134d 100644 --- a/java/src/json/ext/Parser.rl +++ b/java/src/json/ext/Parser.rl @@ -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; @@ -118,6 +119,10 @@ 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 @@ -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; } @@ -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; @@ -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) { @@ -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/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/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" => {} }] |