lib/json.rb in json-0.4.1 vs lib/json.rb in json-0.4.2
- old
+ new
@@ -138,28 +138,82 @@
def support_unicode=(enable)
@support_unicode = enable
end
# Returns _true_ if JSON supports unicode, otherwise _false_ is returned.
+ #
+ # If loading of the iconv library fails, or it doesn't support utf8/utf16
+ # encoding, this will be set to false, as a fallback.
def support_unicode?
!!@support_unicode
end
end
- JSON.support_unicode = true # default, hower it's possible to switch off full
- # unicode support, if non-ascii bytes should be
+ JSON.support_unicode = true # default, however it's possible to switch off
+ # full unicode support, if non-ascii bytes should be
# just passed through.
begin
require 'iconv'
# An iconv instance to convert from UTF8 to UTF16 Big Endian.
UTF16toUTF8 = Iconv.new('utf-8', 'utf-16be')
# An iconv instance to convert from UTF16 Big Endian to UTF8.
UTF8toUTF16 = Iconv.new('utf-16be', 'utf-8'); UTF8toUTF16.iconv('no bom')
+ rescue Errno::EINVAL
+ begin
+ old_verbose = $VERBOSE
+ $VERBOSE = nil
+ # An iconv instance to convert from UTF8 to UTF16 Big Endian.
+ UTF16toUTF8 = Iconv.new('utf-8', 'utf-16')
+ # An iconv instance to convert from UTF16 Big Endian to UTF8.
+ UTF8toUTF16 = Iconv.new('utf-16', 'utf-8'); UTF8toUTF16.iconv('no bom')
+ if UTF8toUTF16.iconv("\xe2\x82\xac") == "\xac\x20"
+ swapper = Class.new do
+ def initialize(iconv)
+ @iconv = iconv
+ end
+
+ def iconv(string)
+ result = @iconv.iconv(string)
+ JSON.swap!(result)
+ end
+ end
+ UTF8toUTF16 = swapper.new(UTF8toUTF16)
+ end
+ if UTF16toUTF8.iconv("\xac\x20") == "\xe2\x82\xac"
+ swapper = Class.new do
+ def initialize(iconv)
+ @iconv = iconv
+ end
+
+ def iconv(string)
+ string = JSON.swap!(string.dup)
+ @iconv.iconv(string)
+ end
+ end
+ UTF16toUTF8 = swapper.new(UTF16toUTF8)
+ end
+ rescue Errno::EINVAL
+ # Enforce disabling of unicode support, if iconv doesn't support
+ # UTF8/UTF16 at all.
+ JSON.support_unicode = false
+ ensure
+ $VERBOSE = old_verbose
+ end
rescue LoadError
- JSON.support_unicode = false # enforce disabling of unicode support
+ # Enforce disabling of unicode support, if iconv doesn't exist.
+ JSON.support_unicode = false
end
+ # Swap consecutive bytes in string in place.
+ def self.swap!(string)
+ 0.upto(string.size / 2) do |i|
+ break unless string[2 * i + 1]
+ string[2 * i], string[2 * i + 1] = string[2 * i + 1], string[2 * i]
+ end
+ string
+ end
+
# This class implements the JSON parser that is used to parse a JSON string
# into a Ruby data structure.
class Parser < StringScanner
STRING = /"((?:[^"\\]|\\.)*)"/
INTEGER = /-?\d+/
@@ -213,19 +267,20 @@
private
def parse_string
if scan(STRING)
return '' if self[1].empty?
- self[1].gsub(/\\(?:[\\bfnrt"]|u([A-Fa-f\d]{4}))/) do
+ self[1].gsub(%r(\\(?:[\\bfnrt"/]|u([A-Fa-f\d]{4})))) do
case $~[0]
when '\\\\' then '\\'
when '\\b' then "\b"
when '\\f' then "\f"
when '\\n' then "\n"
when '\\r' then "\r"
when '\\t' then "\t"
when '\\"' then '"'
+ when '\\/' then '/'
else
if JSON.support_unicode? and $KCODE == 'UTF8'
JSON.utf16_to_utf8($~[1])
else
# if utf8 mode is switched off or unicode not supported, try to
@@ -406,9 +461,10 @@
when char == ?\n then result << '\n'
when char == ?\f then result << '\f'
when char == ?\r then result << '\r'
when char == ?" then result << '\"'
when char == ?\\ then result << '\\\\'
+ when char == ?/ then result << '\/'
when char.between?(0x0, 0x1f) then result << "\\u%04x" % char
when char.between?(0x20, 0x7f) then result << char
when !(JSON.support_unicode? && $KCODE == 'UTF8')
# if utf8 mode is switched off or unicode not supported, just pass
# bytes through: