diff options
author | Jean Boussier <[email protected]> | 2024-11-05 16:35:58 +0100 |
---|---|---|
committer | Jean Boussier <[email protected]> | 2024-11-05 18:00:36 +0100 |
commit | ca8f21ace86e9c7ab184b3f0087ff458c06b178c () | |
tree | e5a4c05ba4bff8d9dc19963936d2c81248200881 /ext/json/parser | |
parent | e8522f06b51f86214d28259118c736ac8951d8cd (diff) |
[ruby/json] Resync
Notes: Merged: https://.com/ruby/ruby/pull/12003
-rw-r--r-- | ext/json/parser/extconf.rb | 5 | ||||
-rw-r--r-- | ext/json/parser/parser.c | 1752 | ||||
-rw-r--r-- | ext/json/parser/parser.h | 78 | ||||
-rw-r--r-- | ext/json/parser/parser.rl | 747 |
4 files changed, 1937 insertions, 645 deletions
@@ -2,7 +2,10 @@ require 'mkmf' have_func("rb_enc_interned_str", "ruby.h") # RUBY_VERSION >= 3.0 -have_func("rb_gc_mark_locations") # Missing on TruffleRuby append_cflags("-std=c99") create_makefile 'json/ext/parser' @@ -1,7 +1,310 @@ /* This file is automatically generated from parser.rl by using ragel */ #line 1 "parser.rl" #include "../fbuffer/fbuffer.h" -#include "parser.h" /* unicode */ @@ -69,6 +372,50 @@ static int convert_UTF32_to_UTF8(char *buf, uint32_t ch) return len; } #define PARSE_ERROR_FRAGMENT_LEN 32 #ifdef RBIMPL_ATTR_NORETURN RBIMPL_ATTR_NORETURN() @@ -86,60 +433,49 @@ static void raise_parse_error(const char *format, const char *start) ptr = buffer; } - rb_enc_raise(rb_utf8_encoding(), rb_path2class("JSON::ParserError"), format, ptr); } -static VALUE mJSON, mExt, cParser, eNestingError, Encoding_UTF_8; -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_deep_const_get, i_match, i_match_string, i_aset, i_aref, - i_leftshift, i_new, i_try_convert, i_freeze, i_uminus, i_encode; -static int binary_encindex; -static int utf8_encindex; -#line 129 "parser.rl" - - -#line 111 "parser.c" enum {JSON_object_start = 1}; -enum {JSON_object_first_final = 27}; enum {JSON_object_error = 0}; enum {JSON_object_en_main = 1}; -#line 171 "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; 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); -#line 135 "parser.c" { cs = JSON_object_start; } -#line 186 "parser.rl" -#line 142 "parser.c" { if ( p == pe ) goto _test_eof; switch ( cs ) @@ -159,27 +495,30 @@ case 2: 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 153 "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; case 3: -#line 183 "parser.c" switch( (*p) ) { case 13: goto st3; case 32: goto st3; @@ -230,7 +569,7 @@ case 8: 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; @@ -246,19 +585,12 @@ case 8: goto st8; goto st0; tr11: -#line 137 "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;} } } @@ -267,16 +599,75 @@ st9: if ( ++p == pe ) goto _test_eof9; case 9: -#line 271 "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 ) @@ -285,8 +676,9 @@ 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; @@ -296,139 +688,288 @@ st11: goto _test_eof11; case 11: switch( (*p) ) { - case 42: goto st12; - case 47: goto st14; } goto st0; st12: if ( ++p == pe ) goto _test_eof12; case 12: - if ( (*p) == 42 ) - goto st13; - goto st12; st13: if ( ++p == pe ) goto _test_eof13; case 13: - switch( (*p) ) { - case 42: goto st13; - case 47: goto st10; - } - goto st12; st14: if ( ++p == pe ) goto _test_eof14; case 14: - if ( (*p) == 10 ) - goto st10; - goto st14; st15: if ( ++p == pe ) goto _test_eof15; case 15: - switch( (*p) ) { - case 42: goto st16; - case 47: goto st18; - } - goto st0; st16: if ( ++p == pe ) goto _test_eof16; case 16: - if ( (*p) == 42 ) - goto st17; - goto st16; st17: if ( ++p == pe ) goto _test_eof17; case 17: - switch( (*p) ) { - case 42: goto st17; - case 47: goto st9; - } - goto st16; st18: if ( ++p == pe ) goto _test_eof18; case 18: - if ( (*p) == 10 ) - goto st9; - goto st18; -tr4: -#line 161 "parser.rl" - { p--; {p++; cs = 27; goto _out;} } - goto st27; -st27: - if ( ++p == pe ) - goto _test_eof27; -case 27: -#line 367 "parser.c" - goto st0; st19: if ( ++p == pe ) goto _test_eof19; case 19: - switch( (*p) ) { - case 42: goto st20; - case 47: goto st22; - } - goto st0; st20: if ( ++p == pe ) goto _test_eof20; case 20: - if ( (*p) == 42 ) - goto st21; - goto st20; st21: if ( ++p == pe ) goto _test_eof21; case 21: - switch( (*p) ) { - case 42: goto st21; - case 47: goto st8; - } - goto st20; st22: if ( ++p == pe ) goto _test_eof22; case 22: - if ( (*p) == 10 ) - goto st8; - goto st22; st23: if ( ++p == pe ) goto _test_eof23; case 23: - switch( (*p) ) { - case 42: goto st24; - case 47: goto st26; - } goto st0; st24: if ( ++p == pe ) goto _test_eof24; case 24: - if ( (*p) == 42 ) - goto st25; - goto st24; st25: if ( ++p == pe ) goto _test_eof25; case 25: - switch( (*p) ) { - case 42: goto st25; - case 47: goto st2; - } - goto st24; st26: if ( ++p == pe ) goto _test_eof26; case 26: if ( (*p) == 10 ) goto st2; - goto st26; } _test_eof2: cs = 2; goto _test_eof; _test_eof3: cs = 3; goto _test_eof; @@ -438,6 +979,7 @@ case 26: _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; @@ -447,7 +989,6 @@ case 26: _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; @@ -456,20 +997,49 @@ case 26: _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 187 "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); @@ -488,8 +1058,7 @@ case 26: } - -#line 493 "parser.c" enum {JSON_value_start = 1}; enum {JSON_value_first_final = 29}; enum {JSON_value_error = 0}; @@ -497,7 +1066,7 @@ enum {JSON_value_error = 0}; enum {JSON_value_en_main = 1}; -#line 290 "parser.rl" static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting) @@ -505,14 +1074,14 @@ static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *resul int cs = EVIL; -#line 509 "parser.c" { cs = JSON_value_start; } -#line 297 "parser.rl" -#line 516 "parser.c" { if ( p == pe ) goto _test_eof; @@ -546,14 +1115,19 @@ st0: cs = 0; goto _out; tr2: -#line 242 "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 247 "parser.rl" { char *np; if(pe > p + 8 && !strncmp(MinusInfinity, p, 9)) { @@ -566,14 +1140,18 @@ tr3: } } 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 265 "parser.rl" { char *np; np = JSON_parse_array(json, p, pe, result, current_nesting + 1); @@ -581,7 +1159,7 @@ tr7: } goto st29; tr11: -#line 271 "parser.rl" { char *np; np = JSON_parse_object(json, p, pe, result, current_nesting + 1); @@ -589,7 +1167,7 @@ tr11: } goto st29; tr25: -#line 235 "parser.rl" { if (json->allow_nan) { *result = CInfinity; @@ -599,7 +1177,7 @@ tr25: } goto st29; tr27: -#line 228 "parser.rl" { if (json->allow_nan) { *result = CNaN; @@ -609,19 +1187,19 @@ tr27: } goto st29; tr31: -#line 222 "parser.rl" { *result = Qfalse; } goto st29; tr34: -#line 219 "parser.rl" { *result = Qnil; } goto st29; tr37: -#line 225 "parser.rl" { *result = Qtrue; } @@ -630,9 +1208,9 @@ st29: if ( ++p == pe ) goto _test_eof29; case 29: -#line 277 "parser.rl" { p--; {p++; cs = 29; goto _out;} } -#line 636 "parser.c" switch( (*p) ) { case 13: goto st29; case 32: goto st29; @@ -873,13 +1451,14 @@ case 28: _out: {} } -#line 298 "parser.rl" if (json->freeze) { OBJ_FREEZE(*result); } if (cs >= JSON_value_first_final) { return p; } else { return NULL; @@ -887,7 +1466,7 @@ case 28: } -#line 891 "parser.c" enum {JSON_integer_start = 1}; enum {JSON_integer_first_final = 3}; enum {JSON_integer_error = 0}; @@ -895,7 +1474,7 @@ enum {JSON_integer_error = 0}; enum {JSON_integer_en_main = 1}; -#line 318 "parser.rl" static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *result) @@ -903,15 +1482,15 @@ static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *res int cs = EVIL; -#line 907 "parser.c" { cs = JSON_integer_start; } -#line 325 "parser.rl" json->memo = p; -#line 915 "parser.c" { if ( p == pe ) goto _test_eof; @@ -945,14 +1524,14 @@ case 3: goto st0; goto tr4; tr4: -#line 315 "parser.rl" { p--; {p++; cs = 4; goto _out;} } goto st4; st4: if ( ++p == pe ) goto _test_eof4; case 4: -#line 956 "parser.c" goto st0; st5: if ( ++p == pe ) @@ -971,7 +1550,7 @@ case 5: _out: {} } -#line 327 "parser.rl" if (cs >= JSON_integer_first_final) { long len = p - json->memo; @@ -986,7 +1565,7 @@ case 5: } -#line 990 "parser.c" enum {JSON_float_start = 1}; enum {JSON_float_first_final = 8}; enum {JSON_float_error = 0}; @@ -994,7 +1573,7 @@ enum {JSON_float_error = 0}; enum {JSON_float_en_main = 1}; -#line 352 "parser.rl" static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *result) @@ -1002,15 +1581,15 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul int cs = EVIL; -#line 1006 "parser.c" { cs = JSON_float_start; } -#line 359 "parser.rl" json->memo = p; -#line 1014 "parser.c" { if ( p == pe ) goto _test_eof; @@ -1068,14 +1647,14 @@ case 8: goto st0; goto tr9; tr9: -#line 346 "parser.rl" { p--; {p++; cs = 9; goto _out;} } goto st9; st9: if ( ++p == pe ) goto _test_eof9; case 9: -#line 1079 "parser.c" goto st0; st5: if ( ++p == pe ) @@ -1136,12 +1715,12 @@ case 7: _out: {} } -#line 361 "parser.rl" if (cs >= JSON_float_first_final) { VALUE mod = Qnil; ID method_id = 0; - if (!NIL_P(json->decimal_class)) { if (rb_respond_to(json->decimal_class, i_try_convert)) { mod = json->decimal_class; method_id = i_try_convert; @@ -1189,37 +1768,37 @@ case 7: -#line 1193 "parser.c" enum {JSON_array_start = 1}; -enum {JSON_array_first_final = 17}; enum {JSON_array_error = 0}; enum {JSON_array_en_main = 1}; -#line 441 "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; 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 1215 "parser.c" { cs = JSON_array_start; } -#line 454 "parser.rl" -#line 1222 "parser.c" { if ( p == pe ) goto _test_eof; switch ( cs ) @@ -1240,7 +1819,7 @@ case 2: 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; @@ -1257,18 +1836,13 @@ case 2: goto st2; goto st0; tr2: -#line 418 "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;} } } @@ -1277,15 +1851,23 @@ st3: if ( ++p == pe ) goto _test_eof3; case 3: -#line 1281 "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: @@ -1293,57 +1875,67 @@ st4: goto _test_eof4; 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; case 5: - switch( (*p) ) { - case 42: goto st6; - case 47: goto st8; - } - goto st0; st6: if ( ++p == pe ) goto _test_eof6; case 6: - if ( (*p) == 42 ) - goto st7; - goto st6; st7: if ( ++p == pe ) goto _test_eof7; case 7: - switch( (*p) ) { - case 42: goto st7; - case 47: goto st4; - } - goto st6; st8: if ( ++p == pe ) goto _test_eof8; case 8: - if ( (*p) == 10 ) - goto st4; - goto st8; st9: if ( ++p == pe ) goto _test_eof9; @@ -1366,7 +1958,7 @@ st11: case 11: switch( (*p) ) { case 42: goto st11; - case 47: goto st3; } goto st10; st12: @@ -1374,50 +1966,252 @@ st12: goto _test_eof12; case 12: if ( (*p) == 10 ) - goto st3; goto st12; -tr4: -#line 433 "parser.rl" - { p--; {p++; cs = 17; goto _out;} } - goto st17; -st17: - if ( ++p == pe ) - goto _test_eof17; -case 17: -#line 1388 "parser.c" - goto st0; st13: if ( ++p == pe ) goto _test_eof13; case 13: - switch( (*p) ) { - case 42: goto st14; - case 47: goto st16; - } goto st0; st14: if ( ++p == pe ) goto _test_eof14; case 14: - if ( (*p) == 42 ) - goto st15; - goto st14; st15: if ( ++p == pe ) goto _test_eof15; case 15: - switch( (*p) ) { - case 42: goto st15; - case 47: goto st2; - } - goto st14; st16: if ( ++p == pe ) goto _test_eof16; case 16: if ( (*p) == 10 ) goto st2; - goto st16; } _test_eof2: cs = 2; goto _test_eof; _test_eof3: cs = 3; goto _test_eof; @@ -1425,24 +2219,45 @@ case 16: _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 455 "parser.rl" if(cs >= JSON_array_first_final) { return p + 1; } else { raise_parse_error("unexpected token at '%s'", p); @@ -1458,7 +2273,7 @@ static inline VALUE build_string(const char *start, const char *end, bool intern VALUE result; # ifdef HAVE_RB_ENC_INTERNED_STR if (intern) { - result = rb_enc_interned_str(start, (long)(end - start), rb_utf8_encoding()); } else { result = rb_utf8_str_new(start, (long)(end - start)); } @@ -1476,13 +2291,26 @@ static inline VALUE build_string(const char *start, const char *end, bool intern return result; } -static VALUE json_string_unescape(char *string, char *stringEnd, bool intern, bool symbolize) { size_t bufferSize = stringEnd - string; char *p = string, *pe = string, *unescape, *bufferStart, *buffer; int unescape_len; char buf[4]; pe = memchr(p, '\\', bufferSize); if (RB_LIKELY(pe == NULL)) { return build_string(string, stringEnd, intern, symbolize); @@ -1585,7 +2413,7 @@ static VALUE json_string_unescape(char *string, char *stringEnd, bool intern, bo } -#line 1589 "parser.c" enum {JSON_string_start = 1}; enum {JSON_string_first_final = 8}; enum {JSON_string_error = 0}; @@ -1593,7 +2421,7 @@ enum {JSON_string_error = 0}; enum {JSON_string_en_main = 1}; -#line 617 "parser.rl" static int @@ -1614,15 +2442,15 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu VALUE match_string; -#line 1618 "parser.c" { cs = JSON_string_start; } -#line 637 "parser.rl" json->memo = p; -#line 1626 "parser.c" { if ( p == pe ) goto _test_eof; @@ -1647,9 +2475,9 @@ case 2: goto st0; goto st2; tr2: -#line 604 "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;} @@ -1657,14 +2485,14 @@ tr2: {p = (( p + 1))-1;} } } -#line 614 "parser.rl" { p--; {p++; cs = 8; goto _out;} } goto st8; st8: if ( ++p == pe ) goto _test_eof8; case 8: -#line 1668 "parser.c" goto st0; st3: if ( ++p == pe ) @@ -1740,7 +2568,7 @@ case 7: _out: {} } -#line 639 "parser.rl" if (json->create_additions && RTEST(match_string = json->match_string)) { VALUE klass; @@ -1776,7 +2604,7 @@ static VALUE convert_encoding(VALUE source) { int encindex = RB_ENCODING_GET(source); - if (encindex == utf8_encindex) { return source; } @@ -1788,6 +2616,68 @@ static VALUE convert_encoding(VALUE source) return rb_funcall(source, i_encode, 1, Encoding_UTF_8); } /* * call-seq: new(source, opts => {}) * @@ -1822,122 +2712,16 @@ static VALUE convert_encoding(VALUE source) */ 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"); - } - rb_check_arity(argc, 1, 2); - source = argv[0]; - opts = Qnil; - if (argc == 2) { - opts = argv[1]; - Check_Type(argv[1], T_HASH); - if (RHASH_SIZE(argv[1]) > 0) { - opts = argv[1]; - } - } - if (!NIL_P(opts)) { - 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)) { - tmp = rb_hash_aref(opts, tmp); - if (NIL_P(tmp)) { - json->create_additions = 1; - json->deprecated_create_additions = 1; - } else { - json->create_additions = RTEST(tmp); - json->deprecated_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; - } - } else { - json->max_nesting = 100; - json->allow_nan = 0; - json->create_additions = 0; - json->create_id = Qnil; - json->object_class = Qnil; - json->array_class = Qnil; - json->decimal_class = Qnil; - } - source = convert_encoding(StringValue(source)); - StringValue(source); - json->len = RSTRING_LEN(source); - json->source = RSTRING_PTR(source); - json->Vsource = source; return self; } -#line 1941 "parser.c" enum {JSON_start = 1}; enum {JSON_first_final = 10}; enum {JSON_error = 0}; @@ -1945,7 +2729,7 @@ enum {JSON_error = 0}; enum {JSON_en_main = 1}; -#line 849 "parser.rl" /* @@ -1962,17 +2746,28 @@ static VALUE cParser_parse(VALUE self) VALUE result = Qnil; GET_PARSER; -#line 1967 "parser.c" { cs = JSON_start; } -#line 866 "parser.rl" p = json->source; pe = p + json->len; -#line 1976 "parser.c" { if ( p == pe ) goto _test_eof; @@ -2006,7 +2801,7 @@ st0: cs = 0; goto _out; tr2: -#line 841 "parser.rl" { char *np = JSON_parse_value(json, p, pe, &result, 0); if (np == NULL) { p--; {p++; cs = 10; goto _out;} } else {p = (( np))-1;} @@ -2016,7 +2811,7 @@ st10: if ( ++p == pe ) goto _test_eof10; case 10: -#line 2020 "parser.c" switch( (*p) ) { case 13: goto st10; case 32: goto st10; @@ -2105,7 +2900,11 @@ case 9: _out: {} } -#line 869 "parser.rl" if (cs >= JSON_first_final && p == pe) { return result; @@ -2115,18 +2914,183 @@ case 9: } } -#ifndef HAVE_RB_GC_MARK_LOCATIONS -// For TruffleRuby -void rb_gc_mark_locations(const VALUE *start, const VALUE *end) { - VALUE *value = start; - while (value < end) { - rb_gc_mark(*value); - value++; } } -#endif static void JSON_mark(void *ptr) { @@ -2137,6 +3101,8 @@ static void JSON_mark(void *ptr) rb_gc_mark(json->array_class); rb_gc_mark(json->decimal_class); rb_gc_mark(json->match_string); const VALUE *name_cache_entries = &json->name_cache.entries[0]; rb_gc_mark_locations(name_cache_entries, name_cache_entries + json->name_cache.length); } @@ -2199,6 +3165,8 @@ void Init_parser(void) 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); @@ -2211,31 +3179,35 @@ void Init_parser(void) rb_global_variable(&Encoding_UTF_8); Encoding_UTF_8 = rb_const_get(rb_path2class("Encoding"), rb_intern("UTF_8")); 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_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("-@"); i_encode = rb_intern("encode"); binary_encindex = rb_ascii8bit_encindex(); utf8_encindex = rb_utf8_encindex(); } /* @@ -1,78 +0,0 @@ -#ifndef _PARSER_H_ -#define _PARSER_H_ - -#include "ruby.h" - -/* This is the fallback definition from Ruby 3.4 */ -#ifndef RBIMPL_STDBOOL_H -#if defined(__cplusplus) -# if defined(HAVE_STDBOOL_H) && (__cplusplus >= 201103L) -# include <cstdbool> -# endif -#elif defined(HAVE_STDBOOL_H) -# include <stdbool.h> -#elif !defined(HAVE__BOOL) -typedef unsigned char _Bool; -# define bool _Bool -# define true ((_Bool)+1) -# define false ((_Bool)+0) -# define __bool_true_false_are_defined -#endif -#endif - -#ifndef MAYBE_UNUSED -# define MAYBE_UNUSED(x) x -#endif - -#define option_given_p(opts, key) (rb_hash_lookup2(opts, key, Qundef) != Qundef) - -typedef struct JSON_ParserStruct { - VALUE Vsource; - char *source; - long len; - char *memo; - VALUE create_id; - VALUE object_class; - VALUE array_class; - VALUE decimal_class; - VALUE match_string; - FBuffer fbuffer; - int max_nesting; - char allow_nan; - char parsing_name; - char symbolize_names; - char freeze; - char create_additions; - char deprecated_create_additions; -} JSON_Parser; - -#define GET_PARSER \ - GET_PARSER_INIT; \ - if (!json->Vsource) rb_raise(rb_eTypeError, "uninitialized instance") -#define GET_PARSER_INIT \ - JSON_Parser *json; \ - TypedData_Get_Struct(self, JSON_Parser, &JSON_Parser_type, json) - -#define MinusInfinity "-Infinity" -#define EVIL 0x666 - -static uint32_t unescape_unicode(const unsigned char *p); -static int convert_UTF32_to_UTF8(char *buf, uint32_t ch); -static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting); -static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting); -static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *result); -static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *result); -static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting); -static VALUE json_string_unescape(char *string, char *stringEnd, bool intern, bool symbolize); -static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *result); -static VALUE convert_encoding(VALUE source); -static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self); -static VALUE cParser_parse(VALUE self); -static void JSON_mark(void *json); -static void JSON_free(void *json); -static VALUE cJSON_parser_s_allocate(VALUE klass); -static VALUE cParser_source(VALUE self); - -static const rb_data_type_t JSON_Parser_type; - -#endif @@ -1,5 +1,308 @@ #include "../fbuffer/fbuffer.h" -#include "parser.h" /* unicode */ @@ -67,6 +370,50 @@ static int convert_UTF32_to_UTF8(char *buf, uint32_t ch) return len; } #define PARSE_ERROR_FRAGMENT_LEN 32 #ifdef RBIMPL_ATTR_NORETURN RBIMPL_ATTR_NORETURN() @@ -84,21 +431,9 @@ static void raise_parse_error(const char *format, const char *start) ptr = buffer; } - rb_enc_raise(rb_utf8_encoding(), rb_path2class("JSON::ParserError"), format, ptr); } -static VALUE mJSON, mExt, cParser, eNestingError, Encoding_UTF_8; -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_deep_const_get, i_match, i_match_string, i_aset, i_aref, - i_leftshift, i_new, i_try_convert, i_freeze, i_uminus, i_encode; - -static int binary_encindex; -static int utf8_encindex; - %%{ machine JSON_common; @@ -135,27 +470,25 @@ static int utf8_encindex; write data; action parse_value { - VALUE v = Qnil; - char *np = JSON_parse_value(json, fpc, pe, &v, current_nesting); if (np == NULL) { fhold; fbreak; } 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); - } fexec np; } } action parse_name { char *np; - json->parsing_name = 1; - np = JSON_parse_string(json, fpc, pe, &last_name); - json->parsing_name = 0; - if (np == NULL) { fhold; fbreak; } else fexec np; } action exit { fhold; fbreak; } @@ -165,33 +498,57 @@ static int utf8_encindex; main := ( begin_object - (pair (next_pair)*)? ignore* end_object ) @exit; }%% 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; 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); %% write init; %% write exec; 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); @@ -209,7 +566,6 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu } } - %%{ machine JSON_value; include JSON_common; @@ -241,7 +597,12 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu } action parse_string { char *np = JSON_parse_string(json, fpc, pe, result); - if (np == NULL) { fhold; fbreak; } else fexec np; } action parse_number { @@ -256,9 +617,13 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu } } np = JSON_parse_float(json, fpc, pe, result); - if (np != NULL) fexec np; np = JSON_parse_integer(json, fpc, pe, result); - if (np != NULL) fexec np; fhold; fbreak; } @@ -301,6 +666,7 @@ static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *resul } if (cs >= JSON_value_first_final) { return p; } else { return NULL; @@ -362,7 +728,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 (!NIL_P(json->decimal_class)) { if (rb_respond_to(json->decimal_class, i_try_convert)) { mod = json->decimal_class; method_id = i_try_convert; @@ -421,39 +787,51 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul if (np == NULL) { fhold; fbreak; } else { - if (NIL_P(json->array_class)) { - rb_ary_push(*result, v); - } else { - rb_funcall(*result, i_leftshift, 1, v); - } fexec np; } } action exit { fhold; fbreak; } next_element = value_separator ignore* begin_value >parse_value; main := begin_array ignore* ((begin_value >parse_value ignore*) - (ignore* next_element ignore*)*)? end_array @exit; }%% 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; 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); %% write init; %% write exec; if(cs >= JSON_array_first_final) { return p + 1; } else { raise_parse_error("unexpected token at '%s'", p); @@ -469,7 +847,7 @@ static inline VALUE build_string(const char *start, const char *end, bool intern VALUE result; # ifdef HAVE_RB_ENC_INTERNED_STR if (intern) { - result = rb_enc_interned_str(start, (long)(end - start), rb_utf8_encoding()); } else { result = rb_utf8_str_new(start, (long)(end - start)); } @@ -487,13 +865,26 @@ static inline VALUE build_string(const char *start, const char *end, bool intern return result; } -static VALUE json_string_unescape(char *string, char *stringEnd, bool intern, bool symbolize) { size_t bufferSize = stringEnd - string; char *p = string, *pe = string, *unescape, *bufferStart, *buffer; int unescape_len; char buf[4]; pe = memchr(p, '\\', bufferSize); if (RB_LIKELY(pe == NULL)) { return build_string(string, stringEnd, intern, symbolize); @@ -602,7 +993,7 @@ static VALUE json_string_unescape(char *string, char *stringEnd, bool intern, bo write data; action parse_string { - *result = json_string_unescape(json->memo + 1, p, json->parsing_name || json-> freeze, json->parsing_name && json->symbolize_names); if (NIL_P(*result)) { fhold; fbreak; @@ -671,7 +1062,7 @@ static VALUE convert_encoding(VALUE source) { int encindex = RB_ENCODING_GET(source); - if (encindex == utf8_encindex) { return source; } @@ -683,6 +1074,68 @@ static VALUE convert_encoding(VALUE source) return rb_funcall(source, i_encode, 1, Encoding_UTF_8); } /* * call-seq: new(source, opts => {}) * @@ -717,117 +1170,11 @@ static VALUE convert_encoding(VALUE source) */ 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"); - } - rb_check_arity(argc, 1, 2); - source = argv[0]; - opts = Qnil; - if (argc == 2) { - opts = argv[1]; - Check_Type(argv[1], T_HASH); - if (RHASH_SIZE(argv[1]) > 0) { - opts = argv[1]; - } - } - - if (!NIL_P(opts)) { - 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)) { - tmp = rb_hash_aref(opts, tmp); - if (NIL_P(tmp)) { - json->create_additions = 1; - json->deprecated_create_additions = 1; - } else { - json->create_additions = RTEST(tmp); - json->deprecated_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; - } - } else { - json->max_nesting = 100; - json->allow_nan = 0; - json->create_additions = 0; - json->create_id = Qnil; - 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; } @@ -862,11 +1209,26 @@ static VALUE cParser_parse(VALUE self) VALUE result = Qnil; GET_PARSER; %% write init; p = json->source; pe = p + json->len; %% write exec; if (cs >= JSON_first_final && p == pe) { return result; } else { @@ -875,18 +1237,43 @@ static VALUE cParser_parse(VALUE self) } } -#ifndef HAVE_RB_GC_MARK_LOCATIONS -// For TruffleRuby -void rb_gc_mark_locations(const VALUE *start, const VALUE *end) { - VALUE *value = start; - while (value < end) { - rb_gc_mark(*value); - value++; } } -#endif static void JSON_mark(void *ptr) { @@ -897,6 +1284,8 @@ static void JSON_mark(void *ptr) rb_gc_mark(json->array_class); rb_gc_mark(json->decimal_class); rb_gc_mark(json->match_string); const VALUE *name_cache_entries = &json->name_cache.entries[0]; rb_gc_mark_locations(name_cache_entries, name_cache_entries + json->name_cache.length); } @@ -959,6 +1348,8 @@ void Init_parser(void) 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); @@ -971,31 +1362,35 @@ void Init_parser(void) rb_global_variable(&Encoding_UTF_8); Encoding_UTF_8 = rb_const_get(rb_path2class("Encoding"), rb_intern("UTF_8")); 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_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("-@"); i_encode = rb_intern("encode"); binary_encindex = rb_ascii8bit_encindex(); utf8_encindex = rb_utf8_encindex(); } /* |