summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog9
-rw-r--r--ext/json/lib/json/pure.rb53
-rw-r--r--ext/json/lib/json/pure/generator.rb7
-rw-r--r--ext/json/lib/json/pure/parser.rb26
4 files changed, 30 insertions, 65 deletions
diff --git a/ChangeLog b/ChangeLog
index 8ba33abd8d..e2d5bae826 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+Fri Oct 3 19:33:21 2008 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * ext/json/lib/json/pure.rb (module JSON): remove Iconv dependency.
+
+ * ext/json/lib/json/pure/generator.rb (utf8_to_json): process as
+ binary and remove Iconv dependency.
+
+ * ext/json/lib/json/pure/parser.rb (parse_string): ditto.
+
Fri Oct 3 14:04:05 2008 NAKAMURA Usaku <usa@ruby-lang.org>
* win32/{configure.bat,setup.mak,Makefile.sub): add --program-prefix
diff --git a/ext/json/lib/json/pure.rb b/ext/json/lib/json/pure.rb
index b86d905523..6af8705c5b 100644
--- a/ext/json/lib/json/pure.rb
+++ b/ext/json/lib/json/pure.rb
@@ -3,59 +3,6 @@ require 'json/pure/parser'
require 'json/pure/generator'
module JSON
- begin
- require 'iconv'
- # An iconv instance to convert from UTF8 to UTF16 Big Endian.
- UTF16toUTF8 = Iconv.new('utf-8', 'utf-16be') # :nodoc:
- # An iconv instance to convert from UTF16 Big Endian to UTF8.
- UTF8toUTF16 = Iconv.new('utf-16be', 'utf-8') # :nodoc:
- UTF8toUTF16.iconv('no bom')
- rescue Errno::EINVAL, Iconv::InvalidEncoding
- # Iconv doesn't support big endian utf-16. Let's try to hack this manually
- # into the converters.
- begin
- old_verbose, $VERBSOSE = $VERBOSE, nil
- # An iconv instance to convert from UTF8 to UTF16 Big Endian.
- UTF16toUTF8 = Iconv.new('utf-8', 'utf-16') # :nodoc:
- # An iconv instance to convert from UTF16 Big Endian to UTF8.
- UTF8toUTF16 = Iconv.new('utf-16', 'utf-8') # :nodoc:
- UTF8toUTF16.iconv('no bom')
- if UTF8toUTF16.iconv("\xe2\x82\xac") == "\xac\x20"
- swapper = Class.new do
- def initialize(iconv) # :nodoc:
- @iconv = iconv
- end
-
- def iconv(string) # :nodoc:
- result = @iconv.iconv(string)
- JSON.swap!(result)
- end
- end
- UTF8toUTF16 = swapper.new(UTF8toUTF16) # :nodoc:
- end
- if UTF16toUTF8.iconv("\xac\x20") == "\xe2\x82\xac"
- swapper = Class.new do
- def initialize(iconv) # :nodoc:
- @iconv = iconv
- end
-
- def iconv(string) # :nodoc:
- string = JSON.swap!(string.dup)
- @iconv.iconv(string)
- end
- end
- UTF16toUTF8 = swapper.new(UTF16toUTF8) # :nodoc:
- end
- rescue Errno::EINVAL, Iconv::InvalidEncoding
- raise MissingUnicodeSupport, "iconv doesn't seem to support UTF-8/UTF-16 conversions"
- ensure
- $VERBOSE = old_verbose
- end
- rescue LoadError
- raise MissingUnicodeSupport,
- "iconv couldn't be loaded, which is required for UTF-8/UTF-16 conversions"
- end
-
# Swap consecutive bytes of _string_ in place.
def self.swap!(string) # :nodoc:
0.upto(string.size / 2) do |i|
diff --git a/ext/json/lib/json/pure/generator.rb b/ext/json/lib/json/pure/generator.rb
index c8bbfd09ee..91bdc0ff41 100644
--- a/ext/json/lib/json/pure/generator.rb
+++ b/ext/json/lib/json/pure/generator.rb
@@ -41,6 +41,7 @@ module JSON
# UTF16 big endian characters as \u????, and return it.
def utf8_to_json(string) # :nodoc:
string = string.gsub(/["\\\/\x0-\x1f]/) { MAP[$&] }
+ string.force_encoding(Encoding::ASCII_8BIT)
string.gsub!(/(
(?:
[\xc2-\xdf][\x80-\xbf] |
@@ -50,12 +51,10 @@ module JSON
[\x80-\xc1\xf5-\xff] # invalid
)/nx) { |c|
c.size == 1 and raise GeneratorError, "invalid utf8 byte: '#{c}'"
- s = JSON::UTF8toUTF16.iconv(c).unpack('H*')[0]
- s.gsub!(/.{4}/n, '\\\\u\&')
+ c = c.unpack("U*")[0]
+ c > 0xFFFF ? ('\uD%03X\uD%03X' % [0x7C0+c/1024, 0xC00+c%1024]) : ('\u%04X'%c)
}
string
- rescue Iconv::Failure => e
- raise GeneratorError, "Caught #{e.class}: #{e}"
end
module_function :utf8_to_json
diff --git a/ext/json/lib/json/pure/parser.rb b/ext/json/lib/json/pure/parser.rb
index 9b30f15c07..a0ab3075fe 100644
--- a/ext/json/lib/json/pure/parser.rb
+++ b/ext/json/lib/json/pure/parser.rb
@@ -126,20 +126,30 @@ module JSON
if u = UNESCAPE_MAP[$&[1]]
u
else # \uXXXX
- bytes = ''
- i = 0
- while c[6 * i] == ?\\ && c[6 * i + 1] == ?u
- bytes << c[6 * i + 2, 2].to_i(16) << c[6 * i + 4, 2].to_i(16)
- i += 1
+ res = []
+ stack = nil
+ [c.delete!('\\\\u')].pack("H*").unpack("n*").each do |c|
+ case c
+ when 0xD800..0xDBFF
+ raise JSON::ParserError, "partial character in source" if stack
+ stack = c
+ when 0xDC00..0xDFFF
+ raise JSON::ParserError,
+ "partial character in source" unless (0xD800..0xDBFF).include?(stack)
+ res << (stack << 10) - 0x35fdc00 + c
+ stack = nil
+ else
+ raise JSON::ParserError, "partial character in source" if stack
+ res << c
+ end
end
- JSON::UTF16toUTF8.iconv(bytes)
+ raise JSON::ParserError, "partial character in source" if stack
+ res.pack("U*")
end
end
else
UNPARSED
end
- rescue Iconv::Failure => e
- raise GeneratorError, "Caught #{e.class}: #{e}"
end
def parse_value