ruby-changes:21073
From: naruse <ko1@a...>
Date: Tue, 30 Aug 2011 11:23:27 +0900 (JST)
Subject: [ruby-changes:21073] naruse:r33122 (trunk): * ext/json: Merge json gem 1.5.4+ (2149f4185c598fb97db1).
naruse 2011-08-30 11:23:12 +0900 (Tue, 30 Aug 2011) New Revision: 33122 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=33122 Log: * ext/json: Merge json gem 1.5.4+ (2149f4185c598fb97db1). [Bug #5173] [ruby-core:38866] Modified files: trunk/ChangeLog trunk/ext/json/generator/generator.c trunk/ext/json/generator/generator.h trunk/ext/json/lib/json/add/core.rb trunk/ext/json/lib/json/common.rb trunk/ext/json/lib/json/ext.rb trunk/ext/json/lib/json.rb trunk/ext/json/parser/parser.c trunk/ext/json/parser/parser.h trunk/ext/json/parser/parser.rl trunk/test/json/test_json.rb trunk/test/json/test_json_addition.rb trunk/test/json/test_json_generate.rb Index: ChangeLog =================================================================== --- ChangeLog (revision 33121) +++ ChangeLog (revision 33122) @@ -1,3 +1,8 @@ +Tue Aug 30 11:06:19 2011 NARUSE, Yui <naruse@r...> + + * ext/json: Merge json gem 1.5.4+ (2149f4185c598fb97db1). + [Bug #5173] [ruby-core:38866] + Tue Aug 30 09:57:50 2011 KOSAKI Motohiro <kosaki.motohiro@g...> * lib/thread.rb (Queue#pop): fix a race against Thread.wakeup. Index: ext/json/generator/generator.c =================================================================== --- ext/json/generator/generator.c (revision 33121) +++ ext/json/generator/generator.c (revision 33122) @@ -13,8 +13,8 @@ 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_dup; + i_quirks_mode, 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_dup; /* * Copyright 2001-2004 Unicode, Inc. @@ -349,6 +349,16 @@ } } +static void fbuffer_append_str(FBuffer *fb, VALUE str) +{ + const char *newstr = StringValuePtr(str); + unsigned long len = RSTRING_LEN(str); + + RB_GC_GUARD(str); + + fbuffer_append(fb, newstr, len); +} + static void fbuffer_append_char(FBuffer *fb, char newchr) { fbuffer_inc_capa(fb, 1); @@ -688,6 +698,8 @@ 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_quirks_mode)); + state->quirks_mode = RTEST(tmp); return self; } @@ -708,6 +720,7 @@ rb_hash_aset(result, ID2SYM(i_array_nl), rb_str_new(state->array_nl, state->array_nl_len)); 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_quirks_mode), state->quirks_mode ? Qtrue : Qfalse); rb_hash_aset(result, ID2SYM(i_max_nesting), LONG2FIX(state->max_nesting)); rb_hash_aset(result, ID2SYM(i_depth), LONG2FIX(state->depth)); return result; @@ -852,7 +865,7 @@ static void generate_json_bignum(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj) { VALUE tmp = rb_funcall(obj, i_to_s, 0); - fbuffer_append(buffer, RSTRING_PAIR(tmp)); + fbuffer_append_str(buffer, tmp); } static void generate_json_float(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj) @@ -869,7 +882,7 @@ rb_raise(eGeneratorError, "%u: %s not allowed in JSON", __LINE__, StringValueCStr(tmp)); } } - fbuffer_append(buffer, RSTRING_PAIR(tmp)); + fbuffer_append_str(buffer, tmp); } static void generate_json(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj) @@ -897,7 +910,7 @@ } else if (rb_respond_to(obj, i_to_json)) { tmp = rb_funcall(obj, i_to_json, 1, Vstate); Check_Type(tmp, T_STRING); - fbuffer_append(buffer, RSTRING_PAIR(tmp)); + fbuffer_append_str(buffer, tmp); } else { tmp = rb_funcall(obj, i_to_s, 0); Check_Type(tmp, T_STRING); @@ -961,11 +974,14 @@ { VALUE result = cState_partial_generate(self, obj); VALUE re, args[2]; - args[0] = rb_str_new2("\\A\\s*(?:\\[.*\\]|\\{.*\\})\\s*\\Z"); - args[1] = CRegexp_MULTILINE; - re = rb_class_new_instance(2, args, rb_cRegexp); - if (NIL_P(rb_funcall(re, i_match, 1, result))) { - rb_raise(eGeneratorError, "only generation of JSON objects or arrays allowed"); + GET_STATE(self); + if (!state->quirks_mode) { + args[0] = rb_str_new2("\\A\\s*(?:\\[.*\\]|\\{.*\\})\\s*\\Z"); + args[1] = CRegexp_MULTILINE; + re = rb_class_new_instance(2, args, rb_cRegexp); + if (NIL_P(rb_funcall(re, i_match, 1, result))) { + rb_raise(eGeneratorError, "only generation of JSON objects or arrays allowed"); + } } return result; } @@ -1288,6 +1304,29 @@ } /* + * call-seq: quirks_mode? + * + * Returns true, if quirks mode is enabled. Otherwise returns false. + */ +static VALUE cState_quirks_mode_p(VALUE self) +{ + GET_STATE(self); + return state->quirks_mode ? Qtrue : Qfalse; +} + +/* + * call-seq: quirks_mode=(enable) + * + * If set to true, enables the quirks_mode mode. + */ +static VALUE cState_quirks_mode_set(VALUE self, VALUE enable) +{ + GET_STATE(self); + state->quirks_mode = RTEST(enable); + return Qnil; +} + +/* * call-seq: depth * * This integer returns the current depth of data structure nesting. @@ -1345,6 +1384,9 @@ 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); + rb_define_method(cState, "quirks_mode?", cState_quirks_mode_p, 0); + rb_define_method(cState, "quirks_mode", cState_quirks_mode_p, 0); + rb_define_method(cState, "quirks_mode=", cState_quirks_mode_set, 1); rb_define_method(cState, "depth", cState_depth, 0); rb_define_method(cState, "depth=", cState_depth_set, 1); rb_define_method(cState, "configure", cState_configure, 1); @@ -1392,6 +1434,7 @@ i_max_nesting = rb_intern("max_nesting"); i_allow_nan = rb_intern("allow_nan"); i_ascii_only = rb_intern("ascii_only"); + i_quirks_mode = rb_intern("quirks_mode"); i_depth = rb_intern("depth"); i_pack = rb_intern("pack"); i_unpack = rb_intern("unpack"); Index: ext/json/generator/generator.h =================================================================== --- ext/json/generator/generator.h (revision 33121) +++ ext/json/generator/generator.h (revision 33122) @@ -45,7 +45,10 @@ #define RSTRING_LEN(string) RSTRING(string)->len #endif -#define RSTRING_PAIR(string) RSTRING_PTR(string), RSTRING_LEN(string) +/* We don't need to guard objects for rbx, so let's do nothing at all. */ +#ifndef RB_GC_GUARD +#define RB_GC_GUARD(object) +#endif /* fbuffer implementation */ @@ -123,6 +126,7 @@ long max_nesting; char allow_nan; char ascii_only; + char quirks_mode; long depth; } JSON_Generator_State; Index: ext/json/lib/json/ext.rb =================================================================== --- ext/json/lib/json/ext.rb (revision 33121) +++ ext/json/lib/json/ext.rb (revision 33122) @@ -4,21 +4,8 @@ # This module holds all the modules/classes that implement JSON's # functionality as C extensions. module Ext - begin - if defined?(RUBY_ENGINE) == 'constant' and RUBY_ENGINE == 'ruby' and RUBY_VERSION =~ /\A1\.9\./ - require 'json/ext/1.9/parser' - require 'json/ext/1.9/generator' - elsif !defined?(RUBY_ENGINE) && RUBY_VERSION =~ /\A1\.8\./ - require 'json/ext/1.8/parser' - require 'json/ext/1.8/generator' - else - require 'json/ext/parser' - require 'json/ext/generator' - end - rescue LoadError - require 'json/ext/parser' - require 'json/ext/generator' - end + require 'json/ext/parser' + require 'json/ext/generator' $DEBUG and warn "Using Ext extension for JSON." JSON.parser = Parser JSON.generator = Generator Index: ext/json/lib/json/add/core.rb =================================================================== --- ext/json/lib/json/add/core.rb (revision 33121) +++ ext/json/lib/json/add/core.rb (revision 33122) @@ -5,6 +5,8 @@ require 'json' end require 'date' +require 'complex' +require 'rational' # Symbol serialization/deserialization class Symbol @@ -230,8 +232,8 @@ def as_json(*) { JSON.create_id => self.class.name, - 'o' => options, - 's' => source, + 'o' => options, + 's' => source, } end @@ -241,3 +243,39 @@ as_json.to_json end end + +class Rational + def self.json_create(object) + Rational(object['n'], object['d']) + end + + def as_json(*) + { + JSON.create_id => self.class.name, + 'n' => numerator, + 'd' => denominator, + } + end + + def to_json(*) + as_json.to_json + end +end + +class Complex + def self.json_create(object) + Complex(object['r'], object['i']) + end + + def as_json(*) + { + JSON.create_id => self.class.name, + 'r' => real, + 'i' => imag, + } + end + + def to_json(*) + as_json.to_json + end +end Index: ext/json/lib/json/common.rb =================================================================== --- ext/json/lib/json/common.rb (revision 33121) +++ ext/json/lib/json/common.rb (revision 33122) @@ -2,11 +2,11 @@ module JSON class << self - # If _object_ is string-like parse the string and return the parsed result + # If _object_ is string-like, parse the string and return the parsed result # as a Ruby data structure. Otherwise generate a JSON text from the Ruby # data structure object and return it. # - # The _opts_ argument is passed through to generate/parse respectively, see + # The _opts_ argument is passed through to generate/parse respectively. See # generate and parse for their documentation. def [](object, opts = {}) if object.respond_to? :to_str @@ -16,7 +16,7 @@ end end - # Returns the JSON parser class, that is used by JSON. This might be either + # Returns the JSON parser class that is used by JSON. This is either # JSON::Ext::Parser or JSON::Pure::Parser. attr_reader :parser @@ -28,7 +28,7 @@ end # Return the constant located at _path_. The format of _path_ has to be - # either ::A::B::C or A::B::C. In any case A has to be located at the top + # either ::A::B::C or A::B::C. In any case, A has to be located at the top # level (absolute namespace path?). If there doesn't exist a constant at # the given path, an ArgumentError is raised. def deep_const_get(path) # :nodoc: @@ -81,15 +81,15 @@ $VERBOSE = old end - # Returns the JSON generator modul, that is used by JSON. This might be + # Returns the JSON generator module that is used by JSON. This is # either JSON::Ext::Generator or JSON::Pure::Generator. attr_reader :generator - # Returns the JSON generator state class, that is used by JSON. This might - # be either JSON::Ext::Generator::State or JSON::Pure::Generator::State. + # Returns the JSON generator state class that is used by JSON. This is + # either JSON::Ext::Generator::State or JSON::Pure::Generator::State. attr_accessor :state - # This is create identifier, that is used to decide, if the _json_create_ + # This is create identifier, which is used to decide if the _json_create_ # hook of a class should be called. It defaults to 'json_class'. attr_accessor :create_id end @@ -104,10 +104,10 @@ # The base exception for JSON errors. class JSONError < StandardError; end - # This exception is raised, if a parser error occurs. + # This exception is raised if a parser error occurs. class ParserError < JSONError; end - # This exception is raised, if the nesting of parsed datastructures is too + # This exception is raised if the nesting of parsed data structures is too # deep. class NestingError < ParserError; end @@ -115,13 +115,13 @@ class CircularDatastructure < NestingError; end # :startdoc: - # This exception is raised, if a generator or unparser error occurs. + # This exception is raised if a generator or unparser error occurs. class GeneratorError < JSONError; end # For backwards compatibility UnparserError = GeneratorError - # This exception is raised, if the required unicode support is missing on the - # system. Usually this means, that the iconv library is not installed. + # This exception is raised if the required unicode support is missing on the + # system. Usually this means that the iconv library is not installed. class MissingUnicodeSupport < JSONError; end module_function @@ -131,16 +131,16 @@ # _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, it defaults + # structures. Disable depth checking with :max_nesting => false. It defaults # to 19. # * *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 + # (keys) in a JSON object. Otherwise strings are returned. Strings are # the default. # * *create_additions*: If set to false, the Parser doesn't create - # additions even if a matchin class and create_id was found. This option + # additions even if a matching class and create_id was found. This option # defaults to true. # * *object_class*: Defaults to Hash # * *array_class*: Defaults to Array @@ -149,19 +149,19 @@ end # Parse the JSON document _source_ into a Ruby data structure and return it. - # The bang version of the parse method, defaults to the more dangerous values + # The bang version of the parse method defaults to the more dangerous values # for the _opts_ hash, so be sure only to parse trusted _source_ documents. # # _opts_ can have the following keys: # * *max_nesting*: The maximum depth of nesting allowed in the parsed data # structures. Enable depth checking with :max_nesting => anInteger. The parse! - # methods defaults to not doing max depth checking: This can be dangerous, + # methods defaults to not doing max depth checking: This can be dangerous # if someone wants to fill up your stack. # * *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 true. # * *create_additions*: If set to false, the Parser doesn't create - # additions even if a matchin class and create_id was found. This option + # additions even if a matching class and create_id was found. This option # defaults to true. def parse!(source, opts = {}) opts = { @@ -188,7 +188,7 @@ # * *object_nl*: a string that is put at the end of a JSON object (default: ''), # * *array_nl*: a string that is put at the end of a JSON array (default: ''), # * *allow_nan*: true if NaN, Infinity, and -Infinity should be - # generated, otherwise an exception is thrown, if these values are + # generated, otherwise an exception is thrown if these values are # encountered. This options defaults to false. # * *max_nesting*: The maximum depth of nesting allowed in the data # structures from which JSON is to be generated. Disable depth checking @@ -196,9 +196,13 @@ # # See also the fast_generate for the fastest creation method with the least # amount of sanity checks, and the pretty_generate method for some - # defaults for a pretty output. + # defaults for pretty output. def generate(obj, opts = nil) - state = SAFE_STATE_PROTOTYPE.dup + if State === opts + state, opts = opts, nil + else + state = SAFE_STATE_PROTOTYPE.dup + end if opts if opts.respond_to? :to_hash opts = opts.to_hash @@ -223,9 +227,13 @@ # This method disables the checks for circles in Ruby objects. # # *WARNING*: Be careful not to pass any Ruby data structures with circles as - # _obj_ argument, because this will cause JSON to go into an infinite loop. + # _obj_ argument because this will cause JSON to go into an infinite loop. def fast_generate(obj, opts = nil) - state = FAST_STATE_PROTOTYPE.dup + if State === opts + state, opts = opts, nil + else + state = FAST_STATE_PROTOTYPE.dup + end if opts if opts.respond_to? :to_hash opts = opts.to_hash @@ -249,10 +257,14 @@ # The returned document is a prettier form of the document returned by # #unparse. # - # The _opts_ argument can be used to configure the generator, see the + # The _opts_ argument can be used to configure the generator. See the # generate method for a more detailed explanation. def pretty_generate(obj, opts = nil) - state = PRETTY_STATE_PROTOTYPE.dup + if State === opts + state, opts = opts, nil + else + state = PRETTY_STATE_PROTOTYPE.dup + end if opts if opts.respond_to? :to_hash opts = opts.to_hash @@ -273,7 +285,7 @@ # :startdoc: # Load a ruby data structure from a JSON _source_ and return it. A source can - # either be a string-like object, an IO like object, or an object responding + # either be a string-like object, an IO-like object, or an object responding # to the read method. If _proc_ was given, it will be called with any nested # Ruby object as an argument recursively in depth first order. # @@ -312,10 +324,10 @@ # Dumps _obj_ as a JSON string, i.e. calls generate on the object and returns # the result. # - # If anIO (an IO like object or an object that responds to the write method) + # If anIO (an IO-like object or an object that responds to the write method) # was given, the resulting JSON is written to it. # - # If the number of nested arrays or objects exceeds _limit_ an ArgumentError + # If the number of nested arrays or objects exceeds _limit_, an ArgumentError # exception is raised. This argument is similar (but not exactly the # same!) to the _limit_ argument in Marshal.dump. # @@ -396,11 +408,11 @@ nil end - # If _object_ is string-like parse the string and return the parsed result as - # a Ruby data structure. Otherwise generate a JSON text from the Ruby data + # If _object_ is string-like, parse the string and return the parsed result as + # a Ruby data structure. Otherwise, generate a JSON text from the Ruby data # structure object and return it. # - # The _opts_ argument is passed through to generate/parse respectively, see + # The _opts_ argument is passed through to generate/parse respectively. See # generate and parse for their documentation. def JSON(object, *args) if object.respond_to? :to_str @@ -413,10 +425,10 @@ # Extends any Class to include _json_creatable?_ method. class ::Class - # Returns true, if this class can be used to create an instance + # Returns true if this class can be used to create an instance # from a serialised JSON string. The class has to implement a class - # method _json_create_ that expects a hash as first parameter, which includes - # the required data. + # method _json_create_ that expects a hash as first parameter. The hash + # should include the required data. def json_creatable? respond_to?(:json_create) end Index: ext/json/lib/json.rb =================================================================== --- ext/json/lib/json.rb (revision 33121) +++ ext/json/lib/json.rb (revision 33122) @@ -7,13 +7,13 @@ # # Built on two universally available structures: # 1. A collection of name/value pairs. Often referred to as an _object_, hash table, record, struct, keyed list, or associative array. -# 2. An orderd list of values. More commonly named as an _array_, vector, sequence, or list. +# 2. An ordered list of values. More commonly called an _array_, vector, sequence or list. # # To read more about JSON visit: http://json.org # # == Parsing JSON # -# To parse a JSON string received by another application, or generated within +# To parse a JSON string received by another application or gene (... truncated) -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/