lib/json/pure/generator.rb in json_pure-1.8.6 vs lib/json/pure/generator.rb in json_pure-2.0.0

- old
+ new

@@ -1,5 +1,6 @@ +#frozen_string_literal: false module JSON MAP = { "\x0" => '\u0000', "\x1" => '\u0001', "\x2" => '\u0002', @@ -36,89 +37,49 @@ '\\' => '\\\\', } # :nodoc: # Convert a UTF8 encoded Ruby string _string_ to a JSON string, encoded with # UTF16 big endian characters as \u????, and return it. - if defined?(::Encoding) - def utf8_to_json(string) # :nodoc: - string = string.dup - string.force_encoding(::Encoding::ASCII_8BIT) - string.gsub!(/["\\\x0-\x1f]/) { MAP[$&] } - string.force_encoding(::Encoding::UTF_8) - string - end + def utf8_to_json(string) # :nodoc: + string = string.dup + string.force_encoding(::Encoding::ASCII_8BIT) + string.gsub!(/["\\\x0-\x1f]/) { MAP[$&] } + string.force_encoding(::Encoding::UTF_8) + string + end - def utf8_to_json_ascii(string) # :nodoc: - string = string.dup - string.force_encoding(::Encoding::ASCII_8BIT) - string.gsub!(/["\\\x0-\x1f]/n) { MAP[$&] } - string.gsub!(/( - (?: - [\xc2-\xdf][\x80-\xbf] | - [\xe0-\xef][\x80-\xbf]{2} | - [\xf0-\xf4][\x80-\xbf]{3} - )+ | - [\x80-\xc1\xf5-\xff] # invalid - )/nx) { |c| - c.size == 1 and raise GeneratorError, "invalid utf8 byte: '#{c}'" - s = JSON.iconv('utf-16be', 'utf-8', c).unpack('H*')[0] - s.force_encoding(::Encoding::ASCII_8BIT) - s.gsub!(/.{4}/n, '\\\\u\&') - s.force_encoding(::Encoding::UTF_8) - } - string.force_encoding(::Encoding::UTF_8) - string - rescue => e - raise GeneratorError.wrap(e) - end + def utf8_to_json_ascii(string) # :nodoc: + string = string.dup + string.force_encoding(::Encoding::ASCII_8BIT) + string.gsub!(/["\\\x0-\x1f]/n) { MAP[$&] } + string.gsub!(/( + (?: + [\xc2-\xdf][\x80-\xbf] | + [\xe0-\xef][\x80-\xbf]{2} | + [\xf0-\xf4][\x80-\xbf]{3} + )+ | + [\x80-\xc1\xf5-\xff] # invalid + )/nx) { |c| + c.size == 1 and raise GeneratorError, "invalid utf8 byte: '#{c}'" + s = JSON.iconv('utf-16be', 'utf-8', c).unpack('H*')[0] + s.force_encoding(::Encoding::ASCII_8BIT) + s.gsub!(/.{4}/n, '\\\\u\&') + s.force_encoding(::Encoding::UTF_8) + } + string.force_encoding(::Encoding::UTF_8) + string + rescue => e + raise GeneratorError.wrap(e) + end - def valid_utf8?(string) - encoding = string.encoding - (encoding == Encoding::UTF_8 || encoding == Encoding::ASCII) && - string.valid_encoding? - end - module_function :valid_utf8? - else - def utf8_to_json(string) # :nodoc: - string.gsub(/["\\\x0-\x1f]/n) { MAP[$&] } - end - - def utf8_to_json_ascii(string) # :nodoc: - string = string.gsub(/["\\\x0-\x1f]/) { MAP[$&] } - string.gsub!(/( - (?: - [\xc2-\xdf][\x80-\xbf] | - [\xe0-\xef][\x80-\xbf]{2} | - [\xf0-\xf4][\x80-\xbf]{3} - )+ | - [\x80-\xc1\xf5-\xff] # invalid - )/nx) { |c| - c.size == 1 and raise GeneratorError, "invalid utf8 byte: '#{c}'" - s = JSON.iconv('utf-16be', 'utf-8', c).unpack('H*')[0] - s.gsub!(/.{4}/n, '\\\\u\&') - } - string - rescue => e - raise GeneratorError.wrap(e) - end - - def valid_utf8?(string) - string =~ - /\A( [\x09\x0a\x0d\x20-\x7e] # ASCII - | [\xc2-\xdf][\x80-\xbf] # non-overlong 2-byte - | \xe0[\xa0-\xbf][\x80-\xbf] # excluding overlongs - | [\xe1-\xec\xee\xef][\x80-\xbf]{2} # straight 3-byte - | \xed[\x80-\x9f][\x80-\xbf] # excluding surrogates - | \xf0[\x90-\xbf][\x80-\xbf]{2} # planes 1-3 - | [\xf1-\xf3][\x80-\xbf]{3} # planes 4-15 - | \xf4[\x80-\x8f][\x80-\xbf]{2} # plane 16 - )*\z/nx - end + def valid_utf8?(string) + encoding = string.encoding + (encoding == Encoding::UTF_8 || encoding == Encoding::ASCII) && + string.valid_encoding? end module_function :utf8_to_json, :utf8_to_json_ascii, :valid_utf8? - module Pure module Generator # This class is used to create State instances, that are use to hold data # while generating a JSON text from a Ruby data structure. class State @@ -152,21 +113,18 @@ # * *max_nesting*: sets the maximum level of data structure nesting in # the generated JSON, max_nesting = 0 if no maximum should be checked. # * *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. - # * *quirks_mode*: Enables quirks_mode for parser, that is for example - # generating single JSON values instead of documents is possible. def initialize(opts = {}) @indent = '' @space = '' @space_before = '' @object_nl = '' @array_nl = '' @allow_nan = false @ascii_only = false - @quirks_mode = false @buffer_initial_length = 1024 configure opts end # This string is used to indent levels in the JSON text. @@ -188,14 +146,10 @@ # This integer returns the maximum level of data structure nesting in # the generated JSON, max_nesting = 0 if no maximum is checked. attr_accessor :max_nesting - # If this attribute is set to true, quirks mode is enabled, otherwise - # it's disabled. - attr_accessor :quirks_mode - # :stopdoc: attr_reader :buffer_initial_length def buffer_initial_length=(length) if length > 0 @@ -231,15 +185,10 @@ # returns false. def ascii_only? @ascii_only end - # Returns true, if quirks mode is enabled. Otherwise returns false. - def quirks_mode? - @quirks_mode - end - # Configure this State instance with the Hash _opts_, and return # itself. def configure(opts) if opts.respond_to?(:to_hash) opts = opts.to_hash @@ -257,11 +206,10 @@ @object_nl = opts[:object_nl] if opts.key?(:object_nl) @array_nl = opts[:array_nl] if opts.key?(:array_nl) @allow_nan = !!opts[:allow_nan] if opts.key?(:allow_nan) @ascii_only = opts[:ascii_only] if opts.key?(:ascii_only) @depth = opts[:depth] || 0 - @quirks_mode = opts[:quirks_mode] if opts.key?(:quirks_mode) @buffer_initial_length ||= opts[:buffer_initial_length] if !opts.key?(:max_nesting) # defaults to 100 @max_nesting = 100 elsif opts[:max_nesting] @@ -284,24 +232,18 @@ result end alias to_hash to_h - # Generates a valid JSON document from object +obj+ and returns the - # result. If no valid JSON document can be created this method raises a + # Generates a valid JSON document from object +obj+ and + # returns the result. If no valid JSON document can be + # created this method raises a # GeneratorError exception. def generate(obj) result = obj.to_json(self) JSON.valid_utf8?(result) or raise GeneratorError, "source sequence #{result.inspect} is illegal/malformed utf-8" - unless @quirks_mode - unless result =~ /\A\s*\[/ && result =~ /\]\s*\Z/ || - result =~ /\A\s*\{/ && result =~ /\}\s*\Z/ - then - raise GeneratorError, "only generation of JSON objects or arrays allowed" - end - end result end # Return the value returned by method +name+. def [](name) @@ -443,37 +385,23 @@ end end end module String - if defined?(::Encoding) - # 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(state = nil, *args) - state = State.from_state(state) - if encoding == ::Encoding::UTF_8 - string = self - else - string = encode(::Encoding::UTF_8) - end - if state.ascii_only? - '"' << JSON.utf8_to_json_ascii(string) << '"' - else - '"' << JSON.utf8_to_json(string) << '"' - end + # 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(state = nil, *args) + state = State.from_state(state) + if encoding == ::Encoding::UTF_8 + string = self + else + string = encode(::Encoding::UTF_8) end - else - # 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(state = nil, *args) - state = State.from_state(state) - if state.ascii_only? - '"' << JSON.utf8_to_json_ascii(self) << '"' - else - '"' << JSON.utf8_to_json(self) << '"' - end + if state.ascii_only? + '"' << JSON.utf8_to_json_ascii(string) << '"' + else + '"' << JSON.utf8_to_json(string) << '"' end end # Module that holds the extinding methods if, the String module is # included.