From 40c2a25a73b320a49a5463dbc9ec0bd3f43c0ff0 Mon Sep 17 00:00:00 2001 From: Jan-Joost Spanjers Date: Thu, 27 May 2021 13:52:34 +0200 Subject: [PATCH] Add option :allow_trailing_comma to JSON#parse --- ext/json/ext/parser/parser.c | 5239 ++++++++++++++------------------- ext/json/ext/parser/parser.h | 1 + ext/json/ext/parser/parser.rl | 21 +- java/src/json/ext/Parser.java | 455 ++- java/src/json/ext/Parser.rl | 17 +- lib/json/pure/parser.rb | 8 +- tests/json_parser_test.rb | 87 + 7 files changed, 2729 insertions(+), 3099 deletions(-) diff --git a/ext/json/ext/parser/parser.c b/ext/json/ext/parser/parser.c index b1dc8810..defa0746 100644 --- a/ext/json/ext/parser/parser.c +++ b/ext/json/ext/parser/parser.c @@ -9,14 +9,14 @@ static void enc_raise(rb_encoding *enc, VALUE exc, const char *fmt, ...) { - va_list args; - VALUE mesg; + va_list args; + VALUE mesg; - va_start(args, fmt); - mesg = rb_enc_vsprintf(enc, fmt, args); - va_end(args); + va_start(args, fmt); + mesg = rb_enc_vsprintf(enc, fmt, args); + va_end(args); - rb_exc_raise(rb_exc_new3(exc, mesg)); + rb_exc_raise(rb_exc_new3(exc, mesg)); } # define rb_enc_raise enc_raise # endif @@ -28,3311 +28,2642 @@ enc_raise(rb_encoding *enc, VALUE exc, const char *fmt, ...) /* unicode */ static const signed char digit_values[256] = { - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, - -1, -1, -1, -1, -1, -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1 + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, + -1, -1, -1, -1, -1, -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1 }; static UTF32 unescape_unicode(const unsigned char *p) { - signed char b; - UTF32 result = 0; - b = digit_values[p[0]]; - if (b < 0) return UNI_REPLACEMENT_CHAR; - result = (result << 4) | (unsigned char)b; - b = digit_values[p[1]]; - if (b < 0) return UNI_REPLACEMENT_CHAR; - result = (result << 4) | (unsigned char)b; - b = digit_values[p[2]]; - if (b < 0) return UNI_REPLACEMENT_CHAR; - result = (result << 4) | (unsigned char)b; - b = digit_values[p[3]]; - if (b < 0) return UNI_REPLACEMENT_CHAR; - result = (result << 4) | (unsigned char)b; - return result; + signed char b; + UTF32 result = 0; + b = digit_values[p[0]]; + if (b < 0) return UNI_REPLACEMENT_CHAR; + result = (result << 4) | (unsigned char)b; + b = digit_values[p[1]]; + if (b < 0) return UNI_REPLACEMENT_CHAR; + result = (result << 4) | (unsigned char)b; + b = digit_values[p[2]]; + if (b < 0) return UNI_REPLACEMENT_CHAR; + result = (result << 4) | (unsigned char)b; + b = digit_values[p[3]]; + if (b < 0) return UNI_REPLACEMENT_CHAR; + result = (result << 4) | (unsigned char)b; + return result; } static int convert_UTF32_to_UTF8(char *buf, UTF32 ch) { - int len = 1; - if (ch <= 0x7F) { - buf[0] = (char) ch; - } else if (ch <= 0x07FF) { - buf[0] = (char) ((ch >> 6) | 0xC0); - buf[1] = (char) ((ch & 0x3F) | 0x80); - len++; - } else if (ch <= 0xFFFF) { - buf[0] = (char) ((ch >> 12) | 0xE0); - buf[1] = (char) (((ch >> 6) & 0x3F) | 0x80); - buf[2] = (char) ((ch & 0x3F) | 0x80); - len += 2; - } else if (ch <= 0x1fffff) { - buf[0] =(char) ((ch >> 18) | 0xF0); - buf[1] =(char) (((ch >> 12) & 0x3F) | 0x80); - buf[2] =(char) (((ch >> 6) & 0x3F) | 0x80); - buf[3] =(char) ((ch & 0x3F) | 0x80); - len += 3; - } else { - buf[0] = '?'; - } - return len; + int len = 1; + if (ch <= 0x7F) { + buf[0] = (char) ch; + } else if (ch <= 0x07FF) { + buf[0] = (char) ((ch >> 6) | 0xC0); + buf[1] = (char) ((ch & 0x3F) | 0x80); + len++; + } else if (ch <= 0xFFFF) { + buf[0] = (char) ((ch >> 12) | 0xE0); + buf[1] = (char) (((ch >> 6) & 0x3F) | 0x80); + buf[2] = (char) ((ch & 0x3F) | 0x80); + len += 2; + } else if (ch <= 0x1fffff) { + buf[0] =(char) ((ch >> 18) | 0xF0); + buf[1] =(char) (((ch >> 12) & 0x3F) | 0x80); + buf[2] =(char) (((ch >> 6) & 0x3F) | 0x80); + buf[3] =(char) ((ch & 0x3F) | 0x80); + len += 3; + } else { + buf[0] = '?'; + } + return len; } 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_decimal_class, i_key_p, -i_deep_const_get, i_match, i_match_string, i_aset, i_aref, -i_leftshift, i_new, i_try_convert, i_freeze, i_uminus; + i_chr, i_max_nesting, i_allow_nan, i_allow_trailing_comma, i_symbolize_names, + i_object_class, i_array_class, i_decimal_class, i_key_p, + i_deep_const_get, i_match, i_match_string, i_aset, i_aref, + i_leftshift, i_new, i_try_convert, i_freeze, i_uminus; #line 125 "parser.rl" +#line 107 "parser.c" enum {JSON_object_start = 1}; -enum {JSON_object_first_final = 27}; +enum {JSON_object_first_final = 32}; enum {JSON_object_error = 0}; enum {JSON_object_en_main = 1}; -static const char MAYBE_UNUSED(_JSON_object_nfa_targs)[] = { - 0, 0 -}; - -static const char MAYBE_UNUSED(_JSON_object_nfa_offsets)[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0 -}; - -static const char MAYBE_UNUSED(_JSON_object_nfa_push_actions)[] = { - 0, 0 -}; - -static const char MAYBE_UNUSED(_JSON_object_nfa_pop_trans)[] = { - 0, 0 -}; - -#line 167 "parser.rl" +#line 169 "parser.rl" static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting) { - int cs = EVIL; - VALUE last_name = Qnil; - VALUE object_class = json->object_class; + int cs = EVIL; + VALUE last_name = Qnil; + VALUE object_class = json->object_class; - if (json->max_nesting && current_nesting > json->max_nesting) { - rb_raise(eNestingError, "nesting of %d is too deep", current_nesting); - } + if (json->max_nesting && current_nesting > json->max_nesting) { + rb_raise(eNestingError, "nesting of %d is too deep", current_nesting); + } - *result = NIL_P(object_class) ? rb_hash_new() : rb_class_new_instance(0, 0, object_class); + *result = NIL_P(object_class) ? rb_hash_new() : rb_class_new_instance(0, 0, object_class); +#line 131 "parser.c" { - cs = (int)JSON_object_start; + cs = JSON_object_start; } - #line 182 "parser.rl" - +#line 184 "parser.rl" +#line 138 "parser.c" { - if ( p == pe ) + short _widec; + if ( p == pe ) goto _test_eof; - switch ( cs ) - { - case 1: - goto st_case_1; - case 0: - goto st_case_0; - case 2: - goto st_case_2; - case 3: - goto st_case_3; - case 4: - goto st_case_4; - case 5: - goto st_case_5; - case 6: - goto st_case_6; - case 7: - goto st_case_7; - case 8: - goto st_case_8; - case 9: - goto st_case_9; - case 10: - goto st_case_10; - case 11: - goto st_case_11; - case 12: - goto st_case_12; - case 13: - goto st_case_13; - case 14: - goto st_case_14; - case 15: - goto st_case_15; - case 16: - goto st_case_16; - case 17: - goto st_case_17; - case 18: - goto st_case_18; - case 27: - goto st_case_27; - case 19: - goto st_case_19; - case 20: - goto st_case_20; - case 21: - goto st_case_21; - case 22: - goto st_case_22; - case 23: - goto st_case_23; - case 24: - goto st_case_24; - case 25: - goto st_case_25; - case 26: - goto st_case_26; - } - goto st_out; - st_case_1: - if ( ( (*( p))) == 123 ) { - goto st2; - } - { - goto st0; - } - st_case_0: - st0: - cs = 0; - goto _out; - st2: - p+= 1; - if ( p == pe ) + switch ( cs ) + { +case 1: + if ( (*p) == 123 ) + goto st2; + goto st0; +st0: +cs = 0; + goto _out; +st2: + if ( ++p == pe ) goto _test_eof2; - st_case_2: - switch( ( (*( p))) ) { - case 13: { - goto st2; - } - case 32: { - goto st2; - } - case 34: { - goto ctr2; - } - case 47: { - goto st23; - } - case 125: { - goto ctr4; - } - } - if ( 9 <= ( (*( p))) && ( (*( p))) <= 10 ) { - goto st2; - } - { - goto st0; - } - ctr2: - { - #line 149 "parser.rl" - - char *np; - json->parsing_name = 1; - np = JSON_parse_string(json, p, pe, &last_name); - json->parsing_name = 0; - if (np == NULL) { {p = p - 1; } {p+= 1; cs = 3; goto _out;} } else {p = (( np))-1;} - - } - - goto st3; - st3: - p+= 1; - if ( p == pe ) +case 2: + switch( (*p) ) { + case 13: goto st2; + case 32: goto st2; + case 34: goto tr2; + case 47: goto st28; + case 125: goto tr4; + } + if ( 9 <= (*p) && (*p) <= 10 ) + goto st2; + goto st0; +tr2: +#line 151 "parser.rl" + { + char *np; + json->parsing_name = 1; + np = JSON_parse_string(json, p, pe, &last_name); + json->parsing_name = 0; + if (np == NULL) { p--; {p++; cs = 3; goto _out;} } else {p = (( np))-1;} + } + goto st3; +st3: + if ( ++p == pe ) goto _test_eof3; - st_case_3: - switch( ( (*( p))) ) { - case 13: { - goto st3; - } - case 32: { - goto st3; - } - case 47: { - goto st4; - } - case 58: { - goto st8; - } - } - if ( 9 <= ( (*( p))) && ( (*( p))) <= 10 ) { - goto st3; - } - { - goto st0; - } - st4: - p+= 1; - if ( p == pe ) +case 3: +#line 180 "parser.c" + switch( (*p) ) { + case 13: goto st3; + case 32: goto st3; + case 47: goto st4; + case 58: goto st8; + } + if ( 9 <= (*p) && (*p) <= 10 ) + goto st3; + goto st0; +st4: + if ( ++p == pe ) goto _test_eof4; - st_case_4: - switch( ( (*( p))) ) { - case 42: { - goto st5; - } - case 47: { - goto st7; - } - } - { - goto st0; - } - st5: - p+= 1; - if ( p == pe ) +case 4: + switch( (*p) ) { + case 42: goto st5; + case 47: goto st7; + } + goto st0; +st5: + if ( ++p == pe ) goto _test_eof5; - st_case_5: - if ( ( (*( p))) == 42 ) { - goto st6; - } - { - goto st5; - } - st6: - p+= 1; - if ( p == pe ) +case 5: + if ( (*p) == 42 ) + goto st6; + goto st5; +st6: + if ( ++p == pe ) goto _test_eof6; - st_case_6: - switch( ( (*( p))) ) { - case 42: { - goto st6; - } - case 47: { - goto st3; - } - } - { - goto st5; - } - st7: - p+= 1; - if ( p == pe ) +case 6: + switch( (*p) ) { + case 42: goto st6; + case 47: goto st3; + } + goto st5; +st7: + if ( ++p == pe ) goto _test_eof7; - st_case_7: - if ( ( (*( p))) == 10 ) { - goto st3; - } - { - goto st7; - } - st8: - p+= 1; - if ( p == pe ) +case 7: + if ( (*p) == 10 ) + goto st3; + goto st7; +st8: + if ( ++p == pe ) goto _test_eof8; - st_case_8: - switch( ( (*( p))) ) { - case 13: { - goto st8; - } - case 32: { - goto st8; - } - case 34: { - goto ctr11; - } - case 45: { - goto ctr11; - } - case 47: { - goto st19; - } - case 73: { - goto ctr11; - } - case 78: { - goto ctr11; - } - case 91: { - goto ctr11; - } - case 102: { - goto ctr11; - } - case 110: { - goto ctr11; - } - case 116: { - goto ctr11; - } - case 123: { - goto ctr11; - } - } - if ( ( (*( p))) > 10 ) { - if ( 48 <= ( (*( p))) && ( (*( p))) <= 57 ) { - goto ctr11; - } - } else if ( ( (*( p))) >= 9 ) { - goto st8; - } - { - goto st0; - } - ctr11: - { - #line 133 "parser.rl" - - VALUE v = Qnil; - char *np = JSON_parse_value(json, p, pe, &v, current_nesting); - if (np == NULL) { - {p = p - 1; } {p+= 1; cs = 9; goto _out;} - } else { - if (NIL_P(json->object_class)) { - OBJ_FREEZE(last_name); - rb_hash_aset(*result, last_name, v); - } else { - rb_funcall(*result, i_aset, 2, last_name, v); - } - {p = (( np))-1;} - - } - } - - goto st9; - st9: - p+= 1; - if ( p == pe ) +case 8: + switch( (*p) ) { + case 13: goto st8; + case 32: goto st8; + case 34: goto tr11; + case 45: goto tr11; + case 47: goto st24; + case 73: goto tr11; + case 78: goto tr11; + case 91: goto tr11; + case 102: goto tr11; + case 110: goto tr11; + case 116: goto tr11; + case 123: goto tr11; + } + if ( (*p) > 10 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr11; + } else if ( (*p) >= 9 ) + goto st8; + goto st0; +tr11: +#line 135 "parser.rl" + { + VALUE v = Qnil; + char *np = JSON_parse_value(json, p, pe, &v, current_nesting); + if (np == NULL) { + p--; {p++; cs = 9; goto _out;} + } else { + if (NIL_P(json->object_class)) { + OBJ_FREEZE(last_name); + rb_hash_aset(*result, last_name, v); + } else { + rb_funcall(*result, i_aset, 2, last_name, v); + } + {p = (( np))-1;} + } + } + goto st9; +st9: + if ( ++p == pe ) goto _test_eof9; - st_case_9: - switch( ( (*( p))) ) { - case 13: { - goto st9; - } - case 32: { - goto st9; - } - case 44: { - goto st10; - } - case 47: { - goto st15; - } - case 125: { - goto ctr4; +case 9: +#line 268 "parser.c" + _widec = (*p); + if ( (*p) < 13 ) { + if ( (*p) > 9 ) { + if ( 10 <= (*p) && (*p) <= 10 ) { + _widec = (short)(128 + ((*p) - -128)); + if ( +#line 133 "parser.rl" + json->allow_trailing_comma ) _widec += 256; + } + } else if ( (*p) >= 9 ) { + _widec = (short)(128 + ((*p) - -128)); + if ( +#line 133 "parser.rl" + json->allow_trailing_comma ) _widec += 256; + } + } else if ( (*p) > 13 ) { + if ( (*p) < 44 ) { + if ( 32 <= (*p) && (*p) <= 32 ) { + _widec = (short)(128 + ((*p) - -128)); + if ( +#line 133 "parser.rl" + json->allow_trailing_comma ) _widec += 256; + } + } else if ( (*p) > 44 ) { + if ( 47 <= (*p) && (*p) <= 47 ) { + _widec = (short)(128 + ((*p) - -128)); + if ( +#line 133 "parser.rl" + json->allow_trailing_comma ) _widec += 256; } + } else { + _widec = (short)(128 + ((*p) - -128)); + if ( +#line 133 "parser.rl" + json->allow_trailing_comma ) _widec += 256; } - if ( 9 <= ( (*( p))) && ( (*( p))) <= 10 ) { + } else { + _widec = (short)(128 + ((*p) - -128)); + if ( +#line 133 "parser.rl" + json->allow_trailing_comma ) _widec += 256; + } + switch( _widec ) { + case 125: goto tr4; + case 269: goto st10; + case 288: goto st10; + case 300: goto st11; + case 303: goto st16; + case 525: goto st9; + case 544: goto st9; + case 556: goto st2; + case 559: goto st20; + } + if ( _widec > 266 ) { + if ( 521 <= _widec && _widec <= 522 ) goto st9; - } - { - goto st0; - } - st10: - p+= 1; - if ( p == pe ) + } else if ( _widec >= 265 ) + goto st10; + goto st0; +tr4: +#line 159 "parser.rl" + { p--; {p++; cs = 32; goto _out;} } + goto st32; +st32: + if ( ++p == pe ) + goto _test_eof32; +case 32: +#line 336 "parser.c" + goto st0; +st10: + if ( ++p == pe ) goto _test_eof10; - st_case_10: - switch( ( (*( p))) ) { - case 13: { - goto st10; - } - case 32: { - goto st10; - } - case 34: { - goto ctr2; - } - case 47: { - goto st11; - } - } - if ( 9 <= ( (*( p))) && ( (*( p))) <= 10 ) { - goto st10; - } - { - goto st0; - } - st11: - p+= 1; - if ( p == pe ) +case 10: + switch( (*p) ) { + case 13: goto st10; + case 32: goto st10; + case 44: goto st11; + case 47: goto st16; + case 125: goto tr4; + } + if ( 9 <= (*p) && (*p) <= 10 ) + goto st10; + goto st0; +st11: + if ( ++p == pe ) goto _test_eof11; - st_case_11: - switch( ( (*( p))) ) { - case 42: { - goto st12; - } - case 47: { - goto st14; - } - } - { - goto st0; - } - st12: - p+= 1; - if ( p == pe ) +case 11: + switch( (*p) ) { + case 13: goto st11; + case 32: goto st11; + case 34: goto tr2; + case 47: goto st12; + } + if ( 9 <= (*p) && (*p) <= 10 ) + goto st11; + goto st0; +st12: + if ( ++p == pe ) goto _test_eof12; - st_case_12: - if ( ( (*( p))) == 42 ) { - goto st13; - } - { - goto st12; - } - st13: - p+= 1; - if ( p == pe ) +case 12: + switch( (*p) ) { + case 42: goto st13; + case 47: goto st15; + } + goto st0; +st13: + if ( ++p == pe ) goto _test_eof13; - st_case_13: - switch( ( (*( p))) ) { - case 42: { - goto st13; - } - case 47: { - goto st10; - } - } - { - goto st12; - } - st14: - p+= 1; - if ( p == pe ) +case 13: + if ( (*p) == 42 ) + goto st14; + goto st13; +st14: + if ( ++p == pe ) goto _test_eof14; - st_case_14: - if ( ( (*( p))) == 10 ) { - goto st10; - } - { - goto st14; - } - st15: - p+= 1; - if ( p == pe ) +case 14: + switch( (*p) ) { + case 42: goto st14; + case 47: goto st11; + } + goto st13; +st15: + if ( ++p == pe ) goto _test_eof15; - st_case_15: - switch( ( (*( p))) ) { - case 42: { - goto st16; - } - case 47: { - goto st18; - } - } - { - goto st0; - } - st16: - p+= 1; - if ( p == pe ) +case 15: + if ( (*p) == 10 ) + goto st11; + goto st15; +st16: + if ( ++p == pe ) goto _test_eof16; - st_case_16: - if ( ( (*( p))) == 42 ) { - goto st17; - } - { - goto st16; - } - st17: - p+= 1; - if ( p == pe ) +case 16: + switch( (*p) ) { + case 42: goto st17; + case 47: goto st19; + } + goto st0; +st17: + if ( ++p == pe ) goto _test_eof17; - st_case_17: - switch( ( (*( p))) ) { - case 42: { - goto st17; - } - case 47: { - goto st9; - } - } - { - goto st16; - } - st18: - p+= 1; - if ( p == pe ) +case 17: + if ( (*p) == 42 ) + goto st18; + goto st17; +st18: + if ( ++p == pe ) goto _test_eof18; - st_case_18: - if ( ( (*( p))) == 10 ) { - goto st9; - } - { - goto st18; - } - ctr4: - { - #line 157 "parser.rl" - {p = p - 1; } {p+= 1; cs = 27; goto _out;} } - - goto st27; - st27: - p+= 1; - if ( p == pe ) - goto _test_eof27; - st_case_27: - { - goto st0; - } - st19: - p+= 1; - if ( p == pe ) +case 18: + switch( (*p) ) { + case 42: goto st18; + case 47: goto st10; + } + goto st17; +st19: + if ( ++p == pe ) goto _test_eof19; - st_case_19: - switch( ( (*( p))) ) { - case 42: { - goto st20; - } - case 47: { - goto st22; - } - } - { - goto st0; - } - st20: - p+= 1; - if ( p == pe ) +case 19: + if ( (*p) == 10 ) + goto st10; + goto st19; +st20: + if ( ++p == pe ) goto _test_eof20; - st_case_20: - if ( ( (*( p))) == 42 ) { - goto st21; - } - { - goto st20; - } - st21: - p+= 1; - if ( p == pe ) +case 20: + _widec = (*p); + if ( (*p) > 42 ) { + if ( 47 <= (*p) && (*p) <= 47 ) { + _widec = (short)(128 + ((*p) - -128)); + if ( +#line 133 "parser.rl" + json->allow_trailing_comma ) _widec += 256; + } + } else if ( (*p) >= 42 ) { + _widec = (short)(128 + ((*p) - -128)); + if ( +#line 133 "parser.rl" + json->allow_trailing_comma ) _widec += 256; + } + switch( _widec ) { + case 298: goto st17; + case 303: goto st19; + case 554: goto st21; + case 559: goto st23; + } + goto st0; +st21: + if ( ++p == pe ) goto _test_eof21; - st_case_21: - switch( ( (*( p))) ) { - case 42: { - goto st21; - } - case 47: { - goto st8; - } - } - { - goto st20; +case 21: + _widec = (*p); + if ( (*p) < 42 ) { + if ( (*p) <= 41 ) { + _widec = (short)(128 + ((*p) - -128)); + if ( +#line 133 "parser.rl" + json->allow_trailing_comma ) _widec += 256; + } + } else if ( (*p) > 42 ) { + if ( 43 <= (*p) ) + { _widec = (short)(128 + ((*p) - -128)); + if ( +#line 133 "parser.rl" + json->allow_trailing_comma ) _widec += 256; } - st22: - p+= 1; - if ( p == pe ) + } else { + _widec = (short)(128 + ((*p) - -128)); + if ( +#line 133 "parser.rl" + json->allow_trailing_comma ) _widec += 256; + } + switch( _widec ) { + case 298: goto st18; + case 554: goto st22; + } + if ( _widec > 383 ) { + if ( 384 <= _widec && _widec <= 639 ) + goto st21; + } else if ( _widec >= 128 ) + goto st17; + goto st0; +st22: + if ( ++p == pe ) goto _test_eof22; - st_case_22: - if ( ( (*( p))) == 10 ) { - goto st8; - } - { - goto st22; - } - st23: - p+= 1; - if ( p == pe ) - goto _test_eof23; - st_case_23: - switch( ( (*( p))) ) { - case 42: { - goto st24; - } - case 47: { - goto st26; +case 22: + _widec = (*p); + if ( (*p) < 43 ) { + if ( (*p) > 41 ) { + if ( 42 <= (*p) && (*p) <= 42 ) { + _widec = (short)(128 + ((*p) - -128)); + if ( +#line 133 "parser.rl" + json->allow_trailing_comma ) _widec += 256; } + } else { + _widec = (short)(128 + ((*p) - -128)); + if ( +#line 133 "parser.rl" + json->allow_trailing_comma ) _widec += 256; + } + } else if ( (*p) > 46 ) { + if ( (*p) > 47 ) { + if ( 48 <= (*p) ) + { _widec = (short)(128 + ((*p) - -128)); + if ( +#line 133 "parser.rl" + json->allow_trailing_comma ) _widec += 256; + } + } else if ( (*p) >= 47 ) { + _widec = (short)(128 + ((*p) - -128)); + if ( +#line 133 "parser.rl" + json->allow_trailing_comma ) _widec += 256; } - { - goto st0; + } else { + _widec = (short)(128 + ((*p) - -128)); + if ( +#line 133 "parser.rl" + json->allow_trailing_comma ) _widec += 256; + } + switch( _widec ) { + case 298: goto st18; + case 303: goto st10; + case 554: goto st22; + case 559: goto st9; + } + if ( _widec > 383 ) { + if ( 384 <= _widec && _widec <= 639 ) + goto st21; + } else if ( _widec >= 128 ) + goto st17; + goto st0; +st23: + if ( ++p == pe ) + goto _test_eof23; +case 23: + _widec = (*p); + if ( (*p) < 10 ) { + if ( (*p) <= 9 ) { + _widec = (short)(128 + ((*p) - -128)); + if ( +#line 133 "parser.rl" + json->allow_trailing_comma ) _widec += 256; + } + } else if ( (*p) > 10 ) { + if ( 11 <= (*p) ) + { _widec = (short)(128 + ((*p) - -128)); + if ( +#line 133 "parser.rl" + json->allow_trailing_comma ) _widec += 256; } - st24: - p+= 1; - if ( p == pe ) + } else { + _widec = (short)(128 + ((*p) - -128)); + if ( +#line 133 "parser.rl" + json->allow_trailing_comma ) _widec += 256; + } + switch( _widec ) { + case 266: goto st10; + case 522: goto st9; + } + if ( _widec > 383 ) { + if ( 384 <= _widec && _widec <= 639 ) + goto st23; + } else if ( _widec >= 128 ) + goto st19; + goto st0; +st24: + if ( ++p == pe ) goto _test_eof24; - st_case_24: - if ( ( (*( p))) == 42 ) { - goto st25; - } - { - goto st24; - } - st25: - p+= 1; - if ( p == pe ) +case 24: + switch( (*p) ) { + case 42: goto st25; + case 47: goto st27; + } + goto st0; +st25: + if ( ++p == pe ) goto _test_eof25; - st_case_25: - switch( ( (*( p))) ) { - case 42: { - goto st25; - } - case 47: { - goto st2; - } - } - { - goto st24; - } - st26: - p+= 1; - if ( p == pe ) +case 25: + if ( (*p) == 42 ) + goto st26; + goto st25; +st26: + if ( ++p == pe ) goto _test_eof26; - st_case_26: - if ( ( (*( p))) == 10 ) { - goto st2; - } - { - goto st26; - } - st_out: - _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_eof10: cs = 10; goto _test_eof; - _test_eof11: cs = 11; goto _test_eof; - _test_eof12: cs = 12; goto _test_eof; - _test_eof13: cs = 13; goto _test_eof; - _test_eof14: cs = 14; goto _test_eof; - _test_eof15: cs = 15; goto _test_eof; - _test_eof16: cs = 16; goto _test_eof; - _test_eof17: cs = 17; goto _test_eof; - _test_eof18: cs = 18; goto _test_eof; - _test_eof27: cs = 27; goto _test_eof; - _test_eof19: cs = 19; goto _test_eof; - _test_eof20: cs = 20; goto _test_eof; - _test_eof21: cs = 21; goto _test_eof; - _test_eof22: cs = 22; goto _test_eof; - _test_eof23: cs = 23; goto _test_eof; - _test_eof24: cs = 24; goto _test_eof; - _test_eof25: cs = 25; goto _test_eof; - _test_eof26: cs = 26; goto _test_eof; - - _test_eof: {} - _out: {} - } - - #line 183 "parser.rl" - - - if (cs >= JSON_object_first_final) { - if (json->create_additions) { - VALUE klassname; - if (NIL_P(json->object_class)) { - klassname = rb_hash_aref(*result, json->create_id); - } else { - klassname = rb_funcall(*result, i_aref, 1, json->create_id); - } - if (!NIL_P(klassname)) { - VALUE klass = rb_funcall(mJSON, i_deep_const_get, 1, klassname); - if (RTEST(rb_funcall(klass, i_json_creatable_p, 0))) { - *result = rb_funcall(klass, i_json_create, 1, *result); - } - } - } - return p + 1; - } else { - return NULL; +case 26: + switch( (*p) ) { + case 42: goto st26; + case 47: goto st8; + } + goto st25; +st27: + if ( ++p == pe ) + goto _test_eof27; +case 27: + if ( (*p) == 10 ) + goto st8; + goto st27; +st28: + if ( ++p == pe ) + goto _test_eof28; +case 28: + switch( (*p) ) { + case 42: goto st29; + case 47: goto st31; + } + goto st0; +st29: + if ( ++p == pe ) + goto _test_eof29; +case 29: + if ( (*p) == 42 ) + goto st30; + goto st29; +st30: + if ( ++p == pe ) + goto _test_eof30; +case 30: + switch( (*p) ) { + case 42: goto st30; + case 47: goto st2; + } + goto st29; +st31: + if ( ++p == pe ) + goto _test_eof31; +case 31: + if ( (*p) == 10 ) + goto st2; + goto st31; + } + _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_eof32: cs = 32; goto _test_eof; + _test_eof10: cs = 10; goto _test_eof; + _test_eof11: cs = 11; goto _test_eof; + _test_eof12: cs = 12; goto _test_eof; + _test_eof13: cs = 13; goto _test_eof; + _test_eof14: cs = 14; goto _test_eof; + _test_eof15: cs = 15; goto _test_eof; + _test_eof16: cs = 16; goto _test_eof; + _test_eof17: cs = 17; goto _test_eof; + _test_eof18: cs = 18; goto _test_eof; + _test_eof19: cs = 19; goto _test_eof; + _test_eof20: cs = 20; goto _test_eof; + _test_eof21: cs = 21; goto _test_eof; + _test_eof22: cs = 22; goto _test_eof; + _test_eof23: cs = 23; goto _test_eof; + _test_eof24: cs = 24; goto _test_eof; + _test_eof25: cs = 25; goto _test_eof; + _test_eof26: cs = 26; goto _test_eof; + _test_eof27: cs = 27; goto _test_eof; + _test_eof28: cs = 28; goto _test_eof; + _test_eof29: cs = 29; goto _test_eof; + _test_eof30: cs = 30; goto _test_eof; + _test_eof31: cs = 31; goto _test_eof; + + _test_eof: {} + _out: {} } + +#line 185 "parser.rl" + + if (cs >= JSON_object_first_final) { + if (json->create_additions) { + VALUE klassname; + if (NIL_P(json->object_class)) { + klassname = rb_hash_aref(*result, json->create_id); + } else { + klassname = rb_funcall(*result, i_aref, 1, json->create_id); + } + if (!NIL_P(klassname)) { + VALUE klass = rb_funcall(mJSON, i_deep_const_get, 1, klassname); + if (RTEST(rb_funcall(klass, i_json_creatable_p, 0))) { + *result = rb_funcall(klass, i_json_create, 1, *result); + } + } + } + return p + 1; + } else { + return NULL; + } } +#line 701 "parser.c" enum {JSON_value_start = 1}; enum {JSON_value_first_final = 29}; enum {JSON_value_error = 0}; enum {JSON_value_en_main = 1}; -static const char MAYBE_UNUSED(_JSON_value_nfa_targs)[] = { - 0, 0 -}; - -static const char MAYBE_UNUSED(_JSON_value_nfa_offsets)[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0 -}; - -static const char MAYBE_UNUSED(_JSON_value_nfa_push_actions)[] = { - 0, 0 -}; - -static const char MAYBE_UNUSED(_JSON_value_nfa_pop_trans)[] = { - 0, 0 -}; - -#line 283 "parser.rl" +#line 285 "parser.rl" static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting) { - int cs = EVIL; + int cs = EVIL; +#line 717 "parser.c" { - cs = (int)JSON_value_start; + cs = JSON_value_start; } - #line 290 "parser.rl" - +#line 292 "parser.rl" +#line 724 "parser.c" { - if ( p == pe ) + if ( p == pe ) goto _test_eof; - switch ( cs ) - { - case 1: - goto st_case_1; - case 0: - goto st_case_0; - case 29: - goto st_case_29; - case 2: - goto st_case_2; - case 3: - goto st_case_3; - case 4: - goto st_case_4; - case 5: - goto st_case_5; - case 6: - goto st_case_6; - case 7: - goto st_case_7; - case 8: - goto st_case_8; - case 9: - goto st_case_9; - case 10: - goto st_case_10; - case 11: - goto st_case_11; - case 12: - goto st_case_12; - case 13: - goto st_case_13; - case 14: - goto st_case_14; - case 15: - goto st_case_15; - case 16: - goto st_case_16; - case 17: - goto st_case_17; - case 18: - goto st_case_18; - case 19: - goto st_case_19; - case 20: - goto st_case_20; - case 21: - goto st_case_21; - case 22: - goto st_case_22; - case 23: - goto st_case_23; - case 24: - goto st_case_24; - case 25: - goto st_case_25; - case 26: - goto st_case_26; - case 27: - goto st_case_27; - case 28: - goto st_case_28; - } - goto st_out; - st1: - p+= 1; - if ( p == pe ) + switch ( cs ) + { +st1: + if ( ++p == pe ) goto _test_eof1; - st_case_1: - switch( ( (*( p))) ) { - case 13: { - goto st1; - } - case 32: { - goto st1; - } - case 34: { - goto ctr2; - } - case 45: { - goto ctr3; - } - case 47: { - goto st6; - } - case 73: { - goto st10; - } - case 78: { - goto st17; - } - case 91: { - goto ctr7; - } - case 102: { - goto st19; - } - case 110: { - goto st23; - } - case 116: { - goto st26; - } - case 123: { - goto ctr11; - } - } - if ( ( (*( p))) > 10 ) { - if ( 48 <= ( (*( p))) && ( (*( p))) <= 57 ) { - goto ctr3; - } - } else if ( ( (*( p))) >= 9 ) { - goto st1; - } - { - goto st0; - } - st_case_0: - st0: - cs = 0; - goto _out; - ctr2: - { - #line 235 "parser.rl" - - char *np = JSON_parse_string(json, p, pe, result); - if (np == NULL) { {p = p - 1; } {p+= 1; cs = 29; goto _out;} } else {p = (( np))-1;} - - } - - goto st29; - ctr3: - { - #line 240 "parser.rl" - - char *np; - if(pe > p + 8 && !strncmp(MinusInfinity, p, 9)) { - if (json->allow_nan) { - *result = CMinusInfinity; - {p = (( p + 10))-1;} - - {p = p - 1; } {p+= 1; cs = 29; goto _out;} - } else { - rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p); - } - } - np = JSON_parse_float(json, p, pe, result); - if (np != NULL) {p = (( np))-1;} - - np = JSON_parse_integer(json, p, pe, result); - if (np != NULL) {p = (( np))-1;} - - {p = p - 1; } {p+= 1; cs = 29; goto _out;} - } - - goto st29; - ctr7: - { - #line 258 "parser.rl" - - char *np; - np = JSON_parse_array(json, p, pe, result, current_nesting + 1); - if (np == NULL) { {p = p - 1; } {p+= 1; cs = 29; goto _out;} } else {p = (( np))-1;} - - } - - goto st29; - ctr11: - { - #line 264 "parser.rl" - - char *np; - np = JSON_parse_object(json, p, pe, result, current_nesting + 1); - if (np == NULL) { {p = p - 1; } {p+= 1; cs = 29; goto _out;} } else {p = (( np))-1;} - - } - - goto st29; - ctr25: - { - #line 228 "parser.rl" - - if (json->allow_nan) { - *result = CInfinity; - } else { - rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p - 8); - } - } - - goto st29; - ctr27: - { - #line 221 "parser.rl" - - if (json->allow_nan) { - *result = CNaN; - } else { - rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p - 2); - } - } - - goto st29; - ctr31: - { - #line 215 "parser.rl" - - *result = Qfalse; - } - - goto st29; - ctr34: - { - #line 212 "parser.rl" - - *result = Qnil; - } - - goto st29; - ctr37: - { - #line 218 "parser.rl" - - *result = Qtrue; - } - - goto st29; - st29: - p+= 1; - if ( p == pe ) +case 1: + switch( (*p) ) { + case 13: goto st1; + case 32: goto st1; + case 34: goto tr2; + case 45: goto tr3; + case 47: goto st6; + case 73: goto st10; + case 78: goto st17; + case 91: goto tr7; + case 102: goto st19; + case 110: goto st23; + case 116: goto st26; + case 123: goto tr11; + } + if ( (*p) > 10 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr3; + } else if ( (*p) >= 9 ) + goto st1; + goto st0; +st0: +cs = 0; + goto _out; +tr2: +#line 237 "parser.rl" + { + char *np = JSON_parse_string(json, p, pe, result); + if (np == NULL) { p--; {p++; cs = 29; goto _out;} } else {p = (( np))-1;} + } + goto st29; +tr3: +#line 242 "parser.rl" + { + char *np; + if(pe > p + 8 && !strncmp(MinusInfinity, p, 9)) { + if (json->allow_nan) { + *result = CMinusInfinity; + {p = (( p + 10))-1;} + p--; {p++; cs = 29; goto _out;} + } else { + rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p); + } + } + np = JSON_parse_float(json, p, pe, result); + if (np != NULL) {p = (( np))-1;} + np = JSON_parse_integer(json, p, pe, result); + if (np != NULL) {p = (( np))-1;} + p--; {p++; cs = 29; goto _out;} + } + goto st29; +tr7: +#line 260 "parser.rl" + { + char *np; + np = JSON_parse_array(json, p, pe, result, current_nesting + 1); + if (np == NULL) { p--; {p++; cs = 29; goto _out;} } else {p = (( np))-1;} + } + goto st29; +tr11: +#line 266 "parser.rl" + { + char *np; + np = JSON_parse_object(json, p, pe, result, current_nesting + 1); + if (np == NULL) { p--; {p++; cs = 29; goto _out;} } else {p = (( np))-1;} + } + goto st29; +tr25: +#line 230 "parser.rl" + { + if (json->allow_nan) { + *result = CInfinity; + } else { + rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p - 8); + } + } + goto st29; +tr27: +#line 223 "parser.rl" + { + if (json->allow_nan) { + *result = CNaN; + } else { + rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p - 2); + } + } + goto st29; +tr31: +#line 217 "parser.rl" + { + *result = Qfalse; + } + goto st29; +tr34: +#line 214 "parser.rl" + { + *result = Qnil; + } + goto st29; +tr37: +#line 220 "parser.rl" + { + *result = Qtrue; + } + goto st29; +st29: + if ( ++p == pe ) goto _test_eof29; - st_case_29: - { - #line 270 "parser.rl" - {p = p - 1; } {p+= 1; cs = 29; goto _out;} } - switch( ( (*( p))) ) { - case 13: { - goto st29; - } - case 32: { - goto st29; - } - case 47: { - goto st2; - } - } - if ( 9 <= ( (*( p))) && ( (*( p))) <= 10 ) { - goto st29; - } - { - goto st0; - } - st2: - p+= 1; - if ( p == pe ) +case 29: +#line 272 "parser.rl" + { p--; {p++; cs = 29; goto _out;} } +#line 844 "parser.c" + switch( (*p) ) { + case 13: goto st29; + case 32: goto st29; + case 47: goto st2; + } + if ( 9 <= (*p) && (*p) <= 10 ) + goto st29; + goto st0; +st2: + if ( ++p == pe ) goto _test_eof2; - st_case_2: - switch( ( (*( p))) ) { - case 42: { - goto st3; - } - case 47: { - goto st5; - } - } - { - goto st0; - } - st3: - p+= 1; - if ( p == pe ) +case 2: + switch( (*p) ) { + case 42: goto st3; + case 47: goto st5; + } + goto st0; +st3: + if ( ++p == pe ) goto _test_eof3; - st_case_3: - if ( ( (*( p))) == 42 ) { - goto st4; - } - { - goto st3; - } - st4: - p+= 1; - if ( p == pe ) +case 3: + if ( (*p) == 42 ) + goto st4; + goto st3; +st4: + if ( ++p == pe ) goto _test_eof4; - st_case_4: - switch( ( (*( p))) ) { - case 42: { - goto st4; - } - case 47: { - goto st29; - } - } - { - goto st3; - } - st5: - p+= 1; - if ( p == pe ) +case 4: + switch( (*p) ) { + case 42: goto st4; + case 47: goto st29; + } + goto st3; +st5: + if ( ++p == pe ) goto _test_eof5; - st_case_5: - if ( ( (*( p))) == 10 ) { - goto st29; - } - { - goto st5; - } - st6: - p+= 1; - if ( p == pe ) +case 5: + if ( (*p) == 10 ) + goto st29; + goto st5; +st6: + if ( ++p == pe ) goto _test_eof6; - st_case_6: - switch( ( (*( p))) ) { - case 42: { - goto st7; - } - case 47: { - goto st9; - } - } - { - goto st0; - } - st7: - p+= 1; - if ( p == pe ) +case 6: + switch( (*p) ) { + case 42: goto st7; + case 47: goto st9; + } + goto st0; +st7: + if ( ++p == pe ) goto _test_eof7; - st_case_7: - if ( ( (*( p))) == 42 ) { - goto st8; - } - { - goto st7; - } - st8: - p+= 1; - if ( p == pe ) +case 7: + if ( (*p) == 42 ) + goto st8; + goto st7; +st8: + if ( ++p == pe ) goto _test_eof8; - st_case_8: - switch( ( (*( p))) ) { - case 42: { - goto st8; - } - case 47: { - goto st1; - } - } - { - goto st7; - } - st9: - p+= 1; - if ( p == pe ) +case 8: + switch( (*p) ) { + case 42: goto st8; + case 47: goto st1; + } + goto st7; +st9: + if ( ++p == pe ) goto _test_eof9; - st_case_9: - if ( ( (*( p))) == 10 ) { - goto st1; - } - { - goto st9; - } - st10: - p+= 1; - if ( p == pe ) +case 9: + if ( (*p) == 10 ) + goto st1; + goto st9; +st10: + if ( ++p == pe ) goto _test_eof10; - st_case_10: - if ( ( (*( p))) == 110 ) { - goto st11; - } - { - goto st0; - } - st11: - p+= 1; - if ( p == pe ) +case 10: + if ( (*p) == 110 ) + goto st11; + goto st0; +st11: + if ( ++p == pe ) goto _test_eof11; - st_case_11: - if ( ( (*( p))) == 102 ) { - goto st12; - } - { - goto st0; - } - st12: - p+= 1; - if ( p == pe ) +case 11: + if ( (*p) == 102 ) + goto st12; + goto st0; +st12: + if ( ++p == pe ) goto _test_eof12; - st_case_12: - if ( ( (*( p))) == 105 ) { - goto st13; - } - { - goto st0; - } - st13: - p+= 1; - if ( p == pe ) +case 12: + if ( (*p) == 105 ) + goto st13; + goto st0; +st13: + if ( ++p == pe ) goto _test_eof13; - st_case_13: - if ( ( (*( p))) == 110 ) { - goto st14; - } - { - goto st0; - } - st14: - p+= 1; - if ( p == pe ) +case 13: + if ( (*p) == 110 ) + goto st14; + goto st0; +st14: + if ( ++p == pe ) goto _test_eof14; - st_case_14: - if ( ( (*( p))) == 105 ) { - goto st15; - } - { - goto st0; - } - st15: - p+= 1; - if ( p == pe ) +case 14: + if ( (*p) == 105 ) + goto st15; + goto st0; +st15: + if ( ++p == pe ) goto _test_eof15; - st_case_15: - if ( ( (*( p))) == 116 ) { - goto st16; - } - { - goto st0; - } - st16: - p+= 1; - if ( p == pe ) +case 15: + if ( (*p) == 116 ) + goto st16; + goto st0; +st16: + if ( ++p == pe ) goto _test_eof16; - st_case_16: - if ( ( (*( p))) == 121 ) { - goto ctr25; - } - { - goto st0; - } - st17: - p+= 1; - if ( p == pe ) +case 16: + if ( (*p) == 121 ) + goto tr25; + goto st0; +st17: + if ( ++p == pe ) goto _test_eof17; - st_case_17: - if ( ( (*( p))) == 97 ) { - goto st18; - } - { - goto st0; - } - st18: - p+= 1; - if ( p == pe ) +case 17: + if ( (*p) == 97 ) + goto st18; + goto st0; +st18: + if ( ++p == pe ) goto _test_eof18; - st_case_18: - if ( ( (*( p))) == 78 ) { - goto ctr27; - } - { - goto st0; - } - st19: - p+= 1; - if ( p == pe ) +case 18: + if ( (*p) == 78 ) + goto tr27; + goto st0; +st19: + if ( ++p == pe ) goto _test_eof19; - st_case_19: - if ( ( (*( p))) == 97 ) { - goto st20; - } - { - goto st0; - } - st20: - p+= 1; - if ( p == pe ) +case 19: + if ( (*p) == 97 ) + goto st20; + goto st0; +st20: + if ( ++p == pe ) goto _test_eof20; - st_case_20: - if ( ( (*( p))) == 108 ) { - goto st21; - } - { - goto st0; - } - st21: - p+= 1; - if ( p == pe ) +case 20: + if ( (*p) == 108 ) + goto st21; + goto st0; +st21: + if ( ++p == pe ) goto _test_eof21; - st_case_21: - if ( ( (*( p))) == 115 ) { - goto st22; - } - { - goto st0; - } - st22: - p+= 1; - if ( p == pe ) +case 21: + if ( (*p) == 115 ) + goto st22; + goto st0; +st22: + if ( ++p == pe ) goto _test_eof22; - st_case_22: - if ( ( (*( p))) == 101 ) { - goto ctr31; - } - { - goto st0; - } - st23: - p+= 1; - if ( p == pe ) +case 22: + if ( (*p) == 101 ) + goto tr31; + goto st0; +st23: + if ( ++p == pe ) goto _test_eof23; - st_case_23: - if ( ( (*( p))) == 117 ) { - goto st24; - } - { - goto st0; - } - st24: - p+= 1; - if ( p == pe ) +case 23: + if ( (*p) == 117 ) + goto st24; + goto st0; +st24: + if ( ++p == pe ) goto _test_eof24; - st_case_24: - if ( ( (*( p))) == 108 ) { - goto st25; - } - { - goto st0; - } - st25: - p+= 1; - if ( p == pe ) +case 24: + if ( (*p) == 108 ) + goto st25; + goto st0; +st25: + if ( ++p == pe ) goto _test_eof25; - st_case_25: - if ( ( (*( p))) == 108 ) { - goto ctr34; - } - { - goto st0; - } - st26: - p+= 1; - if ( p == pe ) +case 25: + if ( (*p) == 108 ) + goto tr34; + goto st0; +st26: + if ( ++p == pe ) goto _test_eof26; - st_case_26: - if ( ( (*( p))) == 114 ) { - goto st27; - } - { - goto st0; - } - st27: - p+= 1; - if ( p == pe ) +case 26: + if ( (*p) == 114 ) + goto st27; + goto st0; +st27: + if ( ++p == pe ) goto _test_eof27; - st_case_27: - if ( ( (*( p))) == 117 ) { - goto st28; - } - { - goto st0; - } - st28: - p+= 1; - if ( p == pe ) +case 27: + if ( (*p) == 117 ) + goto st28; + goto st0; +st28: + if ( ++p == pe ) goto _test_eof28; - st_case_28: - if ( ( (*( p))) == 101 ) { - goto ctr37; - } - { - goto st0; - } - st_out: - _test_eof1: cs = 1; goto _test_eof; - _test_eof29: cs = 29; 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_eof10: cs = 10; goto _test_eof; - _test_eof11: cs = 11; goto _test_eof; - _test_eof12: cs = 12; goto _test_eof; - _test_eof13: cs = 13; goto _test_eof; - _test_eof14: cs = 14; goto _test_eof; - _test_eof15: cs = 15; goto _test_eof; - _test_eof16: cs = 16; goto _test_eof; - _test_eof17: cs = 17; goto _test_eof; - _test_eof18: cs = 18; goto _test_eof; - _test_eof19: cs = 19; goto _test_eof; - _test_eof20: cs = 20; goto _test_eof; - _test_eof21: cs = 21; goto _test_eof; - _test_eof22: cs = 22; goto _test_eof; - _test_eof23: cs = 23; goto _test_eof; - _test_eof24: cs = 24; goto _test_eof; - _test_eof25: cs = 25; goto _test_eof; - _test_eof26: cs = 26; goto _test_eof; - _test_eof27: cs = 27; goto _test_eof; - _test_eof28: cs = 28; goto _test_eof; - - _test_eof: {} - _out: {} - } - - #line 291 "parser.rl" - - - if (json->freeze) { - OBJ_FREEZE(*result); - } - - if (cs >= JSON_value_first_final) { - return p; - } else { - return NULL; +case 28: + if ( (*p) == 101 ) + goto tr37; + goto st0; + } + _test_eof1: cs = 1; goto _test_eof; + _test_eof29: cs = 29; 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_eof10: cs = 10; goto _test_eof; + _test_eof11: cs = 11; goto _test_eof; + _test_eof12: cs = 12; goto _test_eof; + _test_eof13: cs = 13; goto _test_eof; + _test_eof14: cs = 14; goto _test_eof; + _test_eof15: cs = 15; goto _test_eof; + _test_eof16: cs = 16; goto _test_eof; + _test_eof17: cs = 17; goto _test_eof; + _test_eof18: cs = 18; goto _test_eof; + _test_eof19: cs = 19; goto _test_eof; + _test_eof20: cs = 20; goto _test_eof; + _test_eof21: cs = 21; goto _test_eof; + _test_eof22: cs = 22; goto _test_eof; + _test_eof23: cs = 23; goto _test_eof; + _test_eof24: cs = 24; goto _test_eof; + _test_eof25: cs = 25; goto _test_eof; + _test_eof26: cs = 26; goto _test_eof; + _test_eof27: cs = 27; goto _test_eof; + _test_eof28: cs = 28; goto _test_eof; + + _test_eof: {} + _out: {} } + +#line 293 "parser.rl" + + if (json->freeze) { + OBJ_FREEZE(*result); + } + + if (cs >= JSON_value_first_final) { + return p; + } else { + return NULL; + } } +#line 1099 "parser.c" enum {JSON_integer_start = 1}; enum {JSON_integer_first_final = 3}; enum {JSON_integer_error = 0}; enum {JSON_integer_en_main = 1}; -static const char MAYBE_UNUSED(_JSON_integer_nfa_targs)[] = { - 0, 0 -}; - -static const char MAYBE_UNUSED(_JSON_integer_nfa_offsets)[] = { - 0, 0, 0, 0, 0, 0, 0 -}; - -static const char MAYBE_UNUSED(_JSON_integer_nfa_push_actions)[] = { - 0, 0 -}; - -static const char MAYBE_UNUSED(_JSON_integer_nfa_pop_trans)[] = { - 0, 0 -}; - -#line 311 "parser.rl" +#line 313 "parser.rl" static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *result) { - int cs = EVIL; + int cs = EVIL; +#line 1115 "parser.c" { - cs = (int)JSON_integer_start; + cs = JSON_integer_start; } - #line 318 "parser.rl" - - json->memo = p; +#line 320 "parser.rl" + json->memo = p; +#line 1123 "parser.c" { - if ( p == pe ) + if ( p == pe ) goto _test_eof; - switch ( cs ) - { - case 1: - goto st_case_1; - case 0: - goto st_case_0; - case 2: - goto st_case_2; - case 3: - goto st_case_3; - case 4: - goto st_case_4; - case 5: - goto st_case_5; - } - goto st_out; - st_case_1: - switch( ( (*( p))) ) { - case 45: { - goto st2; - } - case 48: { - goto st3; - } - } - if ( 49 <= ( (*( p))) && ( (*( p))) <= 57 ) { - goto st5; - } - { - goto st0; - } - st_case_0: - st0: - cs = 0; - goto _out; - st2: - p+= 1; - if ( p == pe ) + switch ( cs ) + { +case 1: + switch( (*p) ) { + case 45: goto st2; + case 48: goto st3; + } + if ( 49 <= (*p) && (*p) <= 57 ) + goto st5; + goto st0; +st0: +cs = 0; + goto _out; +st2: + if ( ++p == pe ) goto _test_eof2; - st_case_2: - if ( ( (*( p))) == 48 ) { - goto st3; - } - if ( 49 <= ( (*( p))) && ( (*( p))) <= 57 ) { - goto st5; - } - { - goto st0; - } - st3: - p+= 1; - if ( p == pe ) +case 2: + if ( (*p) == 48 ) + goto st3; + if ( 49 <= (*p) && (*p) <= 57 ) + goto st5; + goto st0; +st3: + if ( ++p == pe ) goto _test_eof3; - st_case_3: - if ( 48 <= ( (*( p))) && ( (*( p))) <= 57 ) { - goto st0; - } - { - goto ctr4; - } - ctr4: - { - #line 308 "parser.rl" - {p = p - 1; } {p+= 1; cs = 4; goto _out;} } - - goto st4; - st4: - p+= 1; - if ( p == pe ) +case 3: + if ( 48 <= (*p) && (*p) <= 57 ) + goto st0; + goto tr4; +tr4: +#line 310 "parser.rl" + { p--; {p++; cs = 4; goto _out;} } + goto st4; +st4: + if ( ++p == pe ) goto _test_eof4; - st_case_4: - { - goto st0; - } - st5: - p+= 1; - if ( p == pe ) +case 4: +#line 1164 "parser.c" + goto st0; +st5: + if ( ++p == pe ) goto _test_eof5; - st_case_5: - if ( 48 <= ( (*( p))) && ( (*( p))) <= 57 ) { - goto st5; - } - { - goto ctr4; - } - st_out: - _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_eof: {} - _out: {} +case 5: + if ( 48 <= (*p) && (*p) <= 57 ) + goto st5; + goto tr4; } + _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; - #line 320 "parser.rl" - - - if (cs >= JSON_integer_first_final) { - long len = p - json->memo; - fbuffer_clear(json->fbuffer); - fbuffer_append(json->fbuffer, json->memo, len); - fbuffer_append_char(json->fbuffer, '\0'); - *result = rb_cstr2inum(FBUFFER_PTR(json->fbuffer), 10); - return p + 1; - } else { - return NULL; + _test_eof: {} + _out: {} } + +#line 322 "parser.rl" + + if (cs >= JSON_integer_first_final) { + long len = p - json->memo; + fbuffer_clear(json->fbuffer); + fbuffer_append(json->fbuffer, json->memo, len); + fbuffer_append_char(json->fbuffer, '\0'); + *result = rb_cstr2inum(FBUFFER_PTR(json->fbuffer), 10); + return p + 1; + } else { + return NULL; + } } +#line 1198 "parser.c" enum {JSON_float_start = 1}; enum {JSON_float_first_final = 8}; enum {JSON_float_error = 0}; enum {JSON_float_en_main = 1}; -static const char MAYBE_UNUSED(_JSON_float_nfa_targs)[] = { - 0, 0 -}; - -static const char MAYBE_UNUSED(_JSON_float_nfa_offsets)[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0 -}; - -static const char MAYBE_UNUSED(_JSON_float_nfa_push_actions)[] = { - 0, 0 -}; - -static const char MAYBE_UNUSED(_JSON_float_nfa_pop_trans)[] = { - 0, 0 -}; - -#line 345 "parser.rl" +#line 347 "parser.rl" static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *result) { - int cs = EVIL; + int cs = EVIL; +#line 1214 "parser.c" { - cs = (int)JSON_float_start; + cs = JSON_float_start; } - #line 352 "parser.rl" - - json->memo = p; +#line 354 "parser.rl" + json->memo = p; +#line 1222 "parser.c" { - if ( p == pe ) + if ( p == pe ) goto _test_eof; - switch ( cs ) - { - case 1: - goto st_case_1; - case 0: - goto st_case_0; - case 2: - goto st_case_2; - case 3: - goto st_case_3; - case 4: - goto st_case_4; - case 8: - goto st_case_8; - case 9: - goto st_case_9; - case 5: - goto st_case_5; - case 6: - goto st_case_6; - case 10: - goto st_case_10; - case 7: - goto st_case_7; - } - goto st_out; - st_case_1: - switch( ( (*( p))) ) { - case 45: { - goto st2; - } - case 48: { - goto st3; - } - } - if ( 49 <= ( (*( p))) && ( (*( p))) <= 57 ) { - goto st7; - } - { - goto st0; - } - st_case_0: - st0: - cs = 0; - goto _out; - st2: - p+= 1; - if ( p == pe ) + switch ( cs ) + { +case 1: + switch( (*p) ) { + case 45: goto st2; + case 48: goto st3; + } + if ( 49 <= (*p) && (*p) <= 57 ) + goto st7; + goto st0; +st0: +cs = 0; + goto _out; +st2: + if ( ++p == pe ) goto _test_eof2; - st_case_2: - if ( ( (*( p))) == 48 ) { - goto st3; - } - if ( 49 <= ( (*( p))) && ( (*( p))) <= 57 ) { - goto st7; - } - { - goto st0; - } - st3: - p+= 1; - if ( p == pe ) +case 2: + if ( (*p) == 48 ) + goto st3; + if ( 49 <= (*p) && (*p) <= 57 ) + goto st7; + goto st0; +st3: + if ( ++p == pe ) goto _test_eof3; - st_case_3: - switch( ( (*( p))) ) { - case 46: { - goto st4; - } - case 69: { - goto st5; - } - case 101: { - goto st5; - } - } - { - goto st0; - } - st4: - p+= 1; - if ( p == pe ) +case 3: + switch( (*p) ) { + case 46: goto st4; + case 69: goto st5; + case 101: goto st5; + } + goto st0; +st4: + if ( ++p == pe ) goto _test_eof4; - st_case_4: - if ( 48 <= ( (*( p))) && ( (*( p))) <= 57 ) { - goto st8; - } - { - goto st0; - } - st8: - p+= 1; - if ( p == pe ) +case 4: + if ( 48 <= (*p) && (*p) <= 57 ) + goto st8; + goto st0; +st8: + if ( ++p == pe ) goto _test_eof8; - st_case_8: - switch( ( (*( p))) ) { - case 69: { - goto st5; - } - case 101: { - goto st5; - } - } - if ( ( (*( p))) > 46 ) { - if ( 48 <= ( (*( p))) && ( (*( p))) <= 57 ) { - goto st8; - } - } else if ( ( (*( p))) >= 45 ) { - goto st0; - } - { - goto ctr9; - } - ctr9: - { - #line 339 "parser.rl" - {p = p - 1; } {p+= 1; cs = 9; goto _out;} } - - goto st9; - st9: - p+= 1; - if ( p == pe ) +case 8: + switch( (*p) ) { + case 69: goto st5; + case 101: goto st5; + } + if ( (*p) > 46 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto st8; + } else if ( (*p) >= 45 ) + goto st0; + goto tr9; +tr9: +#line 341 "parser.rl" + { p--; {p++; cs = 9; goto _out;} } + goto st9; +st9: + if ( ++p == pe ) goto _test_eof9; - st_case_9: - { - goto st0; - } - st5: - p+= 1; - if ( p == pe ) +case 9: +#line 1287 "parser.c" + goto st0; +st5: + if ( ++p == pe ) goto _test_eof5; - st_case_5: - switch( ( (*( p))) ) { - case 43: { - goto st6; - } - case 45: { - goto st6; - } - } - if ( 48 <= ( (*( p))) && ( (*( p))) <= 57 ) { - goto st10; - } - { - goto st0; - } - st6: - p+= 1; - if ( p == pe ) +case 5: + switch( (*p) ) { + case 43: goto st6; + case 45: goto st6; + } + if ( 48 <= (*p) && (*p) <= 57 ) + goto st10; + goto st0; +st6: + if ( ++p == pe ) goto _test_eof6; - st_case_6: - if ( 48 <= ( (*( p))) && ( (*( p))) <= 57 ) { - goto st10; - } - { - goto st0; - } - st10: - p+= 1; - if ( p == pe ) +case 6: + if ( 48 <= (*p) && (*p) <= 57 ) + goto st10; + goto st0; +st10: + if ( ++p == pe ) goto _test_eof10; - st_case_10: - switch( ( (*( p))) ) { - case 69: { - goto st0; - } - case 101: { - goto st0; - } - } - if ( ( (*( p))) > 46 ) { - if ( 48 <= ( (*( p))) && ( (*( p))) <= 57 ) { - goto st10; - } - } else if ( ( (*( p))) >= 45 ) { - goto st0; - } - { - goto ctr9; - } - st7: - p+= 1; - if ( p == pe ) +case 10: + switch( (*p) ) { + case 69: goto st0; + case 101: goto st0; + } + if ( (*p) > 46 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto st10; + } else if ( (*p) >= 45 ) + goto st0; + goto tr9; +st7: + if ( ++p == pe ) goto _test_eof7; - st_case_7: - switch( ( (*( p))) ) { - case 46: { - goto st4; - } - case 69: { - goto st5; - } - case 101: { - goto st5; - } - } - if ( 48 <= ( (*( p))) && ( (*( p))) <= 57 ) { - goto st7; - } - { - goto st0; - } - st_out: - _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_eof6: cs = 6; goto _test_eof; - _test_eof10: cs = 10; goto _test_eof; - _test_eof7: cs = 7; goto _test_eof; - - _test_eof: {} - _out: {} - } - - #line 354 "parser.rl" - - - if (cs >= JSON_float_first_final) { - VALUE mod = Qnil; - ID method_id = 0; - if (rb_respond_to(json->decimal_class, i_try_convert)) { - mod = json->decimal_class; - method_id = i_try_convert; - } else if (rb_respond_to(json->decimal_class, i_new)) { - mod = json->decimal_class; - method_id = i_new; - } else if (RB_TYPE_P(json->decimal_class, T_CLASS)) { - VALUE name = rb_class_name(json->decimal_class); - const char *name_cstr = RSTRING_PTR(name); - const char *last_colon = strrchr(name_cstr, ':'); - if (last_colon) { - const char *mod_path_end = last_colon - 1; - VALUE mod_path = rb_str_substr(name, 0, mod_path_end - name_cstr); - mod = rb_path_to_class(mod_path); - - const char *method_name_beg = last_colon + 1; - long before_len = method_name_beg - name_cstr; - long len = RSTRING_LEN(name) - before_len; - VALUE method_name = rb_str_substr(name, before_len, len); - method_id = SYM2ID(rb_str_intern(method_name)); - } else { - mod = rb_mKernel; - method_id = SYM2ID(rb_str_intern(name)); - } - } - - long len = p - json->memo; - fbuffer_clear(json->fbuffer); - fbuffer_append(json->fbuffer, json->memo, len); - fbuffer_append_char(json->fbuffer, '\0'); - - if (method_id) { - VALUE text = rb_str_new2(FBUFFER_PTR(json->fbuffer)); - *result = rb_funcallv(mod, method_id, 1, &text); - } else { - *result = DBL2NUM(rb_cstr_to_dbl(FBUFFER_PTR(json->fbuffer), 1)); - } - - return p + 1; - } else { - return NULL; +case 7: + switch( (*p) ) { + case 46: goto st4; + case 69: goto st5; + case 101: goto st5; + } + if ( 48 <= (*p) && (*p) <= 57 ) + 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_eof6: cs = 6; goto _test_eof; + _test_eof10: cs = 10; goto _test_eof; + _test_eof7: cs = 7; goto _test_eof; + + _test_eof: {} + _out: {} } + +#line 356 "parser.rl" + + if (cs >= JSON_float_first_final) { + VALUE mod = Qnil; + ID method_id = 0; + if (rb_respond_to(json->decimal_class, i_try_convert)) { + mod = json->decimal_class; + method_id = i_try_convert; + } else if (rb_respond_to(json->decimal_class, i_new)) { + mod = json->decimal_class; + method_id = i_new; + } else if (RB_TYPE_P(json->decimal_class, T_CLASS)) { + VALUE name = rb_class_name(json->decimal_class); + const char *name_cstr = RSTRING_PTR(name); + const char *last_colon = strrchr(name_cstr, ':'); + if (last_colon) { + const char *mod_path_end = last_colon - 1; + VALUE mod_path = rb_str_substr(name, 0, mod_path_end - name_cstr); + mod = rb_path_to_class(mod_path); + + const char *method_name_beg = last_colon + 1; + long before_len = method_name_beg - name_cstr; + long len = RSTRING_LEN(name) - before_len; + VALUE method_name = rb_str_substr(name, before_len, len); + method_id = SYM2ID(rb_str_intern(method_name)); + } else { + mod = rb_mKernel; + method_id = SYM2ID(rb_str_intern(name)); + } + } + + long len = p - json->memo; + fbuffer_clear(json->fbuffer); + fbuffer_append(json->fbuffer, json->memo, len); + fbuffer_append_char(json->fbuffer, '\0'); + + if (method_id) { + VALUE text = rb_str_new2(FBUFFER_PTR(json->fbuffer)); + *result = rb_funcallv(mod, method_id, 1, &text); + } else { + *result = DBL2NUM(rb_cstr_to_dbl(FBUFFER_PTR(json->fbuffer), 1)); + } + + return p + 1; + } else { + return NULL; + } } +#line 1399 "parser.c" enum {JSON_array_start = 1}; -enum {JSON_array_first_final = 17}; +enum {JSON_array_first_final = 22}; enum {JSON_array_error = 0}; enum {JSON_array_en_main = 1}; -static const char MAYBE_UNUSED(_JSON_array_nfa_targs)[] = { - 0, 0 -}; - -static const char MAYBE_UNUSED(_JSON_array_nfa_offsets)[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0 -}; - -static const char MAYBE_UNUSED(_JSON_array_nfa_push_actions)[] = { - 0, 0 -}; - -static const char MAYBE_UNUSED(_JSON_array_nfa_pop_trans)[] = { - 0, 0 -}; - -#line 432 "parser.rl" +#line 436 "parser.rl" static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting) { - int cs = EVIL; - VALUE array_class = json->array_class; + int cs = EVIL; + VALUE array_class = json->array_class; - if (json->max_nesting && current_nesting > json->max_nesting) { - rb_raise(eNestingError, "nesting of %d is too deep", current_nesting); - } - *result = NIL_P(array_class) ? rb_ary_new() : rb_class_new_instance(0, 0, array_class); + if (json->max_nesting && current_nesting > json->max_nesting) { + rb_raise(eNestingError, "nesting of %d is too deep", current_nesting); + } + *result = NIL_P(array_class) ? rb_ary_new() : rb_class_new_instance(0, 0, array_class); +#line 1421 "parser.c" { - cs = (int)JSON_array_start; + cs = JSON_array_start; } - #line 445 "parser.rl" - +#line 449 "parser.rl" +#line 1428 "parser.c" { - if ( p == pe ) + short _widec; + if ( p == pe ) goto _test_eof; - switch ( cs ) - { - case 1: - goto st_case_1; - case 0: - goto st_case_0; - case 2: - goto st_case_2; - case 3: - goto st_case_3; - case 4: - goto st_case_4; - case 5: - goto st_case_5; - case 6: - goto st_case_6; - case 7: - goto st_case_7; - case 8: - goto st_case_8; - case 9: - goto st_case_9; - case 10: - goto st_case_10; - case 11: - goto st_case_11; - case 12: - goto st_case_12; - case 17: - goto st_case_17; - case 13: - goto st_case_13; - case 14: - goto st_case_14; - case 15: - goto st_case_15; - case 16: - goto st_case_16; - } - goto st_out; - st_case_1: - if ( ( (*( p))) == 91 ) { - goto st2; - } - { - goto st0; - } - st_case_0: - st0: - cs = 0; - goto _out; - st2: - p+= 1; - if ( p == pe ) + switch ( cs ) + { +case 1: + if ( (*p) == 91 ) + goto st2; + goto st0; +st0: +cs = 0; + goto _out; +st2: + if ( ++p == pe ) goto _test_eof2; - st_case_2: - switch( ( (*( p))) ) { - case 13: { - goto st2; - } - case 32: { - goto st2; - } - case 34: { - goto ctr2; - } - case 45: { - goto ctr2; - } - case 47: { - goto st13; - } - case 73: { - goto ctr2; - } - case 78: { - goto ctr2; - } - case 91: { - goto ctr2; - } - case 93: { - goto ctr4; - } - case 102: { - goto ctr2; - } - case 110: { - goto ctr2; - } - case 116: { - goto ctr2; - } - case 123: { - goto ctr2; - } - } - if ( ( (*( p))) > 10 ) { - if ( 48 <= ( (*( p))) && ( (*( p))) <= 57 ) { - goto ctr2; - } - } else if ( ( (*( p))) >= 9 ) { - goto st2; - } - { - goto st0; - } - ctr2: - { - #line 409 "parser.rl" - - VALUE v = Qnil; - char *np = JSON_parse_value(json, p, pe, &v, current_nesting); - if (np == NULL) { - {p = p - 1; } {p+= 1; cs = 3; goto _out;} - } else { - if (NIL_P(json->array_class)) { - rb_ary_push(*result, v); - } else { - rb_funcall(*result, i_leftshift, 1, v); - } - {p = (( np))-1;} - - } - } - - goto st3; - st3: - p+= 1; - if ( p == pe ) +case 2: + switch( (*p) ) { + case 13: goto st2; + case 32: goto st2; + case 34: goto tr2; + case 45: goto tr2; + case 47: goto st18; + case 73: goto tr2; + case 78: goto tr2; + case 91: goto tr2; + case 93: goto tr4; + 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 st2; + goto st0; +tr2: +#line 413 "parser.rl" + { + VALUE v = Qnil; + char *np = JSON_parse_value(json, p, pe, &v, current_nesting); + if (np == NULL) { + p--; {p++; cs = 3; goto _out;} + } else { + if (NIL_P(json->array_class)) { + rb_ary_push(*result, v); + } else { + rb_funcall(*result, i_leftshift, 1, v); + } + {p = (( np))-1;} + } + } + goto st3; +st3: + if ( ++p == pe ) goto _test_eof3; - st_case_3: - switch( ( (*( p))) ) { - case 13: { - goto st3; - } - case 32: { - goto st3; - } - case 44: { - goto st4; - } - case 47: { - goto st9; - } - case 93: { - goto ctr4; - } - } - if ( 9 <= ( (*( p))) && ( (*( p))) <= 10 ) { - goto st3; - } - { - goto st0; - } - st4: - p+= 1; - if ( p == pe ) +case 3: +#line 1488 "parser.c" + _widec = (*p); + if ( 44 <= (*p) && (*p) <= 44 ) { + _widec = (short)(128 + ((*p) - -128)); + if ( +#line 411 "parser.rl" + json->allow_trailing_comma ) _widec += 256; + } + switch( _widec ) { + case 13: goto st3; + case 32: goto st3; + case 47: goto st4; + case 93: goto tr4; + case 300: goto st8; + case 556: goto st13; + } + if ( 9 <= _widec && _widec <= 10 ) + goto st3; + goto st0; +st4: + if ( ++p == pe ) goto _test_eof4; - st_case_4: - switch( ( (*( p))) ) { - case 13: { - goto st4; - } - case 32: { - goto st4; - } - case 34: { - goto ctr2; - } - case 45: { - goto ctr2; - } - case 47: { - goto st5; - } - case 73: { - goto ctr2; - } - case 78: { - goto ctr2; - } - case 91: { - goto ctr2; - } - case 102: { - goto ctr2; - } - case 110: { - goto ctr2; - } - case 116: { - goto ctr2; - } - case 123: { - goto ctr2; - } - } - if ( ( (*( p))) > 10 ) { - if ( 48 <= ( (*( p))) && ( (*( p))) <= 57 ) { - goto ctr2; - } - } else if ( ( (*( p))) >= 9 ) { - goto st4; - } - { - goto st0; - } - st5: - p+= 1; - if ( p == pe ) +case 4: + switch( (*p) ) { + case 42: goto st5; + case 47: goto st7; + } + goto st0; +st5: + if ( ++p == pe ) goto _test_eof5; - st_case_5: - switch( ( (*( p))) ) { - case 42: { - goto st6; - } - case 47: { - goto st8; - } - } - { - goto st0; - } - st6: - p+= 1; - if ( p == pe ) +case 5: + if ( (*p) == 42 ) + goto st6; + goto st5; +st6: + if ( ++p == pe ) goto _test_eof6; - st_case_6: - if ( ( (*( p))) == 42 ) { - goto st7; - } - { - goto st6; - } - st7: - p+= 1; - if ( p == pe ) +case 6: + switch( (*p) ) { + case 42: goto st6; + case 47: goto st3; + } + goto st5; +st7: + if ( ++p == pe ) goto _test_eof7; - st_case_7: - switch( ( (*( p))) ) { - case 42: { - goto st7; - } - case 47: { - goto st4; - } - } - { - goto st6; - } - st8: - p+= 1; - if ( p == pe ) +case 7: + if ( (*p) == 10 ) + goto st3; + goto st7; +tr4: +#line 428 "parser.rl" + { p--; {p++; cs = 22; goto _out;} } + goto st22; +st22: + if ( ++p == pe ) + goto _test_eof22; +case 22: +#line 1547 "parser.c" + goto st0; +st8: + if ( ++p == pe ) goto _test_eof8; - st_case_8: - if ( ( (*( p))) == 10 ) { - goto st4; - } - { - goto st8; - } - st9: - p+= 1; - if ( p == pe ) +case 8: + switch( (*p) ) { + case 13: goto st8; + case 32: goto st8; + case 34: goto tr2; + case 45: goto tr2; + case 47: goto st9; + 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 st8; + goto st0; +st9: + if ( ++p == pe ) goto _test_eof9; - st_case_9: - switch( ( (*( p))) ) { - case 42: { - goto st10; - } - case 47: { - goto st12; - } - } - { - goto st0; - } - st10: - p+= 1; - if ( p == pe ) +case 9: + switch( (*p) ) { + case 42: goto st10; + case 47: goto st12; + } + goto st0; +st10: + if ( ++p == pe ) goto _test_eof10; - st_case_10: - if ( ( (*( p))) == 42 ) { - goto st11; - } - { - goto st10; - } - st11: - p+= 1; - if ( p == pe ) +case 10: + if ( (*p) == 42 ) + goto st11; + goto st10; +st11: + if ( ++p == pe ) goto _test_eof11; - st_case_11: - switch( ( (*( p))) ) { - case 42: { - goto st11; - } - case 47: { - goto st3; - } - } - { - goto st10; - } - st12: - p+= 1; - if ( p == pe ) +case 11: + switch( (*p) ) { + case 42: goto st11; + case 47: goto st8; + } + goto st10; +st12: + if ( ++p == pe ) goto _test_eof12; - st_case_12: - if ( ( (*( p))) == 10 ) { - goto st3; - } - { - goto st12; - } - ctr4: - { - #line 424 "parser.rl" - {p = p - 1; } {p+= 1; cs = 17; goto _out;} } - - goto st17; - st17: - p+= 1; - if ( p == pe ) - goto _test_eof17; - st_case_17: - { - goto st0; - } - st13: - p+= 1; - if ( p == pe ) +case 12: + if ( (*p) == 10 ) + goto st8; + goto st12; +st13: + if ( ++p == pe ) goto _test_eof13; - st_case_13: - switch( ( (*( p))) ) { - case 42: { - goto st14; - } - case 47: { - goto st16; - } - } - { - goto st0; +case 13: + _widec = (*p); + if ( (*p) < 13 ) { + if ( (*p) > 9 ) { + if ( 10 <= (*p) && (*p) <= 10 ) { + _widec = (short)(128 + ((*p) - -128)); + if ( +#line 411 "parser.rl" + json->allow_trailing_comma ) _widec += 256; + } + } else if ( (*p) >= 9 ) { + _widec = (short)(128 + ((*p) - -128)); + if ( +#line 411 "parser.rl" + json->allow_trailing_comma ) _widec += 256; + } + } else if ( (*p) > 13 ) { + if ( (*p) > 32 ) { + if ( 47 <= (*p) && (*p) <= 47 ) { + _widec = (short)(128 + ((*p) - -128)); + if ( +#line 411 "parser.rl" + json->allow_trailing_comma ) _widec += 256; + } + } else if ( (*p) >= 32 ) { + _widec = (short)(128 + ((*p) - -128)); + if ( +#line 411 "parser.rl" + json->allow_trailing_comma ) _widec += 256; } - st14: - p+= 1; - if ( p == pe ) + } else { + _widec = (short)(128 + ((*p) - -128)); + if ( +#line 411 "parser.rl" + json->allow_trailing_comma ) _widec += 256; + } + switch( _widec ) { + case 34: goto tr2; + case 45: goto tr2; + case 73: goto tr2; + case 78: goto tr2; + case 91: goto tr2; + case 93: goto tr4; + case 102: goto tr2; + case 110: goto tr2; + case 116: goto tr2; + case 123: goto tr2; + case 269: goto st8; + case 288: goto st8; + case 303: goto st9; + case 525: goto st13; + case 544: goto st13; + case 559: goto st14; + } + if ( _widec < 265 ) { + if ( 48 <= _widec && _widec <= 57 ) + goto tr2; + } else if ( _widec > 266 ) { + if ( 521 <= _widec && _widec <= 522 ) + goto st13; + } else + goto st8; + goto st0; +st14: + if ( ++p == pe ) goto _test_eof14; - st_case_14: - if ( ( (*( p))) == 42 ) { - goto st15; - } - { - goto st14; - } - st15: - p+= 1; - if ( p == pe ) +case 14: + _widec = (*p); + if ( (*p) > 42 ) { + if ( 47 <= (*p) && (*p) <= 47 ) { + _widec = (short)(128 + ((*p) - -128)); + if ( +#line 411 "parser.rl" + json->allow_trailing_comma ) _widec += 256; + } + } else if ( (*p) >= 42 ) { + _widec = (short)(128 + ((*p) - -128)); + if ( +#line 411 "parser.rl" + json->allow_trailing_comma ) _widec += 256; + } + switch( _widec ) { + case 298: goto st10; + case 303: goto st12; + case 554: goto st15; + case 559: goto st17; + } + goto st0; +st15: + if ( ++p == pe ) goto _test_eof15; - st_case_15: - switch( ( (*( p))) ) { - case 42: { - goto st15; - } - case 47: { - goto st2; - } - } - { - goto st14; - } - st16: - p+= 1; - if ( p == pe ) - goto _test_eof16; - st_case_16: - if ( ( (*( p))) == 10 ) { - goto st2; +case 15: + _widec = (*p); + if ( (*p) < 42 ) { + if ( (*p) <= 41 ) { + _widec = (short)(128 + ((*p) - -128)); + if ( +#line 411 "parser.rl" + json->allow_trailing_comma ) _widec += 256; + } + } else if ( (*p) > 42 ) { + if ( 43 <= (*p) ) + { _widec = (short)(128 + ((*p) - -128)); + if ( +#line 411 "parser.rl" + json->allow_trailing_comma ) _widec += 256; } - { - goto st16; - } - st_out: - _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_eof10: cs = 10; goto _test_eof; - _test_eof11: cs = 11; goto _test_eof; - _test_eof12: cs = 12; goto _test_eof; - _test_eof17: cs = 17; goto _test_eof; - _test_eof13: cs = 13; goto _test_eof; - _test_eof14: cs = 14; goto _test_eof; - _test_eof15: cs = 15; goto _test_eof; - _test_eof16: cs = 16; goto _test_eof; - - _test_eof: {} - _out: {} - } - - #line 446 "parser.rl" - - - if(cs >= JSON_array_first_final) { - return p + 1; } else { - rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p); - return NULL; + _widec = (short)(128 + ((*p) - -128)); + if ( +#line 411 "parser.rl" + json->allow_trailing_comma ) _widec += 256; } -} - -static const size_t MAX_STACK_BUFFER_SIZE = 128; -static VALUE json_string_unescape(char *string, char *stringEnd, int intern, int symbolize) -{ - VALUE result = Qnil; - size_t bufferSize = stringEnd - string; - char *p = string, *pe = string, *unescape, *bufferStart, *buffer; - int unescape_len; - char buf[4]; - - if (bufferSize > MAX_STACK_BUFFER_SIZE) { - bufferStart = buffer = ALLOC_N(char, bufferSize); - } else { - bufferStart = buffer = ALLOCA_N(char, bufferSize); + switch( _widec ) { + case 298: goto st11; + case 554: goto st16; } - - while (pe < stringEnd) { - if (*pe == '\\') { - unescape = (char *) "?"; - unescape_len = 1; - if (pe > p) { - MEMCPY(buffer, p, char, pe - p); - buffer += pe - p; - } - switch (*++pe) { - case 'n': - unescape = (char *) "\n"; - break; - case 'r': - unescape = (char *) "\r"; - break; - case 't': - unescape = (char *) "\t"; - break; - case '"': - unescape = (char *) "\""; - break; - case '\\': - unescape = (char *) "\\"; - break; - case 'b': - unescape = (char *) "\b"; - break; - case 'f': - unescape = (char *) "\f"; - break; - case 'u': - if (pe > stringEnd - 4) { - if (bufferSize > MAX_STACK_BUFFER_SIZE) { - free(bufferStart); - } - rb_enc_raise( - EXC_ENCODING eParserError, - "%u: incomplete unicode character escape sequence at '%s'", __LINE__, p - ); - } else { - UTF32 ch = unescape_unicode((unsigned char *) ++pe); - pe += 3; - if (UNI_SUR_HIGH_START == (ch & 0xFC00)) { - pe++; - if (pe > stringEnd - 6) { - if (bufferSize > MAX_STACK_BUFFER_SIZE) { - free(bufferStart); - } - rb_enc_raise( - EXC_ENCODING eParserError, - "%u: incomplete surrogate pair at '%s'", __LINE__, p - ); - } - if (pe[0] == '\\' && pe[1] == 'u') { - UTF32 sur = unescape_unicode((unsigned char *) pe + 2); - ch = (((ch & 0x3F) << 10) | ((((ch >> 6) & 0xF) + 1) << 16) - | (sur & 0x3FF)); - pe += 5; - } else { - unescape = (char *) "?"; - break; - } - } - unescape_len = convert_UTF32_to_UTF8(buf, ch); - unescape = buf; - } - break; - default: - p = pe; - continue; + if ( _widec > 383 ) { + if ( 384 <= _widec && _widec <= 639 ) + goto st15; + } else if ( _widec >= 128 ) + goto st10; + goto st0; +st16: + if ( ++p == pe ) + goto _test_eof16; +case 16: + _widec = (*p); + if ( (*p) < 43 ) { + if ( (*p) > 41 ) { + if ( 42 <= (*p) && (*p) <= 42 ) { + _widec = (short)(128 + ((*p) - -128)); + if ( +#line 411 "parser.rl" + json->allow_trailing_comma ) _widec += 256; } - MEMCPY(buffer, unescape, char, unescape_len); - buffer += unescape_len; - p = ++pe; } else { - pe++; + _widec = (short)(128 + ((*p) - -128)); + if ( +#line 411 "parser.rl" + json->allow_trailing_comma ) _widec += 256; + } + } else if ( (*p) > 46 ) { + if ( (*p) > 47 ) { + if ( 48 <= (*p) ) + { _widec = (short)(128 + ((*p) - -128)); + if ( +#line 411 "parser.rl" + json->allow_trailing_comma ) _widec += 256; + } + } else if ( (*p) >= 47 ) { + _widec = (short)(128 + ((*p) - -128)); + if ( +#line 411 "parser.rl" + json->allow_trailing_comma ) _widec += 256; } + } else { + _widec = (short)(128 + ((*p) - -128)); + if ( +#line 411 "parser.rl" + json->allow_trailing_comma ) _widec += 256; } - - if (pe > p) { - MEMCPY(buffer, p, char, pe - p); - buffer += pe - p; + switch( _widec ) { + case 298: goto st11; + case 303: goto st8; + case 554: goto st16; + case 559: goto st13; } - - # ifdef HAVE_RB_ENC_INTERNED_STR - if (intern) { - result = rb_enc_interned_str(bufferStart, (long)(buffer - bufferStart), rb_utf8_encoding()); + if ( _widec > 383 ) { + if ( 384 <= _widec && _widec <= 639 ) + goto st15; + } else if ( _widec >= 128 ) + goto st10; + goto st0; +st17: + if ( ++p == pe ) + goto _test_eof17; +case 17: + _widec = (*p); + if ( (*p) < 10 ) { + if ( (*p) <= 9 ) { + _widec = (short)(128 + ((*p) - -128)); + if ( +#line 411 "parser.rl" + json->allow_trailing_comma ) _widec += 256; + } + } else if ( (*p) > 10 ) { + if ( 11 <= (*p) ) + { _widec = (short)(128 + ((*p) - -128)); + if ( +#line 411 "parser.rl" + json->allow_trailing_comma ) _widec += 256; + } } else { - result = rb_utf8_str_new(bufferStart, (long)(buffer - bufferStart)); + _widec = (short)(128 + ((*p) - -128)); + if ( +#line 411 "parser.rl" + json->allow_trailing_comma ) _widec += 256; } - if (bufferSize > MAX_STACK_BUFFER_SIZE) { - free(bufferStart); + switch( _widec ) { + case 266: goto st8; + case 522: goto st13; } - # else - result = rb_utf8_str_new(bufferStart, (long)(buffer - bufferStart)); - - if (bufferSize > MAX_STACK_BUFFER_SIZE) { - free(bufferStart); + if ( _widec > 383 ) { + if ( 384 <= _widec && _widec <= 639 ) + goto st17; + } else if ( _widec >= 128 ) + goto st12; + goto st0; +st18: + if ( ++p == pe ) + goto _test_eof18; +case 18: + switch( (*p) ) { + case 42: goto st19; + case 47: goto st21; } - - if (intern) { - # if STR_UMINUS_DEDUPE_FROZEN - // Starting from MRI 2.8 it is preferable to freeze the string - // before deduplication so that it can be interned directly - // otherwise it would be duplicated first which is wasteful. - result = rb_funcall(rb_str_freeze(result), i_uminus, 0); - # elif STR_UMINUS_DEDUPE - // MRI 2.5 and older do not deduplicate strings that are already - // frozen. - result = rb_funcall(result, i_uminus, 0); - # else - result = rb_str_freeze(result); - # endif + goto st0; +st19: + if ( ++p == pe ) + goto _test_eof19; +case 19: + if ( (*p) == 42 ) + goto st20; + goto st19; +st20: + if ( ++p == pe ) + goto _test_eof20; +case 20: + switch( (*p) ) { + case 42: goto st20; + case 47: goto st2; } - # endif - - if (symbolize) { - result = rb_str_intern(result); + goto st19; +st21: + if ( ++p == pe ) + goto _test_eof21; +case 21: + if ( (*p) == 10 ) + goto st2; + goto st21; + } + _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_eof22: cs = 22; goto _test_eof; + _test_eof8: cs = 8; goto _test_eof; + _test_eof9: cs = 9; goto _test_eof; + _test_eof10: cs = 10; goto _test_eof; + _test_eof11: cs = 11; goto _test_eof; + _test_eof12: cs = 12; goto _test_eof; + _test_eof13: cs = 13; goto _test_eof; + _test_eof14: cs = 14; goto _test_eof; + _test_eof15: cs = 15; goto _test_eof; + _test_eof16: cs = 16; goto _test_eof; + _test_eof17: cs = 17; goto _test_eof; + _test_eof18: cs = 18; goto _test_eof; + _test_eof19: cs = 19; goto _test_eof; + _test_eof20: cs = 20; goto _test_eof; + _test_eof21: cs = 21; goto _test_eof; + + _test_eof: {} + _out: {} } - return result; +#line 450 "parser.rl" + + if(cs >= JSON_array_first_final) { + return p + 1; + } else { + rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p); + return NULL; + } +} + +static const size_t MAX_STACK_BUFFER_SIZE = 128; +static VALUE json_string_unescape(char *string, char *stringEnd, int intern, int symbolize) +{ + VALUE result = Qnil; + size_t bufferSize = stringEnd - string; + char *p = string, *pe = string, *unescape, *bufferStart, *buffer; + int unescape_len; + char buf[4]; + + if (bufferSize > MAX_STACK_BUFFER_SIZE) { + bufferStart = buffer = ALLOC_N(char, bufferSize); + } else { + bufferStart = buffer = ALLOCA_N(char, bufferSize); + } + + while (pe < stringEnd) { + if (*pe == '\\') { + unescape = (char *) "?"; + unescape_len = 1; + if (pe > p) { + MEMCPY(buffer, p, char, pe - p); + buffer += pe - p; + } + switch (*++pe) { + case 'n': + unescape = (char *) "\n"; + break; + case 'r': + unescape = (char *) "\r"; + break; + case 't': + unescape = (char *) "\t"; + break; + case '"': + unescape = (char *) "\""; + break; + case '\\': + unescape = (char *) "\\"; + break; + case 'b': + unescape = (char *) "\b"; + break; + case 'f': + unescape = (char *) "\f"; + break; + case 'u': + if (pe > stringEnd - 4) { + if (bufferSize > MAX_STACK_BUFFER_SIZE) { + free(bufferStart); + } + rb_enc_raise( + EXC_ENCODING eParserError, + "%u: incomplete unicode character escape sequence at '%s'", __LINE__, p + ); + } else { + UTF32 ch = unescape_unicode((unsigned char *) ++pe); + pe += 3; + if (UNI_SUR_HIGH_START == (ch & 0xFC00)) { + pe++; + if (pe > stringEnd - 6) { + if (bufferSize > MAX_STACK_BUFFER_SIZE) { + free(bufferStart); + } + rb_enc_raise( + EXC_ENCODING eParserError, + "%u: incomplete surrogate pair at '%s'", __LINE__, p + ); + } + if (pe[0] == '\\' && pe[1] == 'u') { + UTF32 sur = unescape_unicode((unsigned char *) pe + 2); + ch = (((ch & 0x3F) << 10) | ((((ch >> 6) & 0xF) + 1) << 16) + | (sur & 0x3FF)); + pe += 5; + } else { + unescape = (char *) "?"; + break; + } + } + unescape_len = convert_UTF32_to_UTF8(buf, ch); + unescape = buf; + } + break; + default: + p = pe; + continue; + } + MEMCPY(buffer, unescape, char, unescape_len); + buffer += unescape_len; + p = ++pe; + } else { + pe++; + } + } + + if (pe > p) { + MEMCPY(buffer, p, char, pe - p); + buffer += pe - p; + } + +# ifdef HAVE_RB_ENC_INTERNED_STR + if (intern) { + result = rb_enc_interned_str(bufferStart, (long)(buffer - bufferStart), rb_utf8_encoding()); + } else { + result = rb_utf8_str_new(bufferStart, (long)(buffer - bufferStart)); + } + if (bufferSize > MAX_STACK_BUFFER_SIZE) { + free(bufferStart); + } +# else + result = rb_utf8_str_new(bufferStart, (long)(buffer - bufferStart)); + + if (bufferSize > MAX_STACK_BUFFER_SIZE) { + free(bufferStart); + } + + if (intern) { + # if STR_UMINUS_DEDUPE_FROZEN + // Starting from MRI 2.8 it is preferable to freeze the string + // before deduplication so that it can be interned directly + // otherwise it would be duplicated first which is wasteful. + result = rb_funcall(rb_str_freeze(result), i_uminus, 0); + # elif STR_UMINUS_DEDUPE + // MRI 2.5 and older do not deduplicate strings that are already + // frozen. + result = rb_funcall(result, i_uminus, 0); + # else + result = rb_str_freeze(result); + # endif + } +# endif + + if (symbolize) { + result = rb_str_intern(result); + } + + return result; } +#line 2025 "parser.c" enum {JSON_string_start = 1}; enum {JSON_string_first_final = 8}; enum {JSON_string_error = 0}; enum {JSON_string_en_main = 1}; -static const char MAYBE_UNUSED(_JSON_string_nfa_targs)[] = { - 0, 0 -}; - -static const char MAYBE_UNUSED(_JSON_string_nfa_offsets)[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0 -}; - -static const char MAYBE_UNUSED(_JSON_string_nfa_push_actions)[] = { - 0, 0 -}; - -static const char MAYBE_UNUSED(_JSON_string_nfa_pop_trans)[] = { - 0, 0 -}; - -#line 612 "parser.rl" +#line 616 "parser.rl" static int match_i(VALUE regexp, VALUE klass, VALUE memo) { - if (regexp == Qundef) return ST_STOP; - if (RTEST(rb_funcall(klass, i_json_creatable_p, 0)) && - RTEST(rb_funcall(regexp, i_match, 1, rb_ary_entry(memo, 0)))) { - rb_ary_push(memo, klass); - return ST_STOP; - } - return ST_CONTINUE; + if (regexp == Qundef) return ST_STOP; + if (RTEST(rb_funcall(klass, i_json_creatable_p, 0)) && + RTEST(rb_funcall(regexp, i_match, 1, rb_ary_entry(memo, 0)))) { + rb_ary_push(memo, klass); + return ST_STOP; + } + return ST_CONTINUE; } static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *result) { - int cs = EVIL; - VALUE match_string; + int cs = EVIL; + VALUE match_string; +#line 2054 "parser.c" { - cs = (int)JSON_string_start; + cs = JSON_string_start; } - #line 632 "parser.rl" - - json->memo = p; +#line 636 "parser.rl" + json->memo = p; +#line 2062 "parser.c" { - if ( p == pe ) + if ( p == pe ) goto _test_eof; - switch ( cs ) - { - case 1: - goto st_case_1; - case 0: - goto st_case_0; - case 2: - goto st_case_2; - case 8: - goto st_case_8; - case 3: - goto st_case_3; - case 4: - goto st_case_4; - case 5: - goto st_case_5; - case 6: - goto st_case_6; - case 7: - goto st_case_7; - } - goto st_out; - st_case_1: - if ( ( (*( p))) == 34 ) { - goto st2; - } - { - goto st0; - } - st_case_0: - st0: - cs = 0; - goto _out; - st2: - p+= 1; - if ( p == pe ) + switch ( cs ) + { +case 1: + if ( (*p) == 34 ) + goto st2; + goto st0; +st0: +cs = 0; + goto _out; +st2: + if ( ++p == pe ) goto _test_eof2; - st_case_2: - switch( ( (*( p))) ) { - case 34: { - goto ctr2; - } - case 92: { - goto st3; - } - } - if ( 0 <= (signed char)(*(p)) && (*(p)) <= 31 ) { - goto st0; - } - { - goto st2; - } - ctr2: - { - #line 599 "parser.rl" - - *result = json_string_unescape(json->memo + 1, p, json->parsing_name || json-> freeze, json->parsing_name && json->symbolize_names); - if (NIL_P(*result)) { - {p = p - 1; } - {p+= 1; cs = 8; goto _out;} - } else { - {p = (( p + 1))-1;} - - } - } - { - #line 609 "parser.rl" - {p = p - 1; } {p+= 1; cs = 8; goto _out;} } - - goto st8; - st8: - p+= 1; - if ( p == pe ) +case 2: + switch( (*p) ) { + case 34: goto tr2; + case 92: goto st3; + } + if ( 0 <= (signed char)(*(p)) && (*(p)) <= 31 ) + goto st0; + goto st2; +tr2: +#line 603 "parser.rl" + { + *result = json_string_unescape(json->memo + 1, p, json->parsing_name || json-> freeze, json->parsing_name && json->symbolize_names); + if (NIL_P(*result)) { + p--; + {p++; cs = 8; goto _out;} + } else { + {p = (( p + 1))-1;} + } + } +#line 613 "parser.rl" + { p--; {p++; cs = 8; goto _out;} } + goto st8; +st8: + if ( ++p == pe ) goto _test_eof8; - st_case_8: - { - goto st0; - } - st3: - p+= 1; - if ( p == pe ) +case 8: +#line 2104 "parser.c" + goto st0; +st3: + if ( ++p == pe ) goto _test_eof3; - st_case_3: - if ( ( (*( p))) == 117 ) { - goto st4; - } - if ( 0 <= (signed char)(*(p)) && (*(p)) <= 31 ) { - goto st0; - } - { - goto st2; - } - st4: - p+= 1; - if ( p == pe ) +case 3: + if ( (*p) == 117 ) + goto st4; + if ( 0 <= (signed char)(*(p)) && (*(p)) <= 31 ) + goto st0; + goto st2; +st4: + if ( ++p == pe ) goto _test_eof4; - st_case_4: - if ( ( (*( p))) < 65 ) { - if ( 48 <= ( (*( p))) && ( (*( p))) <= 57 ) { - goto st5; - } - } else if ( ( (*( p))) > 70 ) { - if ( 97 <= ( (*( p))) && ( (*( p))) <= 102 ) { - goto st5; - } - } else { +case 4: + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) goto st5; - } - { - goto st0; - } - st5: - p+= 1; - if ( p == pe ) + } else if ( (*p) > 70 ) { + if ( 97 <= (*p) && (*p) <= 102 ) + goto st5; + } else + goto st5; + goto st0; +st5: + if ( ++p == pe ) goto _test_eof5; - st_case_5: - if ( ( (*( p))) < 65 ) { - if ( 48 <= ( (*( p))) && ( (*( p))) <= 57 ) { - goto st6; - } - } else if ( ( (*( p))) > 70 ) { - if ( 97 <= ( (*( p))) && ( (*( p))) <= 102 ) { - goto st6; - } - } else { +case 5: + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) goto st6; - } - { - goto st0; - } - st6: - p+= 1; - if ( p == pe ) + } else if ( (*p) > 70 ) { + if ( 97 <= (*p) && (*p) <= 102 ) + goto st6; + } else + goto st6; + goto st0; +st6: + if ( ++p == pe ) goto _test_eof6; - st_case_6: - if ( ( (*( p))) < 65 ) { - if ( 48 <= ( (*( p))) && ( (*( p))) <= 57 ) { - goto st7; - } - } else if ( ( (*( p))) > 70 ) { - if ( 97 <= ( (*( p))) && ( (*( p))) <= 102 ) { - goto st7; - } - } else { +case 6: + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) goto st7; - } - { - goto st0; - } - st7: - p+= 1; - if ( p == pe ) + } else if ( (*p) > 70 ) { + if ( 97 <= (*p) && (*p) <= 102 ) + goto st7; + } else + goto st7; + goto st0; +st7: + if ( ++p == pe ) goto _test_eof7; - st_case_7: - if ( ( (*( p))) < 65 ) { - if ( 48 <= ( (*( p))) && ( (*( p))) <= 57 ) { - goto st2; - } - } else if ( ( (*( p))) > 70 ) { - if ( 97 <= ( (*( p))) && ( (*( p))) <= 102 ) { - goto st2; - } - } else { +case 7: + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) goto st2; - } - { - goto st0; - } - st_out: - _test_eof2: cs = 2; goto _test_eof; - _test_eof8: cs = 8; 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_eof: {} - _out: {} - } - - #line 634 "parser.rl" - - - if (json->create_additions && RTEST(match_string = json->match_string)) { - VALUE klass; - VALUE memo = rb_ary_new2(2); - rb_ary_push(memo, *result); - rb_hash_foreach(match_string, match_i, memo); - klass = rb_ary_entry(memo, 1); - if (RTEST(klass)) { - *result = rb_funcall(klass, i_json_create, 1, *result); - } + } else if ( (*p) > 70 ) { + if ( 97 <= (*p) && (*p) <= 102 ) + goto st2; + } else + goto st2; + goto st0; } - - if (cs >= JSON_string_first_final) { - return p + 1; - } else { - return NULL; + _test_eof2: cs = 2; goto _test_eof; + _test_eof8: cs = 8; 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_eof: {} + _out: {} } + +#line 638 "parser.rl" + + if (json->create_additions && RTEST(match_string = json->match_string)) { + VALUE klass; + VALUE memo = rb_ary_new2(2); + rb_ary_push(memo, *result); + rb_hash_foreach(match_string, match_i, memo); + klass = rb_ary_entry(memo, 1); + if (RTEST(klass)) { + *result = rb_funcall(klass, i_json_create, 1, *result); + } + } + + if (cs >= JSON_string_first_final) { + return p + 1; + } else { + return NULL; + } } /* -* Document-class: JSON::Ext::Parser -* -* This is the JSON parser implemented as a C extension. It can be configured -* to be used by setting -* -* JSON.parser = JSON::Ext::Parser -* -* with the method parser= in JSON. -* -*/ + * Document-class: JSON::Ext::Parser + * + * This is the JSON parser implemented as a C extension. It can be configured + * to be used by setting + * + * JSON.parser = JSON::Ext::Parser + * + * with the method parser= in JSON. + * + */ static VALUE convert_encoding(VALUE source) { - #ifdef HAVE_RUBY_ENCODING_H - rb_encoding *enc = rb_enc_get(source); - if (enc == rb_ascii8bit_encoding()) { - if (OBJ_FROZEN(source)) { - source = rb_str_dup(source); - } - FORCE_UTF8(source); - } else { - source = rb_str_conv_enc(source, rb_enc_get(source), rb_utf8_encoding()); - } - #endif - return source; +#ifdef HAVE_RUBY_ENCODING_H + rb_encoding *enc = rb_enc_get(source); + if (enc == rb_ascii8bit_encoding()) { + if (OBJ_FROZEN(source)) { + source = rb_str_dup(source); + } + FORCE_UTF8(source); + } else { + source = rb_str_conv_enc(source, rb_enc_get(source), rb_utf8_encoding()); + } +#endif + return source; } /* -* call-seq: new(source, opts => {}) -* -* Creates a new JSON::Ext::Parser instance for the string _source_. -* -* Creates a new JSON::Ext::Parser instance for the string _source_. -* -* It will be configured by the _opts_ hash. _opts_ can have the following -* keys: -* -* _opts_ can have the following keys: -* * *max_nesting*: The maximum depth of nesting allowed in the parsed data -* structures. Disable depth checking with :max_nesting => false|nil|0, it -* defaults to 100. -* * *allow_nan*: If set to true, allow NaN, Infinity and -Infinity in -* defiance of RFC 4627 to be parsed by the Parser. This option defaults to -* false. -* * *symbolize_names*: If set to true, returns symbols for the names -* (keys) in a JSON object. Otherwise strings are returned, which is -* also the default. It's not possible to use this option in -* conjunction with the *create_additions* option. -* * *create_additions*: If set to false, the Parser doesn't create -* additions even if a matching class and create_id was found. This option -* defaults to false. -* * *object_class*: Defaults to Hash -* * *array_class*: Defaults to Array -*/ + * call-seq: new(source, opts => {}) + * + * Creates a new JSON::Ext::Parser instance for the string _source_. + * + * Creates a new JSON::Ext::Parser instance for the string _source_. + * + * It will be configured by the _opts_ hash. _opts_ can have the following + * keys: + * + * _opts_ can have the following keys: + * * *max_nesting*: The maximum depth of nesting allowed in the parsed data + * structures. Disable depth checking with :max_nesting => false|nil|0, it + * defaults to 100. + * * *allow_nan*: If set to true, allow NaN, Infinity and -Infinity in + * defiance of RFC 4627 to be parsed by the Parser. This option defaults to + * false. + * * *allow_trailing_comma*: If set to true, allow arrays and objects with a + * trailing comma in defiance of RFC 4627 to be parsed by the Parser. + * This option defaults to false. + * * *symbolize_names*: If set to true, returns symbols for the names + * (keys) in a JSON object. Otherwise strings are returned, which is + * also the default. It's not possible to use this option in + * conjunction with the *create_additions* option. + * * *create_additions*: If set to false, the Parser doesn't create + * additions even if a matching class and create_id was found. This option + * defaults to false. + * * *object_class*: Defaults to Hash + * * *array_class*: Defaults to Array + */ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self) { - VALUE source, opts; - GET_PARSER_INIT; - - if (json->Vsource) { - rb_raise(rb_eTypeError, "already initialized instance"); - } - #ifdef HAVE_RB_SCAN_ARGS_OPTIONAL_HASH - rb_scan_args(argc, argv, "1:", &source, &opts); - #else - rb_scan_args(argc, argv, "11", &source, &opts); - #endif - if (!NIL_P(opts)) { - #ifndef HAVE_RB_SCAN_ARGS_OPTIONAL_HASH - opts = rb_convert_type(opts, T_HASH, "Hash", "to_hash"); - if (NIL_P(opts)) { - rb_raise(rb_eArgError, "opts needs to be like a hash"); - } else { - #endif - VALUE tmp = ID2SYM(i_max_nesting); - if (option_given_p(opts, tmp)) { - VALUE max_nesting = rb_hash_aref(opts, tmp); - if (RTEST(max_nesting)) { - Check_Type(max_nesting, T_FIXNUM); - json->max_nesting = FIX2INT(max_nesting); - } else { - json->max_nesting = 0; - } - } else { - json->max_nesting = 100; - } - tmp = ID2SYM(i_allow_nan); - if (option_given_p(opts, tmp)) { - json->allow_nan = RTEST(rb_hash_aref(opts, tmp)) ? 1 : 0; - } else { - json->allow_nan = 0; - } - tmp = ID2SYM(i_symbolize_names); - if (option_given_p(opts, tmp)) { - json->symbolize_names = RTEST(rb_hash_aref(opts, tmp)) ? 1 : 0; - } else { - json->symbolize_names = 0; - } - tmp = ID2SYM(i_freeze); - if (option_given_p(opts, tmp)) { - json->freeze = RTEST(rb_hash_aref(opts, tmp)) ? 1 : 0; - } else { - json->freeze = 0; - } - tmp = ID2SYM(i_create_additions); - if (option_given_p(opts, tmp)) { - json->create_additions = RTEST(rb_hash_aref(opts, tmp)); - } else { - json->create_additions = 0; - } - if (json->symbolize_names && json->create_additions) { - rb_raise(rb_eArgError, - "options :symbolize_names and :create_additions cannot be " - " used in conjunction"); - } - tmp = ID2SYM(i_create_id); - if (option_given_p(opts, tmp)) { - json->create_id = rb_hash_aref(opts, tmp); - } else { - json->create_id = rb_funcall(mJSON, i_create_id, 0); - } - tmp = ID2SYM(i_object_class); - if (option_given_p(opts, tmp)) { - json->object_class = rb_hash_aref(opts, tmp); - } else { - json->object_class = Qnil; - } - tmp = ID2SYM(i_array_class); - if (option_given_p(opts, tmp)) { - json->array_class = rb_hash_aref(opts, tmp); - } else { - json->array_class = Qnil; - } - tmp = ID2SYM(i_decimal_class); - if (option_given_p(opts, tmp)) { - json->decimal_class = rb_hash_aref(opts, tmp); - } else { - json->decimal_class = Qnil; - } - tmp = ID2SYM(i_match_string); - if (option_given_p(opts, tmp)) { - VALUE match_string = rb_hash_aref(opts, tmp); - json->match_string = RTEST(match_string) ? match_string : Qnil; - } else { - json->match_string = Qnil; - } - #ifndef HAVE_RB_SCAN_ARGS_OPTIONAL_HASH - } - #endif - } else { - json->max_nesting = 100; - json->allow_nan = 0; - json->create_additions = 0; - json->create_id = rb_funcall(mJSON, i_create_id, 0); - json->object_class = Qnil; - json->array_class = Qnil; - json->decimal_class = Qnil; - } - source = convert_encoding(StringValue(source)); - StringValue(source); - json->len = RSTRING_LEN(source); - json->source = RSTRING_PTR(source);; - json->Vsource = source; - return self; + VALUE source, opts; + GET_PARSER_INIT; + + if (json->Vsource) { + rb_raise(rb_eTypeError, "already initialized instance"); + } +#ifdef HAVE_RB_SCAN_ARGS_OPTIONAL_HASH + rb_scan_args(argc, argv, "1:", &source, &opts); +#else + rb_scan_args(argc, argv, "11", &source, &opts); +#endif + if (!NIL_P(opts)) { +#ifndef HAVE_RB_SCAN_ARGS_OPTIONAL_HASH + opts = rb_convert_type(opts, T_HASH, "Hash", "to_hash"); + if (NIL_P(opts)) { + rb_raise(rb_eArgError, "opts needs to be like a hash"); + } else { +#endif + VALUE tmp = ID2SYM(i_max_nesting); + if (option_given_p(opts, tmp)) { + VALUE max_nesting = rb_hash_aref(opts, tmp); + if (RTEST(max_nesting)) { + Check_Type(max_nesting, T_FIXNUM); + json->max_nesting = FIX2INT(max_nesting); + } else { + json->max_nesting = 0; + } + } else { + json->max_nesting = 100; + } + tmp = ID2SYM(i_allow_nan); + if (option_given_p(opts, tmp)) { + json->allow_nan = RTEST(rb_hash_aref(opts, tmp)) ? 1 : 0; + } else { + json->allow_nan = 0; + } + tmp = ID2SYM(i_allow_trailing_comma); + if (option_given_p(opts, tmp)) { + json->allow_trailing_comma = RTEST(rb_hash_aref(opts, tmp)) ? 1 : 0; + } else { + json->allow_trailing_comma = 0; + } + tmp = ID2SYM(i_symbolize_names); + if (option_given_p(opts, tmp)) { + json->symbolize_names = RTEST(rb_hash_aref(opts, tmp)) ? 1 : 0; + } else { + json->symbolize_names = 0; + } + tmp = ID2SYM(i_freeze); + if (option_given_p(opts, tmp)) { + json->freeze = RTEST(rb_hash_aref(opts, tmp)) ? 1 : 0; + } else { + json->freeze = 0; + } + tmp = ID2SYM(i_create_additions); + if (option_given_p(opts, tmp)) { + json->create_additions = RTEST(rb_hash_aref(opts, tmp)); + } else { + json->create_additions = 0; + } + if (json->symbolize_names && json->create_additions) { + rb_raise(rb_eArgError, + "options :symbolize_names and :create_additions cannot be " + " used in conjunction"); + } + tmp = ID2SYM(i_create_id); + if (option_given_p(opts, tmp)) { + json->create_id = rb_hash_aref(opts, tmp); + } else { + json->create_id = rb_funcall(mJSON, i_create_id, 0); + } + tmp = ID2SYM(i_object_class); + if (option_given_p(opts, tmp)) { + json->object_class = rb_hash_aref(opts, tmp); + } else { + json->object_class = Qnil; + } + tmp = ID2SYM(i_array_class); + if (option_given_p(opts, tmp)) { + json->array_class = rb_hash_aref(opts, tmp); + } else { + json->array_class = Qnil; + } + tmp = ID2SYM(i_decimal_class); + if (option_given_p(opts, tmp)) { + json->decimal_class = rb_hash_aref(opts, tmp); + } else { + json->decimal_class = Qnil; + } + tmp = ID2SYM(i_match_string); + if (option_given_p(opts, tmp)) { + VALUE match_string = rb_hash_aref(opts, tmp); + json->match_string = RTEST(match_string) ? match_string : Qnil; + } else { + json->match_string = Qnil; + } +#ifndef HAVE_RB_SCAN_ARGS_OPTIONAL_HASH + } +#endif + } else { + json->max_nesting = 100; + json->allow_nan = 0; + json->allow_trailing_comma = 0; + json->create_additions = 0; + json->create_id = rb_funcall(mJSON, i_create_id, 0); + json->object_class = Qnil; + json->array_class = Qnil; + json->decimal_class = Qnil; + } + source = convert_encoding(StringValue(source)); + StringValue(source); + json->len = RSTRING_LEN(source); + json->source = RSTRING_PTR(source);; + json->Vsource = source; + return self; } +#line 2378 "parser.c" enum {JSON_start = 1}; enum {JSON_first_final = 10}; enum {JSON_error = 0}; enum {JSON_en_main = 1}; -static const char MAYBE_UNUSED(_JSON_nfa_targs)[] = { - 0, 0 -}; - -static const char MAYBE_UNUSED(_JSON_nfa_offsets)[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0 -}; - -static const char MAYBE_UNUSED(_JSON_nfa_push_actions)[] = { - 0, 0 -}; - -static const char MAYBE_UNUSED(_JSON_nfa_pop_trans)[] = { - 0, 0 -}; - -#line 835 "parser.rl" +#line 849 "parser.rl" /* -* call-seq: parse() -* -* Parses the current JSON text _source_ and returns the complete data -* structure as a result. -*/ + * call-seq: parse() + * + * Parses the current JSON text _source_ and returns the complete data + * structure as a result. + */ static VALUE cParser_parse(VALUE self) { - char *p, *pe; - int cs = EVIL; - VALUE result = Qnil; - GET_PARSER; + char *p, *pe; + int cs = EVIL; + VALUE result = Qnil; + GET_PARSER; +#line 2403 "parser.c" { - cs = (int)JSON_start; + cs = JSON_start; } - #line 851 "parser.rl" - - p = json->source; - pe = p + json->len; +#line 865 "parser.rl" + p = json->source; + pe = p + json->len; +#line 2412 "parser.c" { - if ( p == pe ) + if ( p == pe ) goto _test_eof; - switch ( cs ) - { - case 1: - goto st_case_1; - case 0: - goto st_case_0; - case 10: - goto st_case_10; - case 2: - goto st_case_2; - case 3: - goto st_case_3; - case 4: - goto st_case_4; - case 5: - goto st_case_5; - case 6: - goto st_case_6; - case 7: - goto st_case_7; - case 8: - goto st_case_8; - case 9: - goto st_case_9; - } - goto st_out; - st1: - p+= 1; - if ( p == pe ) + switch ( cs ) + { +st1: + if ( ++p == pe ) goto _test_eof1; - st_case_1: - switch( ( (*( p))) ) { - case 13: { - goto st1; - } - case 32: { - goto st1; - } - case 34: { - goto ctr2; - } - case 45: { - goto ctr2; - } - case 47: { - goto st6; - } - case 73: { - goto ctr2; - } - case 78: { - goto ctr2; - } - case 91: { - goto ctr2; - } - case 102: { - goto ctr2; - } - case 110: { - goto ctr2; - } - case 116: { - goto ctr2; - } - case 123: { - goto ctr2; - } - } - if ( ( (*( p))) > 10 ) { - if ( 48 <= ( (*( p))) && ( (*( p))) <= 57 ) { - goto ctr2; - } - } else if ( ( (*( p))) >= 9 ) { - goto st1; - } - { - goto st0; - } - st_case_0: - st0: - cs = 0; - goto _out; - ctr2: - { - #line 827 "parser.rl" - - char *np = JSON_parse_value(json, p, pe, &result, 0); - if (np == NULL) { {p = p - 1; } {p+= 1; cs = 10; goto _out;} } else {p = (( np))-1;} - - } - - goto st10; - st10: - p+= 1; - if ( p == pe ) +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 841 "parser.rl" + { + char *np = JSON_parse_value(json, p, pe, &result, 0); + if (np == NULL) { p--; {p++; cs = 10; goto _out;} } else {p = (( np))-1;} + } + goto st10; +st10: + if ( ++p == pe ) goto _test_eof10; - st_case_10: - switch( ( (*( p))) ) { - case 13: { - goto st10; - } - case 32: { - goto st10; - } - case 47: { - goto st2; - } - } - if ( 9 <= ( (*( p))) && ( (*( p))) <= 10 ) { - goto st10; - } - { - goto st0; - } - st2: - p+= 1; - if ( p == pe ) +case 10: +#line 2456 "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; - st_case_2: - switch( ( (*( p))) ) { - case 42: { - goto st3; - } - case 47: { - goto st5; - } - } - { - goto st0; - } - st3: - p+= 1; - if ( p == pe ) +case 2: + switch( (*p) ) { + case 42: goto st3; + case 47: goto st5; + } + goto st0; +st3: + if ( ++p == pe ) goto _test_eof3; - st_case_3: - if ( ( (*( p))) == 42 ) { - goto st4; - } - { - goto st3; - } - st4: - p+= 1; - if ( p == pe ) +case 3: + if ( (*p) == 42 ) + goto st4; + goto st3; +st4: + if ( ++p == pe ) goto _test_eof4; - st_case_4: - switch( ( (*( p))) ) { - case 42: { - goto st4; - } - case 47: { - goto st10; - } - } - { - goto st3; - } - st5: - p+= 1; - if ( p == pe ) +case 4: + switch( (*p) ) { + case 42: goto st4; + case 47: goto st10; + } + goto st3; +st5: + if ( ++p == pe ) goto _test_eof5; - st_case_5: - if ( ( (*( p))) == 10 ) { - goto st10; - } - { - goto st5; - } - st6: - p+= 1; - if ( p == pe ) +case 5: + if ( (*p) == 10 ) + goto st10; + goto st5; +st6: + if ( ++p == pe ) goto _test_eof6; - st_case_6: - switch( ( (*( p))) ) { - case 42: { - goto st7; - } - case 47: { - goto st9; - } - } - { - goto st0; - } - st7: - p+= 1; - if ( p == pe ) +case 6: + switch( (*p) ) { + case 42: goto st7; + case 47: goto st9; + } + goto st0; +st7: + if ( ++p == pe ) goto _test_eof7; - st_case_7: - if ( ( (*( p))) == 42 ) { - goto st8; - } - { - goto st7; - } - st8: - p+= 1; - if ( p == pe ) +case 7: + if ( (*p) == 42 ) + goto st8; + goto st7; +st8: + if ( ++p == pe ) goto _test_eof8; - st_case_8: - switch( ( (*( p))) ) { - case 42: { - goto st8; - } - case 47: { - goto st1; - } - } - { - goto st7; - } - st9: - p+= 1; - if ( p == pe ) +case 8: + switch( (*p) ) { + case 42: goto st8; + case 47: goto st1; + } + goto st7; +st9: + if ( ++p == pe ) goto _test_eof9; - st_case_9: - if ( ( (*( p))) == 10 ) { - goto st1; - } - { - goto st9; - } - st_out: - _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: {} +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 854 "parser.rl" - +#line 868 "parser.rl" - if (cs >= JSON_first_final && p == pe) { - return result; - } else { - rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p); - return Qnil; - } + if (cs >= JSON_first_final && p == pe) { + return result; + } else { + rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p); + return Qnil; + } } static void JSON_mark(void *ptr) { - JSON_Parser *json = ptr; - rb_gc_mark_maybe(json->Vsource); - rb_gc_mark_maybe(json->create_id); - rb_gc_mark_maybe(json->object_class); - rb_gc_mark_maybe(json->array_class); - rb_gc_mark_maybe(json->decimal_class); - rb_gc_mark_maybe(json->match_string); + JSON_Parser *json = ptr; + rb_gc_mark_maybe(json->Vsource); + rb_gc_mark_maybe(json->create_id); + rb_gc_mark_maybe(json->object_class); + rb_gc_mark_maybe(json->array_class); + rb_gc_mark_maybe(json->decimal_class); + rb_gc_mark_maybe(json->match_string); } static void JSON_free(void *ptr) { - JSON_Parser *json = ptr; - fbuffer_free(json->fbuffer); - ruby_xfree(json); + JSON_Parser *json = ptr; + fbuffer_free(json->fbuffer); + ruby_xfree(json); } static size_t JSON_memsize(const void *ptr) { - const JSON_Parser *json = ptr; - return sizeof(*json) + FBUFFER_CAPA(json->fbuffer); + const JSON_Parser *json = ptr; + return sizeof(*json) + FBUFFER_CAPA(json->fbuffer); } #ifdef NEW_TYPEDDATA_WRAPPER static const rb_data_type_t JSON_Parser_type = { - "JSON/Parser", - {JSON_mark, JSON_free, JSON_memsize,}, - #ifdef RUBY_TYPED_FREE_IMMEDIATELY - 0, 0, - RUBY_TYPED_FREE_IMMEDIATELY, - #endif + "JSON/Parser", + {JSON_mark, JSON_free, JSON_memsize,}, +#ifdef RUBY_TYPED_FREE_IMMEDIATELY + 0, 0, + RUBY_TYPED_FREE_IMMEDIATELY, +#endif }; #endif static VALUE cJSON_parser_s_allocate(VALUE klass) { - JSON_Parser *json; - VALUE obj = TypedData_Make_Struct(klass, JSON_Parser, &JSON_Parser_type, json); - json->fbuffer = fbuffer_alloc(0); - return obj; + JSON_Parser *json; + VALUE obj = TypedData_Make_Struct(klass, JSON_Parser, &JSON_Parser_type, json); + json->fbuffer = fbuffer_alloc(0); + return obj; } /* -* call-seq: source() -* -* Returns a copy of the current _source_ string, that was used to construct -* this Parser. -*/ + * call-seq: source() + * + * Returns a copy of the current _source_ string, that was used to construct + * this Parser. + */ static VALUE cParser_source(VALUE self) { - GET_PARSER; - return rb_str_dup(json->Vsource); + GET_PARSER; + return rb_str_dup(json->Vsource); } void Init_parser(void) { - #ifdef HAVE_RB_EXT_RACTOR_SAFE - rb_ext_ractor_safe(true); - #endif - - #undef rb_intern - rb_require("json/common"); - mJSON = rb_define_module("JSON"); - mExt = rb_define_module_under(mJSON, "Ext"); - cParser = rb_define_class_under(mExt, "Parser", rb_cObject); - eParserError = rb_path2class("JSON::ParserError"); - eNestingError = rb_path2class("JSON::NestingError"); - rb_gc_register_mark_object(eParserError); - rb_gc_register_mark_object(eNestingError); - rb_define_alloc_func(cParser, cJSON_parser_s_allocate); - rb_define_method(cParser, "initialize", cParser_initialize, -1); - rb_define_method(cParser, "parse", cParser_parse, 0); - rb_define_method(cParser, "source", cParser_source, 0); - - CNaN = rb_const_get(mJSON, rb_intern("NaN")); - rb_gc_register_mark_object(CNaN); - - CInfinity = rb_const_get(mJSON, rb_intern("Infinity")); - rb_gc_register_mark_object(CInfinity); - - CMinusInfinity = rb_const_get(mJSON, rb_intern("MinusInfinity")); - rb_gc_register_mark_object(CMinusInfinity); - - i_json_creatable_p = rb_intern("json_creatable?"); - i_json_create = rb_intern("json_create"); - i_create_id = rb_intern("create_id"); - i_create_additions = rb_intern("create_additions"); - i_chr = rb_intern("chr"); - i_max_nesting = rb_intern("max_nesting"); - i_allow_nan = rb_intern("allow_nan"); - i_symbolize_names = rb_intern("symbolize_names"); - i_object_class = rb_intern("object_class"); - i_array_class = rb_intern("array_class"); - i_decimal_class = rb_intern("decimal_class"); - i_match = rb_intern("match"); - i_match_string = rb_intern("match_string"); - i_key_p = rb_intern("key?"); - i_deep_const_get = rb_intern("deep_const_get"); - i_aset = rb_intern("[]="); - i_aref = rb_intern("[]"); - i_leftshift = rb_intern("<<"); - i_new = rb_intern("new"); - i_try_convert = rb_intern("try_convert"); - i_freeze = rb_intern("freeze"); - i_uminus = rb_intern("-@"); +#ifdef HAVE_RB_EXT_RACTOR_SAFE + rb_ext_ractor_safe(true); +#endif + +#undef rb_intern + rb_require("json/common"); + mJSON = rb_define_module("JSON"); + mExt = rb_define_module_under(mJSON, "Ext"); + cParser = rb_define_class_under(mExt, "Parser", rb_cObject); + eParserError = rb_path2class("JSON::ParserError"); + eNestingError = rb_path2class("JSON::NestingError"); + rb_gc_register_mark_object(eParserError); + rb_gc_register_mark_object(eNestingError); + rb_define_alloc_func(cParser, cJSON_parser_s_allocate); + rb_define_method(cParser, "initialize", cParser_initialize, -1); + rb_define_method(cParser, "parse", cParser_parse, 0); + rb_define_method(cParser, "source", cParser_source, 0); + + CNaN = rb_const_get(mJSON, rb_intern("NaN")); + rb_gc_register_mark_object(CNaN); + + CInfinity = rb_const_get(mJSON, rb_intern("Infinity")); + rb_gc_register_mark_object(CInfinity); + + CMinusInfinity = rb_const_get(mJSON, rb_intern("MinusInfinity")); + rb_gc_register_mark_object(CMinusInfinity); + + i_json_creatable_p = rb_intern("json_creatable?"); + i_json_create = rb_intern("json_create"); + i_create_id = rb_intern("create_id"); + i_create_additions = rb_intern("create_additions"); + i_chr = rb_intern("chr"); + i_max_nesting = rb_intern("max_nesting"); + i_allow_nan = rb_intern("allow_nan"); + i_allow_trailing_comma = rb_intern("allow_trailing_comma"); + i_symbolize_names = rb_intern("symbolize_names"); + i_object_class = rb_intern("object_class"); + i_array_class = rb_intern("array_class"); + i_decimal_class = rb_intern("decimal_class"); + i_match = rb_intern("match"); + i_match_string = rb_intern("match_string"); + i_key_p = rb_intern("key?"); + i_deep_const_get = rb_intern("deep_const_get"); + i_aset = rb_intern("[]="); + i_aref = rb_intern("[]"); + i_leftshift = rb_intern("<<"); + i_new = rb_intern("new"); + i_try_convert = rb_intern("try_convert"); + i_freeze = rb_intern("freeze"); + i_uminus = rb_intern("-@"); } /* -* Local variables: -* mode: c -* c-file-style: ruby -* indent-tabs-mode: nil -* End: -*/ + * Local variables: + * mode: c + * c-file-style: ruby + * indent-tabs-mode: nil + * End: + */ diff --git a/ext/json/ext/parser/parser.h b/ext/json/ext/parser/parser.h index 92ed3fdc..61847cf7 100644 --- a/ext/json/ext/parser/parser.h +++ b/ext/json/ext/parser/parser.h @@ -39,6 +39,7 @@ typedef struct JSON_ParserStruct { VALUE create_id; int max_nesting; int allow_nan; + int allow_trailing_comma; int parsing_name; int symbolize_names; int freeze; diff --git a/ext/json/ext/parser/parser.rl b/ext/json/ext/parser/parser.rl index f7be1a5a..8eaf189a 100644 --- a/ext/json/ext/parser/parser.rl +++ b/ext/json/ext/parser/parser.rl @@ -91,7 +91,7 @@ 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_chr, i_max_nesting, i_allow_nan, i_allow_trailing_comma, i_symbolize_names, i_object_class, i_array_class, i_decimal_class, i_key_p, i_deep_const_get, i_match, i_match_string, i_aset, i_aref, i_leftshift, i_new, i_try_convert, i_freeze, i_uminus; @@ -130,6 +130,8 @@ static ID i_json_creatable_p, i_json_create, i_create_id, i_create_additions, write data; + action allow_trailing_comma { json->allow_trailing_comma } + action parse_value { VALUE v = Qnil; char *np = JSON_parse_value(json, fpc, pe, &v, current_nesting); @@ -161,7 +163,7 @@ static ID i_json_creatable_p, i_json_create, i_create_id, i_create_additions, main := ( begin_object - (pair (next_pair)*)? ignore* + (pair (next_pair)*((ignore* value_separator) when allow_trailing_comma)?)? ignore* end_object ) @exit; }%% @@ -406,6 +408,8 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul write data; + action allow_trailing_comma { json->allow_trailing_comma } + action parse_value { VALUE v = Qnil; char *np = JSON_parse_value(json, fpc, pe, &v, current_nesting); @@ -427,7 +431,7 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul main := begin_array ignore* ((begin_value >parse_value ignore*) - (ignore* next_element ignore*)*)? + (ignore* next_element ignore*)*((value_separator ignore*) when allow_trailing_comma)?)? end_array @exit; }%% @@ -695,6 +699,9 @@ static VALUE convert_encoding(VALUE source) * * *allow_nan*: If set to true, allow NaN, Infinity and -Infinity in * defiance of RFC 4627 to be parsed by the Parser. This option defaults to * false. + * * *allow_trailing_comma*: If set to true, allow arrays and objects with a + * trailing comma in defiance of RFC 4627 to be parsed by the Parser. + * This option defaults to false. * * *symbolize_names*: If set to true, returns symbols for the names * (keys) in a JSON object. Otherwise strings are returned, which is * also the default. It's not possible to use this option in @@ -743,6 +750,12 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self) } else { json->allow_nan = 0; } + tmp = ID2SYM(i_allow_trailing_comma); + if (option_given_p(opts, tmp)) { + json->allow_trailing_comma = RTEST(rb_hash_aref(opts, tmp)) ? 1 : 0; + } else { + json->allow_trailing_comma = 0; + } tmp = ID2SYM(i_symbolize_names); if (option_given_p(opts, tmp)) { json->symbolize_names = RTEST(rb_hash_aref(opts, tmp)) ? 1 : 0; @@ -803,6 +816,7 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self) } else { json->max_nesting = 100; json->allow_nan = 0; + json->allow_trailing_comma = 0; json->create_additions = 0; json->create_id = rb_funcall(mJSON, i_create_id, 0); json->object_class = Qnil; @@ -951,6 +965,7 @@ void Init_parser(void) i_chr = rb_intern("chr"); i_max_nesting = rb_intern("max_nesting"); i_allow_nan = rb_intern("allow_nan"); + i_allow_trailing_comma = rb_intern("allow_trailing_comma"); i_symbolize_names = rb_intern("symbolize_names"); i_object_class = rb_intern("object_class"); i_array_class = rb_intern("array_class"); diff --git a/java/src/json/ext/Parser.java b/java/src/json/ext/Parser.java index ef283932..d6724883 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 boolean createAdditions; private int maxNesting; private boolean allowNaN; + private boolean allowTrailingComma; private boolean symbolizeNames; private boolean freeze; private RubyClass objectClass; @@ -120,6 +121,11 @@ public Parser(Ruby runtime, RubyClass metaClass) { * Infinity and -Infinity in defiance of RFC 4627 * to be parsed by the Parser. This option defaults to false. * + *
:allow_trailing_comma + *
If set to true, allow arrays and objects with a trailing + * comma in defiance of RFC 4627 to be parsed by the Parser. + * This option defaults to false. + * *
:symbolize_names *
If set to true, returns symbols for the names (keys) in * a JSON object. Otherwise strings are returned, which is also the default. @@ -160,6 +166,7 @@ public IRubyObject initialize(ThreadContext context, IRubyObject[] args) { 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.allowTrailingComma = opts.getBool("allow_trailing_comma", false); this.symbolizeNames = opts.getBool("symbolize_names", false); this.freeze = opts.getBool("freeze", false); this.createId = opts.getString("create_id", getCreateId(context)); @@ -315,11 +322,11 @@ private Ruby getRuntime() { } -// line 341 "Parser.rl" +// line 348 "Parser.rl" -// line 323 "Parser.java" +// line 330 "Parser.java" private static byte[] init__JSON_value_actions_0() { return new byte [] { @@ -433,7 +440,7 @@ private static byte[] init__JSON_value_from_state_actions_0() static final int JSON_value_en_main = 1; -// line 447 "Parser.rl" +// line 454 "Parser.rl" void parseValue(ParserResult res, int p, int pe) { @@ -441,14 +448,14 @@ void parseValue(ParserResult res, int p, int pe) { IRubyObject result = null; -// line 445 "Parser.java" +// line 452 "Parser.java" { cs = JSON_value_start; } -// line 454 "Parser.rl" +// line 461 "Parser.rl" -// line 452 "Parser.java" +// line 459 "Parser.java" { int _klen; int _trans = 0; @@ -474,13 +481,13 @@ void parseValue(ParserResult res, int p, int pe) { while ( _nacts-- > 0 ) { switch ( _JSON_value_actions[_acts++] ) { case 9: -// line 432 "Parser.rl" +// line 439 "Parser.rl" { p--; { p += 1; _goto_targ = 5; if (true) continue _goto;} } break; -// line 484 "Parser.java" +// line 491 "Parser.java" } } @@ -543,25 +550,25 @@ else if ( data[p] > _JSON_value_trans_keys[_mid+1] ) switch ( _JSON_value_actions[_acts++] ) { case 0: -// line 349 "Parser.rl" +// line 356 "Parser.rl" { result = getRuntime().getNil(); } break; case 1: -// line 352 "Parser.rl" +// line 359 "Parser.rl" { result = getRuntime().getFalse(); } break; case 2: -// line 355 "Parser.rl" +// line 362 "Parser.rl" { result = getRuntime().getTrue(); } break; case 3: -// line 358 "Parser.rl" +// line 365 "Parser.rl" { if (parser.allowNaN) { result = getConstant(CONST_NAN); @@ -571,7 +578,7 @@ else if ( data[p] > _JSON_value_trans_keys[_mid+1] ) } break; case 4: -// line 365 "Parser.rl" +// line 372 "Parser.rl" { if (parser.allowNaN) { result = getConstant(CONST_INFINITY); @@ -581,7 +588,7 @@ else if ( data[p] > _JSON_value_trans_keys[_mid+1] ) } break; case 5: -// line 372 "Parser.rl" +// line 379 "Parser.rl" { if (pe > p + 8 && absSubSequence(p, p + 9).equals(JSON_MINUS_INFINITY)) { @@ -610,7 +617,7 @@ else if ( data[p] > _JSON_value_trans_keys[_mid+1] ) } break; case 6: -// line 398 "Parser.rl" +// line 405 "Parser.rl" { parseString(res, p, pe); if (res.result == null) { @@ -623,7 +630,7 @@ else if ( data[p] > _JSON_value_trans_keys[_mid+1] ) } break; case 7: -// line 408 "Parser.rl" +// line 415 "Parser.rl" { currentNesting++; parseArray(res, p, pe); @@ -638,7 +645,7 @@ else if ( data[p] > _JSON_value_trans_keys[_mid+1] ) } break; case 8: -// line 420 "Parser.rl" +// line 427 "Parser.rl" { currentNesting++; parseObject(res, p, pe); @@ -652,7 +659,7 @@ else if ( data[p] > _JSON_value_trans_keys[_mid+1] ) } } break; -// line 656 "Parser.java" +// line 663 "Parser.java" } } } @@ -672,7 +679,7 @@ else if ( data[p] > _JSON_value_trans_keys[_mid+1] ) break; } } -// line 455 "Parser.rl" +// line 462 "Parser.rl" if (cs >= JSON_value_first_final && result != null) { if (parser.freeze) { @@ -685,7 +692,7 @@ else if ( data[p] > _JSON_value_trans_keys[_mid+1] ) } -// line 689 "Parser.java" +// line 696 "Parser.java" private static byte[] init__JSON_integer_actions_0() { return new byte [] { @@ -784,7 +791,7 @@ private static byte[] init__JSON_integer_trans_actions_0() static final int JSON_integer_en_main = 1; -// line 477 "Parser.rl" +// line 484 "Parser.rl" void parseInteger(ParserResult res, int p, int pe) { @@ -802,15 +809,15 @@ int parseIntegerInternal(int p, int pe) { int cs = EVIL; -// line 806 "Parser.java" +// line 813 "Parser.java" { cs = JSON_integer_start; } -// line 494 "Parser.rl" +// line 501 "Parser.rl" int memo = p; -// line 814 "Parser.java" +// line 821 "Parser.java" { int _klen; int _trans = 0; @@ -891,13 +898,13 @@ else if ( data[p] > _JSON_integer_trans_keys[_mid+1] ) switch ( _JSON_integer_actions[_acts++] ) { case 0: -// line 471 "Parser.rl" +// line 478 "Parser.rl" { p--; { p += 1; _goto_targ = 5; if (true) continue _goto;} } break; -// line 901 "Parser.java" +// line 908 "Parser.java" } } } @@ -917,7 +924,7 @@ else if ( data[p] > _JSON_integer_trans_keys[_mid+1] ) break; } } -// line 496 "Parser.rl" +// line 503 "Parser.rl" if (cs < JSON_integer_first_final) { return -1; @@ -939,7 +946,7 @@ RubyInteger bytesToInum(Ruby runtime, ByteList num) { } -// line 943 "Parser.java" +// line 950 "Parser.java" private static byte[] init__JSON_float_actions_0() { return new byte [] { @@ -1041,7 +1048,7 @@ private static byte[] init__JSON_float_trans_actions_0() static final int JSON_float_en_main = 1; -// line 531 "Parser.rl" +// line 538 "Parser.rl" void parseFloat(ParserResult res, int p, int pe) { @@ -1061,15 +1068,15 @@ int parseFloatInternal(int p, int pe) { int cs = EVIL; -// line 1065 "Parser.java" +// line 1072 "Parser.java" { cs = JSON_float_start; } -// line 550 "Parser.rl" +// line 557 "Parser.rl" int memo = p; -// line 1073 "Parser.java" +// line 1080 "Parser.java" { int _klen; int _trans = 0; @@ -1150,13 +1157,13 @@ else if ( data[p] > _JSON_float_trans_keys[_mid+1] ) switch ( _JSON_float_actions[_acts++] ) { case 0: -// line 522 "Parser.rl" +// line 529 "Parser.rl" { p--; { p += 1; _goto_targ = 5; if (true) continue _goto;} } break; -// line 1160 "Parser.java" +// line 1167 "Parser.java" } } } @@ -1176,7 +1183,7 @@ else if ( data[p] > _JSON_float_trans_keys[_mid+1] ) break; } } -// line 552 "Parser.rl" +// line 559 "Parser.rl" if (cs < JSON_float_first_final) { return -1; @@ -1199,7 +1206,7 @@ IRubyObject createCustomDecimal(int p, int new_p) { } -// line 1203 "Parser.java" +// line 1210 "Parser.java" private static byte[] init__JSON_string_actions_0() { return new byte [] { @@ -1301,7 +1308,7 @@ private static byte[] init__JSON_string_trans_actions_0() static final int JSON_string_en_main = 1; -// line 604 "Parser.rl" +// line 611 "Parser.rl" void parseString(ParserResult res, int p, int pe) { @@ -1309,15 +1316,15 @@ void parseString(ParserResult res, int p, int pe) { IRubyObject result = null; -// line 1313 "Parser.java" +// line 1320 "Parser.java" { cs = JSON_string_start; } -// line 611 "Parser.rl" +// line 618 "Parser.rl" int memo = p; -// line 1321 "Parser.java" +// line 1328 "Parser.java" { int _klen; int _trans = 0; @@ -1398,7 +1405,7 @@ else if ( data[p] > _JSON_string_trans_keys[_mid+1] ) switch ( _JSON_string_actions[_acts++] ) { case 0: -// line 579 "Parser.rl" +// line 586 "Parser.rl" { int offset = byteList.begin(); ByteList decoded = decoder.decode(byteList, memo + 1 - offset, @@ -1413,13 +1420,13 @@ else if ( data[p] > _JSON_string_trans_keys[_mid+1] ) } break; case 1: -// line 592 "Parser.rl" +// line 599 "Parser.rl" { p--; { p += 1; _goto_targ = 5; if (true) continue _goto;} } break; -// line 1423 "Parser.java" +// line 1430 "Parser.java" } } } @@ -1439,7 +1446,7 @@ else if ( data[p] > _JSON_string_trans_keys[_mid+1] ) break; } } -// line 613 "Parser.rl" +// line 620 "Parser.rl" if (parser.createAdditions) { RubyHash matchString = parser.match_string; @@ -1484,7 +1491,7 @@ public void visit(IRubyObject pattern, IRubyObject klass) { } -// line 1488 "Parser.java" +// line 1495 "Parser.java" private static byte[] init__JSON_array_actions_0() { return new byte [] { @@ -1495,36 +1502,86 @@ private static byte[] init__JSON_array_actions_0() private static final byte _JSON_array_actions[] = init__JSON_array_actions_0(); +private static byte[] init__JSON_array_cond_offsets_0() +{ + return new byte [] { + 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 6, 6, 6, 6, 6, 8, 11, 16, 19 + }; +} + +private static final byte _JSON_array_cond_offsets[] = init__JSON_array_cond_offsets_0(); + + +private static byte[] init__JSON_array_cond_lengths_0() +{ + return new byte [] { + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 5, 0, 0, 0, 0, 2, 3, 5, 3, 0 + }; +} + +private static final byte _JSON_array_cond_lengths[] = init__JSON_array_cond_lengths_0(); + + +private static int[] init__JSON_array_cond_keys_0() +{ + return new int [] { + 44, 44, 9, 9, 10, 10, 13, 13, 32, 32, 47, 47, + 42, 42, 47, 47, 0, 41, 42, 42, 43,65535, 0, 41, + 42, 42, 43, 46, 47, 47, 48,65535, 0, 9, 10, 10, + 11,65535, 0 + }; +} + +private static final int _JSON_array_cond_keys[] = init__JSON_array_cond_keys_0(); + + +private static byte[] init__JSON_array_cond_spaces_0() +{ + return new byte [] { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 + }; +} + +private static final byte _JSON_array_cond_spaces[] = init__JSON_array_cond_spaces_0(); + + private static byte[] init__JSON_array_key_offsets_0() { return new byte [] { - 0, 0, 1, 18, 25, 41, 43, 44, 46, 47, 49, 50, - 52, 53, 55, 56, 58, 59 + 0, 0, 1, 18, 26, 28, 29, 31, 32, 48, 50, 51, + 53, 54, 76, 78, 79, 81, 82, 86, 92, 100, 106 }; } private static final byte _JSON_array_key_offsets[] = init__JSON_array_key_offsets_0(); -private static char[] init__JSON_array_trans_keys_0() +private static int[] init__JSON_array_trans_keys_0() { - return new char [] { + return new int [] { 91, 13, 32, 34, 45, 47, 73, 78, 91, 93, 102, 110, - 116, 123, 9, 10, 48, 57, 13, 32, 44, 47, 93, 9, - 10, 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, 42, 47, 42, 42, 47, 10, 0 + 116, 123, 9, 10, 48, 57, 13, 32, 47, 93,65580,131116, + 9, 10, 42, 47, 42, 42, 47, 10, 13, 32, 34, 45, + 47, 73, 78, 91, 102, 110, 116, 123, 9, 10, 48, 57, + 42, 47, 42, 42, 47, 10, 34, 45, 73, 78, 91, 93, + 102, 110, 116, 123,65549,65568,65583,131085,131104,131119, 48, 57, + 65545,65546,131081,131082, 42, 47, 42, 42, 47, 10,65578,65583, + 131114,131119,65578,131114,65536,131071,131072,196607,65578,65583,131114,131119, + 65536,131071,131072,196607,65546,131082,65536,131071,131072,196607, 0 }; } -private static final char _JSON_array_trans_keys[] = init__JSON_array_trans_keys_0(); +private static final int _JSON_array_trans_keys[] = init__JSON_array_trans_keys_0(); private static byte[] init__JSON_array_single_lengths_0() { return new byte [] { - 0, 1, 13, 5, 12, 2, 1, 2, 1, 2, 1, 2, - 1, 2, 1, 2, 1, 0 + 0, 1, 13, 6, 2, 1, 2, 1, 12, 2, 1, 2, + 1, 16, 2, 1, 2, 1, 4, 2, 4, 2, 0 }; } @@ -1534,34 +1591,38 @@ private static byte[] init__JSON_array_single_lengths_0() private static byte[] init__JSON_array_range_lengths_0() { return new byte [] { - 0, 0, 2, 1, 2, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0 + 0, 0, 2, 1, 0, 0, 0, 0, 2, 0, 0, 0, + 0, 3, 0, 0, 0, 0, 0, 2, 2, 2, 0 }; } private static final byte _JSON_array_range_lengths[] = init__JSON_array_range_lengths_0(); -private static byte[] init__JSON_array_index_offsets_0() +private static short[] init__JSON_array_index_offsets_0() { - return new byte [] { - 0, 0, 2, 18, 25, 40, 43, 45, 48, 50, 53, 55, - 58, 60, 63, 65, 68, 70 + return new short [] { + 0, 0, 2, 18, 26, 29, 31, 34, 36, 51, 54, 56, + 59, 61, 81, 84, 86, 89, 91, 96, 101, 108, 113 }; } -private static final byte _JSON_array_index_offsets[] = init__JSON_array_index_offsets_0(); +private static final short _JSON_array_index_offsets[] = init__JSON_array_index_offsets_0(); private static byte[] init__JSON_array_indicies_0() { return new byte [] { 0, 1, 0, 0, 2, 2, 3, 2, 2, 2, 4, 2, - 2, 2, 2, 0, 2, 1, 5, 5, 6, 7, 4, 5, - 1, 6, 6, 2, 2, 8, 2, 2, 2, 2, 2, 2, - 2, 6, 2, 1, 9, 10, 1, 11, 9, 11, 6, 9, - 6, 10, 12, 13, 1, 14, 12, 14, 5, 12, 5, 13, - 15, 16, 1, 17, 15, 17, 0, 15, 0, 16, 1, 0 + 2, 2, 2, 0, 2, 1, 5, 5, 6, 4, 7, 8, + 5, 1, 9, 10, 1, 11, 9, 11, 5, 9, 5, 10, + 7, 7, 2, 2, 12, 2, 2, 2, 2, 2, 2, 2, + 7, 2, 1, 13, 14, 1, 15, 13, 15, 7, 13, 7, + 14, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 0, + 0, 3, 8, 8, 16, 2, 0, 8, 1, 17, 18, 1, + 19, 17, 19, 0, 17, 0, 18, 17, 18, 20, 21, 1, + 19, 22, 17, 20, 1, 19, 0, 22, 8, 17, 20, 1, + 0, 8, 18, 21, 1, 1, 0 }; } @@ -1571,8 +1632,8 @@ private static byte[] init__JSON_array_indicies_0() private static byte[] init__JSON_array_trans_targs_0() { return new byte [] { - 2, 0, 3, 13, 17, 3, 4, 9, 5, 6, 8, 7, - 10, 12, 11, 14, 16, 15 + 2, 0, 3, 14, 22, 3, 4, 8, 13, 5, 7, 6, + 9, 10, 12, 11, 18, 15, 17, 16, 19, 21, 20 }; } @@ -1583,7 +1644,7 @@ private static byte[] init__JSON_array_trans_actions_0() { return new byte [] { 0, 0, 1, 0, 3, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; } @@ -1591,13 +1652,13 @@ private static byte[] init__JSON_array_trans_actions_0() static final int JSON_array_start = 1; -static final int JSON_array_first_final = 17; +static final int JSON_array_first_final = 22; static final int JSON_array_error = 0; static final int JSON_array_en_main = 1; -// line 693 "Parser.rl" +// line 702 "Parser.rl" void parseArray(ParserResult res, int p, int pe) { @@ -1617,17 +1678,18 @@ void parseArray(ParserResult res, int p, int pe) { } -// line 1621 "Parser.java" +// line 1682 "Parser.java" { cs = JSON_array_start; } -// line 712 "Parser.rl" +// line 721 "Parser.rl" -// line 1628 "Parser.java" +// line 1689 "Parser.java" { int _klen; int _trans = 0; + int _widec; int _acts; int _nacts; int _keys; @@ -1645,6 +1707,37 @@ void parseArray(ParserResult res, int p, int pe) { continue _goto; } case 1: + _widec = data[p]; + _keys = _JSON_array_cond_offsets[cs]*2 +; _klen = _JSON_array_cond_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 ( _widec < _JSON_array_cond_keys[_mid] ) + _upper = _mid - 2; + else if ( _widec > _JSON_array_cond_keys[_mid+1] ) + _lower = _mid + 2; + else { + switch ( _JSON_array_cond_spaces[_JSON_array_cond_offsets[cs] + ((_mid - _keys)>>1)] ) { + case 0: { + _widec = 65536 + (data[p] - 0); + if ( +// line 669 "Parser.rl" + parser.allowTrailingComma ) _widec += 65536; + break; + } + } + break; + } + } + } + _match: do { _keys = _JSON_array_key_offsets[cs]; _trans = _JSON_array_index_offsets[cs]; @@ -1658,9 +1751,9 @@ void parseArray(ParserResult res, int p, int pe) { break; _mid = _lower + ((_upper-_lower) >> 1); - if ( data[p] < _JSON_array_trans_keys[_mid] ) + if ( _widec < _JSON_array_trans_keys[_mid] ) _upper = _mid - 1; - else if ( data[p] > _JSON_array_trans_keys[_mid] ) + else if ( _widec > _JSON_array_trans_keys[_mid] ) _lower = _mid + 1; else { _trans += (_mid - _keys); @@ -1681,9 +1774,9 @@ else if ( data[p] > _JSON_array_trans_keys[_mid] ) break; _mid = _lower + (((_upper-_lower) >> 1) & ~1); - if ( data[p] < _JSON_array_trans_keys[_mid] ) + if ( _widec < _JSON_array_trans_keys[_mid] ) _upper = _mid - 2; - else if ( data[p] > _JSON_array_trans_keys[_mid+1] ) + else if ( _widec > _JSON_array_trans_keys[_mid+1] ) _lower = _mid + 2; else { _trans += ((_mid - _keys)>>1); @@ -1705,7 +1798,7 @@ else if ( data[p] > _JSON_array_trans_keys[_mid+1] ) switch ( _JSON_array_actions[_acts++] ) { case 0: -// line 662 "Parser.rl" +// line 671 "Parser.rl" { parseValue(res, p, pe); if (res.result == null) { @@ -1722,13 +1815,13 @@ else if ( data[p] > _JSON_array_trans_keys[_mid+1] ) } break; case 1: -// line 677 "Parser.rl" +// line 686 "Parser.rl" { p--; { p += 1; _goto_targ = 5; if (true) continue _goto;} } break; -// line 1732 "Parser.java" +// line 1825 "Parser.java" } } } @@ -1748,7 +1841,7 @@ else if ( data[p] > _JSON_array_trans_keys[_mid+1] ) break; } } -// line 713 "Parser.rl" +// line 722 "Parser.rl" if (cs >= JSON_array_first_final) { res.update(result, p + 1); @@ -1758,7 +1851,7 @@ else if ( data[p] > _JSON_array_trans_keys[_mid+1] ) } -// line 1762 "Parser.java" +// line 1855 "Parser.java" private static byte[] init__JSON_object_actions_0() { return new byte [] { @@ -1769,40 +1862,91 @@ private static byte[] init__JSON_object_actions_0() private static final byte _JSON_object_actions[] = init__JSON_object_actions_0(); +private static byte[] init__JSON_object_cond_offsets_0() +{ + return new byte [] { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 8, 11, 16, + 19, 19, 19, 19, 19, 19, 19, 19, 19 + }; +} + +private static final byte _JSON_object_cond_offsets[] = init__JSON_object_cond_offsets_0(); + + +private static byte[] init__JSON_object_cond_lengths_0() +{ + return new byte [] { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 5, 3, + 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; +} + +private static final byte _JSON_object_cond_lengths[] = init__JSON_object_cond_lengths_0(); + + +private static int[] init__JSON_object_cond_keys_0() +{ + return new int [] { + 9, 9, 10, 10, 13, 13, 32, 32, 44, 44, 47, 47, + 42, 42, 47, 47, 0, 41, 42, 42, 43,65535, 0, 41, + 42, 42, 43, 46, 47, 47, 48,65535, 0, 9, 10, 10, + 11,65535, 0 + }; +} + +private static final int _JSON_object_cond_keys[] = init__JSON_object_cond_keys_0(); + + +private static byte[] init__JSON_object_cond_spaces_0() +{ + return new byte [] { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 + }; +} + +private static final byte _JSON_object_cond_spaces[] = init__JSON_object_cond_spaces_0(); + + private static byte[] init__JSON_object_key_offsets_0() { return new byte [] { - 0, 0, 1, 8, 14, 16, 17, 19, 20, 36, 43, 49, - 51, 52, 54, 55, 57, 58, 60, 61, 63, 64, 66, 67, - 69, 70, 72, 73 + 0, 0, 1, 8, 14, 16, 17, 19, 20, 36, 49, 56, + 62, 64, 65, 67, 68, 70, 71, 73, 74, 78, 84, 92, + 98, 100, 101, 103, 104, 106, 107, 109, 110 }; } private static final byte _JSON_object_key_offsets[] = init__JSON_object_key_offsets_0(); -private static char[] init__JSON_object_trans_keys_0() +private static int[] init__JSON_object_trans_keys_0() { - return new char [] { + return new int [] { 123, 13, 32, 34, 47, 125, 9, 10, 13, 32, 47, 58, 9, 10, 42, 47, 42, 42, 47, 10, 13, 32, 34, 45, 47, 73, 78, 91, 102, 110, 116, 123, 9, 10, 48, 57, - 13, 32, 44, 47, 125, 9, 10, 13, 32, 34, 47, 9, - 10, 42, 47, 42, 42, 47, 10, 42, 47, 42, 42, 47, - 10, 42, 47, 42, 42, 47, 10, 42, 47, 42, 42, 47, - 10, 0 + 125,65549,65568,65580,65583,131085,131104,131116,131119,65545,65546,131081, + 131082, 13, 32, 44, 47, 125, 9, 10, 13, 32, 34, 47, + 9, 10, 42, 47, 42, 42, 47, 10, 42, 47, 42, 42, + 47, 10,65578,65583,131114,131119,65578,131114,65536,131071,131072,196607, + 65578,65583,131114,131119,65536,131071,131072,196607,65546,131082,65536,131071, + 131072,196607, 42, 47, 42, 42, 47, 10, 42, 47, 42, 42, + 47, 10, 0 }; } -private static final char _JSON_object_trans_keys[] = init__JSON_object_trans_keys_0(); +private static final int _JSON_object_trans_keys[] = init__JSON_object_trans_keys_0(); private static byte[] init__JSON_object_single_lengths_0() { return new byte [] { - 0, 1, 5, 4, 2, 1, 2, 1, 12, 5, 4, 2, - 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, - 1, 2, 1, 0 + 0, 1, 5, 4, 2, 1, 2, 1, 12, 9, 5, 4, + 2, 1, 2, 1, 2, 1, 2, 1, 4, 2, 4, 2, + 2, 1, 2, 1, 2, 1, 2, 1, 0 }; } @@ -1812,25 +1956,25 @@ private static byte[] init__JSON_object_single_lengths_0() private static byte[] init__JSON_object_range_lengths_0() { return new byte [] { - 0, 0, 1, 1, 0, 0, 0, 0, 2, 1, 1, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0 + 0, 0, 1, 1, 0, 0, 0, 0, 2, 2, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, + 0, 0, 0, 0, 0, 0, 0, 0, 0 }; } private static final byte _JSON_object_range_lengths[] = init__JSON_object_range_lengths_0(); -private static byte[] init__JSON_object_index_offsets_0() +private static short[] init__JSON_object_index_offsets_0() { - return new byte [] { - 0, 0, 2, 9, 15, 18, 20, 23, 25, 40, 47, 53, - 56, 58, 61, 63, 66, 68, 71, 73, 76, 78, 81, 83, - 86, 88, 91, 93 + return new short [] { + 0, 0, 2, 9, 15, 18, 20, 23, 25, 40, 52, 59, + 65, 68, 70, 73, 75, 78, 80, 83, 85, 90, 95, 102, + 107, 110, 112, 115, 117, 120, 122, 125, 127 }; } -private static final byte _JSON_object_index_offsets[] = init__JSON_object_index_offsets_0(); +private static final short _JSON_object_index_offsets[] = init__JSON_object_index_offsets_0(); private static byte[] init__JSON_object_indicies_0() @@ -1839,11 +1983,14 @@ private static byte[] init__JSON_object_indicies_0() 0, 1, 0, 0, 2, 3, 4, 0, 1, 5, 5, 6, 7, 5, 1, 8, 9, 1, 10, 8, 10, 5, 8, 5, 9, 7, 7, 11, 11, 12, 11, 11, 11, 11, 11, 11, - 11, 7, 11, 1, 13, 13, 14, 15, 4, 13, 1, 14, - 14, 2, 16, 14, 1, 17, 18, 1, 19, 17, 19, 14, - 17, 14, 18, 20, 21, 1, 22, 20, 22, 13, 20, 13, - 21, 23, 24, 1, 25, 23, 25, 7, 23, 7, 24, 26, - 27, 1, 28, 26, 28, 0, 26, 0, 27, 1, 0 + 11, 7, 11, 1, 4, 13, 13, 14, 15, 16, 16, 0, + 17, 13, 16, 1, 13, 13, 14, 15, 4, 13, 1, 14, + 14, 2, 18, 14, 1, 19, 20, 1, 21, 19, 21, 14, + 19, 14, 20, 22, 23, 1, 24, 22, 24, 13, 22, 13, + 23, 22, 23, 25, 26, 1, 24, 27, 22, 25, 1, 24, + 13, 27, 16, 22, 25, 1, 13, 16, 23, 26, 1, 28, + 29, 1, 30, 28, 30, 7, 28, 7, 29, 31, 32, 1, + 33, 31, 33, 0, 31, 0, 32, 1, 0 }; } @@ -1853,9 +2000,9 @@ private static byte[] init__JSON_object_indicies_0() private static byte[] init__JSON_object_trans_targs_0() { return new byte [] { - 2, 0, 3, 23, 27, 3, 4, 8, 5, 7, 6, 9, - 19, 9, 10, 15, 11, 12, 14, 13, 16, 18, 17, 20, - 22, 21, 24, 26, 25 + 2, 0, 3, 28, 32, 3, 4, 8, 5, 7, 6, 9, + 24, 10, 11, 16, 9, 20, 12, 13, 15, 14, 17, 19, + 18, 21, 23, 22, 25, 27, 26, 29, 31, 30 }; } @@ -1867,7 +2014,7 @@ private static byte[] init__JSON_object_trans_actions_0() return new byte [] { 0, 0, 3, 0, 5, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; } @@ -1875,13 +2022,13 @@ private static byte[] init__JSON_object_trans_actions_0() static final int JSON_object_start = 1; -static final int JSON_object_first_final = 27; +static final int JSON_object_first_final = 32; static final int JSON_object_error = 0; static final int JSON_object_en_main = 1; -// line 772 "Parser.rl" +// line 785 "Parser.rl" void parseObject(ParserResult res, int p, int pe) { @@ -1906,17 +2053,18 @@ void parseObject(ParserResult res, int p, int pe) { } -// line 1910 "Parser.java" +// line 2057 "Parser.java" { cs = JSON_object_start; } -// line 796 "Parser.rl" +// line 809 "Parser.rl" -// line 1917 "Parser.java" +// line 2064 "Parser.java" { int _klen; int _trans = 0; + int _widec; int _acts; int _nacts; int _keys; @@ -1934,6 +2082,37 @@ void parseObject(ParserResult res, int p, int pe) { continue _goto; } case 1: + _widec = data[p]; + _keys = _JSON_object_cond_offsets[cs]*2 +; _klen = _JSON_object_cond_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 ( _widec < _JSON_object_cond_keys[_mid] ) + _upper = _mid - 2; + else if ( _widec > _JSON_object_cond_keys[_mid+1] ) + _lower = _mid + 2; + else { + switch ( _JSON_object_cond_spaces[_JSON_object_cond_offsets[cs] + ((_mid - _keys)>>1)] ) { + case 0: { + _widec = 65536 + (data[p] - 0); + if ( +// line 736 "Parser.rl" + parser.allowTrailingComma ) _widec += 65536; + break; + } + } + break; + } + } + } + _match: do { _keys = _JSON_object_key_offsets[cs]; _trans = _JSON_object_index_offsets[cs]; @@ -1947,9 +2126,9 @@ void parseObject(ParserResult res, int p, int pe) { break; _mid = _lower + ((_upper-_lower) >> 1); - if ( data[p] < _JSON_object_trans_keys[_mid] ) + if ( _widec < _JSON_object_trans_keys[_mid] ) _upper = _mid - 1; - else if ( data[p] > _JSON_object_trans_keys[_mid] ) + else if ( _widec > _JSON_object_trans_keys[_mid] ) _lower = _mid + 1; else { _trans += (_mid - _keys); @@ -1970,9 +2149,9 @@ else if ( data[p] > _JSON_object_trans_keys[_mid] ) break; _mid = _lower + (((_upper-_lower) >> 1) & ~1); - if ( data[p] < _JSON_object_trans_keys[_mid] ) + if ( _widec < _JSON_object_trans_keys[_mid] ) _upper = _mid - 2; - else if ( data[p] > _JSON_object_trans_keys[_mid+1] ) + else if ( _widec > _JSON_object_trans_keys[_mid+1] ) _lower = _mid + 2; else { _trans += ((_mid - _keys)>>1); @@ -1994,7 +2173,7 @@ else if ( data[p] > _JSON_object_trans_keys[_mid+1] ) switch ( _JSON_object_actions[_acts++] ) { case 0: -// line 727 "Parser.rl" +// line 738 "Parser.rl" { parseValue(res, p, pe); if (res.result == null) { @@ -2011,7 +2190,7 @@ else if ( data[p] > _JSON_object_trans_keys[_mid+1] ) } break; case 1: -// line 742 "Parser.rl" +// line 753 "Parser.rl" { parseString(res, p, pe); if (res.result == null) { @@ -2031,13 +2210,13 @@ else if ( data[p] > _JSON_object_trans_keys[_mid+1] ) } break; case 2: -// line 760 "Parser.rl" +// line 771 "Parser.rl" { p--; { p += 1; _goto_targ = 5; if (true) continue _goto;} } break; -// line 2041 "Parser.java" +// line 2220 "Parser.java" } } } @@ -2057,7 +2236,7 @@ else if ( data[p] > _JSON_object_trans_keys[_mid+1] ) break; } } -// line 797 "Parser.rl" +// line 810 "Parser.rl" if (cs < JSON_object_first_final) { res.update(null, p + 1); @@ -2090,7 +2269,7 @@ else if ( data[p] > _JSON_object_trans_keys[_mid+1] ) } -// line 2094 "Parser.java" +// line 2273 "Parser.java" private static byte[] init__JSON_actions_0() { return new byte [] { @@ -2193,7 +2372,7 @@ private static byte[] init__JSON_trans_actions_0() static final int JSON_en_main = 1; -// line 848 "Parser.rl" +// line 861 "Parser.rl" public IRubyObject parseImplemetation() { @@ -2203,16 +2382,16 @@ public IRubyObject parseImplemetation() { ParserResult res = new ParserResult(); -// line 2207 "Parser.java" +// line 2386 "Parser.java" { cs = JSON_start; } -// line 857 "Parser.rl" +// line 870 "Parser.rl" p = byteList.begin(); pe = p + byteList.length(); -// line 2216 "Parser.java" +// line 2395 "Parser.java" { int _klen; int _trans = 0; @@ -2293,7 +2472,7 @@ else if ( data[p] > _JSON_trans_keys[_mid+1] ) switch ( _JSON_actions[_acts++] ) { case 0: -// line 834 "Parser.rl" +// line 847 "Parser.rl" { parseValue(res, p, pe); if (res.result == null) { @@ -2305,7 +2484,7 @@ else if ( data[p] > _JSON_trans_keys[_mid+1] ) } } break; -// line 2309 "Parser.java" +// line 2488 "Parser.java" } } } @@ -2325,7 +2504,7 @@ else if ( data[p] > _JSON_trans_keys[_mid+1] ) break; } } -// line 860 "Parser.rl" +// line 873 "Parser.rl" if (cs >= JSON_first_final && p == pe) { return result; diff --git a/java/src/json/ext/Parser.rl b/java/src/json/ext/Parser.rl index f670bad1..0d64b7fe 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 boolean createAdditions; private int maxNesting; private boolean allowNaN; + private boolean allowTrailingComma; private boolean symbolizeNames; private boolean freeze; private RubyClass objectClass; @@ -118,6 +119,11 @@ public class Parser extends RubyObject { * Infinity and -Infinity in defiance of RFC 4627 * to be parsed by the Parser. This option defaults to false. * + *
:allow_trailing_comma + *
If set to true, allow arrays and objects with a trailing + * comma in defiance of RFC 4627 to be parsed by the Parser. + * This option defaults to false. + * *
:symbolize_names *
If set to true, returns symbols for the names (keys) in * a JSON object. Otherwise strings are returned, which is also the default. @@ -158,6 +164,7 @@ public class Parser extends RubyObject { 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.allowTrailingComma = opts.getBool("allow_trailing_comma", false); this.symbolizeNames = opts.getBool("symbolize_names", false); this.freeze = opts.getBool("freeze", false); this.createId = opts.getString("create_id", getCreateId(context)); @@ -659,6 +666,8 @@ public class Parser extends RubyObject { write data; + action allow_trailing_comma { parser.allowTrailingComma } + action parse_value { parseValue(res, fpc, pe); if (res.result == null) { @@ -687,7 +696,7 @@ public class Parser extends RubyObject { ignore* ) ( ignore* next_element - ignore* )* )? + ignore* )* ( (value_separator ignore*) when allow_trailing_comma )? )? ignore* end_array @exit; }%% @@ -724,6 +733,8 @@ public class Parser extends RubyObject { write data; + action allow_trailing_comma { parser.allowTrailingComma } + action parse_value { parseValue(res, fpc, pe); if (res.result == null) { @@ -767,7 +778,9 @@ public class Parser extends RubyObject { next_pair = ignore* value_separator pair; main := ( - begin_object (pair (next_pair)*)? ignore* end_object + begin_object + (pair (next_pair)*((ignore* value_separator) when allow_trailing_comma)?)? ignore* + end_object ) @exit; }%% diff --git a/lib/json/pure/parser.rb b/lib/json/pure/parser.rb index e1d701b3..8f75eb77 100644 --- a/lib/json/pure/parser.rb +++ b/lib/json/pure/parser.rb @@ -61,6 +61,9 @@ class Parser < StringScanner # * *allow_nan*: If set to true, allow NaN, Infinity and -Infinity in # defiance of RFC 7159 to be parsed by the Parser. This option defaults # to false. + # * *allow_trailing_comma*: If set to true, allow arrays and objects with a + # trailing comma in defiance of RFC 7159 to be parsed by the Parser. + # This option defaults to false. # * *freeze*: If set to true, all parsed objects will be frozen. Parsed # string will be deduplicated if possible. # * *symbolize_names*: If set to true, returns symbols for the names @@ -87,6 +90,7 @@ def initialize(source, opts = {}) @max_nesting = 0 end @allow_nan = !!opts[:allow_nan] + @allow_trailing_comma = !!opts[:allow_trailing_comma] @symbolize_names = !!opts[:symbolize_names] @freeze = !!opts[:freeze] if opts.key?(:create_additions) @@ -272,7 +276,7 @@ def parse_array raise ParserError, "expected ',' or ']' in array at '#{peek(20)}'!" end when scan(ARRAY_CLOSE) - if delim + if delim && !@allow_trailing_comma raise ParserError, "expected next element in array at '#{peek(20)}'!" end break @@ -315,7 +319,7 @@ def parse_object raise ParserError, "expected value in object at '#{peek(20)}'!" end when scan(OBJECT_CLOSE) - if delim + if delim && !@allow_trailing_comma raise ParserError, "expected next name, value pair in object at '#{peek(20)}'!" end if @create_additions and klassname = result[@create_id] diff --git a/tests/json_parser_test.rb b/tests/json_parser_test.rb index dce693e5..1d4e4349 100644 --- a/tests/json_parser_test.rb +++ b/tests/json_parser_test.rb @@ -150,6 +150,33 @@ def test_parse_arrays , [2718.0E-3 ],\r[ null] , [[1, -2, 3 ]], [false ],[ true]\n ] })) end + def test_parse_arrays_with_allow_trailing_comma + assert_equal([], parse('[]', allow_trailing_comma: true)) + assert_equal([], parse('[]', allow_trailing_comma: false)) + assert_raise(JSON::ParserError) { parse('[,]', allow_trailing_comma: true) } + assert_raise(JSON::ParserError) { parse('[,]', allow_trailing_comma: false) } + + assert_equal([1], parse('[1]', allow_trailing_comma: true)) + assert_equal([1], parse('[1]', allow_trailing_comma: false)) + assert_equal([1], parse('[1,]', allow_trailing_comma: true)) + assert_raise(JSON::ParserError) { parse('[1,]', allow_trailing_comma: false) } + + assert_equal([1, 2, 3], parse('[1,2,3]', allow_trailing_comma: true)) + assert_equal([1, 2, 3], parse('[1,2,3]', allow_trailing_comma: false)) + assert_equal([1, 2, 3], parse('[1,2,3,]', allow_trailing_comma: true)) + assert_raise(JSON::ParserError) { parse('[1,2,3,]', allow_trailing_comma: false) } + + assert_equal([1, 2, 3], parse('[ 1 , 2 , 3 ]', allow_trailing_comma: true)) + assert_equal([1, 2, 3], parse('[ 1 , 2 , 3 ]', allow_trailing_comma: false)) + assert_equal([1, 2, 3], parse('[ 1 , 2 , 3 , ]', allow_trailing_comma: true)) + assert_raise(JSON::ParserError) { parse('[ 1 , 2 , 3 , ]', allow_trailing_comma: false) } + + assert_equal({'foo' => [1, 2, 3]}, parse('{ "foo": [1,2,3] }', allow_trailing_comma: true)) + assert_equal({'foo' => [1, 2, 3]}, parse('{ "foo": [1,2,3] }', allow_trailing_comma: false)) + assert_equal({'foo' => [1, 2, 3]}, parse('{ "foo": [1,2,3,] }', allow_trailing_comma: true)) + assert_raise(JSON::ParserError) { parse('{ "foo": [1,2,3,] }', allow_trailing_comma: false) } + end + def test_parse_json_primitive_values assert_raise(JSON::ParserError) { parse('') } assert_raise(TypeError) { parse(nil) } @@ -377,6 +404,66 @@ def test_parse_object assert_equal({'foo'=>'bar'}, parse(' { "foo" : "bar" } ')) end + def test_parse_object_with_allow_trailing_comma + assert_equal({}, parse('{}', allow_trailing_comma: true)) + assert_equal({}, parse('{}', allow_trailing_comma: false)) + assert_raise(JSON::ParserError) { parse('{,}', allow_trailing_comma: true) } + assert_raise(JSON::ParserError) { parse('{,}', allow_trailing_comma: false) } + + assert_equal({'foo'=>'bar'}, parse('{"foo":"bar"}', allow_trailing_comma: true)) + assert_equal({'foo'=>'bar'}, parse('{"foo":"bar"}', allow_trailing_comma: false)) + assert_equal({'foo'=>'bar'}, parse('{"foo":"bar",}', allow_trailing_comma: true)) + assert_raise(JSON::ParserError) { parse('{"foo":"bar",}', allow_trailing_comma: false) } + + assert_equal( + {'foo'=>'bar', 'baz'=>'qux', 'quux'=>'garply'}, + parse('{"foo":"bar","baz":"qux","quux":"garply"}', allow_trailing_comma: true) + ) + assert_equal( + {'foo'=>'bar', 'baz'=>'qux', 'quux'=>'garply'}, + parse('{"foo":"bar","baz":"qux","quux":"garply"}', allow_trailing_comma: false) + ) + assert_equal( + {'foo'=>'bar', 'baz'=>'qux', 'quux'=>'garply'}, + parse('{"foo":"bar","baz":"qux","quux":"garply",}', allow_trailing_comma: true) + ) + assert_raise(JSON::ParserError) { + parse('{"foo":"bar","baz":"qux","quux":"garply",}', allow_trailing_comma: false) + } + + assert_equal( + {'foo'=>'bar', 'baz'=>'qux', 'quux'=>'garply'}, + parse('{ "foo":"bar" , "baz":"qux" , "quux":"garply" }', allow_trailing_comma: true) + ) + assert_equal( + {'foo'=>'bar', 'baz'=>'qux', 'quux'=>'garply'}, + parse('{ "foo":"bar" , "baz":"qux" , "quux":"garply" }', allow_trailing_comma: false) + ) + assert_equal( + {'foo'=>'bar', 'baz'=>'qux', 'quux'=>'garply'}, + parse('{ "foo":"bar" , "baz":"qux" , "quux":"garply" , }', allow_trailing_comma: true) + ) + assert_raise(JSON::ParserError) { + parse('{ "foo":"bar" , "baz":"qux" , "quux":"garply" , }', allow_trailing_comma: false) + } + + assert_equal( + [{'foo'=>'bar', 'baz'=>'qux', 'quux'=>'garply'}], + parse('[{"foo":"bar","baz":"qux","quux":"garply"}]', allow_trailing_comma: true) + ) + assert_equal( + [{'foo'=>'bar', 'baz'=>'qux', 'quux'=>'garply'}], + parse('[{"foo":"bar","baz":"qux","quux":"garply"}]', allow_trailing_comma: false) + ) + assert_equal( + [{'foo'=>'bar', 'baz'=>'qux', 'quux'=>'garply'}], + parse('[{"foo":"bar","baz":"qux","quux":"garply",}]', allow_trailing_comma: true) + ) + assert_raise(JSON::ParserError) { + parse('[{"foo":"bar","baz":"qux","quux":"garply",}]', allow_trailing_comma: false) + } + end + class SubHash < Hash def []=(k, v) @item_set = true