summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Frank <flori@ping.de>2009-10-21 12:36:13 +0200
committerFlorian Frank <flori@ping.de>2009-10-26 22:56:27 +0100
commite837a02041d3bde8429ecb12c1c550c39b99ac93 (patch)
tree0c4380219fbbe9795e44385d1abcfa92f4efc1a5
parent3bbcb665d5aa1ffa56a94265bc29108317b6c092 (diff)
downloadjson-e837a02041d3bde8429ecb12c1c550c39b99ac93.tar.gz
optimised pure variant a bit
-rw-r--r--lib/json/common.rb31
-rw-r--r--lib/json/pure/generator.rb101
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) << ']'