json 1.7.0 → 2.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (88) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +7 -0
  3. data/.travis.yml +18 -10
  4. data/{CHANGES → CHANGES.md} +217 -69
  5. data/Gemfile +11 -12
  6. data/{COPYING-json-jruby → LICENSE} +5 -6
  7. data/{README-json-jruby.markdown → README-json-jruby.md} +0 -0
  8. data/{README.rdoc → README.md} +188 -137
  9. data/Rakefile +52 -37
  10. data/VERSION +1 -1
  11. data/ext/json/ext/fbuffer/fbuffer.h +38 -7
  12. data/ext/json/ext/generator/depend +1 -0
  13. data/ext/json/ext/generator/extconf.rb +1 -10
  14. data/ext/json/ext/generator/generator.c +239 -133
  15. data/ext/json/ext/generator/generator.h +35 -26
  16. data/ext/json/ext/parser/depend +1 -0
  17. data/ext/json/ext/parser/extconf.rb +2 -9
  18. data/ext/json/ext/parser/parser.c +446 -514
  19. data/ext/json/ext/parser/parser.h +23 -9
  20. data/ext/json/ext/parser/parser.rl +177 -208
  21. data/ext/json/extconf.rb +2 -0
  22. data/java/src/json/ext/ByteListTranscoder.java +1 -2
  23. data/java/src/json/ext/Generator.java +49 -20
  24. data/java/src/json/ext/GeneratorMethods.java +1 -2
  25. data/java/src/json/ext/GeneratorService.java +1 -2
  26. data/java/src/json/ext/GeneratorState.java +25 -57
  27. data/java/src/json/ext/OptionsReader.java +5 -5
  28. data/java/src/json/ext/Parser.java +141 -419
  29. data/java/src/json/ext/Parser.rl +57 -128
  30. data/java/src/json/ext/ParserService.java +1 -2
  31. data/java/src/json/ext/RuntimeInfo.java +1 -6
  32. data/java/src/json/ext/StringDecoder.java +1 -2
  33. data/java/src/json/ext/StringEncoder.java +5 -0
  34. data/java/src/json/ext/Utils.java +1 -2
  35. data/json-java.gemspec +17 -2
  36. data/json.gemspec +0 -0
  37. data/json_pure.gemspec +25 -26
  38. data/lib/json.rb +3 -2
  39. data/lib/json/add/bigdecimal.rb +10 -2
  40. data/lib/json/add/complex.rb +9 -2
  41. data/lib/json/add/core.rb +1 -0
  42. data/lib/json/add/date.rb +1 -1
  43. data/lib/json/add/date_time.rb +1 -1
  44. data/lib/json/add/exception.rb +1 -1
  45. data/lib/json/add/ostruct.rb +3 -3
  46. data/lib/json/add/range.rb +1 -1
  47. data/lib/json/add/rational.rb +8 -2
  48. data/lib/json/add/regexp.rb +3 -3
  49. data/lib/json/add/set.rb +29 -0
  50. data/lib/json/add/struct.rb +1 -1
  51. data/lib/json/add/symbol.rb +1 -1
  52. data/lib/json/add/time.rb +6 -3
  53. data/lib/json/common.rb +51 -66
  54. data/lib/json/ext.rb +0 -6
  55. data/lib/json/generic_object.rb +36 -4
  56. data/lib/json/pure.rb +2 -8
  57. data/lib/json/pure/generator.rb +106 -119
  58. data/lib/json/pure/parser.rb +48 -88
  59. data/lib/json/version.rb +2 -1
  60. data/references/rfc7159.txt +899 -0
  61. data/tests/fixtures/fail18.json +1 -1
  62. data/tests/fixtures/obsolete_fail1.json +1 -0
  63. data/tests/{test_json_addition.rb → json_addition_test.rb} +53 -38
  64. data/tests/json_common_interface_test.rb +126 -0
  65. data/tests/json_encoding_test.rb +107 -0
  66. data/tests/json_ext_parser_test.rb +15 -0
  67. data/tests/{test_json_fixtures.rb → json_fixtures_test.rb} +5 -8
  68. data/tests/json_generator_test.rb +421 -0
  69. data/tests/json_generic_object_test.rb +82 -0
  70. data/tests/json_parser_test.rb +472 -0
  71. data/tests/json_string_matching_test.rb +38 -0
  72. data/tests/{setup_variant.rb → test_helper.rb} +6 -0
  73. data/tools/diff.sh +18 -0
  74. data/tools/fuzz.rb +1 -9
  75. metadata +49 -72
  76. data/COPYING +0 -58
  77. data/GPL +0 -340
  78. data/TODO +0 -1
  79. data/data/example.json +0 -1
  80. data/data/index.html +0 -38
  81. data/data/prototype.js +0 -4184
  82. data/tests/fixtures/fail1.json +0 -1
  83. data/tests/test_json.rb +0 -539
  84. data/tests/test_json_encoding.rb +0 -65
  85. data/tests/test_json_generate.rb +0 -251
  86. data/tests/test_json_generic_object.rb +0 -35
  87. data/tests/test_json_string_matching.rb +0 -40
  88. data/tests/test_json_unicode.rb +0 -72
data/lib/json/ext.rb CHANGED
@@ -1,9 +1,3 @@
1
- if ENV['SIMPLECOV_COVERAGE'].to_i == 1
2
- require 'simplecov'
3
- SimpleCov.start do
4
- add_filter "/tests/"
5
- end
6
- end
7
1
  require 'json/common'
8
2
 
9
3
  module JSON
@@ -1,3 +1,4 @@
1
+ #frozen_string_literal: false
1
2
  require 'ostruct'
2
3
 
3
4
  module JSON
@@ -5,24 +6,55 @@ module JSON
5
6
  class << self
6
7
  alias [] new
7
8
 
9
+ def json_creatable?
10
+ @json_creatable
11
+ end
12
+
13
+ attr_writer :json_creatable
14
+
8
15
  def json_create(data)
9
16
  data = data.dup
10
17
  data.delete JSON.create_id
11
18
  self[data]
12
19
  end
20
+
21
+ def from_hash(object)
22
+ case
23
+ when object.respond_to?(:to_hash)
24
+ result = new
25
+ object.to_hash.each do |key, value|
26
+ result[key] = from_hash(value)
27
+ end
28
+ result
29
+ when object.respond_to?(:to_ary)
30
+ object.to_ary.map { |a| from_hash(a) }
31
+ else
32
+ object
33
+ end
34
+ end
35
+
36
+ def load(source, proc = nil, opts = {})
37
+ result = ::JSON.load(source, proc, opts.merge(:object_class => self))
38
+ result.nil? ? new : result
39
+ end
40
+
41
+ def dump(obj, *args)
42
+ ::JSON.dump(obj, *args)
43
+ end
13
44
  end
45
+ self.json_creatable = false
14
46
 
15
47
  def to_hash
16
48
  table
17
49
  end
18
50
 
19
51
  def [](name)
20
- table[name.to_sym]
21
- end
52
+ __send__(name)
53
+ end unless method_defined?(:[])
22
54
 
23
55
  def []=(name, value)
24
- __send__ "#{name}=", value
25
- end
56
+ __send__("#{name}=", value)
57
+ end unless method_defined?(:[]=)
26
58
 
27
59
  def |(other)
28
60
  self.class[other.to_hash.merge(to_hash)]
data/lib/json/pure.rb CHANGED
@@ -1,17 +1,11 @@
1
- if ENV['SIMPLECOV_COVERAGE'].to_i == 1
2
- require 'simplecov'
3
- SimpleCov.start do
4
- add_filter "/tests/"
5
- end
6
- end
7
1
  require 'json/common'
8
- require 'json/pure/parser'
9
- require 'json/pure/generator'
10
2
 
11
3
  module JSON
12
4
  # This module holds all the modules/classes that implement JSON's
13
5
  # functionality in pure ruby.
14
6
  module Pure
7
+ require 'json/pure/parser'
8
+ require 'json/pure/generator'
15
9
  $DEBUG and warn "Using Pure library for JSON."
16
10
  JSON.parser = Parser
17
11
  JSON.generator = Generator
@@ -1,3 +1,4 @@
1
+ #frozen_string_literal: false
1
2
  module JSON
2
3
  MAP = {
3
4
  "\x0" => '\u0000',
@@ -38,63 +39,44 @@ module JSON
38
39
 
39
40
  # Convert a UTF8 encoded Ruby string _string_ to a JSON string, encoded with
40
41
  # UTF16 big endian characters as \u????, and return it.
41
- if defined?(::Encoding)
42
- def utf8_to_json(string) # :nodoc:
43
- string = string.dup
44
- string << '' # XXX workaround: avoid buffer sharing
45
- string.force_encoding(::Encoding::ASCII_8BIT)
46
- string.gsub!(/["\\\x0-\x1f]/) { MAP[$&] }
47
- string.force_encoding(::Encoding::UTF_8)
48
- string
49
- end
42
+ def utf8_to_json(string) # :nodoc:
43
+ string = string.dup
44
+ string.force_encoding(::Encoding::ASCII_8BIT)
45
+ string.gsub!(/["\\\x0-\x1f]/) { MAP[$&] }
46
+ string.force_encoding(::Encoding::UTF_8)
47
+ string
48
+ end
50
49
 
51
- def utf8_to_json_ascii(string) # :nodoc:
52
- string = string.dup
53
- string << '' # XXX workaround: avoid buffer sharing
54
- string.force_encoding(::Encoding::ASCII_8BIT)
55
- string.gsub!(/["\\\x0-\x1f]/) { MAP[$&] }
56
- string.gsub!(/(
57
- (?:
58
- [\xc2-\xdf][\x80-\xbf] |
59
- [\xe0-\xef][\x80-\xbf]{2} |
60
- [\xf0-\xf4][\x80-\xbf]{3}
61
- )+ |
62
- [\x80-\xc1\xf5-\xff] # invalid
63
- )/nx) { |c|
64
- c.size == 1 and raise GeneratorError, "invalid utf8 byte: '#{c}'"
65
- s = JSON.iconv('utf-16be', 'utf-8', c).unpack('H*')[0]
66
- s.gsub!(/.{4}/n, '\\\\u\&')
67
- }
68
- string.force_encoding(::Encoding::UTF_8)
69
- string
70
- rescue => e
71
- raise GeneratorError, "Caught #{e.class}: #{e}"
72
- end
73
- else
74
- def utf8_to_json(string) # :nodoc:
75
- string.gsub(/["\\\x0-\x1f]/) { MAP[$&] }
76
- end
50
+ def utf8_to_json_ascii(string) # :nodoc:
51
+ string = string.dup
52
+ string.force_encoding(::Encoding::ASCII_8BIT)
53
+ string.gsub!(/["\\\x0-\x1f]/n) { MAP[$&] }
54
+ string.gsub!(/(
55
+ (?:
56
+ [\xc2-\xdf][\x80-\xbf] |
57
+ [\xe0-\xef][\x80-\xbf]{2} |
58
+ [\xf0-\xf4][\x80-\xbf]{3}
59
+ )+ |
60
+ [\x80-\xc1\xf5-\xff] # invalid
61
+ )/nx) { |c|
62
+ c.size == 1 and raise GeneratorError, "invalid utf8 byte: '#{c}'"
63
+ s = JSON.iconv('utf-16be', 'utf-8', c).unpack('H*')[0]
64
+ s.force_encoding(::Encoding::ASCII_8BIT)
65
+ s.gsub!(/.{4}/n, '\\\\u\&')
66
+ s.force_encoding(::Encoding::UTF_8)
67
+ }
68
+ string.force_encoding(::Encoding::UTF_8)
69
+ string
70
+ rescue => e
71
+ raise GeneratorError.wrap(e)
72
+ end
77
73
 
78
- def utf8_to_json_ascii(string) # :nodoc:
79
- string = string.gsub(/["\\\x0-\x1f]/) { MAP[$&] }
80
- string.gsub!(/(
81
- (?:
82
- [\xc2-\xdf][\x80-\xbf] |
83
- [\xe0-\xef][\x80-\xbf]{2} |
84
- [\xf0-\xf4][\x80-\xbf]{3}
85
- )+ |
86
- [\x80-\xc1\xf5-\xff] # invalid
87
- )/nx) { |c|
88
- c.size == 1 and raise GeneratorError, "invalid utf8 byte: '#{c}'"
89
- s = JSON.iconv('utf-16be', 'utf-8', c).unpack('H*')[0]
90
- s.gsub!(/.{4}/n, '\\\\u\&')
91
- }
92
- string
93
- rescue => e
94
- raise GeneratorError, "Caught #{e.class}: #{e}"
95
- end
74
+ def valid_utf8?(string)
75
+ encoding = string.encoding
76
+ (encoding == Encoding::UTF_8 || encoding == Encoding::ASCII) &&
77
+ string.valid_encoding?
96
78
  end
97
- module_function :utf8_to_json, :utf8_to_json_ascii
79
+ module_function :utf8_to_json, :utf8_to_json_ascii, :valid_utf8?
98
80
 
99
81
  module Pure
100
82
  module Generator
@@ -133,8 +115,6 @@ module JSON
133
115
  # * *allow_nan*: true if NaN, Infinity, and -Infinity should be
134
116
  # generated, otherwise an exception is thrown, if these values are
135
117
  # encountered. This options defaults to false.
136
- # * *quirks_mode*: Enables quirks_mode for parser, that is for example
137
- # generating single JSON values instead of documents is possible.
138
118
  def initialize(opts = {})
139
119
  @indent = ''
140
120
  @space = ''
@@ -143,7 +123,6 @@ module JSON
143
123
  @array_nl = ''
144
124
  @allow_nan = false
145
125
  @ascii_only = false
146
- @quirks_mode = false
147
126
  @buffer_initial_length = 1024
148
127
  configure opts
149
128
  end
@@ -169,10 +148,6 @@ module JSON
169
148
  # the generated JSON, max_nesting = 0 if no maximum is checked.
170
149
  attr_accessor :max_nesting
171
150
 
172
- # If this attribute is set to true, quirks mode is enabled, otherwise
173
- # it's disabled.
174
- attr_accessor :quirks_mode
175
-
176
151
  # :stopdoc:
177
152
  attr_reader :buffer_initial_length
178
153
 
@@ -212,25 +187,31 @@ module JSON
212
187
  @ascii_only
213
188
  end
214
189
 
215
- # Returns true, if quirks mode is enabled. Otherwise returns false.
216
- def quirks_mode?
217
- @quirks_mode
218
- end
219
-
220
190
  # Configure this State instance with the Hash _opts_, and return
221
191
  # itself.
222
192
  def configure(opts)
223
- @indent = opts[:indent] if opts.key?(:indent)
224
- @space = opts[:space] if opts.key?(:space)
225
- @space_before = opts[:space_before] if opts.key?(:space_before)
226
- @object_nl = opts[:object_nl] if opts.key?(:object_nl)
227
- @array_nl = opts[:array_nl] if opts.key?(:array_nl)
228
- @allow_nan = !!opts[:allow_nan] if opts.key?(:allow_nan)
229
- @ascii_only = opts[:ascii_only] if opts.key?(:ascii_only)
230
- @depth = opts[:depth] || 0
231
- @quirks_mode = opts[:quirks_mode] if opts.key?(:quirks_mode)
232
- if !opts.key?(:max_nesting) # defaults to 19
233
- @max_nesting = 19
193
+ if opts.respond_to?(:to_hash)
194
+ opts = opts.to_hash
195
+ elsif opts.respond_to?(:to_h)
196
+ opts = opts.to_h
197
+ else
198
+ raise TypeError, "can't convert #{opts.class} into Hash"
199
+ end
200
+ for key, value in opts
201
+ instance_variable_set "@#{key}", value
202
+ end
203
+ @indent = opts[:indent] if opts.key?(:indent)
204
+ @space = opts[:space] if opts.key?(:space)
205
+ @space_before = opts[:space_before] if opts.key?(:space_before)
206
+ @object_nl = opts[:object_nl] if opts.key?(:object_nl)
207
+ @array_nl = opts[:array_nl] if opts.key?(:array_nl)
208
+ @allow_nan = !!opts[:allow_nan] if opts.key?(:allow_nan)
209
+ @ascii_only = opts[:ascii_only] if opts.key?(:ascii_only)
210
+ @depth = opts[:depth] || 0
211
+ @buffer_initial_length ||= opts[:buffer_initial_length]
212
+
213
+ if !opts.key?(:max_nesting) # defaults to 100
214
+ @max_nesting = 100
234
215
  elsif opts[:max_nesting]
235
216
  @max_nesting = opts[:max_nesting]
236
217
  else
@@ -244,30 +225,42 @@ module JSON
244
225
  # passed to the configure method.
245
226
  def to_h
246
227
  result = {}
247
- for iv in %w[indent space space_before object_nl array_nl allow_nan max_nesting ascii_only quirks_mode buffer_initial_length depth]
248
- result[iv.intern] = instance_variable_get("@#{iv}")
228
+ for iv in instance_variables
229
+ iv = iv.to_s[1..-1]
230
+ result[iv.to_sym] = self[iv]
249
231
  end
250
232
  result
251
233
  end
252
234
 
253
- # Generates a valid JSON document from object +obj+ and returns the
254
- # result. If no valid JSON document can be created this method raises a
235
+ alias to_hash to_h
236
+
237
+ # Generates a valid JSON document from object +obj+ and
238
+ # returns the result. If no valid JSON document can be
239
+ # created this method raises a
255
240
  # GeneratorError exception.
256
241
  def generate(obj)
257
242
  result = obj.to_json(self)
258
- unless @quirks_mode
259
- unless result =~ /\A\s*\[/ && result =~ /\]\s*\Z/ ||
260
- result =~ /\A\s*\{/ && result =~ /\}\s*\Z/
261
- then
262
- raise GeneratorError, "only generation of JSON objects or arrays allowed"
263
- end
264
- end
243
+ JSON.valid_utf8?(result) or raise GeneratorError,
244
+ "source sequence #{result.inspect} is illegal/malformed utf-8"
265
245
  result
266
246
  end
267
247
 
268
248
  # Return the value returned by method +name+.
269
249
  def [](name)
270
- __send__ name
250
+ if respond_to?(name)
251
+ __send__(name)
252
+ else
253
+ instance_variable_get("@#{name}") if
254
+ instance_variables.include?("@#{name}".to_sym) # avoid warning
255
+ end
256
+ end
257
+
258
+ def []=(name, value)
259
+ if respond_to?(name_writer = "#{name}=")
260
+ __send__ name_writer, value
261
+ else
262
+ instance_variable_set "@#{name}", value
263
+ end
271
264
  end
272
265
  end
273
266
 
@@ -313,12 +306,16 @@ module JSON
313
306
  result << state.space_before
314
307
  result << ':'
315
308
  result << state.space
316
- result << value.to_json(state)
309
+ if value.respond_to?(:to_json)
310
+ result << value.to_json(state)
311
+ else
312
+ result << %{"#{String(value)}"}
313
+ end
317
314
  first = false
318
315
  }
319
316
  depth = state.depth -= 1
320
317
  result << state.object_nl
321
- result << state.indent * depth if indent if indent
318
+ result << state.indent * depth if indent
322
319
  result << '}'
323
320
  result
324
321
  end
@@ -348,7 +345,11 @@ module JSON
348
345
  each { |value|
349
346
  result << delim unless first
350
347
  result << state.indent * depth if indent
351
- result << value.to_json(state)
348
+ if value.respond_to?(:to_json)
349
+ result << value.to_json(state)
350
+ else
351
+ result << %{"#{String(value)}"}
352
+ end
352
353
  first = false
353
354
  }
354
355
  depth = state.depth -= 1
@@ -387,34 +388,20 @@ module JSON
387
388
  end
388
389
 
389
390
  module String
390
- if defined?(::Encoding)
391
- # This string should be encoded with UTF-8 A call to this method
392
- # returns a JSON string encoded with UTF16 big endian characters as
393
- # \u????.
394
- def to_json(state = nil, *args)
395
- state = State.from_state(state)
396
- if encoding == ::Encoding::UTF_8
397
- string = self
398
- else
399
- string = encode(::Encoding::UTF_8)
400
- end
401
- if state.ascii_only?
402
- '"' << JSON.utf8_to_json_ascii(string) << '"'
403
- else
404
- '"' << JSON.utf8_to_json(string) << '"'
405
- end
391
+ # This string should be encoded with UTF-8 A call to this method
392
+ # returns a JSON string encoded with UTF16 big endian characters as
393
+ # \u????.
394
+ def to_json(state = nil, *args)
395
+ state = State.from_state(state)
396
+ if encoding == ::Encoding::UTF_8
397
+ string = self
398
+ else
399
+ string = encode(::Encoding::UTF_8)
406
400
  end
407
- else
408
- # This string should be encoded with UTF-8 A call to this method
409
- # returns a JSON string encoded with UTF16 big endian characters as
410
- # \u????.
411
- def to_json(state = nil, *args)
412
- state = State.from_state(state)
413
- if state.ascii_only?
414
- '"' << JSON.utf8_to_json_ascii(self) << '"'
415
- else
416
- '"' << JSON.utf8_to_json(self) << '"'
417
- end
401
+ if state.ascii_only?
402
+ '"' << JSON.utf8_to_json_ascii(string) << '"'
403
+ else
404
+ '"' << JSON.utf8_to_json(string) << '"'
418
405
  end
419
406
  end
420
407
 
@@ -1,3 +1,4 @@
1
+ #frozen_string_literal: false
1
2
  require 'strscan'
2
3
 
3
4
  module JSON
@@ -48,7 +49,7 @@ module JSON
48
49
  )+
49
50
  )mx
50
51
 
51
- UNPARSED = Object.new
52
+ UNPARSED = Object.new.freeze
52
53
 
53
54
  # Creates a new JSON::Pure::Parser instance for the string _source_.
54
55
  #
@@ -56,28 +57,28 @@ module JSON
56
57
  # keys:
57
58
  # * *max_nesting*: The maximum depth of nesting allowed in the parsed data
58
59
  # structures. Disable depth checking with :max_nesting => false|nil|0,
59
- # it defaults to 19.
60
+ # it defaults to 100.
60
61
  # * *allow_nan*: If set to true, allow NaN, Infinity and -Infinity in
61
- # defiance of RFC 4627 to be parsed by the Parser. This option defaults
62
+ # defiance of RFC 7159 to be parsed by the Parser. This option defaults
62
63
  # to false.
63
64
  # * *symbolize_names*: If set to true, returns symbols for the names
64
- # (keys) in a JSON object. Otherwise strings are returned, which is also
65
- # the default.
66
- # * *create_additions*: If set to false, the Parser doesn't create
67
- # additions even if a matchin class and create_id was found. This option
68
- # defaults to true.
65
+ # (keys) in a JSON object. Otherwise strings are returned, which is
66
+ # also the default. It's not possible to use this option in
67
+ # conjunction with the *create_additions* option.
68
+ # * *create_additions*: If set to true, the Parser creates
69
+ # additions when if a matching class and create_id was found. This
70
+ # option defaults to false.
69
71
  # * *object_class*: Defaults to Hash
70
72
  # * *array_class*: Defaults to Array
71
- # * *quirks_mode*: Enables quirks_mode for parser, that is for example
72
- # parsing single JSON values instead of documents is possible.
73
+ # * *decimal_class*: Specifies which class to use instead of the default
74
+ # (Float) when parsing decimal numbers. This class must accept a single
75
+ # string argument in its constructor.
73
76
  def initialize(source, opts = {})
74
77
  opts ||= {}
75
- unless @quirks_mode = opts[:quirks_mode]
76
- source = convert_encoding source
77
- end
78
+ source = convert_encoding source
78
79
  super source
79
- if !opts.key?(:max_nesting) # defaults to 19
80
- @max_nesting = 19
80
+ if !opts.key?(:max_nesting) # defaults to 100
81
+ @max_nesting = 100
81
82
  elsif opts[:max_nesting]
82
83
  @max_nesting = opts[:max_nesting]
83
84
  else
@@ -88,58 +89,40 @@ module JSON
88
89
  if opts.key?(:create_additions)
89
90
  @create_additions = !!opts[:create_additions]
90
91
  else
91
- @create_additions = true
92
+ @create_additions = false
92
93
  end
94
+ @symbolize_names && @create_additions and raise ArgumentError,
95
+ 'options :symbolize_names and :create_additions cannot be used '\
96
+ 'in conjunction'
93
97
  @create_id = @create_additions ? JSON.create_id : nil
94
98
  @object_class = opts[:object_class] || Hash
95
99
  @array_class = opts[:array_class] || Array
100
+ @decimal_class = opts[:decimal_class]
96
101
  @match_string = opts[:match_string]
97
102
  end
98
103
 
99
104
  alias source string
100
105
 
101
- def quirks_mode?
102
- !!@quirks_mode
103
- end
104
-
105
106
  def reset
106
107
  super
107
108
  @current_nesting = 0
108
109
  end
109
110
 
110
- # Parses the current JSON string _source_ and returns the complete data
111
- # structure as a result.
111
+ # Parses the current JSON string _source_ and returns the
112
+ # complete data structure as a result.
112
113
  def parse
113
114
  reset
114
115
  obj = nil
115
- if @quirks_mode
116
- while !eos? && skip(IGNORE)
117
- end
118
- if eos?
119
- raise ParserError, "source did not contain any JSON!"
120
- else
121
- obj = parse_value
122
- obj == UNPARSED and raise ParserError, "source did not contain any JSON!"
123
- end
116
+ while !eos? && skip(IGNORE) do end
117
+ if eos?
118
+ raise ParserError, "source is not valid JSON!"
124
119
  else
125
- until eos?
126
- case
127
- when scan(OBJECT_OPEN)
128
- obj and raise ParserError, "source '#{peek(20)}' not in JSON!"
129
- @current_nesting = 1
130
- obj = parse_object
131
- when scan(ARRAY_OPEN)
132
- obj and raise ParserError, "source '#{peek(20)}' not in JSON!"
133
- @current_nesting = 1
134
- obj = parse_array
135
- when skip(IGNORE)
136
- ;
137
- else
138
- raise ParserError, "source '#{peek(20)}' not in JSON!"
139
- end
140
- end
141
- obj or raise ParserError, "source did not contain any JSON!"
120
+ obj = parse_value
121
+ UNPARSED.equal?(obj) and raise ParserError,
122
+ "source is not valid JSON!"
142
123
  end
124
+ while !eos? && skip(IGNORE) do end
125
+ eos? or raise ParserError, "source is not valid JSON!"
143
126
  obj
144
127
  end
145
128
 
@@ -149,43 +132,12 @@ module JSON
149
132
  if source.respond_to?(:to_str)
150
133
  source = source.to_str
151
134
  else
152
- raise TypeError, "#{source.inspect} is not like a string"
135
+ raise TypeError,
136
+ "#{source.inspect} is not like a string"
153
137
  end
154
- if defined?(::Encoding)
155
- if source.encoding == ::Encoding::ASCII_8BIT
156
- b = source[0, 4].bytes.to_a
157
- source =
158
- case
159
- when b.size >= 4 && b[0] == 0 && b[1] == 0 && b[2] == 0
160
- source.dup.force_encoding(::Encoding::UTF_32BE).encode!(::Encoding::UTF_8)
161
- when b.size >= 4 && b[0] == 0 && b[2] == 0
162
- source.dup.force_encoding(::Encoding::UTF_16BE).encode!(::Encoding::UTF_8)
163
- when b.size >= 4 && b[1] == 0 && b[2] == 0 && b[3] == 0
164
- source.dup.force_encoding(::Encoding::UTF_32LE).encode!(::Encoding::UTF_8)
165
- when b.size >= 4 && b[1] == 0 && b[3] == 0
166
- source.dup.force_encoding(::Encoding::UTF_16LE).encode!(::Encoding::UTF_8)
167
- else
168
- source.dup
169
- end
170
- else
171
- source = source.encode(::Encoding::UTF_8)
172
- end
138
+ if source.encoding != ::Encoding::ASCII_8BIT
139
+ source = source.encode(::Encoding::UTF_8)
173
140
  source.force_encoding(::Encoding::ASCII_8BIT)
174
- else
175
- b = source
176
- source =
177
- case
178
- when b.size >= 4 && b[0] == 0 && b[1] == 0 && b[2] == 0
179
- JSON.iconv('utf-8', 'utf-32be', b)
180
- when b.size >= 4 && b[0] == 0 && b[2] == 0
181
- JSON.iconv('utf-8', 'utf-16be', b)
182
- when b.size >= 4 && b[1] == 0 && b[2] == 0 && b[3] == 0
183
- JSON.iconv('utf-8', 'utf-32le', b)
184
- when b.size >= 4 && b[1] == 0 && b[3] == 0
185
- JSON.iconv('utf-8', 'utf-16le', b)
186
- else
187
- b
188
- end
189
141
  end
190
142
  source
191
143
  end
@@ -245,7 +197,15 @@ module JSON
245
197
  def parse_value
246
198
  case
247
199
  when scan(FLOAT)
248
- Float(self[1])
200
+ if @decimal_class then
201
+ if @decimal_class == BigDecimal then
202
+ BigDecimal(self[1])
203
+ else
204
+ @decimal_class.new(self[1]) || Float(self[1])
205
+ end
206
+ else
207
+ Float(self[1])
208
+ end
249
209
  when scan(INTEGER)
250
210
  Integer(self[1])
251
211
  when scan(TRUE)
@@ -254,7 +214,7 @@ module JSON
254
214
  false
255
215
  when scan(NULL)
256
216
  nil
257
- when (string = parse_string) != UNPARSED
217
+ when !UNPARSED.equal?(string = parse_string)
258
218
  string
259
219
  when scan(ARRAY_OPEN)
260
220
  @current_nesting += 1
@@ -284,7 +244,7 @@ module JSON
284
244
  delim = false
285
245
  until eos?
286
246
  case
287
- when (value = parse_value) != UNPARSED
247
+ when !UNPARSED.equal?(value = parse_value)
288
248
  delim = false
289
249
  result << value
290
250
  skip(IGNORE)
@@ -316,13 +276,13 @@ module JSON
316
276
  delim = false
317
277
  until eos?
318
278
  case
319
- when (string = parse_string) != UNPARSED
279
+ when !UNPARSED.equal?(string = parse_string)
320
280
  skip(IGNORE)
321
281
  unless scan(PAIR_DELIMITER)
322
282
  raise ParserError, "expected ':' in object at '#{peek(20)}'!"
323
283
  end
324
284
  skip(IGNORE)
325
- unless (value = parse_value).equal? UNPARSED
285
+ unless UNPARSED.equal?(value = parse_value)
326
286
  result[@symbolize_names ? string.to_sym : string] = value
327
287
  delim = false
328
288
  skip(IGNORE)