json 1.4.6 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of json might be problematic. Click here for more details.

Files changed (48) hide show
  1. data/CHANGES +6 -0
  2. data/COPYING-json-jruby +57 -0
  3. data/README-json-jruby.markdown +33 -0
  4. data/Rakefile +224 -119
  5. data/VERSION +1 -1
  6. data/benchmarks/generator2_benchmark.rb +1 -1
  7. data/benchmarks/generator_benchmark.rb +1 -1
  8. data/ext/json/ext/generator/generator.c +20 -20
  9. data/ext/json/ext/generator/generator.h +7 -7
  10. data/ext/json/ext/parser/extconf.rb +1 -0
  11. data/ext/json/ext/parser/parser.c +122 -88
  12. data/ext/json/ext/parser/parser.h +7 -0
  13. data/ext/json/ext/parser/parser.rl +54 -20
  14. data/java/lib/bytelist-1.0.6.jar +0 -0
  15. data/java/lib/jcodings.jar +0 -0
  16. data/java/src/json/ext/ByteListTranscoder.java +167 -0
  17. data/java/src/json/ext/Generator.java +441 -0
  18. data/java/src/json/ext/GeneratorMethods.java +231 -0
  19. data/java/src/json/ext/GeneratorService.java +42 -0
  20. data/java/src/json/ext/GeneratorState.java +473 -0
  21. data/java/src/json/ext/OptionsReader.java +119 -0
  22. data/java/src/json/ext/Parser.java +2295 -0
  23. data/java/src/json/ext/Parser.rl +825 -0
  24. data/java/src/json/ext/ParserService.java +34 -0
  25. data/java/src/json/ext/RuntimeInfo.java +119 -0
  26. data/java/src/json/ext/StringDecoder.java +166 -0
  27. data/java/src/json/ext/StringEncoder.java +106 -0
  28. data/java/src/json/ext/Utils.java +89 -0
  29. data/json-java.gemspec +20 -0
  30. data/lib/json/add/core.rb +1 -2
  31. data/lib/json/add/rails.rb +4 -54
  32. data/lib/json/common.rb +36 -8
  33. data/lib/json/editor.rb +1 -3
  34. data/lib/json/ext.rb +2 -2
  35. data/lib/json/pure.rb +2 -64
  36. data/lib/json/pure/generator.rb +10 -8
  37. data/lib/json/pure/parser.rb +23 -12
  38. data/lib/json/version.rb +1 -1
  39. data/tests/setup_variant.rb +11 -0
  40. data/tests/test_json.rb +1 -5
  41. data/tests/test_json_addition.rb +14 -9
  42. data/tests/test_json_encoding.rb +9 -12
  43. data/tests/test_json_fixtures.rb +9 -8
  44. data/tests/test_json_generate.rb +3 -5
  45. data/tests/test_json_string_matching.rb +40 -0
  46. data/tests/test_json_unicode.rb +1 -5
  47. metadata +51 -13
  48. data/tests/test_json_rails.rb +0 -144
@@ -0,0 +1,20 @@
1
+ #! /usr/bin/env jruby
2
+ require "rubygems"
3
+
4
+ spec = Gem::Specification.new do |s|
5
+ s.name = "json"
6
+ s.version = File.read("VERSION").chomp
7
+ s.summary = "JSON implementation for JRuby"
8
+ s.description = "A JSON implementation as a JRuby extension."
9
+ s.author = "Daniel Luz"
10
+ s.email = "dev+ruby@mernen.com"
11
+ s.homepage = "http://json-jruby.rubyforge.org/"
12
+ s.platform = 'java'
13
+ s.rubyforge_project = "json-jruby"
14
+
15
+ s.files = Dir["{docs,lib,tests}/**/*"]
16
+ end
17
+
18
+ if $0 == __FILE__
19
+ Gem::Builder.new(spec).build
20
+ end
@@ -1,8 +1,7 @@
1
1
  # This file contains implementations of ruby core's custom objects for
2
2
  # serialisation/deserialisation.
3
3
 
4
- unless Object.const_defined?(:JSON) and ::JSON.const_defined?(:JSON_LOADED) and
5
- ::JSON::JSON_LOADED
4
+ unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
6
5
  require 'json'
7
6
  end
8
7
  require 'date'
@@ -1,58 +1,8 @@
1
- # This file contains implementations of rails custom objects for
2
- # serialisation/deserialisation.
1
+ # This file used to implementations of rails custom objects for
2
+ # serialisation/deserialisation and is obsoleted now.
3
3
 
4
- unless Object.const_defined?(:JSON) and ::JSON.const_defined?(:JSON_LOADED) and
5
- ::JSON::JSON_LOADED
4
+ unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
6
5
  require 'json'
7
6
  end
8
7
 
9
- class Object
10
- def self.json_create(object)
11
- obj = new
12
- for key, value in object
13
- next if key == JSON.create_id
14
- instance_variable_set "@#{key}", value
15
- end
16
- obj
17
- end
18
-
19
- def to_json(*a)
20
- result = {
21
- JSON.create_id => self.class.name
22
- }
23
- instance_variables.inject(result) do |r, name|
24
- r[name[1..-1]] = instance_variable_get name
25
- r
26
- end
27
- result.to_json(*a)
28
- end
29
- end
30
-
31
- class Symbol
32
- def to_json(*a)
33
- to_s.to_json(*a)
34
- end
35
- end
36
-
37
- module Enumerable
38
- def to_json(*a)
39
- to_a.to_json(*a)
40
- end
41
- end
42
-
43
- # class Regexp
44
- # def to_json(*)
45
- # inspect
46
- # end
47
- # end
48
- #
49
- # The above rails definition has some problems:
50
- #
51
- # 1. { 'foo' => /bar/ }.to_json # => "{foo: /bar/}"
52
- # This isn't valid JSON, because the regular expression syntax is not
53
- # defined in RFC 4627. (And unquoted strings are disallowed there, too.)
54
- # Though it is valid Javascript.
55
- #
56
- # 2. { 'foo' => /bar/mix }.to_json # => "{foo: /bar/mix}"
57
- # This isn't even valid Javascript.
58
-
8
+ $DEBUG and warn "required json/add/rails which is obsolete now!"
@@ -1,5 +1,4 @@
1
1
  require 'json/version'
2
- require 'iconv'
3
2
 
4
3
  module JSON
5
4
  class << self
@@ -24,7 +23,7 @@ module JSON
24
23
  # Set the JSON parser class _parser_ to be used by JSON.
25
24
  def parser=(parser) # :nodoc:
26
25
  @parser = parser
27
- remove_const :Parser if const_defined? :Parser
26
+ remove_const :Parser if JSON.const_defined_in?(self, :Parser)
28
27
  const_set :Parser, parser
29
28
  end
30
29
 
@@ -35,13 +34,13 @@ module JSON
35
34
  def deep_const_get(path) # :nodoc:
36
35
  path.to_s.split(/::/).inject(Object) do |p, c|
37
36
  case
38
- when c.empty? then p
39
- when p.const_defined?(c) then p.const_get(c)
37
+ when c.empty? then p
38
+ when JSON.const_defined_in?(p, c) then p.const_get(c)
40
39
  else
41
40
  begin
42
41
  p.const_missing(c)
43
- rescue NameError
44
- raise ArgumentError, "can't find const #{path}"
42
+ rescue NameError => e
43
+ raise ArgumentError, "can't get const #{path}: #{e}"
45
44
  end
46
45
  end
47
46
  end
@@ -49,6 +48,7 @@ module JSON
49
48
 
50
49
  # Set the module _generator_ to be used by JSON.
51
50
  def generator=(generator) # :nodoc:
51
+ old, $VERBOSE = $VERBOSE, nil
52
52
  @generator = generator
53
53
  generator_methods = generator::GeneratorMethods
54
54
  for const in generator_methods.constants
@@ -77,6 +77,8 @@ module JSON
77
77
  :object_nl => "\n",
78
78
  :array_nl => "\n"
79
79
  )
80
+ ensure
81
+ $VERBOSE = old
80
82
  end
81
83
 
82
84
  # Returns the JSON generator modul, that is used by JSON. This might be
@@ -338,9 +340,35 @@ module JSON
338
340
  raise ArgumentError, "exceed depth limit"
339
341
  end
340
342
 
343
+ # Swap consecutive bytes of _string_ in place.
344
+ def self.swap!(string) # :nodoc:
345
+ 0.upto(string.size / 2) do |i|
346
+ break unless string[2 * i + 1]
347
+ string[2 * i], string[2 * i + 1] = string[2 * i + 1], string[2 * i]
348
+ end
349
+ string
350
+ end
351
+
341
352
  # Shortuct for iconv.
342
- def self.iconv(to, from, string)
343
- Iconv.iconv(to, from, string).first
353
+ if ::String.method_defined?(:encode)
354
+ def self.iconv(to, from, string)
355
+ string.encode(to, from)
356
+ end
357
+ else
358
+ require 'iconv'
359
+ def self.iconv(to, from, string)
360
+ Iconv.iconv(to, from, string).first
361
+ end
362
+ end
363
+
364
+ if ::Object.method(:const_defined?).arity == 1
365
+ def self.const_defined_in?(modul, constant)
366
+ modul.const_defined?(constant)
367
+ end
368
+ else
369
+ def self.const_defined_in?(modul, constant)
370
+ modul.const_defined?(constant, false)
371
+ end
344
372
  end
345
373
  end
346
374
 
@@ -2,7 +2,6 @@
2
2
  # requires ruby-gtk to be installed.
3
3
 
4
4
  require 'gtk2'
5
- require 'iconv'
6
5
  require 'json'
7
6
  require 'rbconfig'
8
7
  require 'open-uri'
@@ -1272,8 +1271,7 @@ module JSON
1272
1271
  def parse_json(json)
1273
1272
  check_pretty_printed(json)
1274
1273
  if @encoding && !/^utf8$/i.match(@encoding)
1275
- iconverter = Iconv.new('utf8', @encoding)
1276
- json = iconverter.iconv(json)
1274
+ json = JSON.iconv 'utf-8', @encoding, json
1277
1275
  end
1278
1276
  JSON::parse(json, :max_nesting => false, :create_additions => false)
1279
1277
  end
@@ -6,10 +6,10 @@ module JSON
6
6
  module Ext
7
7
  require 'json/ext/parser'
8
8
  require 'json/ext/generator'
9
- $DEBUG and warn "Using c extension for JSON."
9
+ $DEBUG and warn "Using Ext extension for JSON."
10
10
  JSON.parser = Parser
11
11
  JSON.generator = Generator
12
12
  end
13
13
 
14
- JSON_LOADED = true
14
+ JSON_LOADED = true unless defined?(::JSON::JSON_LOADED)
15
15
  end
@@ -3,75 +3,13 @@ require 'json/pure/parser'
3
3
  require 'json/pure/generator'
4
4
 
5
5
  module JSON
6
- begin
7
- require 'iconv'
8
- # An iconv instance to convert from UTF8 to UTF16 Big Endian.
9
- UTF16toUTF8 = Iconv.new('utf-8', 'utf-16be') # :nodoc:
10
- # An iconv instance to convert from UTF16 Big Endian to UTF8.
11
- UTF8toUTF16 = Iconv.new('utf-16be', 'utf-8') # :nodoc:
12
- UTF8toUTF16.iconv('no bom')
13
- rescue LoadError
14
- raise MissingUnicodeSupport,
15
- "iconv couldn't be loaded, which is required for UTF-8/UTF-16 conversions"
16
- rescue Errno::EINVAL, Iconv::InvalidEncoding
17
- # Iconv doesn't support big endian utf-16. Let's try to hack this manually
18
- # into the converters.
19
- begin
20
- old_verbose, $VERBSOSE = $VERBOSE, nil
21
- # An iconv instance to convert from UTF8 to UTF16 Big Endian.
22
- UTF16toUTF8 = Iconv.new('utf-8', 'utf-16') # :nodoc:
23
- # An iconv instance to convert from UTF16 Big Endian to UTF8.
24
- UTF8toUTF16 = Iconv.new('utf-16', 'utf-8') # :nodoc:
25
- UTF8toUTF16.iconv('no bom')
26
- if UTF8toUTF16.iconv("\xe2\x82\xac") == "\xac\x20"
27
- swapper = Class.new do
28
- def initialize(iconv) # :nodoc:
29
- @iconv = iconv
30
- end
31
-
32
- def iconv(string) # :nodoc:
33
- result = @iconv.iconv(string)
34
- JSON.swap!(result)
35
- end
36
- end
37
- UTF8toUTF16 = swapper.new(UTF8toUTF16) # :nodoc:
38
- end
39
- if UTF16toUTF8.iconv("\xac\x20") == "\xe2\x82\xac"
40
- swapper = Class.new do
41
- def initialize(iconv) # :nodoc:
42
- @iconv = iconv
43
- end
44
-
45
- def iconv(string) # :nodoc:
46
- string = JSON.swap!(string.dup)
47
- @iconv.iconv(string)
48
- end
49
- end
50
- UTF16toUTF8 = swapper.new(UTF16toUTF8) # :nodoc:
51
- end
52
- rescue Errno::EINVAL, Iconv::InvalidEncoding
53
- raise MissingUnicodeSupport, "iconv doesn't seem to support UTF-8/UTF-16 conversions"
54
- ensure
55
- $VERBOSE = old_verbose
56
- end
57
- end
58
-
59
- # Swap consecutive bytes of _string_ in place.
60
- def self.swap!(string) # :nodoc:
61
- 0.upto(string.size / 2) do |i|
62
- break unless string[2 * i + 1]
63
- string[2 * i], string[2 * i + 1] = string[2 * i + 1], string[2 * i]
64
- end
65
- string
66
- end
67
-
68
6
  # This module holds all the modules/classes that implement JSON's
69
7
  # functionality in pure ruby.
70
8
  module Pure
71
- $DEBUG and warn "Using pure library for JSON."
9
+ $DEBUG and warn "Using Pure library for JSON."
72
10
  JSON.parser = Parser
73
11
  JSON.generator = Generator
74
12
  end
75
13
 
76
- JSON_LOADED = true
14
+ JSON_LOADED = true unless defined?(::JSON::JSON_LOADED)
77
15
  end
@@ -62,12 +62,12 @@ module JSON
62
62
  [\x80-\xc1\xf5-\xff] # invalid
63
63
  )/nx) { |c|
64
64
  c.size == 1 and raise GeneratorError, "invalid utf8 byte: '#{c}'"
65
- s = JSON::UTF8toUTF16.iconv(c).unpack('H*')[0]
65
+ s = JSON.iconv('utf-16be', 'utf-8', c).unpack('H*')[0]
66
66
  s.gsub!(/.{4}/n, '\\\\u\&')
67
67
  }
68
68
  string.force_encoding(::Encoding::UTF_8)
69
69
  string
70
- rescue Iconv::Failure => e
70
+ rescue => e
71
71
  raise GeneratorError, "Caught #{e.class}: #{e}"
72
72
  end
73
73
  else
@@ -86,11 +86,11 @@ module JSON
86
86
  [\x80-\xc1\xf5-\xff] # invalid
87
87
  )/nx) { |c|
88
88
  c.size == 1 and raise GeneratorError, "invalid utf8 byte: '#{c}'"
89
- s = JSON::UTF8toUTF16.iconv(c).unpack('H*')[0]
89
+ s = JSON.iconv('utf-16be', 'utf-8', c).unpack('H*')[0]
90
90
  s.gsub!(/.{4}/n, '\\\\u\&')
91
91
  }
92
92
  string
93
- rescue Iconv::Failure => e
93
+ rescue => e
94
94
  raise GeneratorError, "Caught #{e.class}: #{e}"
95
95
  end
96
96
  end
@@ -106,11 +106,13 @@ module JSON
106
106
  # an unconfigured instance. If _opts_ is a State object, it is just
107
107
  # returned.
108
108
  def self.from_state(opts)
109
- case opts
110
- when self
109
+ case
110
+ when self === opts
111
111
  opts
112
- when Hash
113
- new(opts)
112
+ when opts.respond_to?(:to_hash)
113
+ new(opts.to_hash)
114
+ when opts.respond_to?(:to_h)
115
+ new(opts.to_h)
114
116
  else
115
117
  SAFE_STATE_PROTOTYPE.dup
116
118
  end
@@ -113,13 +113,13 @@ module JSON
113
113
  else
114
114
  @max_nesting = 0
115
115
  end
116
- @allow_nan = !!opts[:allow_nan]
117
- @symbolize_names = !!opts[:symbolize_names]
118
- ca = true
119
- ca = opts[:create_additions] if opts.key?(:create_additions)
120
- @create_id = ca ? JSON.create_id : nil
121
- @object_class = opts[:object_class] || Hash
122
- @array_class = opts[:array_class] || Array
116
+ @allow_nan = !!opts[:allow_nan]
117
+ @symbolize_names = !!opts[:symbolize_names]
118
+ @create_additions = opts.key?(:create_additions) ? !!opts[:create_additions] : true
119
+ @create_id = opts[:create_id] || JSON.create_id
120
+ @object_class = opts[:object_class] || Hash
121
+ @array_class = opts[:array_class] || Array
122
+ @match_string = opts[:match_string]
123
123
  end
124
124
 
125
125
  alias source string
@@ -165,6 +165,11 @@ module JSON
165
165
  ?u => nil,
166
166
  })
167
167
 
168
+ EMPTY_8BIT_STRING = ''
169
+ if ::String.method_defined?(:encode)
170
+ EMPTY_8BIT_STRING.force_encoding Encoding::ASCII_8BIT
171
+ end
172
+
168
173
  def parse_string
169
174
  if scan(STRING)
170
175
  return '' if self[1].empty?
@@ -172,24 +177,30 @@ module JSON
172
177
  if u = UNESCAPE_MAP[$&[1]]
173
178
  u
174
179
  else # \uXXXX
175
- bytes = ''
180
+ bytes = EMPTY_8BIT_STRING.dup
176
181
  i = 0
177
182
  while c[6 * i] == ?\\ && c[6 * i + 1] == ?u
178
183
  bytes << c[6 * i + 2, 2].to_i(16) << c[6 * i + 4, 2].to_i(16)
179
184
  i += 1
180
185
  end
181
- JSON::UTF16toUTF8.iconv(bytes)
186
+ JSON.iconv('utf-8', 'utf-16be', bytes)
182
187
  end
183
188
  end
184
189
  if string.respond_to?(:force_encoding)
185
190
  string.force_encoding(::Encoding::UTF_8)
186
191
  end
192
+ if @create_additions and @match_string
193
+ for (regexp, klass) in @match_string
194
+ klass.json_creatable? or next
195
+ string =~ regexp and return klass.json_create(string)
196
+ end
197
+ end
187
198
  string
188
199
  else
189
200
  UNPARSED
190
201
  end
191
- rescue Iconv::Failure => e
192
- raise GeneratorError, "Caught #{e.class}: #{e}"
202
+ rescue => e
203
+ raise ParserError, "Caught #{e.class} at '#{peek(20)}': #{e}"
193
204
  end
194
205
 
195
206
  def parse_value
@@ -290,7 +301,7 @@ module JSON
290
301
  if delim
291
302
  raise ParserError, "expected next name, value pair in object at '#{peek(20)}'!"
292
303
  end
293
- if @create_id and klassname = result[@create_id]
304
+ if @create_additions and klassname = result[@create_id]
294
305
  klass = JSON.deep_const_get klassname
295
306
  break unless klass and klass.json_creatable?
296
307
  result = klass.json_create(result)
@@ -1,6 +1,6 @@
1
1
  module JSON
2
2
  # JSON version
3
- VERSION = '1.4.6'
3
+ VERSION = '1.5.0'
4
4
  VERSION_ARRAY = VERSION.split(/\./).map { |x| x.to_i } # :nodoc:
5
5
  VERSION_MAJOR = VERSION_ARRAY[0] # :nodoc:
6
6
  VERSION_MINOR = VERSION_ARRAY[1] # :nodoc:
@@ -0,0 +1,11 @@
1
+ case ENV['JSON']
2
+ when 'pure'
3
+ $:.unshift 'lib'
4
+ require 'json/pure'
5
+ when 'ext'
6
+ $:.unshift 'ext', 'lib'
7
+ require 'json/ext'
8
+ else
9
+ $:.unshift 'ext', 'lib'
10
+ require 'json'
11
+ end
@@ -2,11 +2,7 @@
2
2
  # -*- coding: utf-8 -*-
3
3
 
4
4
  require 'test/unit'
5
- case ENV['JSON']
6
- when 'pure' then require 'json/pure'
7
- when 'ext' then require 'json/ext'
8
- else require 'json'
9
- end
5
+ require File.join(File.dirname(__FILE__), 'setup_variant')
10
6
  require 'stringio'
11
7
 
12
8
  unless Array.method_defined?(:permutation)