diff options
author | Florian Frank <flori@ping.de> | 2010-08-07 11:09:56 +0200 |
---|---|---|
committer | Florian Frank <flori@ping.de> | 2010-08-07 12:08:06 +0200 |
commit | 1edf726ff3029e877350bc8db3217a64a74de581 (patch) | |
tree | 9d06ca2d650a514f5f42e2d46342a5fac45da0fd | |
parent | bec5586cd5318e722fd599263105fa56b0bbe3e1 (diff) | |
download | json-1edf726ff3029e877350bc8db3217a64a74de581.tar.gz |
do not forget to dup the state
use state for depth checking in pure as well
-rw-r--r-- | ext/json/ext/generator/generator.c | 5 | ||||
-rw-r--r-- | lib/json/pure/generator.rb | 132 | ||||
-rwxr-xr-x | tests/test_json_generate.rb | 17 |
3 files changed, 77 insertions, 77 deletions
diff --git a/ext/json/ext/generator/generator.c b/ext/json/ext/generator/generator.c index b4cb740..0617466 100644 --- a/ext/json/ext/generator/generator.c +++ b/ext/json/ext/generator/generator.c @@ -14,7 +14,7 @@ static VALUE mJSON, mExt, mGenerator, cState, mGeneratorMethods, mObject, 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_respond_to_p, i_match, i_keys, i_depth, i_dup; /* * Copyright 2001-2004 Unicode, Inc. @@ -1043,7 +1043,7 @@ static VALUE cState_from_state_s(VALUE self, VALUE opts) if (NIL_P(CJSON_SAFE_STATE_PROTOTYPE)) { CJSON_SAFE_STATE_PROTOTYPE = rb_const_get(mJSON, i_SAFE_STATE_PROTOTYPE); } - return CJSON_SAFE_STATE_PROTOTYPE; + return rb_funcall(CJSON_SAFE_STATE_PROTOTYPE, i_dup, 0); } } @@ -1406,6 +1406,7 @@ void Init_generator() i_respond_to_p = rb_intern("respond_to?"); i_match = rb_intern("match"); i_keys = rb_intern("keys"); + i_dup = rb_intern("dup"); #ifdef HAVE_RUBY_ENCODING_H CEncoding_UTF_8 = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("utf-8")); i_encoding = rb_intern("encoding"); diff --git a/lib/json/pure/generator.rb b/lib/json/pure/generator.rb index 12959bf..335c6ae 100644 --- a/lib/json/pure/generator.rb +++ b/lib/json/pure/generator.rb @@ -112,7 +112,7 @@ module JSON when Hash new(opts) else - SAFE_STATE_PROTOTYPE + SAFE_STATE_PROTOTYPE.dup end end @@ -167,7 +167,7 @@ module JSON # generated JSON. attr_accessor :depth - def check_max_nesting(depth) # :nodoc: + def check_max_nesting # :nodoc: return if @max_nesting.zero? current_nesting = depth + 1 current_nesting > @max_nesting and @@ -252,51 +252,41 @@ module JSON # _state_ is a JSON::State object, that can also be used to configure the # produced JSON string output further. # _depth_ is used to find out nesting depth, to indent accordingly. - def to_json(state = nil, depth = 0, *) - if state - state = State.from_state(state) - state.check_max_nesting(depth) - end - json_transform(state, depth) + def to_json(state = nil, *) + state = State.from_state(state) + state.check_max_nesting + json_transform(state) end private - def json_shift(state, depth) - state and not state.object_nl.empty? or return '' - state.indent * depth + def json_shift(state) + state.object_nl.empty? or return '' + state.indent * state.depth end - def json_transform(state, depth) + def json_transform(state) delim = ',' - if state - delim << state.object_nl - result = '{' - result << state.object_nl - depth += 1 - first = true - indent = state && !state.object_nl.empty? - each { |key,value| - result << delim unless first - result << state.indent * depth if indent - result << key.to_s.to_json(state, depth) - result << state.space_before - result << ':' - result << state.space - result << value.to_json(state, depth) - first = false - } - depth -= 1 - result << state.object_nl - result << state.indent * depth if indent if indent - result << '}' - else - result = '{' - result << map { |key,value| - key.to_s.to_json << ':' << value.to_json - }.join(delim) - result << '}' - end + delim << state.object_nl + result = '{' + result << state.object_nl + depth = state.depth += 1 + first = true + indent = !state.object_nl.empty? + each { |key,value| + result << delim unless first + result << state.indent * depth if indent + result << key.to_s.to_json(state) + result << state.space_before + result << ':' + result << state.space + result << value.to_json(state) + first = false + } + depth = state.depth -= 1 + result << state.object_nl + result << state.indent * depth if indent if indent + result << '}' result end end @@ -306,39 +296,32 @@ module JSON # this Array instance. # _state_ is a JSON::State object, that can also be used to configure the # produced JSON string output further. - # _depth_ is used to find out nesting depth, to indent accordingly. - def to_json(state = nil, depth = 0, *) - if state - state = State.from_state(state) - state.check_max_nesting(depth) - end - json_transform(state, depth) + def to_json(state = nil, *) + state = State.from_state(state) + state.check_max_nesting + json_transform(state) end private - def json_transform(state, depth) + def json_transform(state) delim = ',' - if state - delim << state.array_nl - result = '[' - result << state.array_nl - depth += 1 - first = true - indent = state && !state.array_nl.empty? - each { |value| - result << delim unless first - result << state.indent * depth if indent - result << value.to_json(state, depth) - first = false - } - depth -= 1 - result << state.array_nl + delim << state.array_nl + result = '[' + result << state.array_nl + depth = state.depth += 1 + first = true + indent = !state.array_nl.empty? + each { |value| + result << delim unless first result << state.indent * depth if indent - result << ']' - else - '[' << map { |value| value.to_json }.join(delim) << ']' - end + result << value.to_json(state) + first = false + } + depth = state.depth -= 1 + result << state.array_nl + result << state.indent * depth if indent + result << ']' end end @@ -350,15 +333,16 @@ module JSON module Float # Returns a JSON string representation for this Float number. def to_json(state = nil, *) + state = State.from_state(state) case when infinite? - if state && state.allow_nan? + if state.allow_nan? to_s else raise GeneratorError, "#{self} not allowed in JSON" end when nan? - if state && state.allow_nan? + if state.allow_nan? to_s else raise GeneratorError, "#{self} not allowed in JSON" @@ -374,9 +358,8 @@ module JSON # This string should be encoded with UTF-8 A call to this method # returns a JSON string encoded with UTF16 big endian characters as # \u????. - def to_json(*args) - state, = *args - state ||= State.from_state(state) + def to_json(state = nil, *args) + state = State.from_state(state) if encoding == ::Encoding::UTF_8 string = self else @@ -392,9 +375,8 @@ module JSON # This string should be encoded with UTF-8 A call to this method # returns a JSON string encoded with UTF16 big endian characters as # \u????. - def to_json(*args) - state, = *args - state ||= State.from_state(state) + def to_json(state = nil, *args) + state = State.from_state(state) if state.ascii_only? '"' << JSON.utf8_to_json_ascii(self) << '"' else diff --git a/tests/test_json_generate.rb b/tests/test_json_generate.rb index 8dc804b..d67a4b2 100755 --- a/tests/test_json_generate.rb +++ b/tests/test_json_generate.rb @@ -164,4 +164,21 @@ EOT assert_raises(GeneratorError) { pretty_generate([JSON::MinusInfinity]) } assert_equal "[\n -Infinity\n]", pretty_generate([JSON::MinusInfinity], :allow_nan => true) end + + def test_depth + ary = []; ary << ary + assert_equal 0, JSON::SAFE_STATE_PROTOTYPE.depth + assert_raises(JSON::NestingError) { JSON.generate(ary) } + assert_equal 0, JSON::SAFE_STATE_PROTOTYPE.depth + assert_equal 0, JSON::FAST_STATE_PROTOTYPE.depth + assert_raises(JSON::NestingError) { JSON.fast_generate(ary) } + assert_equal 0, JSON::FAST_STATE_PROTOTYPE.depth + assert_equal 0, JSON::PRETTY_STATE_PROTOTYPE.depth + assert_raises(JSON::NestingError) { JSON.pretty_generate(ary) } + assert_equal 0, JSON::PRETTY_STATE_PROTOTYPE.depth + s = JSON.state.new + assert_equal 0, s.depth + assert_raises(JSON::NestingError) { ary.to_json(s) } + assert_equal 19, s.depth + end end |