diff options
author | Florian Frank <flori@ping.de> | 2009-10-21 12:36:13 +0200 |
---|---|---|
committer | Florian Frank <flori@ping.de> | 2009-10-26 22:56:27 +0100 |
commit | e837a02041d3bde8429ecb12c1c550c39b99ac93 (patch) | |
tree | 0c4380219fbbe9795e44385d1abcfa92f4efc1a5 | |
parent | 3bbcb665d5aa1ffa56a94265bc29108317b6c092 (diff) | |
download | json-e837a02041d3bde8429ecb12c1c550c39b99ac93.tar.gz |
optimised pure variant a bit
-rw-r--r-- | lib/json/common.rb | 31 | ||||
-rw-r--r-- | lib/json/pure/generator.rb | 101 |
2 files changed, 47 insertions, 85 deletions
diff --git a/lib/json/common.rb b/lib/json/common.rb index 39f6336..f9f6e00 100644 --- a/lib/json/common.rb +++ b/lib/json/common.rb @@ -91,15 +91,15 @@ module JSON # deep. class NestingError < ParserError; end + # :stopdoc: + class CircularDatastructure < NestingError; end + # :startdoc: + # This exception is raised, if a generator or unparser error occurs. class GeneratorError < JSONError; end # For backwards compatibility UnparserError = GeneratorError - # If a circular data structure is encountered while unparsing - # this exception is raised. - class CircularDatastructure < GeneratorError; end - # 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 @@ -162,8 +162,6 @@ module JSON # * *space_before*: a string that is put before a : pair delimiter (default: ''), # * *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: ''), - # * *check_circular*: true if checking for circular data structures - # should be done (the default), false otherwise. # * *allow_nan*: true if NaN, Infinity, and -Infinity should be # generated, otherwise an exception is thrown, if these values are # encountered. This options defaults to false. @@ -180,11 +178,7 @@ module JSON else state = State.new end - result = obj.to_json(state) - if result !~ /\A\s*(?:\[.*\]|\{.*\})\s*\Z/m - raise GeneratorError, "only generation of JSON objects or arrays allowed" - end - result + state.encode(obj) end # :stopdoc: @@ -221,11 +215,10 @@ module JSON # generate method for a more detailed explanation. def pretty_generate(obj, opts = nil) state = JSON.state.new( - :indent => ' ', - :space => ' ', - :object_nl => "\n", - :array_nl => "\n", - :check_circular => true + :indent => ' ', + :space => ' ', + :object_nl => "\n", + :array_nl => "\n" ) if opts if opts.respond_to? :to_hash @@ -237,11 +230,7 @@ module JSON end state.configure(opts) end - result = obj.to_json(state) - if result !~ /\A\s*(?:\[.*\]|\{.*\})\s*\Z/m - raise GeneratorError, "only generation of JSON objects or arrays allowed" - end - result + state.encode(obj) end # :stopdoc: diff --git a/lib/json/pure/generator.rb b/lib/json/pure/generator.rb index 57ef483..46a7230 100644 --- a/lib/json/pure/generator.rb +++ b/lib/json/pure/generator.rb @@ -120,7 +120,6 @@ module JSON # generated, otherwise an exception is thrown, if these values are # encountered. This options defaults to false. def initialize(opts = {}) - @seen = {} @indent = '' @space = '' @space_before = '' @@ -171,23 +170,6 @@ module JSON @allow_nan end - # Returns _true_, if _object_ was already seen during this generating - # run. - def seen?(object) - @seen.key?(object.__id__) - end - - # Remember _object_, to find out if it was already encountered (if a - # cyclic data structure is if a cyclic data structure is rendered). - def remember(object) - @seen[object.__id__] = true - end - - # Forget _object_ for this generating run. - def forget(object) - @seen.delete object.__id__ - end - # Configure this State instance with the Hash _opts_, and return # itself. def configure(opts) @@ -217,6 +199,15 @@ module JSON end result end + + # XXX + def encode(obj) + result = obj.to_json(self) + if result !~ /\A\s*(?:\[.*\]|\{.*\})\s*\Z/m + raise GeneratorError, "only generation of JSON objects or arrays allowed" + end + result + end end module GeneratorMethods @@ -237,25 +228,12 @@ module JSON if state state = JSON.state.from_state(state) state.check_max_nesting(depth) - json_check_circular(state) { json_transform(state, depth) } - else - json_transform(state, depth) end + json_transform(state, depth) end private - def json_check_circular(state) - if state and state.check_circular? - state.seen?(self) and raise JSON::CircularDatastructure, - "circular data structures not supported!" - state.remember self - end - yield - ensure - state and state.forget self - end - def json_shift(state, depth) state and not state.object_nl.empty? or return '' state.indent * depth @@ -267,16 +245,22 @@ module JSON delim << state.object_nl result = '{' result << state.object_nl - result << map { |key,value| - s = json_shift(state, depth + 1) - s << key.to_s.to_json(state, depth + 1) - s << state.space_before - s << ':' - s << state.space - s << value.to_json(state, depth + 1) - }.join(delim) + 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 << json_shift(state, depth) + result << state.indent * depth if indent if indent result << '}' else result = '{' @@ -299,41 +283,30 @@ module JSON if state state = JSON.state.from_state(state) state.check_max_nesting(depth) - json_check_circular(state) { json_transform(state, depth) } - else - json_transform(state, depth) end + json_transform(state, depth) end private - def json_check_circular(state) - if state and state.check_circular? - state.seen?(self) and raise JSON::CircularDatastructure, - "circular data structures not supported!" - state.remember self - end - yield - ensure - state and state.forget self - end - - def json_shift(state, depth) - state and not state.array_nl.empty? or return '' - state.indent * depth - end - def json_transform(state, depth) delim = ',' if state delim << state.array_nl result = '[' result << state.array_nl - result << map { |value| - json_shift(state, depth + 1) << value.to_json(state, depth + 1) - }.join(delim) + 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 - result << json_shift(state, depth) + result << state.indent * depth if indent result << ']' else '[' << map { |value| value.to_json }.join(delim) << ']' |