lib/json/pure/parser.rb in json_pure-2.3.1 vs lib/json/pure/parser.rb in json_pure-2.4.0
- old
+ new
@@ -59,10 +59,12 @@
# 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 7159 to be parsed by the Parser. This option defaults
# to false.
+ # * *freeze*: If set to true, all parsed objects will be frozen. Parsed
+ # string will be deduplicated if possible.
# * *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 true, the Parser creates
@@ -84,10 +86,11 @@
else
@max_nesting = 0
end
@allow_nan = !!opts[:allow_nan]
@symbolize_names = !!opts[:symbolize_names]
+ @freeze = !!opts[:freeze]
if opts.key?(:create_additions)
@create_additions = !!opts[:create_additions]
else
@create_additions = false
end
@@ -118,10 +121,11 @@
raise ParserError, "source is not valid JSON!"
else
obj = parse_value
UNPARSED.equal?(obj) and raise ParserError,
"source is not valid JSON!"
+ obj.freeze if @freeze
end
while !eos? && skip(IGNORE) do end
eos? or raise ParserError, "source is not valid JSON!"
obj
end
@@ -159,10 +163,11 @@
EMPTY_8BIT_STRING = ''
if ::String.method_defined?(:encode)
EMPTY_8BIT_STRING.force_encoding Encoding::ASCII_8BIT
end
+ STR_UMINUS = ''.respond_to?(:-@)
def parse_string
if scan(STRING)
return '' if self[1].empty?
string = self[1].gsub(%r((?:\\[\\bfnrt"/]|(?:\\u(?:[A-Fa-f\d]{4}))+|\\[\x20-\xff]))n) do |c|
if u = UNESCAPE_MAP[$&[1]]
@@ -178,10 +183,19 @@
end
end
if string.respond_to?(:force_encoding)
string.force_encoding(::Encoding::UTF_8)
end
+
+ if @freeze
+ if STR_UMINUS
+ string = -string
+ else
+ string.freeze
+ end
+ end
+
if @create_additions and @match_string
for (regexp, klass) in @match_string
klass.json_creatable? or next
string =~ regexp and return klass.json_create(string)
end
@@ -240,12 +254,14 @@
def parse_array
raise NestingError, "nesting of #@current_nesting is too deep" if
@max_nesting.nonzero? && @current_nesting > @max_nesting
result = @array_class.new
delim = false
- until eos?
+ loop do
case
+ when eos?
+ raise ParserError, "unexpected end of string while parsing array"
when !UNPARSED.equal?(value = parse_value)
delim = false
result << value
skip(IGNORE)
if scan(COLLECTION_DELIMITER)
@@ -272,11 +288,13 @@
def parse_object
raise NestingError, "nesting of #@current_nesting is too deep" if
@max_nesting.nonzero? && @current_nesting > @max_nesting
result = @object_class.new
delim = false
- until eos?
+ loop do
case
+ when eos?
+ raise ParserError, "unexpected end of string while parsing object"
when !UNPARSED.equal?(string = parse_string)
skip(IGNORE)
unless scan(PAIR_DELIMITER)
raise ParserError, "expected ':' in object at '#{peek(20)}'!"
end