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