diff options
author | Florian Frank <flori@ping.de> | 2010-12-31 18:19:36 +0100 |
---|---|---|
committer | Florian Frank <flori@ping.de> | 2011-01-02 21:13:44 +0100 |
commit | 51eb5f8cac8f1a44f503dbeaef027a907c4ac23a (patch) | |
tree | fd5e87ea38115db96bfdfcd4fd7ed3ba20a84fc6 | |
parent | 632804116e13931ffbb41fe4b3916428c911b2c6 (diff) | |
download | json-51eb5f8cac8f1a44f503dbeaef027a907c4ac23a.tar.gz |
use JSON.iconv abstraction
-rw-r--r-- | lib/json/common.rb | 9 | ||||
-rw-r--r-- | lib/json/editor.rb | 4 | ||||
-rw-r--r-- | lib/json/pure.rb | 62 | ||||
-rw-r--r-- | lib/json/pure/generator.rb | 8 | ||||
-rw-r--r-- | lib/json/pure/parser.rb | 6 | ||||
-rwxr-xr-x | tests/test_json_fixtures.rb | 11 |
6 files changed, 25 insertions, 75 deletions
diff --git a/lib/json/common.rb b/lib/json/common.rb index 13debd1..1ca53cb 100644 --- a/lib/json/common.rb +++ b/lib/json/common.rb @@ -340,6 +340,15 @@ module JSON raise ArgumentError, "exceed depth limit" end + # Swap consecutive bytes of _string_ in place. + def self.swap!(string) # :nodoc: + 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 + # Shortuct for iconv. if String.method_defined?(:encode) def self.iconv(to, from, string) diff --git a/lib/json/editor.rb b/lib/json/editor.rb index 1e13f33..3450455 100644 --- a/lib/json/editor.rb +++ b/lib/json/editor.rb @@ -2,7 +2,6 @@ # requires ruby-gtk to be installed. require 'gtk2' -require 'iconv' require 'json' require 'rbconfig' require 'open-uri' @@ -1272,8 +1271,7 @@ module JSON def parse_json(json) check_pretty_printed(json) if @encoding && !/^utf8$/i.match(@encoding) - iconverter = Iconv.new('utf8', @encoding) - json = iconverter.iconv(json) + json = JSON.iconv 'utf-8', @encoding, json end JSON::parse(json, :max_nesting => false, :create_additions => false) end diff --git a/lib/json/pure.rb b/lib/json/pure.rb index 08efa83..f7ee3df 100644 --- a/lib/json/pure.rb +++ b/lib/json/pure.rb @@ -3,68 +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 LoadError - raise MissingUnicodeSupport, - "iconv couldn't be loaded, which is required for UTF-8/UTF-16 conversions" - 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 - end - - # Swap consecutive bytes of _string_ in place. - def self.swap!(string) # :nodoc: - 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 module holds all the modules/classes that implement JSON's # functionality in pure ruby. module Pure diff --git a/lib/json/pure/generator.rb b/lib/json/pure/generator.rb index 94cb239..44cca60 100644 --- a/lib/json/pure/generator.rb +++ b/lib/json/pure/generator.rb @@ -62,12 +62,12 @@ 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 = JSON.iconv('utf-16be', 'utf-8', c).unpack('H*')[0] s.gsub!(/.{4}/n, '\\\\u\&') } string.force_encoding(::Encoding::UTF_8) string - rescue Iconv::Failure => e + rescue => e raise GeneratorError, "Caught #{e.class}: #{e}" end else @@ -86,11 +86,11 @@ 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 = JSON.iconv('utf-16be', 'utf-8', c).unpack('H*')[0] s.gsub!(/.{4}/n, '\\\\u\&') } string - rescue Iconv::Failure => e + rescue => e raise GeneratorError, "Caught #{e.class}: #{e}" end end diff --git a/lib/json/pure/parser.rb b/lib/json/pure/parser.rb index 844931b..c166749 100644 --- a/lib/json/pure/parser.rb +++ b/lib/json/pure/parser.rb @@ -178,7 +178,7 @@ module JSON bytes << c[6 * i + 2, 2].to_i(16) << c[6 * i + 4, 2].to_i(16) i += 1 end - JSON::UTF16toUTF8.iconv(bytes) + JSON.iconv('utf-8', 'utf-16be', bytes) end end if string.respond_to?(:force_encoding) @@ -188,8 +188,8 @@ module JSON else UNPARSED end - rescue Iconv::Failure => e - raise GeneratorError, "Caught #{e.class}: #{e}" + rescue => e + raise ParserError, "Caught #{e.class}: #{e}" end def parse_value diff --git a/tests/test_json_fixtures.rb b/tests/test_json_fixtures.rb index 95e57eb..378667f 100755 --- a/tests/test_json_fixtures.rb +++ b/tests/test_json_fixtures.rb @@ -18,15 +18,20 @@ class TC_JSONFixtures < Test::Unit::TestCase def test_passing for name, source in @passed - assert JSON.parse(source), - "Did not pass for fixture '#{name}'" + begin + assert JSON.parse(source), + "Did not pass for fixture '#{name}': #{source.inspect}" + rescue => e + warn "\nCaught #{e.class}(#{e}) for fixture '#{name}': #{source.inspect}\n#{e.backtrace * "\n"}" + raise e + end end end def test_failing for name, source in @failed assert_raises(JSON::ParserError, JSON::NestingError, - "Did not fail for fixture '#{name}'") do + "Did not fail for fixture '#{name}': #{source.inspect}") do JSON.parse(source) end end |