diff options
Diffstat (limited to 'ext/json')
29 files changed, 2500 insertions, 3309 deletions
diff --git a/ext/json/VERSION b/ext/json/VERSION deleted file mode 100644 index e70b4523ae..0000000000 --- a/ext/json/VERSION +++ /dev/null @@ -1 +0,0 @@ -2.6.0 diff --git a/ext/json/fbuffer/fbuffer.h b/ext/json/fbuffer/fbuffer.h index dc8f406b5b..7ece0cee95 100644 --- a/ext/json/fbuffer/fbuffer.h +++ b/ext/json/fbuffer/fbuffer.h @@ -31,12 +31,8 @@ # define RB_OBJ_STRING(obj) StringValueCStr(obj) #endif -#ifdef HAVE_RUBY_ENCODING_H #include "ruby/encoding.h" #define FORCE_UTF8(obj) rb_enc_associate((obj), rb_utf8_encoding()) -#else -#define FORCE_UTF8(obj) -#endif /* We don't need to guard objects for rbx, so let's do nothing at all. */ #ifndef RB_GC_GUARD diff --git a/ext/json/generator/depend b/ext/json/generator/depend index 855e876cdb..f47e5f3a70 100644 --- a/ext/json/generator/depend +++ b/ext/json/generator/depend @@ -10,7 +10,6 @@ generator.o: $(hdrdir)/ruby/backward.h generator.o: $(hdrdir)/ruby/backward/2/assume.h generator.o: $(hdrdir)/ruby/backward/2/attributes.h generator.o: $(hdrdir)/ruby/backward/2/bool.h -generator.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h generator.o: $(hdrdir)/ruby/backward/2/inttypes.h generator.o: $(hdrdir)/ruby/backward/2/limits.h generator.o: $(hdrdir)/ruby/backward/2/long_long.h @@ -19,6 +18,7 @@ generator.o: $(hdrdir)/ruby/backward/2/stdarg.h generator.o: $(hdrdir)/ruby/defines.h generator.o: $(hdrdir)/ruby/encoding.h generator.o: $(hdrdir)/ruby/intern.h +generator.o: $(hdrdir)/ruby/internal/abi.h generator.o: $(hdrdir)/ruby/internal/anyargs.h generator.o: $(hdrdir)/ruby/internal/arithmetic.h generator.o: $(hdrdir)/ruby/internal/arithmetic/char.h @@ -56,6 +56,7 @@ generator.o: $(hdrdir)/ruby/internal/attr/noexcept.h generator.o: $(hdrdir)/ruby/internal/attr/noinline.h generator.o: $(hdrdir)/ruby/internal/attr/nonnull.h generator.o: $(hdrdir)/ruby/internal/attr/noreturn.h +generator.o: $(hdrdir)/ruby/internal/attr/packed_struct.h generator.o: $(hdrdir)/ruby/internal/attr/pure.h generator.o: $(hdrdir)/ruby/internal/attr/restrict.h generator.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h @@ -125,7 +126,6 @@ generator.o: $(hdrdir)/ruby/internal/intern/enumerator.h generator.o: $(hdrdir)/ruby/internal/intern/error.h generator.o: $(hdrdir)/ruby/internal/intern/eval.h generator.o: $(hdrdir)/ruby/internal/intern/file.h -generator.o: $(hdrdir)/ruby/internal/intern/gc.h generator.o: $(hdrdir)/ruby/internal/intern/hash.h generator.o: $(hdrdir)/ruby/internal/intern/io.h generator.o: $(hdrdir)/ruby/internal/intern/load.h @@ -156,12 +156,12 @@ generator.o: $(hdrdir)/ruby/internal/memory.h generator.o: $(hdrdir)/ruby/internal/method.h generator.o: $(hdrdir)/ruby/internal/module.h generator.o: $(hdrdir)/ruby/internal/newobj.h -generator.o: $(hdrdir)/ruby/internal/rgengc.h generator.o: $(hdrdir)/ruby/internal/scan_args.h generator.o: $(hdrdir)/ruby/internal/special_consts.h generator.o: $(hdrdir)/ruby/internal/static_assert.h generator.o: $(hdrdir)/ruby/internal/stdalign.h generator.o: $(hdrdir)/ruby/internal/stdbool.h +generator.o: $(hdrdir)/ruby/internal/stdckdint.h generator.o: $(hdrdir)/ruby/internal/symbol.h generator.o: $(hdrdir)/ruby/internal/value.h generator.o: $(hdrdir)/ruby/internal/value_type.h diff --git a/ext/json/generator/extconf.rb b/ext/json/generator/extconf.rb index 8627c5f4bd..cf8d5f2bda 100644 --- a/ext/json/generator/extconf.rb +++ b/ext/json/generator/extconf.rb @@ -1,4 +1,9 @@ require 'mkmf' -$defs << "-DJSON_GENERATOR" -create_makefile 'json/ext/generator' +if RUBY_ENGINE == 'truffleruby' + # The pure-Ruby generator is faster on TruffleRuby, so skip compiling the generator extension + File.write('Makefile', dummy_makefile("").join) +else + $defs << "-DJSON_GENERATOR" + create_makefile 'json/ext/generator' +end diff --git a/ext/json/generator/generator.c b/ext/json/generator/generator.c index e3a83472e1..766e199f74 100644 --- a/ext/json/generator/generator.c +++ b/ext/json/generator/generator.c @@ -16,7 +16,7 @@ static ID i_to_s, i_to_json, i_new, i_indent, i_space, i_space_before, i_object_nl, i_array_nl, i_max_nesting, i_allow_nan, i_ascii_only, i_pack, i_unpack, i_create_id, i_extend, i_key_p, i_aref, i_send, i_respond_to_p, i_match, i_keys, i_depth, - i_buffer_initial_length, i_dup, i_escape_slash; + i_buffer_initial_length, i_dup, i_script_safe, i_escape_slash, i_strict; /* * Copyright 2001-2004 Unicode, Inc. @@ -124,7 +124,7 @@ static void unicode_escape_to_buffer(FBuffer *buffer, char buf[6], UTF16 /* Converts string to a JSON string in FBuffer buffer, where all but the ASCII * and control characters are JSON escaped. */ -static void convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string, char escape_slash) +static void convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string, char script_safe) { const UTF8 *source = (UTF8 *) RSTRING_PTR(string); const UTF8 *sourceEnd = source + RSTRING_LEN(string); @@ -175,7 +175,7 @@ static void convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string, char escap fbuffer_append(buffer, "\\\"", 2); break; case '/': - if(escape_slash) { + if(script_safe) { fbuffer_append(buffer, "\\/", 2); break; } @@ -228,7 +228,7 @@ static void convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string, char escap * characters required by the JSON standard are JSON escaped. The remaining * characters (should be UTF8) are just passed through and appended to the * result. */ -static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string, char escape_slash) +static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string, char script_safe) { const char *ptr = RSTRING_PTR(string), *p; unsigned long len = RSTRING_LEN(string), start = 0, end = 0; @@ -280,7 +280,7 @@ static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string, char escape_slas escape_len = 2; break; case '/': - if(escape_slash) { + if(script_safe) { escape = "\\/"; escape_len = 2; break; @@ -294,6 +294,22 @@ static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string, char escape_slas rb_raise(rb_path2class("JSON::GeneratorError"), "partial character in source, but hit end"); } + + if (script_safe && c == 0xE2) { + unsigned char c2 = (unsigned char) *(p+1); + unsigned char c3 = (unsigned char) *(p+2); + if (c2 == 0x80 && (c3 == 0xA8 || c3 == 0xA9)) { + fbuffer_append(buffer, ptr + start, end - start); + start = end = (end + clen); + if (c3 == 0xA8) { + fbuffer_append(buffer, "\\u2028", 6); + } else { + fbuffer_append(buffer, "\\u2029", 6); + } + continue; + } + } + if (!isLegalUTF8((UTF8 *) p, clen)) { rb_raise(rb_path2class("JSON::GeneratorError"), "source sequence is illegal/malformed utf-8"); @@ -478,6 +494,7 @@ static VALUE mFloat_to_json(int argc, VALUE *argv, VALUE self) */ static VALUE mString_included_s(VALUE self, VALUE modul) { VALUE result = rb_funcall(modul, i_extend, 1, mString_Extend); + rb_call_super(1, &modul); return result; } @@ -619,16 +636,12 @@ static size_t State_memsize(const void *ptr) # define RUBY_TYPED_FROZEN_SHAREABLE 0 #endif -#ifdef NEW_TYPEDDATA_WRAPPER static const rb_data_type_t JSON_Generator_State_type = { "JSON/Generator/State", {NULL, State_free, State_memsize,}, -#ifdef RUBY_TYPED_FREE_IMMEDIATELY 0, 0, - RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_FROZEN_SHAREABLE, -#endif + RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_FROZEN_SHAREABLE, }; -#endif static VALUE cState_s_allocate(VALUE klass) { @@ -726,8 +739,14 @@ static VALUE cState_configure(VALUE self, VALUE opts) state->allow_nan = RTEST(tmp); tmp = rb_hash_aref(opts, ID2SYM(i_ascii_only)); state->ascii_only = RTEST(tmp); - tmp = rb_hash_aref(opts, ID2SYM(i_escape_slash)); - state->escape_slash = RTEST(tmp); + tmp = rb_hash_aref(opts, ID2SYM(i_script_safe)); + state->script_safe = RTEST(tmp); + if (!state->script_safe) { + tmp = rb_hash_aref(opts, ID2SYM(i_escape_slash)); + state->script_safe = RTEST(tmp); + } + tmp = rb_hash_aref(opts, ID2SYM(i_strict)); + state->strict = RTEST(tmp); return self; } @@ -762,7 +781,8 @@ static VALUE cState_to_h(VALUE self) rb_hash_aset(result, ID2SYM(i_allow_nan), state->allow_nan ? Qtrue : Qfalse); rb_hash_aset(result, ID2SYM(i_ascii_only), state->ascii_only ? Qtrue : Qfalse); rb_hash_aset(result, ID2SYM(i_max_nesting), LONG2FIX(state->max_nesting)); - rb_hash_aset(result, ID2SYM(i_escape_slash), state->escape_slash ? Qtrue : Qfalse); + rb_hash_aset(result, ID2SYM(i_script_safe), state->script_safe ? Qtrue : Qfalse); + rb_hash_aset(result, ID2SYM(i_strict), state->strict ? Qtrue : Qfalse); rb_hash_aset(result, ID2SYM(i_depth), LONG2FIX(state->depth)); rb_hash_aset(result, ID2SYM(i_buffer_initial_length), LONG2FIX(state->buffer_initial_length)); return result; @@ -843,7 +863,7 @@ json_object_i(VALUE key, VALUE val, VALUE _arg) if (klass == rb_cString) { key_to_s = key; } else if (klass == rb_cSymbol) { - key_to_s = rb_id2str(SYM2ID(key)); + key_to_s = rb_sym2str(key); } else { key_to_s = rb_funcall(key, i_to_s, 0); } @@ -868,7 +888,6 @@ static void generate_json_object(FBuffer *buffer, VALUE Vstate, JSON_Generator_S struct hash_foreach_arg arg; if (max_nesting != 0 && depth > max_nesting) { - fbuffer_free(buffer); rb_raise(eNestingError, "nesting of %ld is too deep", --state->depth); } fbuffer_append_char(buffer, '{'); @@ -903,7 +922,6 @@ static void generate_json_array(FBuffer *buffer, VALUE Vstate, JSON_Generator_St long depth = ++state->depth; int i, j; if (max_nesting != 0 && depth > max_nesting) { - fbuffer_free(buffer); rb_raise(eNestingError, "nesting of %ld is too deep", --state->depth); } fbuffer_append_char(buffer, '['); @@ -929,27 +947,24 @@ static void generate_json_array(FBuffer *buffer, VALUE Vstate, JSON_Generator_St fbuffer_append_char(buffer, ']'); } -#ifdef HAVE_RUBY_ENCODING_H static int enc_utf8_compatible_p(rb_encoding *enc) { if (enc == rb_usascii_encoding()) return 1; if (enc == rb_utf8_encoding()) return 1; return 0; } -#endif static void generate_json_string(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj) { fbuffer_append_char(buffer, '"'); -#ifdef HAVE_RUBY_ENCODING_H if (!enc_utf8_compatible_p(rb_enc_get(obj))) { obj = rb_str_export_to_enc(obj, rb_utf8_encoding()); } -#endif + if (state->ascii_only) { - convert_UTF8_to_JSON_ASCII(buffer, obj, state->escape_slash); + convert_UTF8_to_JSON_ASCII(buffer, obj, state->script_safe); } else { - convert_UTF8_to_JSON(buffer, obj, state->escape_slash); + convert_UTF8_to_JSON(buffer, obj, state->script_safe); } fbuffer_append_char(buffer, '"'); } @@ -996,11 +1011,9 @@ static void generate_json_float(FBuffer *buffer, VALUE Vstate, JSON_Generator_St VALUE tmp = rb_funcall(obj, i_to_s, 0); if (!allow_nan) { if (isinf(value)) { - fbuffer_free(buffer); - rb_raise(eGeneratorError, "%u: %"PRIsVALUE" not allowed in JSON", __LINE__, RB_OBJ_STRING(tmp)); + rb_raise(eGeneratorError, "%"PRIsVALUE" not allowed in JSON", RB_OBJ_STRING(tmp)); } else if (isnan(value)) { - fbuffer_free(buffer); - rb_raise(eGeneratorError, "%u: %"PRIsVALUE" not allowed in JSON", __LINE__, RB_OBJ_STRING(tmp)); + rb_raise(eGeneratorError, "%"PRIsVALUE" not allowed in JSON", RB_OBJ_STRING(tmp)); } } fbuffer_append_str(buffer, tmp); @@ -1028,6 +1041,8 @@ static void generate_json(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *s generate_json_bignum(buffer, Vstate, state, obj); } else if (klass == rb_cFloat) { generate_json_float(buffer, Vstate, state, obj); + } else if (state->strict) { + rb_raise(eGeneratorError, "%"PRIsVALUE" not allowed in JSON", RB_OBJ_STRING(CLASS_OF(obj))); } else if (rb_respond_to(obj, i_to_json)) { tmp = rb_funcall(obj, i_to_json, 1, Vstate); Check_Type(tmp, T_STRING); @@ -1070,11 +1085,45 @@ static FBuffer *cState_prepare_buffer(VALUE self) return buffer; } +struct generate_json_data { + FBuffer *buffer; + VALUE vstate; + JSON_Generator_State *state; + VALUE obj; +}; + +static VALUE generate_json_try(VALUE d) +{ + struct generate_json_data *data = (struct generate_json_data *)d; + + generate_json(data->buffer, data->vstate, data->state, data->obj); + + return Qnil; +} + +static VALUE generate_json_rescue(VALUE d, VALUE exc) +{ + struct generate_json_data *data = (struct generate_json_data *)d; + fbuffer_free(data->buffer); + + rb_exc_raise(exc); + + return Qundef; +} + static VALUE cState_partial_generate(VALUE self, VALUE obj) { FBuffer *buffer = cState_prepare_buffer(self); GET_STATE(self); - generate_json(buffer, self, state, obj); + + struct generate_json_data data = { + .buffer = buffer, + .vstate = self, + .state = state, + .obj = obj + }; + rb_rescue(generate_json_try, (VALUE)&data, generate_json_rescue, (VALUE)&data); + return fbuffer_to_s(buffer); } @@ -1390,27 +1439,58 @@ static VALUE cState_max_nesting_set(VALUE self, VALUE depth) } /* - * call-seq: escape_slash + * call-seq: script_safe * * If this boolean is true, the forward slashes will be escaped in * the json output. */ -static VALUE cState_escape_slash(VALUE self) +static VALUE cState_script_safe(VALUE self) { GET_STATE(self); - return state->escape_slash ? Qtrue : Qfalse; + return state->script_safe ? Qtrue : Qfalse; } /* - * call-seq: escape_slash=(depth) + * call-seq: script_safe=(enable) * * This sets whether or not the forward slashes will be escaped in * the json output. */ -static VALUE cState_escape_slash_set(VALUE self, VALUE enable) +static VALUE cState_script_safe_set(VALUE self, VALUE enable) +{ + GET_STATE(self); + state->script_safe = RTEST(enable); + return Qnil; +} + +/* + * call-seq: strict + * + * If this boolean is false, types unsupported by the JSON format will + * be serialized as strings. + * If this boolean is true, types unsupported by the JSON format will + * raise a JSON::GeneratorError. + */ +static VALUE cState_strict(VALUE self) +{ + GET_STATE(self); + return state->strict ? Qtrue : Qfalse; +} + +/* + * call-seq: strict=(enable) + * + * This sets whether or not to serialize types unsupported by the + * JSON format as strings. + * If this boolean is false, types unsupported by the JSON format will + * be serialized as strings. + * If this boolean is true, types unsupported by the JSON format will + * raise a JSON::GeneratorError. + */ +static VALUE cState_strict_set(VALUE self, VALUE enable) { GET_STATE(self); - state->escape_slash = RTEST(enable); + state->strict = RTEST(enable); return Qnil; } @@ -1530,9 +1610,15 @@ void Init_generator(void) rb_define_method(cState, "array_nl=", cState_array_nl_set, 1); rb_define_method(cState, "max_nesting", cState_max_nesting, 0); rb_define_method(cState, "max_nesting=", cState_max_nesting_set, 1); - rb_define_method(cState, "escape_slash", cState_escape_slash, 0); - rb_define_method(cState, "escape_slash?", cState_escape_slash, 0); - rb_define_method(cState, "escape_slash=", cState_escape_slash_set, 1); + rb_define_method(cState, "script_safe", cState_script_safe, 0); + rb_define_method(cState, "script_safe?", cState_script_safe, 0); + rb_define_method(cState, "script_safe=", cState_script_safe_set, 1); + rb_define_alias(cState, "escape_slash", "script_safe"); + rb_define_alias(cState, "escape_slash?", "script_safe?"); + rb_define_alias(cState, "escape_slash=", "script_safe="); + rb_define_method(cState, "strict", cState_strict, 0); + rb_define_method(cState, "strict?", cState_strict, 0); + rb_define_method(cState, "strict=", cState_strict_set, 1); rb_define_method(cState, "check_circular?", cState_check_circular_p, 0); rb_define_method(cState, "allow_nan?", cState_allow_nan_p, 0); rb_define_method(cState, "ascii_only?", cState_ascii_only_p, 0); @@ -1589,7 +1675,9 @@ void Init_generator(void) i_object_nl = rb_intern("object_nl"); i_array_nl = rb_intern("array_nl"); i_max_nesting = rb_intern("max_nesting"); + i_script_safe = rb_intern("script_safe"); i_escape_slash = rb_intern("escape_slash"); + i_strict = rb_intern("strict"); i_allow_nan = rb_intern("allow_nan"); i_ascii_only = rb_intern("ascii_only"); i_depth = rb_intern("depth"); diff --git a/ext/json/generator/generator.h b/ext/json/generator/generator.h index 3ebd622554..98b7d833f3 100644 --- a/ext/json/generator/generator.h +++ b/ext/json/generator/generator.h @@ -49,8 +49,8 @@ static const UTF32 halfMask = 0x3FFUL; static unsigned char isLegalUTF8(const UTF8 *source, unsigned long length); static void unicode_escape(char *buf, UTF16 character); static void unicode_escape_to_buffer(FBuffer *buffer, char buf[6], UTF16 character); -static void convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string, char escape_slash); -static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string, char escape_slash); +static void convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string, char script_safe); +static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string, char script_safe); static char *fstrndup(const char *ptr, unsigned long len); /* ruby api and some helpers */ @@ -72,7 +72,8 @@ typedef struct JSON_Generator_StateStruct { long max_nesting; char allow_nan; char ascii_only; - char escape_slash; + char script_safe; + char strict; long depth; long buffer_initial_length; } JSON_Generator_State; @@ -151,8 +152,10 @@ static VALUE cState_allow_nan_p(VALUE self); static VALUE cState_ascii_only_p(VALUE self); static VALUE cState_depth(VALUE self); static VALUE cState_depth_set(VALUE self, VALUE depth); -static VALUE cState_escape_slash(VALUE self); -static VALUE cState_escape_slash_set(VALUE self, VALUE depth); +static VALUE cState_script_safe(VALUE self); +static VALUE cState_script_safe_set(VALUE self, VALUE depth); +static VALUE cState_strict(VALUE self); +static VALUE cState_strict_set(VALUE self, VALUE strict); static FBuffer *cState_prepare_buffer(VALUE self); #ifndef ZALLOC #define ZALLOC(type) ((type *)ruby_zalloc(sizeof(type))) @@ -163,12 +166,7 @@ static inline void *ruby_zalloc(size_t n) return p; } #endif -#ifdef TypedData_Make_Struct + static const rb_data_type_t JSON_Generator_State_type; -#define NEW_TYPEDDATA_WRAPPER 1 -#else -#define TypedData_Make_Struct(klass, type, ignore, json) Data_Make_Struct(klass, type, NULL, State_free, json) -#define TypedData_Get_Struct(self, JSON_Generator_State, ignore, json) Data_Get_Struct(self, JSON_Generator_State, json) -#endif #endif diff --git a/ext/json/json.gemspec b/ext/json/json.gemspec index 948e92c501..64d0c81391 100644 --- a/ext/json/json.gemspec +++ b/ext/json/json.gemspec @@ -1,8 +1,10 @@ -# -*- encoding: utf-8 -*- +version = File.foreach(File.join(__dir__, "lib/json/version.rb")) do |line| + /^\s*VERSION\s*=\s*'(.*)'/ =~ line and break $1 +end rescue nil Gem::Specification.new do |s| s.name = "json" - s.version = File.read(File.expand_path('../VERSION', __FILE__)).chomp + s.version = version s.summary = "JSON Implementation for Ruby" s.description = "This is a JSON implementation as a Ruby extension in C." @@ -17,7 +19,6 @@ Gem::Specification.new do |s| "CHANGES.md", "LICENSE", "README.md", - "VERSION", "ext/json/ext/fbuffer/fbuffer.h", "ext/json/ext/generator/depend", "ext/json/ext/generator/extconf.rb", @@ -53,12 +54,12 @@ Gem::Specification.new do |s| "lib/json/pure/parser.rb", "lib/json/version.rb", ] - s.homepage = "http://flori.github.com/json" + s.homepage = "https://flori.github.io/json" s.metadata = { 'bug_tracker_uri' => 'https://github.com/flori/json/issues', 'changelog_uri' => 'https://github.com/flori/json/blob/master/CHANGES.md', - 'documentation_uri' => 'http://flori.github.io/json/doc/index.html', - 'homepage_uri' => 'http://flori.github.io/json/', + 'documentation_uri' => 'https://flori.github.io/json/doc/index.html', + 'homepage_uri' => s.homepage, 'source_code_uri' => 'https://github.com/flori/json', 'wiki_uri' => 'https://github.com/flori/json/wiki' } diff --git a/ext/json/lib/json.rb b/ext/json/lib/json.rb index 1e64bfcb1a..807488ffef 100644 --- a/ext/json/lib/json.rb +++ b/ext/json/lib/json.rb @@ -285,6 +285,15 @@ require 'json/common' # # Raises JSON::NestingError (nesting of 2 is too deep): # JSON.generate(obj, max_nesting: 2) # +# ====== Escaping Options +# +# Options +script_safe+ (boolean) specifies wether <tt>'\u2028'</tt>, <tt>'\u2029'</tt> +# and <tt>'/'</tt> should be escaped as to make the JSON object safe to interpolate in script +# tags. +# +# Options +ascii_only+ (boolean) specifies wether all characters outside the ASCII range +# should be escaped. +# # ====== Output Options # # The default formatting options generate the most compact diff --git a/ext/json/lib/json/add/bigdecimal.rb b/ext/json/lib/json/add/bigdecimal.rb index c8b4f567cb..b1d0cfa043 100644 --- a/ext/json/lib/json/add/bigdecimal.rb +++ b/ext/json/lib/json/add/bigdecimal.rb @@ -2,19 +2,36 @@ unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED require 'json' end -defined?(::BigDecimal) or require 'bigdecimal' +begin + require 'bigdecimal' +rescue LoadError +end class BigDecimal - # Import a JSON Marshalled object. - # - # method used for JSON marshalling support. + + # See #as_json. def self.json_create(object) BigDecimal._load object['b'] end - # Marshal the object to JSON. + # Methods <tt>BigDecimal#as_json</tt> and +BigDecimal.json_create+ may be used + # to serialize and deserialize a \BigDecimal object; + # see Marshal[rdoc-ref:Marshal]. + # + # \Method <tt>BigDecimal#as_json</tt> serializes +self+, + # returning a 2-element hash representing +self+: + # + # require 'json/add/bigdecimal' + # x = BigDecimal(2).as_json # => {"json_class"=>"BigDecimal", "b"=>"27:0.2e1"} + # y = BigDecimal(2.0, 4).as_json # => {"json_class"=>"BigDecimal", "b"=>"36:0.2e1"} + # z = BigDecimal(Complex(2, 0)).as_json # => {"json_class"=>"BigDecimal", "b"=>"27:0.2e1"} + # + # \Method +JSON.create+ deserializes such a hash, returning a \BigDecimal object: + # + # BigDecimal.json_create(x) # => 0.2e1 + # BigDecimal.json_create(y) # => 0.2e1 + # BigDecimal.json_create(z) # => 0.2e1 # - # method used for JSON marshalling support. def as_json(*) { JSON.create_id => self.class.name, @@ -22,8 +39,20 @@ class BigDecimal } end - # return the JSON value + # Returns a JSON string representing +self+: + # + # require 'json/add/bigdecimal' + # puts BigDecimal(2).to_json + # puts BigDecimal(2.0, 4).to_json + # puts BigDecimal(Complex(2, 0)).to_json + # + # Output: + # + # {"json_class":"BigDecimal","b":"27:0.2e1"} + # {"json_class":"BigDecimal","b":"36:0.2e1"} + # {"json_class":"BigDecimal","b":"27:0.2e1"} + # def to_json(*args) as_json.to_json(*args) end -end +end if defined?(::BigDecimal) diff --git a/ext/json/lib/json/add/complex.rb b/ext/json/lib/json/add/complex.rb index e63e29fd22..ef48c554c6 100644 --- a/ext/json/lib/json/add/complex.rb +++ b/ext/json/lib/json/add/complex.rb @@ -5,14 +5,27 @@ end class Complex - # Deserializes JSON string by converting Real value <tt>r</tt>, imaginary - # value <tt>i</tt>, to a Complex object. + # See #as_json. def self.json_create(object) Complex(object['r'], object['i']) end - # Returns a hash, that will be turned into a JSON object and represent this - # object. + # Methods <tt>Complex#as_json</tt> and +Complex.json_create+ may be used + # to serialize and deserialize a \Complex object; + # see Marshal[rdoc-ref:Marshal]. + # + # \Method <tt>Complex#as_json</tt> serializes +self+, + # returning a 2-element hash representing +self+: + # + # require 'json/add/complex' + # x = Complex(2).as_json # => {"json_class"=>"Complex", "r"=>2, "i"=>0} + # y = Complex(2.0, 4).as_json # => {"json_class"=>"Complex", "r"=>2.0, "i"=>4} + # + # \Method +JSON.create+ deserializes such a hash, returning a \Complex object: + # + # Complex.json_create(x) # => (2+0i) + # Complex.json_create(y) # => (2.0+4i) + # def as_json(*) { JSON.create_id => self.class.name, @@ -21,7 +34,17 @@ class Complex } end - # Stores class name (Complex) along with real value <tt>r</tt> and imaginary value <tt>i</tt> as JSON string + # Returns a JSON string representing +self+: + # + # require 'json/add/complex' + # puts Complex(2).to_json + # puts Complex(2.0, 4).to_json + # + # Output: + # + # {"json_class":"Complex","r":2,"i":0} + # {"json_class":"Complex","r":2.0,"i":4} + # def to_json(*args) as_json.to_json(*args) end diff --git a/ext/json/lib/json/add/date.rb b/ext/json/lib/json/add/date.rb index 25523561a5..19688f751b 100644 --- a/ext/json/lib/json/add/date.rb +++ b/ext/json/lib/json/add/date.rb @@ -6,16 +6,29 @@ require 'date' class Date - # Deserializes JSON string by converting Julian year <tt>y</tt>, month - # <tt>m</tt>, day <tt>d</tt> and Day of Calendar Reform <tt>sg</tt> to Date. + # See #as_json. def self.json_create(object) civil(*object.values_at('y', 'm', 'd', 'sg')) end alias start sg unless method_defined?(:start) - # Returns a hash, that will be turned into a JSON object and represent this - # object. + # Methods <tt>Date#as_json</tt> and +Date.json_create+ may be used + # to serialize and deserialize a \Date object; + # see Marshal[rdoc-ref:Marshal]. + # + # \Method <tt>Date#as_json</tt> serializes +self+, + # returning a 2-element hash representing +self+: + # + # require 'json/add/date' + # x = Date.today.as_json + # # => {"json_class"=>"Date", "y"=>2023, "m"=>11, "d"=>21, "sg"=>2299161.0} + # + # \Method +JSON.create+ deserializes such a hash, returning a \Date object: + # + # Date.json_create(x) + # # => #<Date: 2023-11-21 ((2460270j,0s,0n),+0s,2299161j)> + # def as_json(*) { JSON.create_id => self.class.name, @@ -26,8 +39,15 @@ class Date } end - # Stores class name (Date) with Julian year <tt>y</tt>, month <tt>m</tt>, day - # <tt>d</tt> and Day of Calendar Reform <tt>sg</tt> as JSON string + # Returns a JSON string representing +self+: + # + # require 'json/add/date' + # puts Date.today.to_json + # + # Output: + # + # {"json_class":"Date","y":2023,"m":11,"d":21,"sg":2299161.0} + # def to_json(*args) as_json.to_json(*args) end diff --git a/ext/json/lib/json/add/date_time.rb b/ext/json/lib/json/add/date_time.rb index 38b0e86ab8..d7d42591cf 100644 --- a/ext/json/lib/json/add/date_time.rb +++ b/ext/json/lib/json/add/date_time.rb @@ -6,9 +6,7 @@ require 'date' class DateTime - # Deserializes JSON string by converting year <tt>y</tt>, month <tt>m</tt>, - # day <tt>d</tt>, hour <tt>H</tt>, minute <tt>M</tt>, second <tt>S</tt>, - # offset <tt>of</tt> and Day of Calendar Reform <tt>sg</tt> to DateTime. + # See #as_json. def self.json_create(object) args = object.values_at('y', 'm', 'd', 'H', 'M', 'S') of_a, of_b = object['of'].split('/') @@ -23,8 +21,21 @@ class DateTime alias start sg unless method_defined?(:start) - # Returns a hash, that will be turned into a JSON object and represent this - # object. + # Methods <tt>DateTime#as_json</tt> and +DateTime.json_create+ may be used + # to serialize and deserialize a \DateTime object; + # see Marshal[rdoc-ref:Marshal]. + # + # \Method <tt>DateTime#as_json</tt> serializes +self+, + # returning a 2-element hash representing +self+: + # + # require 'json/add/datetime' + # x = DateTime.now.as_json + # # => {"json_class"=>"DateTime", "y"=>2023, "m"=>11, "d"=>21, "sg"=>2299161.0} + # + # \Method +JSON.create+ deserializes such a hash, returning a \DateTime object: + # + # DateTime.json_create(x) # BUG? Raises Date::Error "invalid date" + # def as_json(*) { JSON.create_id => self.class.name, @@ -39,9 +50,15 @@ class DateTime } end - # Stores class name (DateTime) with Julian year <tt>y</tt>, month <tt>m</tt>, - # day <tt>d</tt>, hour <tt>H</tt>, minute <tt>M</tt>, second <tt>S</tt>, - # offset <tt>of</tt> and Day of Calendar Reform <tt>sg</tt> as JSON string + # Returns a JSON string representing +self+: + # + # require 'json/add/datetime' + # puts DateTime.now.to_json + # + # Output: + # + # {"json_class":"DateTime","y":2023,"m":11,"d":21,"sg":2299161.0} + # def to_json(*args) as_json.to_json(*args) end diff --git a/ext/json/lib/json/add/exception.rb b/ext/json/lib/json/add/exception.rb index a107e5b3c4..71d8deb0ea 100644 --- a/ext/json/lib/json/add/exception.rb +++ b/ext/json/lib/json/add/exception.rb @@ -5,16 +5,27 @@ end class Exception - # Deserializes JSON string by constructing new Exception object with message - # <tt>m</tt> and backtrace <tt>b</tt> serialized with <tt>to_json</tt> + # See #as_json. def self.json_create(object) result = new(object['m']) result.set_backtrace object['b'] result end - # Returns a hash, that will be turned into a JSON object and represent this - # object. + # Methods <tt>Exception#as_json</tt> and +Exception.json_create+ may be used + # to serialize and deserialize a \Exception object; + # see Marshal[rdoc-ref:Marshal]. + # + # \Method <tt>Exception#as_json</tt> serializes +self+, + # returning a 2-element hash representing +self+: + # + # require 'json/add/exception' + # x = Exception.new('Foo').as_json # => {"json_class"=>"Exception", "m"=>"Foo", "b"=>nil} + # + # \Method +JSON.create+ deserializes such a hash, returning a \Exception object: + # + # Exception.json_create(x) # => #<Exception: Foo> + # def as_json(*) { JSON.create_id => self.class.name, @@ -23,8 +34,15 @@ class Exception } end - # Stores class name (Exception) with message <tt>m</tt> and backtrace array - # <tt>b</tt> as JSON string + # Returns a JSON string representing +self+: + # + # require 'json/add/exception' + # puts Exception.new('Foo').to_json + # + # Output: + # + # {"json_class":"Exception","m":"Foo","b":null} + # def to_json(*args) as_json.to_json(*args) end diff --git a/ext/json/lib/json/add/ostruct.rb b/ext/json/lib/json/add/ostruct.rb index 686cf0025d..1e6f408248 100644 --- a/ext/json/lib/json/add/ostruct.rb +++ b/ext/json/lib/json/add/ostruct.rb @@ -2,18 +2,34 @@ unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED require 'json' end -require 'ostruct' +begin + require 'ostruct' +rescue LoadError +end class OpenStruct - # Deserializes JSON string by constructing new Struct object with values - # <tt>t</tt> serialized by <tt>to_json</tt>. + # See #as_json. def self.json_create(object) new(object['t'] || object[:t]) end - # Returns a hash, that will be turned into a JSON object and represent this - # object. + # Methods <tt>OpenStruct#as_json</tt> and +OpenStruct.json_create+ may be used + # to serialize and deserialize a \OpenStruct object; + # see Marshal[rdoc-ref:Marshal]. + # + # \Method <tt>OpenStruct#as_json</tt> serializes +self+, + # returning a 2-element hash representing +self+: + # + # require 'json/add/ostruct' + # x = OpenStruct.new('name' => 'Rowdy', :age => nil).as_json + # # => {"json_class"=>"OpenStruct", "t"=>{:name=>'Rowdy', :age=>nil}} + # + # \Method +JSON.create+ deserializes such a hash, returning a \OpenStruct object: + # + # OpenStruct.json_create(x) + # # => #<OpenStruct name='Rowdy', age=nil> + # def as_json(*) klass = self.class.name klass.to_s.empty? and raise JSON::JSONError, "Only named structs are supported!" @@ -23,9 +39,16 @@ class OpenStruct } end - # Stores class name (OpenStruct) with this struct's values <tt>t</tt> as a - # JSON string. + # Returns a JSON string representing +self+: + # + # require 'json/add/ostruct' + # puts OpenStruct.new('name' => 'Rowdy', :age => nil).to_json + # + # Output: + # + # {"json_class":"OpenStruct","t":{'name':'Rowdy',"age":null}} + # def to_json(*args) as_json.to_json(*args) end -end +end if defined?(::OpenStruct) diff --git a/ext/json/lib/json/add/range.rb b/ext/json/lib/json/add/range.rb index 93529fb1c4..53f54ac372 100644 --- a/ext/json/lib/json/add/range.rb +++ b/ext/json/lib/json/add/range.rb @@ -5,14 +5,29 @@ end class Range - # Deserializes JSON string by constructing new Range object with arguments - # <tt>a</tt> serialized by <tt>to_json</tt>. + # See #as_json. def self.json_create(object) new(*object['a']) end - # Returns a hash, that will be turned into a JSON object and represent this - # object. + # Methods <tt>Range#as_json</tt> and +Range.json_create+ may be used + # to serialize and deserialize a \Range object; + # see Marshal[rdoc-ref:Marshal]. + # + # \Method <tt>Range#as_json</tt> serializes +self+, + # returning a 2-element hash representing +self+: + # + # require 'json/add/range' + # x = (1..4).as_json # => {"json_class"=>"Range", "a"=>[1, 4, false]} + # y = (1...4).as_json # => {"json_class"=>"Range", "a"=>[1, 4, true]} + # z = ('a'..'d').as_json # => {"json_class"=>"Range", "a"=>["a", "d", false]} + # + # \Method +JSON.create+ deserializes such a hash, returning a \Range object: + # + # Range.json_create(x) # => 1..4 + # Range.json_create(y) # => 1...4 + # Range.json_create(z) # => "a".."d" + # def as_json(*) { JSON.create_id => self.class.name, @@ -20,9 +35,19 @@ class Range } end - # Stores class name (Range) with JSON array of arguments <tt>a</tt> which - # include <tt>first</tt> (integer), <tt>last</tt> (integer), and - # <tt>exclude_end?</tt> (boolean) as JSON string. + # Returns a JSON string representing +self+: + # + # require 'json/add/range' + # puts (1..4).to_json + # puts (1...4).to_json + # puts ('a'..'d').to_json + # + # Output: + # + # {"json_class":"Range","a":[1,4,false]} + # {"json_class":"Range","a":[1,4,true]} + # {"json_class":"Range","a":["a","d",false]} + # def to_json(*args) as_json.to_json(*args) end diff --git a/ext/json/lib/json/add/rational.rb b/ext/json/lib/json/add/rational.rb index f776226046..8c39a7db55 100644 --- a/ext/json/lib/json/add/rational.rb +++ b/ext/json/lib/json/add/rational.rb @@ -4,14 +4,28 @@ unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED end class Rational - # Deserializes JSON string by converting numerator value <tt>n</tt>, - # denominator value <tt>d</tt>, to a Rational object. + + # See #as_json. def self.json_create(object) Rational(object['n'], object['d']) end - # Returns a hash, that will be turned into a JSON object and represent this - # object. + # Methods <tt>Rational#as_json</tt> and +Rational.json_create+ may be used + # to serialize and deserialize a \Rational object; + # see Marshal[rdoc-ref:Marshal]. + # + # \Method <tt>Rational#as_json</tt> serializes +self+, + # returning a 2-element hash representing +self+: + # + # require 'json/add/rational' + # x = Rational(2, 3).as_json + # # => {"json_class"=>"Rational", "n"=>2, "d"=>3} + # + # \Method +JSON.create+ deserializes such a hash, returning a \Rational object: + # + # Rational.json_create(x) + # # => (2/3) + # def as_json(*) { JSON.create_id => self.class.name, @@ -20,7 +34,15 @@ class Rational } end - # Stores class name (Rational) along with numerator value <tt>n</tt> and denominator value <tt>d</tt> as JSON string + # Returns a JSON string representing +self+: + # + # require 'json/add/rational' + # puts Rational(2, 3).to_json + # + # Output: + # + # {"json_class":"Rational","n":2,"d":3} + # def to_json(*args) as_json.to_json(*args) end diff --git a/ext/json/lib/json/add/regexp.rb b/ext/json/lib/json/add/regexp.rb index 39d69fede7..b63f49608f 100644 --- a/ext/json/lib/json/add/regexp.rb +++ b/ext/json/lib/json/add/regexp.rb @@ -5,15 +5,26 @@ end class Regexp - # Deserializes JSON string by constructing new Regexp object with source - # <tt>s</tt> (Regexp or String) and options <tt>o</tt> serialized by - # <tt>to_json</tt> + # See #as_json. def self.json_create(object) new(object['s'], object['o']) end - # Returns a hash, that will be turned into a JSON object and represent this - # object. + # Methods <tt>Regexp#as_json</tt> and +Regexp.json_create+ may be used + # to serialize and deserialize a \Regexp object; + # see Marshal[rdoc-ref:Marshal]. + # + # \Method <tt>Regexp#as_json</tt> serializes +self+, + # returning a 2-element hash representing +self+: + # + # require 'json/add/regexp' + # x = /foo/.as_json + # # => {"json_class"=>"Regexp", "o"=>0, "s"=>"foo"} + # + # \Method +JSON.create+ deserializes such a hash, returning a \Regexp object: + # + # Regexp.json_create(x) # => /foo/ + # def as_json(*) { JSON.create_id => self.class.name, @@ -22,8 +33,15 @@ class Regexp } end - # Stores class name (Regexp) with options <tt>o</tt> and source <tt>s</tt> - # (Regexp or String) as JSON string + # Returns a JSON string representing +self+: + # + # require 'json/add/regexp' + # puts /foo/.to_json + # + # Output: + # + # {"json_class":"Regexp","o":0,"s":"foo"} + # def to_json(*args) as_json.to_json(*args) end diff --git a/ext/json/lib/json/add/set.rb b/ext/json/lib/json/add/set.rb index 71e2a0ac8b..1918353187 100644 --- a/ext/json/lib/json/add/set.rb +++ b/ext/json/lib/json/add/set.rb @@ -4,16 +4,27 @@ end defined?(::Set) or require 'set' class Set - # Import a JSON Marshalled object. - # - # method used for JSON marshalling support. + + # See #as_json. def self.json_create(object) new object['a'] end - # Marshal the object to JSON. + # Methods <tt>Set#as_json</tt> and +Set.json_create+ may be used + # to serialize and deserialize a \Set object; + # see Marshal[rdoc-ref:Marshal]. + # + # \Method <tt>Set#as_json</tt> serializes +self+, + # returning a 2-element hash representing +self+: + # + # require 'json/add/set' + # x = Set.new(%w/foo bar baz/).as_json + # # => {"json_class"=>"Set", "a"=>["foo", "bar", "baz"]} + # + # \Method +JSON.create+ deserializes such a hash, returning a \Set object: + # + # Set.json_create(x) # => #<Set: {"foo", "bar", "baz"}> # - # method used for JSON marshalling support. def as_json(*) { JSON.create_id => self.class.name, @@ -21,7 +32,15 @@ class Set } end - # return the JSON value + # Returns a JSON string representing +self+: + # + # require 'json/add/set' + # puts Set.new(%w/foo bar baz/).to_json + # + # Output: + # + # {"json_class":"Set","a":["foo","bar","baz"]} + # def to_json(*args) as_json.to_json(*args) end diff --git a/ext/json/lib/json/add/struct.rb b/ext/json/lib/json/add/struct.rb index e8395ed42f..86847762ac 100644 --- a/ext/json/lib/json/add/struct.rb +++ b/ext/json/lib/json/add/struct.rb @@ -5,14 +5,28 @@ end class Struct - # Deserializes JSON string by constructing new Struct object with values - # <tt>v</tt> serialized by <tt>to_json</tt>. + # See #as_json. def self.json_create(object) new(*object['v']) end - # Returns a hash, that will be turned into a JSON object and represent this - # object. + # Methods <tt>Struct#as_json</tt> and +Struct.json_create+ may be used + # to serialize and deserialize a \Struct object; + # see Marshal[rdoc-ref:Marshal]. + # + # \Method <tt>Struct#as_json</tt> serializes +self+, + # returning a 2-element hash representing +self+: + # + # require 'json/add/struct' + # Customer = Struct.new('Customer', :name, :address, :zip) + # x = Struct::Customer.new.as_json + # # => {"json_class"=>"Struct::Customer", "v"=>[nil, nil, nil]} + # + # \Method +JSON.create+ deserializes such a hash, returning a \Struct object: + # + # Struct::Customer.json_create(x) + # # => #<struct Struct::Customer name=nil, address=nil, zip=nil> + # def as_json(*) klass = self.class.name klass.to_s.empty? and raise JSON::JSONError, "Only named structs are supported!" @@ -22,8 +36,16 @@ class Struct } end - # Stores class name (Struct) with Struct values <tt>v</tt> as a JSON string. - # Only named structs are supported. + # Returns a JSON string representing +self+: + # + # require 'json/add/struct' + # Customer = Struct.new('Customer', :name, :address, :zip) + # puts Struct::Customer.new.to_json + # + # Output: + # + # {"json_class":"Struct","t":{'name':'Rowdy',"age":null}} + # def to_json(*args) as_json.to_json(*args) end diff --git a/ext/json/lib/json/add/symbol.rb b/ext/json/lib/json/add/symbol.rb index 74b13a423f..b5f3623158 100644 --- a/ext/json/lib/json/add/symbol.rb +++ b/ext/json/lib/json/add/symbol.rb @@ -1,11 +1,26 @@ + #frozen_string_literal: false unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED require 'json' end class Symbol - # Returns a hash, that will be turned into a JSON object and represent this - # object. + + # Methods <tt>Symbol#as_json</tt> and +Symbol.json_create+ may be used + # to serialize and deserialize a \Symbol object; + # see Marshal[rdoc-ref:Marshal]. + # + # \Method <tt>Symbol#as_json</tt> serializes +self+, + # returning a 2-element hash representing +self+: + # + # require 'json/add/symbol' + # x = :foo.as_json + # # => {"json_class"=>"Symbol", "s"=>"foo"} + # + # \Method +JSON.create+ deserializes such a hash, returning a \Symbol object: + # + # Symbol.json_create(x) # => :foo + # def as_json(*) { JSON.create_id => self.class.name, @@ -13,12 +28,20 @@ class Symbol } end - # Stores class name (Symbol) with String representation of Symbol as a JSON string. + # Returns a JSON string representing +self+: + # + # require 'json/add/symbol' + # puts :foo.to_json + # + # Output: + # + # # {"json_class":"Symbol","s":"foo"} + # def to_json(*a) as_json.to_json(*a) end - # Deserializes JSON string by converting the <tt>string</tt> value stored in the object to a Symbol + # See #as_json. def self.json_create(o) o['s'].to_sym end diff --git a/ext/json/lib/json/add/time.rb b/ext/json/lib/json/add/time.rb index b73acc4086..599ed9e24b 100644 --- a/ext/json/lib/json/add/time.rb +++ b/ext/json/lib/json/add/time.rb @@ -5,7 +5,7 @@ end class Time - # Deserializes JSON string by converting time since epoch to Time + # See #as_json. def self.json_create(object) if usec = object.delete('u') # used to be tv_usec -> tv_nsec object['n'] = usec * 1000 @@ -17,8 +17,22 @@ class Time end end - # Returns a hash, that will be turned into a JSON object and represent this - # object. + # Methods <tt>Time#as_json</tt> and +Time.json_create+ may be used + # to serialize and deserialize a \Time object; + # see Marshal[rdoc-ref:Marshal]. + # + # \Method <tt>Time#as_json</tt> serializes +self+, + # returning a 2-element hash representing +self+: + # + # require 'json/add/time' + # x = Time.now.as_json + # # => {"json_class"=>"Time", "s"=>1700931656, "n"=>472846644} + # + # \Method +JSON.create+ deserializes such a hash, returning a \Time object: + # + # Time.json_create(x) + # # => 2023-11-25 11:00:56.472846644 -0600 + # def as_json(*) nanoseconds = [ tv_usec * 1000 ] respond_to?(:tv_nsec) and nanoseconds << tv_nsec @@ -30,8 +44,15 @@ class Time } end - # Stores class name (Time) with number of seconds since epoch and number of - # microseconds for Time as JSON string + # Returns a JSON string representing +self+: + # + # require 'json/add/time' + # puts Time.now.to_json + # + # Output: + # + # {"json_class":"Time","s":1700931678,"n":980650786} + # def to_json(*args) as_json.to_json(*args) end diff --git a/ext/json/lib/json/common.rb b/ext/json/lib/json/common.rb index ea46896fcc..95098d3bb4 100644 --- a/ext/json/lib/json/common.rb +++ b/ext/json/lib/json/common.rb @@ -1,8 +1,12 @@ #frozen_string_literal: false require 'json/version' -require 'json/generic_object' module JSON + autoload :GenericObject, 'json/generic_object' + + NOT_SET = Object.new.freeze + private_constant :NOT_SET + class << self # :call-seq: # JSON[object] -> new_array or new_string @@ -295,19 +299,9 @@ module JSON # def generate(obj, opts = nil) if State === opts - state, opts = opts, nil + state = opts else - state = State.new - end - if opts - if opts.respond_to? :to_hash - opts = opts.to_hash - elsif opts.respond_to? :to_h - opts = opts.to_h - else - raise TypeError, "can't convert #{opts.class} into Hash" - end - state = state.configure(opts) + state = State.new(opts) end state.generate(obj) end @@ -334,19 +328,9 @@ module JSON # JSON.fast_generate(a) def fast_generate(obj, opts = nil) if State === opts - state, opts = opts, nil + state = opts else - state = JSON.create_fast_state - end - if opts - if opts.respond_to? :to_hash - opts = opts.to_hash - elsif opts.respond_to? :to_h - opts = opts.to_h - else - raise TypeError, "can't convert #{opts.class} into Hash" - end - state.configure(opts) + state = JSON.create_fast_state.configure(opts) end state.generate(obj) end @@ -592,13 +576,13 @@ module JSON # Sets or returns the default options for the JSON.dump method. # Initially: # opts = JSON.dump_default_options - # opts # => {:max_nesting=>false, :allow_nan=>true, :escape_slash=>false} + # opts # => {:max_nesting=>false, :allow_nan=>true, :script_safe=>false} attr_accessor :dump_default_options end self.dump_default_options = { :max_nesting => false, :allow_nan => true, - :escape_slash => false, + :script_safe => false, } # :call-seq: @@ -628,16 +612,18 @@ module JSON # puts File.read(path) # Output: # {"foo":[0,1],"bar":{"baz":2,"bat":3},"bam":"bad"} - def dump(obj, anIO = nil, limit = nil) - if anIO and limit.nil? - anIO = anIO.to_io if anIO.respond_to?(:to_io) - unless anIO.respond_to?(:write) - limit = anIO - anIO = nil - end + def dump(obj, anIO = nil, limit = nil, kwargs = nil) + io_limit_opt = [anIO, limit, kwargs].compact + kwargs = io_limit_opt.pop if io_limit_opt.last.is_a?(Hash) + anIO, limit = io_limit_opt + if anIO.respond_to?(:to_io) + anIO = anIO.to_io + elsif limit.nil? && !anIO.respond_to?(:write) + anIO, limit = nil, anIO end opts = JSON.dump_default_options opts = opts.merge(:max_nesting => limit) if limit + opts = merge_dump_options(opts, **kwargs) if kwargs result = generate(obj, opts) if anIO anIO.write result @@ -653,6 +639,15 @@ module JSON def self.iconv(to, from, string) string.encode(to, from) end + + def merge_dump_options(opts, strict: NOT_SET) + opts = opts.merge(strict: strict) if NOT_SET != strict + opts + end + + class << self + private :merge_dump_options + end end module ::Kernel diff --git a/ext/json/lib/json/ext.rb b/ext/json/lib/json/ext.rb index 7264a857fa..b62e231712 100644 --- a/ext/json/lib/json/ext.rb +++ b/ext/json/lib/json/ext.rb @@ -4,11 +4,19 @@ module JSON # This module holds all the modules/classes that implement JSON's # functionality as C extensions. module Ext - require 'json/ext/parser' - require 'json/ext/generator' - $DEBUG and warn "Using Ext extension for JSON." - JSON.parser = Parser - JSON.generator = Generator + if RUBY_ENGINE == 'truffleruby' + require 'json/ext/parser' + require 'json/pure' + $DEBUG and warn "Using Ext extension for JSON parser and Pure library for JSON generator." + JSON.parser = Parser + JSON.generator = JSON::Pure::Generator + else + require 'json/ext/parser' + require 'json/ext/generator' + $DEBUG and warn "Using Ext extension for JSON." + JSON.parser = Parser + JSON.generator = Generator + end end JSON_LOADED = true unless defined?(::JSON::JSON_LOADED) diff --git a/ext/json/lib/json/generic_object.rb b/ext/json/lib/json/generic_object.rb index 108309db26..56efda6495 100644 --- a/ext/json/lib/json/generic_object.rb +++ b/ext/json/lib/json/generic_object.rb @@ -1,5 +1,9 @@ #frozen_string_literal: false -require 'ostruct' +begin + require 'ostruct' +rescue LoadError + warn "JSON::GenericObject requires 'ostruct'. Please install it with `gem install ostruct`." +end module JSON class GenericObject < OpenStruct @@ -67,5 +71,5 @@ module JSON def to_json(*a) as_json.to_json(*a) end - end + end if defined?(::OpenStruct) end diff --git a/ext/json/lib/json/version.rb b/ext/json/lib/json/version.rb index 7a72272bd0..836f47edf4 100644 --- a/ext/json/lib/json/version.rb +++ b/ext/json/lib/json/version.rb @@ -1,7 +1,7 @@ # frozen_string_literal: false module JSON # JSON version - VERSION = '2.5.1' + VERSION = '2.7.2' VERSION_ARRAY = VERSION.split(/\./).map { |x| x.to_i } # :nodoc: VERSION_MAJOR = VERSION_ARRAY[0] # :nodoc: VERSION_MINOR = VERSION_ARRAY[1] # :nodoc: diff --git a/ext/json/parser/depend b/ext/json/parser/depend index 1a75df405d..f3422b4f84 100644 --- a/ext/json/parser/depend +++ b/ext/json/parser/depend @@ -10,7 +10,6 @@ parser.o: $(hdrdir)/ruby/backward.h parser.o: $(hdrdir)/ruby/backward/2/assume.h parser.o: $(hdrdir)/ruby/backward/2/attributes.h parser.o: $(hdrdir)/ruby/backward/2/bool.h -parser.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h parser.o: $(hdrdir)/ruby/backward/2/inttypes.h parser.o: $(hdrdir)/ruby/backward/2/limits.h parser.o: $(hdrdir)/ruby/backward/2/long_long.h @@ -19,6 +18,7 @@ parser.o: $(hdrdir)/ruby/backward/2/stdarg.h parser.o: $(hdrdir)/ruby/defines.h parser.o: $(hdrdir)/ruby/encoding.h parser.o: $(hdrdir)/ruby/intern.h +parser.o: $(hdrdir)/ruby/internal/abi.h parser.o: $(hdrdir)/ruby/internal/anyargs.h parser.o: $(hdrdir)/ruby/internal/arithmetic.h parser.o: $(hdrdir)/ruby/internal/arithmetic/char.h @@ -56,6 +56,7 @@ parser.o: $(hdrdir)/ruby/internal/attr/noexcept.h parser.o: $(hdrdir)/ruby/internal/attr/noinline.h parser.o: $(hdrdir)/ruby/internal/attr/nonnull.h parser.o: $(hdrdir)/ruby/internal/attr/noreturn.h +parser.o: $(hdrdir)/ruby/internal/attr/packed_struct.h parser.o: $(hdrdir)/ruby/internal/attr/pure.h parser.o: $(hdrdir)/ruby/internal/attr/restrict.h parser.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h @@ -124,7 +125,6 @@ parser.o: $(hdrdir)/ruby/internal/intern/enumerator.h parser.o: $(hdrdir)/ruby/internal/intern/error.h parser.o: $(hdrdir)/ruby/internal/intern/eval.h parser.o: $(hdrdir)/ruby/internal/intern/file.h -parser.o: $(hdrdir)/ruby/internal/intern/gc.h parser.o: $(hdrdir)/ruby/internal/intern/hash.h parser.o: $(hdrdir)/ruby/internal/intern/io.h parser.o: $(hdrdir)/ruby/internal/intern/load.h @@ -155,12 +155,12 @@ parser.o: $(hdrdir)/ruby/internal/memory.h parser.o: $(hdrdir)/ruby/internal/method.h parser.o: $(hdrdir)/ruby/internal/module.h parser.o: $(hdrdir)/ruby/internal/newobj.h -parser.o: $(hdrdir)/ruby/internal/rgengc.h parser.o: $(hdrdir)/ruby/internal/scan_args.h parser.o: $(hdrdir)/ruby/internal/special_consts.h parser.o: $(hdrdir)/ruby/internal/static_assert.h parser.o: $(hdrdir)/ruby/internal/stdalign.h parser.o: $(hdrdir)/ruby/internal/stdbool.h +parser.o: $(hdrdir)/ruby/internal/stdckdint.h parser.o: $(hdrdir)/ruby/internal/symbol.h parser.o: $(hdrdir)/ruby/internal/value.h parser.o: $(hdrdir)/ruby/internal/value_type.h diff --git a/ext/json/parser/parser.c b/ext/json/parser/parser.c index b1dc8810c3..128f683e0f 100644 --- a/ext/json/parser/parser.c +++ b/ext/json/parser/parser.c @@ -3,3336 +3,2181 @@ #include "../fbuffer/fbuffer.h" #include "parser.h" -#if defined HAVE_RUBY_ENCODING_H -# define EXC_ENCODING rb_utf8_encoding(), -# ifndef HAVE_RB_ENC_RAISE -static void -enc_raise(rb_encoding *enc, VALUE exc, const char *fmt, ...) -{ - va_list args; - VALUE mesg; - - va_start(args, fmt); - mesg = rb_enc_vsprintf(enc, fmt, args); - va_end(args); - - rb_exc_raise(rb_exc_new3(exc, mesg)); -} -# define rb_enc_raise enc_raise -# endif -#else -# define EXC_ENCODING /* nothing */ -# define rb_enc_raise rb_raise -#endif - /* 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, "%u: unexpected token at '%s'", __LINE__, p); - } - } - np = JSON_parse_float(json, p, pe, result); - if (np != NULL) {p = (( np))-1;} - - np = JSON_parse_integer(json, p, pe, result); - if (np != NULL) {p = (( np))-1;} - - {p = p - 1; } {p+= 1; cs = 29; goto _out;} - } - - goto st29; - ctr7: - { - #line 258 "parser.rl" - - char *np; - np = JSON_parse_array(json, p, pe, result, current_nesting + 1); - if (np == NULL) { {p = p - 1; } {p+= 1; cs = 29; goto _out;} } else {p = (( np))-1;} - - } - - goto st29; - ctr11: - { - #line 264 "parser.rl" - - char *np; - np = JSON_parse_object(json, p, pe, result, current_nesting + 1); - if (np == NULL) { {p = p - 1; } {p+= 1; cs = 29; goto _out;} } else {p = (( np))-1;} - - } - - goto st29; - ctr25: - { - #line 228 "parser.rl" - - if (json->allow_nan) { - *result = CInfinity; - } else { - rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p - 8); - } - } - - goto st29; - ctr27: - { - #line 221 "parser.rl" - - if (json->allow_nan) { - *result = CNaN; - } else { - rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p - 2); - } - } - - goto st29; - ctr31: - { - #line 215 "parser.rl" - - *result = Qfalse; - } - - goto st29; - ctr34: - { - #line 212 "parser.rl" - - *result = Qnil; - } - - goto st29; - ctr37: - { - #line 218 "parser.rl" - - *result = Qtrue; - } - - goto st29; - st29: - p+= 1; - if ( p == pe ) +case 1: + switch( (*p) ) { + case 13: goto st1; + case 32: goto st1; + case 34: goto tr2; + case 45: goto tr3; + case 47: goto st6; + case 73: goto st10; + case 78: goto st17; + case 91: goto tr7; + case 102: goto st19; + case 110: goto st23; + case 116: goto st26; + case 123: goto tr11; + } + if ( (*p) > 10 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr3; + } else if ( (*p) >= 9 ) + goto st1; + goto st0; +st0: +cs = 0; + goto _out; +tr2: +#line 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(rb_utf8_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(rb_utf8_encoding(), eParserError, "unexpected token at '%s'", p - 7); + } + } + goto st29; +tr27: +#line 221 "parser.rl" + { + if (json->allow_nan) { + *result = CNaN; + } else { + rb_enc_raise(rb_utf8_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: {} - } - - #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; +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; + + _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 (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 1184 "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" 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 1206 "parser.c" { - cs = (int)JSON_array_start; + cs = JSON_array_start; } - #line 445 "parser.rl" - +#line 445 "parser.rl" +#line 1213 "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 409 "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 1272 "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 424 "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 1379 "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, "%u: unexpected token at '%s'", __LINE__, 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 446 "parser.rl" + + if(cs >= JSON_array_first_final) { + return p + 1; + } else { + rb_enc_raise(rb_utf8_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]; - - if (bufferSize > MAX_STACK_BUFFER_SIZE) { - bufferStart = buffer = ALLOC_N(char, bufferSize); - } else { - bufferStart = buffer = ALLOCA_N(char, bufferSize); - } - - while (pe < stringEnd) { - if (*pe == '\\') { - unescape = (char *) "?"; - unescape_len = 1; - if (pe > p) { - MEMCPY(buffer, p, char, pe - p); - buffer += pe - p; - } - switch (*++pe) { - case 'n': - unescape = (char *) "\n"; - break; - case 'r': - unescape = (char *) "\r"; - break; - case 't': - unescape = (char *) "\t"; - break; - case '"': - unescape = (char *) "\""; - break; - case '\\': - unescape = (char *) "\\"; - break; - case 'b': - unescape = (char *) "\b"; - break; - case 'f': - unescape = (char *) "\f"; - break; - case 'u': - if (pe > stringEnd - 4) { - if (bufferSize > MAX_STACK_BUFFER_SIZE) { - free(bufferStart); - } - rb_enc_raise( - EXC_ENCODING eParserError, - "%u: incomplete unicode character escape sequence at '%s'", __LINE__, p - ); - } else { - UTF32 ch = unescape_unicode((unsigned char *) ++pe); - pe += 3; - if (UNI_SUR_HIGH_START == (ch & 0xFC00)) { - pe++; - if (pe > stringEnd - 6) { - if (bufferSize > MAX_STACK_BUFFER_SIZE) { - free(bufferStart); - } - rb_enc_raise( - EXC_ENCODING eParserError, - "%u: incomplete surrogate pair at '%s'", __LINE__, p - ); - } - if (pe[0] == '\\' && pe[1] == 'u') { - UTF32 sur = unescape_unicode((unsigned char *) pe + 2); - ch = (((ch & 0x3F) << 10) | ((((ch >> 6) & 0xF) + 1) << 16) - | (sur & 0x3FF)); - pe += 5; - } else { - unescape = (char *) "?"; - break; - } - } - unescape_len = convert_UTF32_to_UTF8(buf, ch); - unescape = buf; - } - break; - default: - p = pe; - continue; - } - MEMCPY(buffer, unescape, char, unescape_len); - buffer += unescape_len; - p = ++pe; - } else { - pe++; - } - } - - if (pe > p) { - MEMCPY(buffer, p, char, pe - p); - buffer += pe - p; - } - - # ifdef HAVE_RB_ENC_INTERNED_STR - if (intern) { - result = rb_enc_interned_str(bufferStart, (long)(buffer - bufferStart), rb_utf8_encoding()); - } else { - result = rb_utf8_str_new(bufferStart, (long)(buffer - bufferStart)); - } - if (bufferSize > MAX_STACK_BUFFER_SIZE) { - free(bufferStart); - } - # else - result = rb_utf8_str_new(bufferStart, (long)(buffer - bufferStart)); - - if (bufferSize > MAX_STACK_BUFFER_SIZE) { - free(bufferStart); - } - - if (intern) { - # if STR_UMINUS_DEDUPE_FROZEN - // Starting from MRI 2.8 it is preferable to freeze the string - // before deduplication so that it can be interned directly - // otherwise it would be duplicated first which is wasteful. - result = rb_funcall(rb_str_freeze(result), i_uminus, 0); - # elif STR_UMINUS_DEDUPE - // MRI 2.5 and older do not deduplicate strings that are already - // frozen. - result = rb_funcall(result, i_uminus, 0); - # else - result = rb_str_freeze(result); - # endif - } - # endif + 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) { +# ifdef HAVE_RB_ENC_INTERNED_STR + bufferStart = buffer = ALLOC_N(char, bufferSize ? bufferSize : 1); +# else + bufferStart = buffer = ALLOC_N(char, bufferSize); +# endif + } else { +# ifdef HAVE_RB_ENC_INTERNED_STR + bufferStart = buffer = ALLOCA_N(char, bufferSize ? bufferSize : 1); +# else + 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) { + ruby_xfree(bufferStart); + } + rb_enc_raise( + rb_utf8_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) { + ruby_xfree(bufferStart); + } + rb_enc_raise( + rb_utf8_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) { + ruby_xfree(bufferStart); + } +# else + result = rb_utf8_str_new(bufferStart, (long)(buffer - bufferStart)); + + if (bufferSize > MAX_STACK_BUFFER_SIZE) { + ruby_xfree(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); - } + if (symbolize) { + result = rb_str_intern(result); + } - return result; + return result; } +#line 1592 "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 620 "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 1621 "parser.c" { - cs = (int)JSON_string_start; + cs = JSON_string_start; } - #line 632 "parser.rl" - - json->memo = p; +#line 640 "parser.rl" + json->memo = p; +#line 1629 "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 607 "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 617 "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 1671 "parser.c" + goto st0; +st3: + if ( ++p == pe ) goto _test_eof3; - st_case_3: - if ( ( (*( p))) == 117 ) { - goto st4; - } - if ( 0 <= (signed char)(*(p)) && (*(p)) <= 31 ) { - goto st0; - } - { - goto st2; - } - st4: - p+= 1; - if ( p == pe ) +case 3: + if ( (*p) == 117 ) + goto st4; + if ( 0 <= (signed char)(*(p)) && (*(p)) <= 31 ) + goto st0; + goto st2; +st4: + if ( ++p == pe ) goto _test_eof4; - st_case_4: - if ( ( (*( p))) < 65 ) { - if ( 48 <= ( (*( p))) && ( (*( p))) <= 57 ) { - goto st5; - } - } else if ( ( (*( p))) > 70 ) { - if ( 97 <= ( (*( p))) && ( (*( p))) <= 102 ) { - goto st5; - } - } else { +case 4: + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) goto st5; - } - { - goto st0; - } - st5: - p+= 1; - if ( p == pe ) + } else if ( (*p) > 70 ) { + if ( 97 <= (*p) && (*p) <= 102 ) + goto st5; + } else + goto st5; + goto st0; +st5: + if ( ++p == pe ) goto _test_eof5; - st_case_5: - if ( ( (*( p))) < 65 ) { - if ( 48 <= ( (*( p))) && ( (*( p))) <= 57 ) { - goto st6; - } - } else if ( ( (*( p))) > 70 ) { - if ( 97 <= ( (*( p))) && ( (*( p))) <= 102 ) { - goto st6; - } - } else { +case 5: + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto st6; + } else if ( (*p) > 70 ) { + if ( 97 <= (*p) && (*p) <= 102 ) goto st6; - } - { - goto st0; - } - st6: - p+= 1; - if ( p == pe ) + } 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 642 "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; + 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()); + } + 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_. + * + * 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 + VALUE source, opts; + GET_PARSER_INIT; + + if (json->Vsource) { + rb_raise(rb_eTypeError, "already initialized instance"); + } + rb_scan_args(argc, argv, "1:", &source, &opts); + 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->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; + 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; + } + } 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 1920 "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 828 "parser.rl" /* -* call-seq: parse() -* -* Parses the current JSON text _source_ and returns the complete data -* structure as a result. -*/ + * call-seq: parse() + * + * Parses the current JSON text _source_ and returns the complete data + * structure as a result. + * 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 *p, *pe; + int cs = EVIL; + VALUE result = Qnil; + GET_PARSER; +#line 1946 "parser.c" { - cs = (int)JSON_start; + cs = JSON_start; } - #line 851 "parser.rl" - - p = json->source; - pe = p + json->len; +#line 845 "parser.rl" + p = json->source; + pe = p + json->len; +#line 1955 "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 820 "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 1999 "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, "%u: unexpected token at '%s'", __LINE__, 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 848 "parser.rl" + + if (cs >= JSON_first_final && p == pe) { + return result; + } else { + rb_enc_raise(rb_utf8_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(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); } 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,}, + 0, 0, + RUBY_TYPED_FREE_IMMEDIATELY, }; -#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/parser/parser.h b/ext/json/parser/parser.h index 92ed3fdc5d..651d40c074 100644 --- a/ext/json/parser/parser.h +++ b/ext/json/parser/parser.h @@ -85,12 +85,7 @@ static inline void *ruby_zalloc(size_t n) return p; } #endif -#ifdef TypedData_Make_Struct + static const rb_data_type_t JSON_Parser_type; -#define NEW_TYPEDDATA_WRAPPER 1 -#else -#define TypedData_Make_Struct(klass, type, ignore, json) Data_Make_Struct(klass, type, NULL, JSON_free, json) -#define TypedData_Get_Struct(self, JSON_Parser, ignore, json) Data_Get_Struct(self, JSON_Parser, json) -#endif #endif diff --git a/ext/json/parser/parser.rl b/ext/json/parser/parser.rl index f7be1a5acc..873c1b3007 100644 --- a/ext/json/parser/parser.rl +++ b/ext/json/parser/parser.rl @@ -1,28 +1,6 @@ #include "../fbuffer/fbuffer.h" #include "parser.h" -#if defined HAVE_RUBY_ENCODING_H -# define EXC_ENCODING rb_utf8_encoding(), -# ifndef HAVE_RB_ENC_RAISE -static void -enc_raise(rb_encoding *enc, VALUE exc, const char *fmt, ...) -{ - va_list args; - VALUE mesg; - - va_start(args, fmt); - mesg = rb_enc_vsprintf(enc, fmt, args); - va_end(args); - - rb_exc_raise(rb_exc_new3(exc, mesg)); -} -# define rb_enc_raise enc_raise -# endif -#else -# define EXC_ENCODING /* nothing */ -# define rb_enc_raise rb_raise -#endif - /* unicode */ static const signed char digit_values[256] = { @@ -222,14 +200,14 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu if (json->allow_nan) { *result = CNaN; } else { - rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p - 2); + rb_enc_raise(rb_utf8_encoding(), eParserError, "unexpected token at '%s'", p - 2); } } action parse_infinity { if (json->allow_nan) { *result = CInfinity; } else { - rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p - 8); + rb_enc_raise(rb_utf8_encoding(), eParserError, "unexpected token at '%s'", p - 7); } } action parse_string { @@ -245,7 +223,7 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu fexec p + 10; fhold; fbreak; } else { - rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p); + rb_enc_raise(rb_utf8_encoding(), eParserError, "unexpected token at '%s'", p); } } np = JSON_parse_float(json, fpc, pe, result); @@ -447,7 +425,7 @@ static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *resul if(cs >= JSON_array_first_final) { return p + 1; } else { - rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p); + rb_enc_raise(rb_utf8_encoding(), eParserError, "unexpected token at '%s'", p); return NULL; } } @@ -462,9 +440,17 @@ static VALUE json_string_unescape(char *string, char *stringEnd, int intern, int char buf[4]; if (bufferSize > MAX_STACK_BUFFER_SIZE) { +# ifdef HAVE_RB_ENC_INTERNED_STR + bufferStart = buffer = ALLOC_N(char, bufferSize ? bufferSize : 1); +# else bufferStart = buffer = ALLOC_N(char, bufferSize); +# endif } else { +# ifdef HAVE_RB_ENC_INTERNED_STR + bufferStart = buffer = ALLOCA_N(char, bufferSize ? bufferSize : 1); +# else bufferStart = buffer = ALLOCA_N(char, bufferSize); +# endif } while (pe < stringEnd) { @@ -500,11 +486,11 @@ static VALUE json_string_unescape(char *string, char *stringEnd, int intern, int case 'u': if (pe > stringEnd - 4) { if (bufferSize > MAX_STACK_BUFFER_SIZE) { - free(bufferStart); + ruby_xfree(bufferStart); } rb_enc_raise( - EXC_ENCODING eParserError, - "%u: incomplete unicode character escape sequence at '%s'", __LINE__, p + rb_utf8_encoding(), eParserError, + "incomplete unicode character escape sequence at '%s'", p ); } else { UTF32 ch = unescape_unicode((unsigned char *) ++pe); @@ -513,11 +499,11 @@ static VALUE json_string_unescape(char *string, char *stringEnd, int intern, int pe++; if (pe > stringEnd - 6) { if (bufferSize > MAX_STACK_BUFFER_SIZE) { - free(bufferStart); + ruby_xfree(bufferStart); } rb_enc_raise( - EXC_ENCODING eParserError, - "%u: incomplete surrogate pair at '%s'", __LINE__, p + rb_utf8_encoding(), eParserError, + "incomplete surrogate pair at '%s'", p ); } if (pe[0] == '\\' && pe[1] == 'u') { @@ -558,13 +544,13 @@ static VALUE json_string_unescape(char *string, char *stringEnd, int intern, int result = rb_utf8_str_new(bufferStart, (long)(buffer - bufferStart)); } if (bufferSize > MAX_STACK_BUFFER_SIZE) { - free(bufferStart); + ruby_xfree(bufferStart); } # else result = rb_utf8_str_new(bufferStart, (long)(buffer - bufferStart)); if (bufferSize > MAX_STACK_BUFFER_SIZE) { - free(bufferStart); + ruby_xfree(bufferStart); } if (intern) { @@ -683,8 +669,6 @@ static VALUE convert_encoding(VALUE source) * * 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: * @@ -713,98 +697,85 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self) 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 + 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; + } } 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 = Qnil; json->object_class = Qnil; json->array_class = Qnil; json->decimal_class = Qnil; @@ -839,6 +810,7 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self) * * 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) { @@ -855,7 +827,7 @@ static VALUE cParser_parse(VALUE self) if (cs >= JSON_first_final && p == pe) { return result; } else { - rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p); + rb_enc_raise(rb_utf8_encoding(), eParserError, "unexpected token at '%s'", p); return Qnil; } } @@ -863,12 +835,12 @@ static VALUE cParser_parse(VALUE self) 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); + 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); } static void JSON_free(void *ptr) @@ -884,16 +856,12 @@ static size_t JSON_memsize(const void *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 }; -#endif static VALUE cJSON_parser_s_allocate(VALUE klass) { |