diff options
-rw-r--r-- | ext/json/lib/json/common.rb | 11 | ||||
-rw-r--r-- | ext/json/lib/json/ext.rb | 29 | ||||
-rw-r--r-- | ext/json/parser/parser.c | 661 | ||||
-rw-r--r-- | ext/json/parser/parser.rl | 309 | ||||
-rw-r--r-- | test/json/json_ext_parser_test.rb | 8 |
5 files changed, 419 insertions, 599 deletions
@@ -232,12 +232,13 @@ module JSON # - Option +max_nesting+, if not provided, defaults to +false+, # which disables checking for nesting depth. # - Option +allow_nan+, if not provided, defaults to +true+. - def parse!(source, opts = {}) - opts = { :max_nesting => false, :allow_nan => true - }.merge(opts) - Parser.new(source, **(opts||{})).parse end # :call-seq: @@ -258,7 +259,7 @@ module JSON # JSON.parse!(File.read(path, opts)) # # See method #parse! - def load_file!(filespec, opts = {}) parse!(File.read(filespec, encoding: Encoding::UTF_8), opts) end @@ -6,15 +6,36 @@ module JSON # This module holds all the modules/classes that implement JSON's # functionality as C extensions. module Ext if RUBY_ENGINE == 'truffleruby' - require 'json/ext/parser' require 'json/truffle_ruby/generator' - JSON.parser = Parser JSON.generator = ::JSON::TruffleRuby::Generator else - require 'json/ext/parser' require 'json/ext/generator' - JSON.parser = Parser JSON.generator = Generator end end @@ -3,7 +3,7 @@ #include "ruby.h" #include "../fbuffer/fbuffer.h" -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, @@ -374,17 +374,11 @@ static int convert_UTF32_to_UTF8(char *buf, uint32_t ch) } 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 in_array; int max_nesting; bool allow_nan; bool allow_trailing_comma; @@ -393,16 +387,22 @@ typedef struct JSON_ParserStruct { bool freeze; bool create_additions; bool deprecated_create_additions; - rvalue_cache name_cache; - rvalue_stack *stack; - VALUE stack_handle; } 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) @@ -410,12 +410,11 @@ typedef struct JSON_ParserStruct { #define EVIL 0x666 static const rb_data_type_t JSON_Parser_type; -static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *result); -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_number(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); - #ifndef HAVE_STRNLEN static size_t strnlen(const char *s, size_t maxlen) @@ -447,11 +446,11 @@ static void raise_parse_error(const char *format, const char *start) -#line 473 "parser.rl" -#line 455 "parser.c" enum {JSON_object_start = 1}; enum {JSON_object_first_final = 32}; enum {JSON_object_error = 0}; @@ -459,12 +458,12 @@ enum {JSON_object_error = 0}; enum {JSON_object_en_main = 1}; -#line 513 "parser.rl" -#define PUSH(result) rvalue_stack_push(json->stack, result, &json->stack_handle, &json->stack) -static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting) { int cs = EVIL; @@ -472,17 +471,17 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu rb_raise(eNestingError, "nesting of %d is too deep", current_nesting); } - long stack_head = json->stack->head; -#line 479 "parser.c" { cs = JSON_object_start; } -#line 528 "parser.rl" -#line 486 "parser.c" { short _widec; if ( p == pe ) @@ -511,11 +510,11 @@ case 2: goto st2; goto st0; tr2: -#line 492 "parser.rl" { char *np; json->parsing_name = true; - np = JSON_parse_string(json, p, pe, result); json->parsing_name = false; if (np == NULL) { p--; {p++; cs = 3; goto _out;} } else { PUSH(*result); @@ -527,7 +526,7 @@ st3: if ( ++p == pe ) goto _test_eof3; case 3: -#line 531 "parser.c" switch( (*p) ) { case 13: goto st3; case 32: goto st3; @@ -594,9 +593,9 @@ case 8: goto st8; goto st0; tr11: -#line 481 "parser.rl" { - char *np = JSON_parse_value(json, p, pe, result, current_nesting); if (np == NULL) { p--; {p++; cs = 9; goto _out;} } else { @@ -608,20 +607,20 @@ st9: if ( ++p == pe ) goto _test_eof9; case 9: -#line 612 "parser.c" _widec = (*p); if ( (*p) < 13 ) { if ( (*p) > 9 ) { if ( 10 <= (*p) && (*p) <= 10 ) { _widec = (short)(128 + ((*p) - -128)); if ( -#line 490 "parser.rl" json->allow_trailing_comma ) _widec += 256; } } else if ( (*p) >= 9 ) { _widec = (short)(128 + ((*p) - -128)); if ( -#line 490 "parser.rl" json->allow_trailing_comma ) _widec += 256; } } else if ( (*p) > 13 ) { @@ -629,26 +628,26 @@ case 9: if ( 32 <= (*p) && (*p) <= 32 ) { _widec = (short)(128 + ((*p) - -128)); if ( -#line 490 "parser.rl" json->allow_trailing_comma ) _widec += 256; } } else if ( (*p) > 44 ) { if ( 47 <= (*p) && (*p) <= 47 ) { _widec = (short)(128 + ((*p) - -128)); if ( -#line 490 "parser.rl" json->allow_trailing_comma ) _widec += 256; } } else { _widec = (short)(128 + ((*p) - -128)); if ( -#line 490 "parser.rl" json->allow_trailing_comma ) _widec += 256; } } else { _widec = (short)(128 + ((*p) - -128)); if ( -#line 490 "parser.rl" json->allow_trailing_comma ) _widec += 256; } switch( _widec ) { @@ -669,14 +668,14 @@ case 9: goto st10; goto st0; tr4: -#line 503 "parser.rl" { p--; {p++; cs = 32; goto _out;} } goto st32; st32: if ( ++p == pe ) goto _test_eof32; case 32: -#line 680 "parser.c" goto st0; st10: if ( ++p == pe ) @@ -778,13 +777,13 @@ case 20: if ( 47 <= (*p) && (*p) <= 47 ) { _widec = (short)(128 + ((*p) - -128)); if ( -#line 490 "parser.rl" json->allow_trailing_comma ) _widec += 256; } } else if ( (*p) >= 42 ) { _widec = (short)(128 + ((*p) - -128)); if ( -#line 490 "parser.rl" json->allow_trailing_comma ) _widec += 256; } switch( _widec ) { @@ -803,20 +802,20 @@ case 21: if ( (*p) <= 41 ) { _widec = (short)(128 + ((*p) - -128)); if ( -#line 490 "parser.rl" json->allow_trailing_comma ) _widec += 256; } } else if ( (*p) > 42 ) { if ( 43 <= (*p) ) { _widec = (short)(128 + ((*p) - -128)); if ( -#line 490 "parser.rl" json->allow_trailing_comma ) _widec += 256; } } else { _widec = (short)(128 + ((*p) - -128)); if ( -#line 490 "parser.rl" json->allow_trailing_comma ) _widec += 256; } switch( _widec ) { @@ -839,13 +838,13 @@ case 22: if ( 42 <= (*p) && (*p) <= 42 ) { _widec = (short)(128 + ((*p) - -128)); if ( -#line 490 "parser.rl" json->allow_trailing_comma ) _widec += 256; } } else { _widec = (short)(128 + ((*p) - -128)); if ( -#line 490 "parser.rl" json->allow_trailing_comma ) _widec += 256; } } else if ( (*p) > 46 ) { @@ -853,19 +852,19 @@ case 22: if ( 48 <= (*p) ) { _widec = (short)(128 + ((*p) - -128)); if ( -#line 490 "parser.rl" json->allow_trailing_comma ) _widec += 256; } } else if ( (*p) >= 47 ) { _widec = (short)(128 + ((*p) - -128)); if ( -#line 490 "parser.rl" json->allow_trailing_comma ) _widec += 256; } } else { _widec = (short)(128 + ((*p) - -128)); if ( -#line 490 "parser.rl" json->allow_trailing_comma ) _widec += 256; } switch( _widec ) { @@ -889,20 +888,20 @@ case 23: if ( (*p) <= 9 ) { _widec = (short)(128 + ((*p) - -128)); if ( -#line 490 "parser.rl" json->allow_trailing_comma ) _widec += 256; } } else if ( (*p) > 10 ) { if ( 11 <= (*p) ) { _widec = (short)(128 + ((*p) - -128)); if ( -#line 490 "parser.rl" json->allow_trailing_comma ) _widec += 256; } } else { _widec = (short)(128 + ((*p) - -128)); if ( -#line 490 "parser.rl" json->allow_trailing_comma ) _widec += 256; } switch( _widec ) { @@ -1016,15 +1015,15 @@ case 31: _out: {} } -#line 529 "parser.rl" if (cs >= JSON_object_first_final) { - long count = json->stack->head - stack_head; if (RB_UNLIKELY(json->object_class)) { VALUE object = rb_class_new_instance(0, 0, json->object_class); long index = 0; - VALUE *items = rvalue_stack_peek(json->stack, count); while (index < count) { VALUE name = items[index++]; VALUE value = items[index++]; @@ -1038,10 +1037,10 @@ case 31: #else hash = rb_hash_new(); #endif - rb_hash_bulk_insert(count, rvalue_stack_peek(json->stack, count), hash); *result = hash; } - rvalue_stack_pop(json->stack, count); if (RB_UNLIKELY(json->create_additions)) { VALUE klassname; @@ -1067,7 +1066,7 @@ case 31: } -#line 1071 "parser.c" enum {JSON_value_start = 1}; enum {JSON_value_first_final = 29}; enum {JSON_value_error = 0}; @@ -1075,22 +1074,22 @@ enum {JSON_value_error = 0}; enum {JSON_value_en_main = 1}; -#line 662 "parser.rl" -static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting) { int cs = EVIL; -#line 1087 "parser.c" { cs = JSON_value_start; } -#line 669 "parser.rl" -#line 1094 "parser.c" { if ( p == pe ) goto _test_eof; @@ -1124,9 +1123,9 @@ st0: cs = 0; goto _out; tr2: -#line 607 "parser.rl" { - char *np = JSON_parse_string(json, p, pe, result); if (np == NULL) { p--; {p++; cs = 29; goto _out;} @@ -1136,7 +1135,7 @@ tr2: } goto st29; tr3: -#line 617 "parser.rl" { char *np; if(pe > p + 8 && !strncmp(MinusInfinity, p, 9)) { @@ -1148,7 +1147,7 @@ tr3: raise_parse_error("unexpected token at '%s'", p); } } - np = JSON_parse_number(json, p, pe, result); if (np != NULL) { {p = (( np))-1;} } @@ -1156,25 +1155,25 @@ tr3: } goto st29; tr7: -#line 635 "parser.rl" { char *np; - json->in_array++; - np = JSON_parse_array(json, p, pe, result, current_nesting + 1); - json->in_array--; if (np == NULL) { p--; {p++; cs = 29; goto _out;} } else {p = (( np))-1;} } goto st29; tr11: -#line 643 "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 600 "parser.rl" { if (json->allow_nan) { *result = CInfinity; @@ -1184,7 +1183,7 @@ tr25: } goto st29; tr27: -#line 593 "parser.rl" { if (json->allow_nan) { *result = CNaN; @@ -1194,19 +1193,19 @@ tr27: } goto st29; tr31: -#line 587 "parser.rl" { *result = Qfalse; } goto st29; tr34: -#line 584 "parser.rl" { *result = Qnil; } goto st29; tr37: -#line 590 "parser.rl" { *result = Qtrue; } @@ -1215,9 +1214,9 @@ st29: if ( ++p == pe ) goto _test_eof29; case 29: -#line 649 "parser.rl" { p--; {p++; cs = 29; goto _out;} } -#line 1221 "parser.c" switch( (*p) ) { case 13: goto st29; case 32: goto st29; @@ -1458,7 +1457,7 @@ case 28: _out: {} } -#line 670 "parser.rl" if (json->freeze) { OBJ_FREEZE(*result); @@ -1473,7 +1472,7 @@ case 28: } -#line 1477 "parser.c" enum {JSON_integer_start = 1}; enum {JSON_integer_first_final = 3}; enum {JSON_integer_error = 0}; @@ -1481,7 +1480,7 @@ enum {JSON_integer_error = 0}; enum {JSON_integer_en_main = 1}; -#line 691 "parser.rl" #define MAX_FAST_INTEGER_SIZE 18 @@ -1506,22 +1505,22 @@ static inline VALUE fast_parse_integer(char *p, char *pe) return LL2NUM(memo); } -static char *JSON_decode_integer(JSON_Parser *json, char *p, VALUE *result) { - long len = p - json->memo; if (RB_LIKELY(len < MAX_FAST_INTEGER_SIZE)) { - *result = fast_parse_integer(json->memo, p); } else { - 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; } -#line 1525 "parser.c" enum {JSON_float_start = 1}; enum {JSON_float_first_final = 6}; enum {JSON_float_error = 0}; @@ -1529,24 +1528,24 @@ enum {JSON_float_error = 0}; enum {JSON_float_en_main = 1}; -#line 743 "parser.rl" -static char *JSON_parse_number(JSON_Parser *json, char *p, char *pe, VALUE *result) { int cs = EVIL; bool is_float = false; -#line 1542 "parser.c" { cs = JSON_float_start; } -#line 751 "parser.rl" - json->memo = p; -#line 1550 "parser.c" { if ( p == pe ) goto _test_eof; @@ -1586,24 +1585,24 @@ case 6: goto st0; goto tr7; tr7: -#line 735 "parser.rl" { p--; {p++; cs = 7; goto _out;} } goto st7; st7: if ( ++p == pe ) goto _test_eof7; case 7: -#line 1597 "parser.c" goto st0; tr8: -#line 736 "parser.rl" { is_float = true; } goto st3; st3: if ( ++p == pe ) goto _test_eof3; case 3: -#line 1607 "parser.c" if ( 48 <= (*p) && (*p) <= 57 ) goto st8; goto st0; @@ -1622,14 +1621,14 @@ case 8: goto st0; goto tr7; tr9: -#line 736 "parser.rl" { is_float = true; } goto st4; st4: if ( ++p == pe ) goto _test_eof4; case 4: -#line 1633 "parser.c" switch( (*p) ) { case 43: goto st5; case 45: goto st5; @@ -1686,11 +1685,11 @@ case 10: _out: {} } -#line 753 "parser.rl" if (cs >= JSON_float_first_final) { if (!is_float) { - return JSON_decode_integer(json, p, result); } VALUE mod = Qnil; ID method_id = 0; @@ -1722,16 +1721,16 @@ case 10: } } - 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; @@ -1742,7 +1741,7 @@ case 10: -#line 1746 "parser.c" enum {JSON_array_start = 1}; enum {JSON_array_first_final = 22}; enum {JSON_array_error = 0}; @@ -1750,27 +1749,27 @@ enum {JSON_array_error = 0}; enum {JSON_array_en_main = 1}; -#line 833 "parser.rl" -static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting) { int cs = EVIL; if (json->max_nesting && current_nesting > json->max_nesting) { rb_raise(eNestingError, "nesting of %d is too deep", current_nesting); } - long stack_head = json->stack->head; -#line 1767 "parser.c" { cs = JSON_array_start; } -#line 845 "parser.rl" -#line 1774 "parser.c" { short _widec; if ( p == pe ) @@ -1810,10 +1809,10 @@ case 2: goto st2; goto st0; tr2: -#line 813 "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 { @@ -1825,12 +1824,12 @@ st3: if ( ++p == pe ) goto _test_eof3; case 3: -#line 1829 "parser.c" _widec = (*p); if ( 44 <= (*p) && (*p) <= 44 ) { _widec = (short)(128 + ((*p) - -128)); if ( -#line 823 "parser.rl" json->allow_trailing_comma ) _widec += 256; } switch( _widec ) { @@ -1877,14 +1876,14 @@ case 7: goto st3; goto st7; tr4: -#line 825 "parser.rl" { p--; {p++; cs = 22; goto _out;} } goto st22; st22: if ( ++p == pe ) goto _test_eof22; case 22: -#line 1888 "parser.c" goto st0; st8: if ( ++p == pe ) @@ -1952,13 +1951,13 @@ case 13: if ( 10 <= (*p) && (*p) <= 10 ) { _widec = (short)(128 + ((*p) - -128)); if ( -#line 823 "parser.rl" json->allow_trailing_comma ) _widec += 256; } } else if ( (*p) >= 9 ) { _widec = (short)(128 + ((*p) - -128)); if ( -#line 823 "parser.rl" json->allow_trailing_comma ) _widec += 256; } } else if ( (*p) > 13 ) { @@ -1966,19 +1965,19 @@ case 13: if ( 47 <= (*p) && (*p) <= 47 ) { _widec = (short)(128 + ((*p) - -128)); if ( -#line 823 "parser.rl" json->allow_trailing_comma ) _widec += 256; } } else if ( (*p) >= 32 ) { _widec = (short)(128 + ((*p) - -128)); if ( -#line 823 "parser.rl" json->allow_trailing_comma ) _widec += 256; } } else { _widec = (short)(128 + ((*p) - -128)); if ( -#line 823 "parser.rl" json->allow_trailing_comma ) _widec += 256; } switch( _widec ) { @@ -2017,13 +2016,13 @@ case 14: if ( 47 <= (*p) && (*p) <= 47 ) { _widec = (short)(128 + ((*p) - -128)); if ( -#line 823 "parser.rl" json->allow_trailing_comma ) _widec += 256; } } else if ( (*p) >= 42 ) { _widec = (short)(128 + ((*p) - -128)); if ( -#line 823 "parser.rl" json->allow_trailing_comma ) _widec += 256; } switch( _widec ) { @@ -2042,20 +2041,20 @@ case 15: if ( (*p) <= 41 ) { _widec = (short)(128 + ((*p) - -128)); if ( -#line 823 "parser.rl" json->allow_trailing_comma ) _widec += 256; } } else if ( (*p) > 42 ) { if ( 43 <= (*p) ) { _widec = (short)(128 + ((*p) - -128)); if ( -#line 823 "parser.rl" json->allow_trailing_comma ) _widec += 256; } } else { _widec = (short)(128 + ((*p) - -128)); if ( -#line 823 "parser.rl" json->allow_trailing_comma ) _widec += 256; } switch( _widec ) { @@ -2078,13 +2077,13 @@ case 16: if ( 42 <= (*p) && (*p) <= 42 ) { _widec = (short)(128 + ((*p) - -128)); if ( -#line 823 "parser.rl" json->allow_trailing_comma ) _widec += 256; } } else { _widec = (short)(128 + ((*p) - -128)); if ( -#line 823 "parser.rl" json->allow_trailing_comma ) _widec += 256; } } else if ( (*p) > 46 ) { @@ -2092,19 +2091,19 @@ case 16: if ( 48 <= (*p) ) { _widec = (short)(128 + ((*p) - -128)); if ( -#line 823 "parser.rl" json->allow_trailing_comma ) _widec += 256; } } else if ( (*p) >= 47 ) { _widec = (short)(128 + ((*p) - -128)); if ( -#line 823 "parser.rl" json->allow_trailing_comma ) _widec += 256; } } else { _widec = (short)(128 + ((*p) - -128)); if ( -#line 823 "parser.rl" json->allow_trailing_comma ) _widec += 256; } switch( _widec ) { @@ -2128,20 +2127,20 @@ case 17: if ( (*p) <= 9 ) { _widec = (short)(128 + ((*p) - -128)); if ( -#line 823 "parser.rl" json->allow_trailing_comma ) _widec += 256; } } else if ( (*p) > 10 ) { if ( 11 <= (*p) ) { _widec = (short)(128 + ((*p) - -128)); if ( -#line 823 "parser.rl" json->allow_trailing_comma ) _widec += 256; } } else { _widec = (short)(128 + ((*p) - -128)); if ( -#line 823 "parser.rl" json->allow_trailing_comma ) _widec += 256; } switch( _widec ) { @@ -2213,24 +2212,24 @@ case 21: _out: {} } -#line 846 "parser.rl" if(cs >= JSON_array_first_final) { - long count = json->stack->head - stack_head; if (RB_UNLIKELY(json->array_class)) { VALUE array = rb_class_new_instance(0, 0, json->array_class); - VALUE *items = rvalue_stack_peek(json->stack, count); long index; for (index = 0; index < count; index++) { rb_funcall(array, i_leftshift, 1, items[index]); } *result = array; } else { - VALUE array = rb_ary_new_from_values(count, rvalue_stack_peek(json->stack, count)); *result = array; } - rvalue_stack_pop(json->stack, count); return p + 1; } else { @@ -2265,16 +2264,16 @@ static inline VALUE build_string(const char *start, const char *end, bool intern return result; } -static VALUE json_string_fastpath(JSON_Parser *json, char *string, char *stringEnd, bool is_name, bool intern, bool symbolize) { size_t bufferSize = stringEnd - string; - if (is_name && json->in_array) { VALUE cached_key; if (RB_UNLIKELY(symbolize)) { - cached_key = rsymbol_cache_fetch(&json->name_cache, string, bufferSize); } else { - cached_key = rstring_cache_fetch(&json->name_cache, string, bufferSize); } if (RB_LIKELY(cached_key)) { @@ -2285,19 +2284,19 @@ static VALUE json_string_fastpath(JSON_Parser *json, char *string, char *stringE return build_string(string, stringEnd, intern, symbolize); } -static VALUE json_string_unescape(JSON_Parser *json, char *string, char *stringEnd, bool is_name, bool intern, bool symbolize) { size_t bufferSize = stringEnd - string; char *p = string, *pe = string, *unescape, *bufferStart, *buffer; int unescape_len; char buf[4]; - if (is_name && json->in_array) { VALUE cached_key; if (RB_UNLIKELY(symbolize)) { - cached_key = rsymbol_cache_fetch(&json->name_cache, string, bufferSize); } else { - cached_key = rstring_cache_fetch(&json->name_cache, string, bufferSize); } if (RB_LIKELY(cached_key)) { @@ -2407,7 +2406,7 @@ static VALUE json_string_unescape(JSON_Parser *json, char *string, char *stringE } -#line 2411 "parser.c" enum {JSON_string_start = 1}; enum {JSON_string_first_final = 9}; enum {JSON_string_error = 0}; @@ -2415,7 +2414,7 @@ enum {JSON_string_error = 0}; enum {JSON_string_en_main = 1}; -#line 1069 "parser.rl" static int @@ -2430,21 +2429,21 @@ match_i(VALUE regexp, VALUE klass, VALUE memo) return ST_CONTINUE; } -static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *result) { int cs = EVIL; VALUE match_string; -#line 2440 "parser.c" { cs = JSON_string_start; } -#line 1089 "parser.rl" - json->memo = p; -#line 2448 "parser.c" { if ( p == pe ) goto _test_eof; @@ -2469,25 +2468,25 @@ case 2: goto st0; goto st2; tr2: -#line 1051 "parser.rl" { - *result = json_string_fastpath(json, json->memo + 1, p, json->parsing_name, json->parsing_name || json-> freeze, json->parsing_name && json->symbolize_names); {p = (( p + 1))-1;} p--; {p++; cs = 9; goto _out;} } -#line 1044 "parser.rl" { - *result = json_string_unescape(json, json->memo + 1, p, json->parsing_name, json->parsing_name || json-> freeze, json->parsing_name && json->symbolize_names); {p = (( p + 1))-1;} p--; {p++; cs = 9; goto _out;} } goto st9; tr6: -#line 1044 "parser.rl" { - *result = json_string_unescape(json, json->memo + 1, p, json->parsing_name, json->parsing_name || json-> freeze, json->parsing_name && json->symbolize_names); {p = (( p + 1))-1;} p--; {p++; cs = 9; goto _out;} @@ -2497,7 +2496,7 @@ st9: if ( ++p == pe ) goto _test_eof9; case 9: -#line 2501 "parser.c" goto st0; st3: if ( ++p == pe ) @@ -2585,7 +2584,7 @@ case 8: _out: {} } -#line 1091 "parser.rl" if (json->create_additions && RTEST(match_string = json->match_string)) { VALUE klass; @@ -2660,13 +2659,8 @@ static int configure_parser_i(VALUE key, VALUE val, VALUE data) return ST_CONTINUE; } -static void parser_init(JSON_Parser *json, VALUE source, VALUE opts) { - if (json->Vsource) { - rb_raise(rb_eTypeError, "already initialized instance"); - } - - json->fbuffer.initial_length = FBUFFER_INITIAL_LENGTH_DEFAULT; json->max_nesting = 100; if (!NIL_P(opts)) { @@ -2688,17 +2682,12 @@ static void parser_init(JSON_Parser *json, VALUE source, VALUE opts) } } - source = convert_encoding(StringValue(source)); - StringValue(source); - json->len = RSTRING_LEN(source); - json->source = RSTRING_PTR(source); - json->Vsource = source; } /* - * call-seq: new(source, opts => {}) * - * 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: @@ -2727,18 +2716,16 @@ static void parser_init(JSON_Parser *json, VALUE source, VALUE opts) * (Float) when parsing decimal numbers. This class must accept a single * string argument in its constructor. */ -static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self) { - GET_PARSER_INIT; - - rb_check_arity(argc, 1, 2); - parser_init(json, argv[0], argc == 2 ? argv[1] : Qnil); return self; } -#line 2742 "parser.c" enum {JSON_start = 1}; enum {JSON_first_final = 10}; enum {JSON_error = 0}; @@ -2746,45 +2733,28 @@ enum {JSON_error = 0}; enum {JSON_en_main = 1}; -#line 1257 "parser.rl" -/* - * call-seq: parse() - * - * Parses the current JSON text _source_ and returns the complete data - * structure as a result. - * It raises JSON::ParserError if fail to parse. - */ -static VALUE cParser_parse(VALUE self) { char *p, *pe; int cs = EVIL; - VALUE result = Qnil; - GET_PARSER; - - char stack_buffer[FBUFFER_STACK_SIZE]; - fbuffer_stack_init(&json->fbuffer, FBUFFER_INITIAL_LENGTH_DEFAULT, stack_buffer, FBUFFER_STACK_SIZE); - - VALUE rvalue_stack_buffer[RVALUE_STACK_INITIAL_CAPA]; - rvalue_stack stack = { - .type = RVALUE_STACK_STACK_ALLOCATED, - .ptr = rvalue_stack_buffer, - .capa = RVALUE_STACK_INITIAL_CAPA, - }; - json->stack = &stack; -#line 2779 "parser.c" { cs = JSON_start; } -#line 1285 "parser.rl" - p = json->source; - pe = p + json->len; -#line 2788 "parser.c" { if ( p == pe ) goto _test_eof; @@ -2818,9 +2788,9 @@ st0: cs = 0; goto _out; tr2: -#line 1249 "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; @@ -2828,7 +2798,7 @@ st10: if ( ++p == pe ) goto _test_eof10; case 10: -#line 2832 "parser.c" switch( (*p) ) { case 13: goto st10; case 32: goto st10; @@ -2917,10 +2887,10 @@ case 9: _out: {} } -#line 1288 "parser.rl" - if (json->stack_handle) { - rvalue_stack_eagerly_release(json->stack_handle); } if (cs >= JSON_first_final && p == pe) { @@ -2931,18 +2901,10 @@ case 9: } } -static VALUE cParser_m_parse(VALUE klass, VALUE source, VALUE opts) { - char *p, *pe; - int cs = EVIL; - VALUE result = Qnil; - - JSON_Parser _parser = {0}; - JSON_Parser *json = &_parser; - parser_init(json, source, opts); - - char stack_buffer[FBUFFER_STACK_SIZE]; - fbuffer_stack_init(&json->fbuffer, FBUFFER_INITIAL_LENGTH_DEFAULT, stack_buffer, FBUFFER_STACK_SIZE); VALUE rvalue_stack_buffer[RVALUE_STACK_INITIAL_CAPA]; rvalue_stack stack = { @@ -2950,193 +2912,74 @@ static VALUE cParser_m_parse(VALUE klass, VALUE source, VALUE opts) .ptr = rvalue_stack_buffer, .capa = RVALUE_STACK_INITIAL_CAPA, }; - json->stack = &stack; -#line 2957 "parser.c" - { - cs = JSON_start; - } -#line 1323 "parser.rl" - p = json->source; - pe = p + json->len; -#line 2966 "parser.c" - { - if ( p == pe ) - goto _test_eof; - switch ( cs ) - { -st1: - if ( ++p == pe ) - goto _test_eof1; -case 1: - switch( (*p) ) { - case 13: goto st1; - case 32: goto st1; - case 34: goto tr2; - case 45: goto tr2; - case 47: goto st6; - case 73: goto tr2; - case 78: goto tr2; - case 91: goto tr2; - case 102: goto tr2; - case 110: goto tr2; - case 116: goto tr2; - case 123: goto tr2; - } - if ( (*p) > 10 ) { - if ( 48 <= (*p) && (*p) <= 57 ) - goto tr2; - } else if ( (*p) >= 9 ) - goto st1; - goto st0; -st0: -cs = 0; - goto _out; -tr2: -#line 1249 "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; -case 10: -#line 3010 "parser.c" - switch( (*p) ) { - case 13: goto st10; - case 32: goto st10; - case 47: goto st2; - } - if ( 9 <= (*p) && (*p) <= 10 ) - goto st10; - goto st0; -st2: - if ( ++p == pe ) - goto _test_eof2; -case 2: - switch( (*p) ) { - case 42: goto st3; - case 47: goto st5; - } - goto st0; -st3: - if ( ++p == pe ) - goto _test_eof3; -case 3: - if ( (*p) == 42 ) - goto st4; - goto st3; -st4: - if ( ++p == pe ) - goto _test_eof4; -case 4: - switch( (*p) ) { - case 42: goto st4; - case 47: goto st10; - } - goto st3; -st5: - if ( ++p == pe ) - goto _test_eof5; -case 5: - if ( (*p) == 10 ) - goto st10; - goto st5; -st6: - if ( ++p == pe ) - goto _test_eof6; -case 6: - switch( (*p) ) { - case 42: goto st7; - case 47: goto st9; - } - goto st0; -st7: - if ( ++p == pe ) - goto _test_eof7; -case 7: - if ( (*p) == 42 ) - goto st8; - goto st7; -st8: - if ( ++p == pe ) - goto _test_eof8; -case 8: - switch( (*p) ) { - case 42: goto st8; - case 47: goto st1; - } - goto st7; -st9: - if ( ++p == pe ) - goto _test_eof9; -case 9: - if ( (*p) == 10 ) - goto st1; - goto st9; - } - _test_eof1: cs = 1; goto _test_eof; - _test_eof10: cs = 10; goto _test_eof; - _test_eof2: cs = 2; goto _test_eof; - _test_eof3: cs = 3; goto _test_eof; - _test_eof4: cs = 4; goto _test_eof; - _test_eof5: cs = 5; goto _test_eof; - _test_eof6: cs = 6; goto _test_eof; - _test_eof7: cs = 7; goto _test_eof; - _test_eof8: cs = 8; goto _test_eof; - _test_eof9: cs = 9; goto _test_eof; - _test_eof: {} - _out: {} - } -#line 1326 "parser.rl" - if (json->stack_handle) { - rvalue_stack_eagerly_release(json->stack_handle); - } - if (cs >= JSON_first_final && p == pe) { - return result; - } else { - raise_parse_error("unexpected token at '%s'", p); - return Qnil; - } } static void JSON_mark(void *ptr) { JSON_Parser *json = ptr; - rb_gc_mark(json->Vsource); rb_gc_mark(json->create_id); rb_gc_mark(json->object_class); rb_gc_mark(json->array_class); rb_gc_mark(json->decimal_class); rb_gc_mark(json->match_string); - rb_gc_mark(json->stack_handle); - - long index; - for (index = 0; index < json->name_cache.length; index++) { - rb_gc_mark(json->name_cache.entries[index]); - } } static void JSON_free(void *ptr) { 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); } static const rb_data_type_t JSON_Parser_type = { @@ -3149,21 +2992,7 @@ static const rb_data_type_t JSON_Parser_type = { static VALUE cJSON_parser_s_allocate(VALUE klass) { JSON_Parser *json; - VALUE obj = TypedData_Make_Struct(klass, JSON_Parser, &JSON_Parser_type, json); - fbuffer_stack_init(&json->fbuffer, 0, NULL, 0); - return obj; -} - -/* - * 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); } void Init_parser(void) @@ -3175,15 +3004,15 @@ void Init_parser(void) #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); eNestingError = rb_path2class("JSON::NestingError"); 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); rb_define_singleton_method(cParser, "parse", cParser_m_parse, 2); CNaN = rb_const_get(mJSON, rb_intern("NaN")); @@ -1,7 +1,7 @@ #include "ruby.h" #include "../fbuffer/fbuffer.h" -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, @@ -372,17 +372,11 @@ static int convert_UTF32_to_UTF8(char *buf, uint32_t ch) } 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 in_array; int max_nesting; bool allow_nan; bool allow_trailing_comma; @@ -391,16 +385,22 @@ typedef struct JSON_ParserStruct { bool freeze; bool create_additions; bool deprecated_create_additions; - rvalue_cache name_cache; - rvalue_stack *stack; - VALUE stack_handle; } 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) @@ -408,12 +408,11 @@ typedef struct JSON_ParserStruct { #define EVIL 0x666 static const rb_data_type_t JSON_Parser_type; -static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *result); -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_number(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); - #ifndef HAVE_STRNLEN static size_t strnlen(const char *s, size_t maxlen) @@ -479,7 +478,7 @@ static void raise_parse_error(const char *format, const char *start) write data; action parse_value { - char *np = JSON_parse_value(json, fpc, pe, result, current_nesting); if (np == NULL) { fhold; fbreak; } else { @@ -492,7 +491,7 @@ static void raise_parse_error(const char *format, const char *start) action parse_name { char *np; json->parsing_name = true; - np = JSON_parse_string(json, fpc, pe, result); json->parsing_name = false; if (np == NULL) { fhold; fbreak; } else { PUSH(*result); @@ -512,9 +511,9 @@ static void raise_parse_error(const char *format, const char *start) ) @exit; }%% -#define PUSH(result) rvalue_stack_push(json->stack, result, &json->stack_handle, &json->stack) -static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting) { int cs = EVIL; @@ -522,18 +521,18 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu rb_raise(eNestingError, "nesting of %d is too deep", current_nesting); } - long stack_head = json->stack->head; %% write init; %% write exec; if (cs >= JSON_object_first_final) { - long count = json->stack->head - stack_head; if (RB_UNLIKELY(json->object_class)) { VALUE object = rb_class_new_instance(0, 0, json->object_class); long index = 0; - VALUE *items = rvalue_stack_peek(json->stack, count); while (index < count) { VALUE name = items[index++]; VALUE value = items[index++]; @@ -547,10 +546,10 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu #else hash = rb_hash_new(); #endif - rb_hash_bulk_insert(count, rvalue_stack_peek(json->stack, count), hash); *result = hash; } - rvalue_stack_pop(json->stack, count); if (RB_UNLIKELY(json->create_additions)) { VALUE klassname; @@ -605,7 +604,7 @@ 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; @@ -625,7 +624,7 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu raise_parse_error("unexpected token at '%s'", p); } } - np = JSON_parse_number(json, fpc, pe, result); if (np != NULL) { fexec np; } @@ -634,15 +633,15 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu action parse_array { char *np; - json->in_array++; - np = JSON_parse_array(json, fpc, pe, result, current_nesting + 1); - json->in_array--; if (np == NULL) { fhold; fbreak; } else fexec np; } action parse_object { char *np; - np = JSON_parse_object(json, fpc, pe, result, current_nesting + 1); if (np == NULL) { fhold; fbreak; } else fexec np; } @@ -661,7 +660,7 @@ main := ignore* ( ) ignore* %*exit; }%% -static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting) { int cs = EVIL; @@ -712,16 +711,16 @@ static inline VALUE fast_parse_integer(char *p, char *pe) return LL2NUM(memo); } -static char *JSON_decode_integer(JSON_Parser *json, char *p, VALUE *result) { - long len = p - json->memo; if (RB_LIKELY(len < MAX_FAST_INTEGER_SIZE)) { - *result = fast_parse_integer(json->memo, p); } else { - 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; } @@ -742,18 +741,18 @@ static char *JSON_decode_integer(JSON_Parser *json, char *p, VALUE *result) ) (^[0-9Ee.\-]? @exit )); }%% -static char *JSON_parse_number(JSON_Parser *json, char *p, char *pe, VALUE *result) { int cs = EVIL; bool is_float = false; %% write init; - json->memo = p; %% write exec; if (cs >= JSON_float_first_final) { if (!is_float) { - return JSON_decode_integer(json, p, result); } VALUE mod = Qnil; ID method_id = 0; @@ -785,16 +784,16 @@ static char *JSON_parse_number(JSON_Parser *json, char *p, char *pe, VALUE *resu } } - 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; @@ -812,7 +811,7 @@ static char *JSON_parse_number(JSON_Parser *json, char *p, char *pe, VALUE *resu action parse_value { VALUE v = Qnil; - char *np = JSON_parse_value(json, fpc, pe, &v, current_nesting); if (np == NULL) { fhold; fbreak; } else { @@ -832,34 +831,34 @@ static char *JSON_parse_number(JSON_Parser *json, char *p, char *pe, VALUE *resu end_array @exit; }%% -static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting) { int cs = EVIL; if (json->max_nesting && current_nesting > json->max_nesting) { rb_raise(eNestingError, "nesting of %d is too deep", current_nesting); } - long stack_head = json->stack->head; %% write init; %% write exec; if(cs >= JSON_array_first_final) { - long count = json->stack->head - stack_head; if (RB_UNLIKELY(json->array_class)) { VALUE array = rb_class_new_instance(0, 0, json->array_class); - VALUE *items = rvalue_stack_peek(json->stack, count); long index; for (index = 0; index < count; index++) { rb_funcall(array, i_leftshift, 1, items[index]); } *result = array; } else { - VALUE array = rb_ary_new_from_values(count, rvalue_stack_peek(json->stack, count)); *result = array; } - rvalue_stack_pop(json->stack, count); return p + 1; } else { @@ -894,16 +893,16 @@ static inline VALUE build_string(const char *start, const char *end, bool intern return result; } -static VALUE json_string_fastpath(JSON_Parser *json, char *string, char *stringEnd, bool is_name, bool intern, bool symbolize) { size_t bufferSize = stringEnd - string; - if (is_name && json->in_array) { VALUE cached_key; if (RB_UNLIKELY(symbolize)) { - cached_key = rsymbol_cache_fetch(&json->name_cache, string, bufferSize); } else { - cached_key = rstring_cache_fetch(&json->name_cache, string, bufferSize); } if (RB_LIKELY(cached_key)) { @@ -914,19 +913,19 @@ static VALUE json_string_fastpath(JSON_Parser *json, char *string, char *stringE return build_string(string, stringEnd, intern, symbolize); } -static VALUE json_string_unescape(JSON_Parser *json, char *string, char *stringEnd, bool is_name, bool intern, bool symbolize) { size_t bufferSize = stringEnd - string; char *p = string, *pe = string, *unescape, *bufferStart, *buffer; int unescape_len; char buf[4]; - if (is_name && json->in_array) { VALUE cached_key; if (RB_UNLIKELY(symbolize)) { - cached_key = rsymbol_cache_fetch(&json->name_cache, string, bufferSize); } else { - cached_key = rstring_cache_fetch(&json->name_cache, string, bufferSize); } if (RB_LIKELY(cached_key)) { @@ -1042,14 +1041,14 @@ static VALUE json_string_unescape(JSON_Parser *json, char *string, char *stringE write data; action parse_complex_string { - *result = json_string_unescape(json, json->memo + 1, p, json->parsing_name, json->parsing_name || json-> freeze, json->parsing_name && json->symbolize_names); fexec p + 1; fhold; fbreak; } action parse_simple_string { - *result = json_string_fastpath(json, json->memo + 1, p, json->parsing_name, json->parsing_name || json-> freeze, json->parsing_name && json->symbolize_names); fexec p + 1; fhold; fbreak; @@ -1080,13 +1079,13 @@ match_i(VALUE regexp, VALUE klass, VALUE memo) return ST_CONTINUE; } -static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *result) { int cs = EVIL; VALUE match_string; %% write init; - json->memo = p; %% write exec; if (json->create_additions && RTEST(match_string = json->match_string)) { @@ -1162,13 +1161,8 @@ static int configure_parser_i(VALUE key, VALUE val, VALUE data) return ST_CONTINUE; } -static void parser_init(JSON_Parser *json, VALUE source, VALUE opts) { - if (json->Vsource) { - rb_raise(rb_eTypeError, "already initialized instance"); - } - - json->fbuffer.initial_length = FBUFFER_INITIAL_LENGTH_DEFAULT; json->max_nesting = 100; if (!NIL_P(opts)) { @@ -1190,17 +1184,12 @@ static void parser_init(JSON_Parser *json, VALUE source, VALUE opts) } } - source = convert_encoding(StringValue(source)); - StringValue(source); - json->len = RSTRING_LEN(source); - json->source = RSTRING_PTR(source); - json->Vsource = source; } /* - * call-seq: new(source, opts => {}) * - * 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: @@ -1229,13 +1218,11 @@ static void parser_init(JSON_Parser *json, VALUE source, VALUE opts) * (Float) when parsing decimal numbers. This class must accept a single * string argument in its constructor. */ -static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self) { - GET_PARSER_INIT; - - rb_check_arity(argc, 1, 2); - parser_init(json, argv[0], argc == 2 ? argv[1] : Qnil); return self; } @@ -1247,7 +1234,7 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self) include JSON_common; action parse_value { - char *np = JSON_parse_value(json, fpc, pe, &result, 0); if (np == NULL) { fhold; fbreak; } else fexec np; } @@ -1256,38 +1243,21 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self) ) ignore*; }%% -/* - * call-seq: parse() - * - * Parses the current JSON text _source_ and returns the complete data - * structure as a result. - * It raises JSON::ParserError if fail to parse. - */ -static VALUE cParser_parse(VALUE self) { char *p, *pe; int cs = EVIL; - VALUE result = Qnil; - GET_PARSER; - - char stack_buffer[FBUFFER_STACK_SIZE]; - fbuffer_stack_init(&json->fbuffer, FBUFFER_INITIAL_LENGTH_DEFAULT, stack_buffer, FBUFFER_STACK_SIZE); - - VALUE rvalue_stack_buffer[RVALUE_STACK_INITIAL_CAPA]; - rvalue_stack stack = { - .type = RVALUE_STACK_STACK_ALLOCATED, - .ptr = rvalue_stack_buffer, - .capa = RVALUE_STACK_INITIAL_CAPA, - }; - json->stack = &stack; %% write init; - p = json->source; - pe = p + json->len; %% write exec; - if (json->stack_handle) { - rvalue_stack_eagerly_release(json->stack_handle); } if (cs >= JSON_first_final && p == pe) { @@ -1298,18 +1268,10 @@ static VALUE cParser_parse(VALUE self) } } -static VALUE cParser_m_parse(VALUE klass, VALUE source, VALUE opts) { - char *p, *pe; - int cs = EVIL; - VALUE result = Qnil; - - JSON_Parser _parser = {0}; - JSON_Parser *json = &_parser; - parser_init(json, source, opts); - - char stack_buffer[FBUFFER_STACK_SIZE]; - fbuffer_stack_init(&json->fbuffer, FBUFFER_INITIAL_LENGTH_DEFAULT, stack_buffer, FBUFFER_STACK_SIZE); VALUE rvalue_stack_buffer[RVALUE_STACK_INITIAL_CAPA]; rvalue_stack stack = { @@ -1317,53 +1279,74 @@ static VALUE cParser_m_parse(VALUE klass, VALUE source, VALUE opts) .ptr = rvalue_stack_buffer, .capa = RVALUE_STACK_INITIAL_CAPA, }; - json->stack = &stack; - %% write init; - p = json->source; - pe = p + json->len; - %% write exec; - if (json->stack_handle) { - rvalue_stack_eagerly_release(json->stack_handle); - } - if (cs >= JSON_first_final && p == pe) { - return result; - } else { - raise_parse_error("unexpected token at '%s'", p); - return Qnil; } } static void JSON_mark(void *ptr) { JSON_Parser *json = ptr; - rb_gc_mark(json->Vsource); rb_gc_mark(json->create_id); rb_gc_mark(json->object_class); rb_gc_mark(json->array_class); rb_gc_mark(json->decimal_class); rb_gc_mark(json->match_string); - rb_gc_mark(json->stack_handle); - - long index; - for (index = 0; index < json->name_cache.length; index++) { - rb_gc_mark(json->name_cache.entries[index]); - } } static void JSON_free(void *ptr) { 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); } static const rb_data_type_t JSON_Parser_type = { @@ -1376,21 +1359,7 @@ static const rb_data_type_t JSON_Parser_type = { static VALUE cJSON_parser_s_allocate(VALUE klass) { JSON_Parser *json; - VALUE obj = TypedData_Make_Struct(klass, JSON_Parser, &JSON_Parser_type, json); - fbuffer_stack_init(&json->fbuffer, 0, NULL, 0); - return obj; -} - -/* - * 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); } void Init_parser(void) @@ -1402,15 +1371,15 @@ void Init_parser(void) #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); eNestingError = rb_path2class("JSON::NestingError"); 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); rb_define_singleton_method(cParser, "parse", cParser_m_parse, 2); CNaN = rb_const_get(mJSON, rb_intern("NaN")); @@ -6,11 +6,11 @@ class JSONExtParserTest < Test::Unit::TestCase def test_allocate parser = JSON::Ext::Parser.new("{}") - assert_raise(TypeError, '[ruby-core:35079]') do - parser.__send__(:initialize, "{}") - end parser = JSON::Ext::Parser.allocate - assert_raise(TypeError, '[ruby-core:35079]') { parser.source } end def test_error_messages |