json_pure 1.4.6 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
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
data/json-java.gemspec ADDED
@@ -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
data/lib/json/add/core.rb CHANGED
@@ -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!"
data/lib/json/common.rb CHANGED
@@ -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
 
data/lib/json/editor.rb CHANGED
@@ -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
data/lib/json/ext.rb CHANGED
@@ -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
data/lib/json/pure.rb CHANGED
@@ -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)
data/lib/json/version.rb CHANGED
@@ -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
data/tests/test_json.rb CHANGED
@@ -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)