From e525bed4457ad2a785dda5a591ddcd6334ec62a5 Mon Sep 17 00:00:00 2001 From: lukeg Date: Sun, 29 Jan 2023 09:34:13 -0500 Subject: [PATCH 1/2] Make JSON::Parser initialization faster Remove calls to rb_funcall, don't go back in to interpreter if not necessary. Also remove unnecessary calls to rb_respond_to(val) when val is nil. Speedup of JSON.parse when parsing small amount of data in a tight loop is up to 40%. --- ext/json/ext/parser/parser.c | 4811 +++++++++++++-------------------- ext/json/ext/parser/parser.h | 4 +- ext/json/ext/parser/parser.rl | 32 +- 3 files changed, 1864 insertions(+), 2983 deletions(-) diff --git a/ext/json/ext/parser/parser.c b/ext/json/ext/parser/parser.c index 9bd7f197..3cae2352 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,3320 +28,2199 @@ 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_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_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" 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 182 "parser.rl" +#line 138 "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; - 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 st23; + case 125: goto tr4; + } + if ( 9 <= (*p) && (*p) <= 10 ) + goto st2; + goto st0; +tr2: +#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++; 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 179 "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 st19; + 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 133 "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; - } - } - if ( 9 <= ( (*( p))) && ( (*( p))) <= 10 ) { - goto st9; - } - { - goto st0; - } - st10: - p+= 1; - if ( p == pe ) +case 9: +#line 267 "parser.c" + switch( (*p) ) { + case 13: goto st9; + case 32: goto st9; + case 44: goto st10; + case 47: goto st15; + case 125: goto tr4; + } + if ( 9 <= (*p) && (*p) <= 10 ) + goto st9; + 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 34: goto tr2; + case 47: goto st11; + } + 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 42: goto st12; + case 47: goto st14; + } + 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: + if ( (*p) == 42 ) + goto st13; + goto st12; +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: + switch( (*p) ) { + case 42: goto st13; + case 47: goto st10; + } + goto st12; +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: + if ( (*p) == 10 ) + goto st10; + goto st14; +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: + switch( (*p) ) { + case 42: goto st16; + case 47: goto st18; + } + goto st0; +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: + if ( (*p) == 42 ) + goto st17; + goto st16; +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: + switch( (*p) ) { + case 42: goto st17; + case 47: goto st9; + } + goto st16; +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 ) +case 18: + if ( (*p) == 10 ) + goto st9; + goto st18; +tr4: +#line 157 "parser.rl" + { p--; {p++; cs = 27; goto _out;} } + goto st27; +st27: + if ( ++p == pe ) goto _test_eof27; - st_case_27: - { - goto st0; - } - st19: - p+= 1; - if ( p == pe ) +case 27: +#line 363 "parser.c" + goto st0; +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: + switch( (*p) ) { + case 42: goto st20; + case 47: goto st22; + } + goto st0; +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: + if ( (*p) == 42 ) + goto st21; + goto st20; +st21: + if ( ++p == pe ) goto _test_eof21; - st_case_21: - switch( ( (*( p))) ) { - case 42: { - goto st21; - } - case 47: { - goto st8; - } - } - { - goto st20; - } - st22: - p+= 1; - if ( p == pe ) +case 21: + switch( (*p) ) { + case 42: goto st21; + case 47: goto st8; + } + goto st20; +st22: + if ( ++p == pe ) goto _test_eof22; - st_case_22: - if ( ( (*( p))) == 10 ) { - goto st8; - } - { - goto st22; - } - st23: - p+= 1; - if ( p == pe ) +case 22: + if ( (*p) == 10 ) + goto st8; + goto st22; +st23: + if ( ++p == pe ) goto _test_eof23; - st_case_23: - switch( ( (*( p))) ) { - case 42: { - goto st24; - } - case 47: { - goto st26; - } - } - { - goto st0; - } - st24: - p+= 1; - if ( p == pe ) +case 23: + switch( (*p) ) { + case 42: goto st24; + case 47: goto st26; + } + 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: + if ( (*p) == 42 ) + goto st25; + goto st24; +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: + switch( (*p) ) { + case 42: goto st25; + case 47: goto st2; + } + goto st24; +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: + if ( (*p) == 10 ) + goto st2; + goto st26; } + _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; + } } +#line 486 "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" static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting) { - int cs = EVIL; + int cs = EVIL; +#line 502 "parser.c" { - cs = (int)JSON_value_start; + cs = JSON_value_start; } - #line 290 "parser.rl" - +#line 290 "parser.rl" +#line 509 "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, "unexpected token at '%s'", 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, "unexpected token at '%s'", p - 8); - } - } - - goto st29; - ctr27: - { - #line 221 "parser.rl" - - if (json->allow_nan) { - *result = CNaN; - } else { - rb_enc_raise(EXC_ENCODING eParserError, "unexpected token at '%s'", 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 235 "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 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++; cs = 29; goto _out;} + } else { + rb_enc_raise(EXC_ENCODING eParserError, "unexpected token at '%s'", 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 258 "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 264 "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 228 "parser.rl" + { + if (json->allow_nan) { + *result = CInfinity; + } else { + rb_enc_raise(EXC_ENCODING eParserError, "unexpected token at '%s'", p - 8); + } + } + goto st29; +tr27: +#line 221 "parser.rl" + { + if (json->allow_nan) { + *result = CNaN; + } else { + rb_enc_raise(EXC_ENCODING eParserError, "unexpected token at '%s'", p - 2); + } + } + goto st29; +tr31: +#line 215 "parser.rl" + { + *result = Qfalse; + } + goto st29; +tr34: +#line 212 "parser.rl" + { + *result = Qnil; + } + goto st29; +tr37: +#line 218 "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 270 "parser.rl" + { p--; {p++; cs = 29; goto _out;} } +#line 629 "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 291 "parser.rl" + + if (json->freeze) { + OBJ_FREEZE(*result); + } + + if (cs >= JSON_value_first_final) { + return p; + } else { + return NULL; + } } +#line 884 "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" static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *result) { - int cs = EVIL; + int cs = EVIL; +#line 900 "parser.c" { - cs = (int)JSON_integer_start; + cs = JSON_integer_start; } - #line 318 "parser.rl" - - json->memo = p; +#line 318 "parser.rl" + json->memo = p; +#line 908 "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 308 "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 949 "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 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; + } } +#line 983 "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" static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *result) { - int cs = EVIL; + int cs = EVIL; +#line 999 "parser.c" { - cs = (int)JSON_float_start; + cs = JSON_float_start; } - #line 352 "parser.rl" - - json->memo = p; +#line 352 "parser.rl" + json->memo = p; +#line 1007 "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 339 "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 1072 "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 354 "parser.rl" + + if (cs >= JSON_float_first_final) { + VALUE mod = Qnil; + ID method_id = 0; + if (json->decimal_class != Qnil) { + 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 1186 "parser.c" enum {JSON_array_start = 1}; enum {JSON_array_first_final = 17}; 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 434 "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 1208 "parser.c" { - cs = (int)JSON_array_start; + cs = JSON_array_start; } - #line 445 "parser.rl" - +#line 447 "parser.rl" +#line 1215 "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; - 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 st13; + 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 411 "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 1274 "parser.c" + switch( (*p) ) { + case 13: goto st3; + case 32: goto st3; + case 44: goto st4; + case 47: goto st9; + case 93: goto tr4; + } + if ( 9 <= (*p) && (*p) <= 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 13: goto st4; + case 32: goto st4; + case 34: goto tr2; + case 45: goto tr2; + case 47: goto st5; + 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 st4; + 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: + switch( (*p) ) { + case 42: goto st6; + case 47: goto st8; + } + goto st0; +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: + if ( (*p) == 42 ) + goto st7; + goto st6; +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: + switch( (*p) ) { + case 42: goto st7; + case 47: goto st4; + } + goto st6; +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: + if ( (*p) == 10 ) + goto st4; + goto st8; +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 st3; + } + 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 ) +case 12: + if ( (*p) == 10 ) + goto st3; + goto st12; +tr4: +#line 426 "parser.rl" + { p--; {p++; cs = 17; goto _out;} } + goto st17; +st17: + if ( ++p == pe ) goto _test_eof17; - st_case_17: - { - goto st0; - } - st13: - p+= 1; - if ( p == pe ) +case 17: +#line 1381 "parser.c" + goto st0; +st13: + if ( ++p == pe ) goto _test_eof13; - st_case_13: - switch( ( (*( p))) ) { - case 42: { - goto st14; - } - case 47: { - goto st16; - } - } - { - goto st0; - } - st14: - p+= 1; - if ( p == pe ) +case 13: + switch( (*p) ) { + case 42: goto st14; + case 47: goto st16; + } + 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: + if ( (*p) == 42 ) + goto st15; + goto st14; +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 ) +case 15: + switch( (*p) ) { + case 42: goto st15; + case 47: goto st2; + } + goto st14; +st16: + if ( ++p == pe ) goto _test_eof16; - st_case_16: - if ( ( (*( p))) == 10 ) { - goto st2; - } - { - 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, "unexpected token at '%s'", p); - return NULL; +case 16: + if ( (*p) == 10 ) + goto st2; + goto st16; } + _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 448 "parser.rl" + + if(cs >= JSON_array_first_final) { + return p + 1; + } else { + rb_enc_raise(EXC_ENCODING eParserError, "unexpected token at '%s'", 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]; + 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) { + if (bufferSize > MAX_STACK_BUFFER_SIZE) { # ifdef HAVE_RB_ENC_INTERNED_STR - bufferStart = buffer = ALLOC_N(char, bufferSize ? bufferSize : 1); + bufferStart = buffer = ALLOC_N(char, bufferSize ? bufferSize : 1); # else - bufferStart = buffer = ALLOC_N(char, bufferSize); + bufferStart = buffer = ALLOC_N(char, bufferSize); # endif - } else { + } else { # ifdef HAVE_RB_ENC_INTERNED_STR - bufferStart = buffer = ALLOCA_N(char, bufferSize ? bufferSize : 1); + bufferStart = buffer = ALLOCA_N(char, bufferSize ? bufferSize : 1); # else - bufferStart = buffer = ALLOCA_N(char, bufferSize); + bufferStart = buffer = ALLOCA_N(char, bufferSize); # endif - } + } + + 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, + "incomplete unicode character escape sequence at '%s'", 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, + "incomplete surrogate pair at '%s'", 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; + } - 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, - "incomplete unicode character escape sequence at '%s'", 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, - "incomplete surrogate pair at '%s'", 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; +# 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 1594 "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 622 "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 1623 "parser.c" { - cs = (int)JSON_string_start; + cs = JSON_string_start; } - #line 632 "parser.rl" - - json->memo = p; +#line 642 "parser.rl" + json->memo = p; +#line 1631 "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 609 "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 619 "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 1673 "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; + } else if ( (*p) > 70 ) { + if ( 97 <= (*p) && (*p) <= 102 ) goto st5; - } - { - goto st0; - } - st5: - p+= 1; - if ( p == pe ) + } 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; + } else if ( (*p) > 70 ) { + if ( 97 <= (*p) && (*p) <= 102 ) goto st7; - } - { - goto st0; - } - st7: - p+= 1; - if ( p == pe ) + } 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); - } - } - - if (cs >= JSON_string_first_final) { - return p + 1; - } else { - return NULL; + } else if ( (*p) > 70 ) { + if ( 97 <= (*p) && (*p) <= 102 ) + goto st2; + } else + goto st2; + goto st0; + } + _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 644 "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. + * * *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 +#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"); + } +#endif + if (RTEST(opts) && RHASH_SIZE(opts) > 0) { + VALUE tmp = ID2SYM(i_max_nesting); + if (hash_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 (hash_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 (hash_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 (hash_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 (hash_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 (hash_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 (hash_option_given_p(opts, tmp)) { + json->object_class = rb_hash_aref(opts, tmp); + } else { + json->object_class = Qnil; + } + tmp = ID2SYM(i_array_class); + if (hash_option_given_p(opts, tmp)) { + json->array_class = rb_hash_aref(opts, tmp); + } else { + json->array_class = Qnil; + } + tmp = ID2SYM(i_decimal_class); + if (hash_option_given_p(opts, tmp)) { + json->decimal_class = rb_hash_aref(opts, tmp); + } else { + json->decimal_class = Qnil; + } + tmp = ID2SYM(i_match_string); + if (hash_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; + } + } else { + json->max_nesting = 100; + json->allow_nan = 0; + json->create_additions = 0; + json->create_id = 0; + json->object_class = Qnil; + json->array_class = Qnil; + json->decimal_class = Qnil; + json->match_string = Qnil; + } + source = convert_encoding(StringValue(source)); + StringValue(source); + json->len = RSTRING_LEN(source); + json->source = RSTRING_PTR(source);; + json->Vsource = source; + return self; } +#line 1935 "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 843 "parser.rl" /* -* call-seq: parse() -* -* Parses the current JSON text _source_ and returns the complete data -* structure as a result. -* It raises JSON::ParseError if fail to parse. -*/ + * call-seq: parse() + * + * Parses the current JSON text _source_ and returns the complete data + * structure as a result. + * It raises JSON::ParseError if fail to parse. + */ 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 1961 "parser.c" { - cs = (int)JSON_start; + cs = JSON_start; } - #line 851 "parser.rl" - - p = json->source; - pe = p + json->len; +#line 860 "parser.rl" + p = json->source; + pe = p + json->len; +#line 1970 "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 835 "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 2014 "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: {} - } - - #line 854 "parser.rl" - - - if (cs >= JSON_first_final && p == pe) { - return result; - } else { - rb_enc_raise(EXC_ENCODING eParserError, "unexpected token at '%s'", p); - return Qnil; +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 863 "parser.rl" + + if (cs >= JSON_first_final && p == pe) { + return result; + } else { + rb_enc_raise(EXC_ENCODING eParserError, "unexpected token at '%s'", 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_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..fe1868a1 100644 --- a/ext/json/ext/parser/parser.h +++ b/ext/json/ext/parser/parser.h @@ -17,7 +17,9 @@ # define MAYBE_UNUSED(x) x #endif -#define option_given_p(opts, key) RTEST(rb_funcall(opts, i_key_p, 1, key)) +extern VALUE rb_hash_has_key(VALUE hash, VALUE key); + +#define hash_option_given_p(opts, key) (RTEST(rb_hash_has_key(opts, key))) /* unicode */ diff --git a/ext/json/ext/parser/parser.rl b/ext/json/ext/parser/parser.rl index 2dbdc7ef..3baa1f07 100644 --- a/ext/json/ext/parser/parser.rl +++ b/ext/json/ext/parser/parser.rl @@ -355,6 +355,7 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul if (cs >= JSON_float_first_final) { VALUE mod = Qnil; ID method_id = 0; + if (json->decimal_class != Qnil) { if (rb_respond_to(json->decimal_class, i_try_convert)) { mod = json->decimal_class; method_id = i_try_convert; @@ -380,6 +381,7 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul method_id = SYM2ID(rb_str_intern(name)); } } + } long len = p - json->memo; fbuffer_clear(json->fbuffer); @@ -726,15 +728,15 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self) #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 + if (RTEST(opts) && RHASH_SIZE(opts) > 0) { VALUE tmp = ID2SYM(i_max_nesting); - if (option_given_p(opts, tmp)) { + if (hash_option_given_p(opts, tmp)) { VALUE max_nesting = rb_hash_aref(opts, tmp); if (RTEST(max_nesting)) { Check_Type(max_nesting, T_FIXNUM); @@ -746,25 +748,25 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self) json->max_nesting = 100; } tmp = ID2SYM(i_allow_nan); - if (option_given_p(opts, tmp)) { + if (hash_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)) { + if (hash_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)) { + if (hash_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)) { + if (hash_option_given_p(opts, tmp)) { json->create_additions = RTEST(rb_hash_aref(opts, tmp)); } else { json->create_additions = 0; @@ -775,47 +777,45 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self) " used in conjunction"); } tmp = ID2SYM(i_create_id); - if (option_given_p(opts, tmp)) { + if (hash_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)) { + if (hash_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)) { + if (hash_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)) { + if (hash_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)) { + if (hash_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->create_id = 0; json->object_class = Qnil; json->array_class = Qnil; json->decimal_class = Qnil; + json->match_string = Qnil; } source = convert_encoding(StringValue(source)); StringValue(source); From 574c577b21b238b1bd24b443c32c64433b9a61a8 Mon Sep 17 00:00:00 2001 From: lukeg Date: Mon, 3 Apr 2023 12:29:58 -0400 Subject: [PATCH 2/2] JSON parser init commit #2 (temporary) --- ext/json/ext/parser/parser.c | 48 +++++++++++----------- ext/json/ext/parser/parser.h | 11 +++-- ext/json/ext/parser/parser.rl | 76 ++++++++++++++++++----------------- 3 files changed, 72 insertions(+), 63 deletions(-) diff --git a/ext/json/ext/parser/parser.c b/ext/json/ext/parser/parser.c index 3cae2352..9c967590 100644 --- a/ext/json/ext/parser/parser.c +++ b/ext/json/ext/parser/parser.c @@ -1834,14 +1834,16 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self) rb_scan_args(argc, argv, "11", &source, &opts); #endif #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"); - } + if (!NIL_P(opts)) { + opts = rb_convert_type(opts, T_HASH, "Hash", "to_hash"); + if (NIL_P(opts)) { + rb_raise(rb_eArgError, "opts needs to be like a hash"); + } + } #endif if (RTEST(opts) && RHASH_SIZE(opts) > 0) { VALUE tmp = ID2SYM(i_max_nesting); - if (hash_option_given_p(opts, tmp)) { + if (option_given_p(opts, tmp)) { VALUE max_nesting = rb_hash_aref(opts, tmp); if (RTEST(max_nesting)) { Check_Type(max_nesting, T_FIXNUM); @@ -1853,60 +1855,60 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self) json->max_nesting = 100; } tmp = ID2SYM(i_allow_nan); - if (hash_option_given_p(opts, tmp)) { + 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 (hash_option_given_p(opts, tmp)) { + 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 (hash_option_given_p(opts, tmp)) { + 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 (hash_option_given_p(opts, tmp)) { + 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, + rb_raise(rb_eArgError, "options :symbolize_names and :create_additions cannot be " " used in conjunction"); } tmp = ID2SYM(i_create_id); - if (hash_option_given_p(opts, tmp)) { + 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 (hash_option_given_p(opts, tmp)) { + 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 (hash_option_given_p(opts, tmp)) { + 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 (hash_option_given_p(opts, tmp)) { + 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 (hash_option_given_p(opts, tmp)) { + if (option_given_p(opts, tmp)) { VALUE match_string = rb_hash_aref(opts, tmp); json->match_string = RTEST(match_string) ? match_string : Qnil; } else { @@ -1931,7 +1933,7 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self) } -#line 1935 "parser.c" +#line 1937 "parser.c" enum {JSON_start = 1}; enum {JSON_first_final = 10}; enum {JSON_error = 0}; @@ -1939,7 +1941,7 @@ enum {JSON_error = 0}; enum {JSON_en_main = 1}; -#line 843 "parser.rl" +#line 845 "parser.rl" /* @@ -1957,16 +1959,16 @@ static VALUE cParser_parse(VALUE self) GET_PARSER; -#line 1961 "parser.c" +#line 1963 "parser.c" { cs = JSON_start; } -#line 860 "parser.rl" +#line 862 "parser.rl" p = json->source; pe = p + json->len; -#line 1970 "parser.c" +#line 1972 "parser.c" { if ( p == pe ) goto _test_eof; @@ -2000,7 +2002,7 @@ case 1: cs = 0; goto _out; tr2: -#line 835 "parser.rl" +#line 837 "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;} @@ -2010,7 +2012,7 @@ cs = 0; if ( ++p == pe ) goto _test_eof10; case 10: -#line 2014 "parser.c" +#line 2016 "parser.c" switch( (*p) ) { case 13: goto st10; case 32: goto st10; @@ -2099,7 +2101,7 @@ case 9: _out: {} } -#line 863 "parser.rl" +#line 865 "parser.rl" if (cs >= JSON_first_final && p == pe) { return result; diff --git a/ext/json/ext/parser/parser.h b/ext/json/ext/parser/parser.h index fe1868a1..776099dd 100644 --- a/ext/json/ext/parser/parser.h +++ b/ext/json/ext/parser/parser.h @@ -17,9 +17,14 @@ # define MAYBE_UNUSED(x) x #endif -extern VALUE rb_hash_has_key(VALUE hash, VALUE key); - -#define hash_option_given_p(opts, key) (RTEST(rb_hash_has_key(opts, key))) +static VALUE hash_has_key(VALUE hash, VALUE key) +{ + if (Qundef == rb_hash_lookup2(hash, key, Qundef)) { + return Qtrue; + } + return Qfalse; +} +#define option_given_p(opts, key) (RTEST(hash_has_key(opts, key))) /* unicode */ diff --git a/ext/json/ext/parser/parser.rl b/ext/json/ext/parser/parser.rl index 3baa1f07..74c9c4bf 100644 --- a/ext/json/ext/parser/parser.rl +++ b/ext/json/ext/parser/parser.rl @@ -356,32 +356,32 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul VALUE mod = Qnil; ID method_id = 0; if (json->decimal_class != Qnil) { - 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)); + 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); @@ -729,14 +729,16 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self) rb_scan_args(argc, argv, "11", &source, &opts); #endif #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"); + if (!NIL_P(opts)) { + opts = rb_convert_type(opts, T_HASH, "Hash", "to_hash"); + if (NIL_P(opts)) { + rb_raise(rb_eArgError, "opts needs to be like a hash"); + } } #endif if (RTEST(opts) && RHASH_SIZE(opts) > 0) { VALUE tmp = ID2SYM(i_max_nesting); - if (hash_option_given_p(opts, tmp)) { + if (option_given_p(opts, tmp)) { VALUE max_nesting = rb_hash_aref(opts, tmp); if (RTEST(max_nesting)) { Check_Type(max_nesting, T_FIXNUM); @@ -748,25 +750,25 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self) json->max_nesting = 100; } tmp = ID2SYM(i_allow_nan); - if (hash_option_given_p(opts, tmp)) { + 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 (hash_option_given_p(opts, tmp)) { + 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 (hash_option_given_p(opts, tmp)) { + 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 (hash_option_given_p(opts, tmp)) { + if (option_given_p(opts, tmp)) { json->create_additions = RTEST(rb_hash_aref(opts, tmp)); } else { json->create_additions = 0; @@ -777,31 +779,31 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self) " used in conjunction"); } tmp = ID2SYM(i_create_id); - if (hash_option_given_p(opts, tmp)) { + 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 (hash_option_given_p(opts, tmp)) { + 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 (hash_option_given_p(opts, tmp)) { + 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 (hash_option_given_p(opts, tmp)) { + 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 (hash_option_given_p(opts, tmp)) { + if (option_given_p(opts, tmp)) { VALUE match_string = rb_hash_aref(opts, tmp); json->match_string = RTEST(match_string) ? match_string : Qnil; } else {