json 1.8.3 → 2.5.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (93) hide show
  1. checksums.yaml +5 -5
  2. data/{CHANGES → CHANGES.md} +241 -90
  3. data/Gemfile +10 -6
  4. data/{COPYING-json-jruby → LICENSE} +5 -6
  5. data/{README.rdoc → README.md} +201 -134
  6. data/VERSION +1 -1
  7. data/ext/json/ext/fbuffer/fbuffer.h +0 -3
  8. data/ext/json/ext/generator/generator.c +264 -104
  9. data/ext/json/ext/generator/generator.h +12 -4
  10. data/ext/json/ext/parser/extconf.rb +28 -0
  11. data/ext/json/ext/parser/parser.c +425 -462
  12. data/ext/json/ext/parser/parser.h +5 -5
  13. data/ext/json/ext/parser/parser.rl +181 -181
  14. data/ext/json/extconf.rb +1 -1
  15. data/json.gemspec +0 -0
  16. data/lib/json.rb +550 -29
  17. data/lib/json/add/bigdecimal.rb +3 -2
  18. data/lib/json/add/complex.rb +4 -4
  19. data/lib/json/add/core.rb +1 -0
  20. data/lib/json/add/date.rb +1 -1
  21. data/lib/json/add/date_time.rb +1 -1
  22. data/lib/json/add/exception.rb +1 -1
  23. data/lib/json/add/ostruct.rb +3 -3
  24. data/lib/json/add/range.rb +1 -1
  25. data/lib/json/add/rational.rb +3 -3
  26. data/lib/json/add/regexp.rb +3 -3
  27. data/lib/json/add/set.rb +29 -0
  28. data/lib/json/add/struct.rb +1 -1
  29. data/lib/json/add/symbol.rb +1 -1
  30. data/lib/json/add/time.rb +1 -1
  31. data/lib/json/common.rb +381 -162
  32. data/lib/json/ext.rb +0 -6
  33. data/lib/json/generic_object.rb +5 -4
  34. data/lib/json/pure.rb +2 -8
  35. data/lib/json/pure/generator.rb +83 -126
  36. data/lib/json/pure/parser.rb +62 -84
  37. data/lib/json/version.rb +2 -1
  38. data/tests/fixtures/fail29.json +1 -0
  39. data/tests/fixtures/fail30.json +1 -0
  40. data/tests/fixtures/fail31.json +1 -0
  41. data/tests/fixtures/fail32.json +1 -0
  42. data/tests/fixtures/obsolete_fail1.json +1 -0
  43. data/tests/{test_json_addition.rb → json_addition_test.rb} +28 -25
  44. data/tests/json_common_interface_test.rb +169 -0
  45. data/tests/json_encoding_test.rb +107 -0
  46. data/tests/json_ext_parser_test.rb +15 -0
  47. data/tests/{test_json_fixtures.rb → json_fixtures_test.rb} +13 -8
  48. data/tests/{test_json_generate.rb → json_generator_test.rb} +109 -47
  49. data/tests/{test_json_generic_object.rb → json_generic_object_test.rb} +15 -8
  50. data/tests/json_parser_test.rb +497 -0
  51. data/tests/json_string_matching_test.rb +38 -0
  52. data/tests/lib/core_assertions.rb +763 -0
  53. data/tests/lib/envutil.rb +365 -0
  54. data/tests/lib/find_executable.rb +22 -0
  55. data/tests/lib/helper.rb +4 -0
  56. data/tests/ractor_test.rb +30 -0
  57. data/tests/test_helper.rb +17 -0
  58. metadata +48 -76
  59. data/.gitignore +0 -16
  60. data/.travis.yml +0 -26
  61. data/COPYING +0 -58
  62. data/GPL +0 -340
  63. data/README-json-jruby.markdown +0 -33
  64. data/Rakefile +0 -412
  65. data/TODO +0 -1
  66. data/data/example.json +0 -1
  67. data/data/index.html +0 -38
  68. data/data/prototype.js +0 -4184
  69. data/diagrams/.keep +0 -0
  70. data/install.rb +0 -23
  71. data/java/src/json/ext/ByteListTranscoder.java +0 -167
  72. data/java/src/json/ext/Generator.java +0 -444
  73. data/java/src/json/ext/GeneratorMethods.java +0 -232
  74. data/java/src/json/ext/GeneratorService.java +0 -43
  75. data/java/src/json/ext/GeneratorState.java +0 -543
  76. data/java/src/json/ext/OptionsReader.java +0 -114
  77. data/java/src/json/ext/Parser.java +0 -2645
  78. data/java/src/json/ext/Parser.rl +0 -969
  79. data/java/src/json/ext/ParserService.java +0 -35
  80. data/java/src/json/ext/RuntimeInfo.java +0 -121
  81. data/java/src/json/ext/StringDecoder.java +0 -167
  82. data/java/src/json/ext/StringEncoder.java +0 -106
  83. data/java/src/json/ext/Utils.java +0 -89
  84. data/json-java.gemspec +0 -23
  85. data/json_pure.gemspec +0 -40
  86. data/tests/fixtures/fail1.json +0 -1
  87. data/tests/setup_variant.rb +0 -11
  88. data/tests/test_json.rb +0 -553
  89. data/tests/test_json_encoding.rb +0 -65
  90. data/tests/test_json_string_matching.rb +0 -39
  91. data/tests/test_json_unicode.rb +0 -72
  92. data/tools/fuzz.rb +0 -139
  93. data/tools/server.rb +0 -62
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
@@ -48,12 +49,12 @@ module JSON
48
49
  end
49
50
 
50
51
  def [](name)
51
- table[name.to_sym]
52
- end
52
+ __send__(name)
53
+ end unless method_defined?(:[])
53
54
 
54
55
  def []=(name, value)
55
- __send__ "#{name}=", value
56
- end
56
+ __send__("#{name}=", value)
57
+ end unless method_defined?(:[]=)
57
58
 
58
59
  def |(other)
59
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',
@@ -36,87 +37,53 @@ module JSON
36
37
  '\\' => '\\\\',
37
38
  } # :nodoc:
38
39
 
40
+ ESCAPE_SLASH_MAP = MAP.merge(
41
+ '/' => '\\/',
42
+ )
43
+
39
44
  # Convert a UTF8 encoded Ruby string _string_ to a JSON string, encoded with
40
45
  # 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.force_encoding(::Encoding::ASCII_8BIT)
45
- string.gsub!(/["\\\x0-\x1f]/) { MAP[$&] }
46
- string.force_encoding(::Encoding::UTF_8)
47
- string
48
- end
49
-
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
73
-
74
- def valid_utf8?(string)
75
- encoding = string.encoding
76
- (encoding == Encoding::UTF_8 || encoding == Encoding::ASCII) &&
77
- string.valid_encoding?
78
- end
79
- module_function :valid_utf8?
80
- else
81
- def utf8_to_json(string) # :nodoc:
82
- string.gsub(/["\\\x0-\x1f]/n) { MAP[$&] }
83
- end
46
+ def utf8_to_json(string, escape_slash = false) # :nodoc:
47
+ string = string.dup
48
+ string.force_encoding(::Encoding::ASCII_8BIT)
49
+ map = escape_slash ? ESCAPE_SLASH_MAP : MAP
50
+ string.gsub!(/[\/"\\\x0-\x1f]/) { map[$&] || $& }
51
+ string.force_encoding(::Encoding::UTF_8)
52
+ string
53
+ end
84
54
 
85
- def utf8_to_json_ascii(string) # :nodoc:
86
- string = string.gsub(/["\\\x0-\x1f]/) { MAP[$&] }
87
- string.gsub!(/(
88
- (?:
89
- [\xc2-\xdf][\x80-\xbf] |
90
- [\xe0-\xef][\x80-\xbf]{2} |
91
- [\xf0-\xf4][\x80-\xbf]{3}
92
- )+ |
93
- [\x80-\xc1\xf5-\xff] # invalid
94
- )/nx) { |c|
95
- c.size == 1 and raise GeneratorError, "invalid utf8 byte: '#{c}'"
96
- s = JSON.iconv('utf-16be', 'utf-8', c).unpack('H*')[0]
97
- s.gsub!(/.{4}/n, '\\\\u\&')
98
- }
99
- string
100
- rescue => e
101
- raise GeneratorError.wrap(e)
102
- end
55
+ def utf8_to_json_ascii(string, escape_slash = false) # :nodoc:
56
+ string = string.dup
57
+ string.force_encoding(::Encoding::ASCII_8BIT)
58
+ map = escape_slash ? ESCAPE_SLASH_MAP : MAP
59
+ string.gsub!(/[\/"\\\x0-\x1f]/n) { map[$&] || $& }
60
+ string.gsub!(/(
61
+ (?:
62
+ [\xc2-\xdf][\x80-\xbf] |
63
+ [\xe0-\xef][\x80-\xbf]{2} |
64
+ [\xf0-\xf4][\x80-\xbf]{3}
65
+ )+ |
66
+ [\x80-\xc1\xf5-\xff] # invalid
67
+ )/nx) { |c|
68
+ c.size == 1 and raise GeneratorError, "invalid utf8 byte: '#{c}'"
69
+ s = JSON.iconv('utf-16be', 'utf-8', c).unpack('H*')[0]
70
+ s.force_encoding(::Encoding::ASCII_8BIT)
71
+ s.gsub!(/.{4}/n, '\\\\u\&')
72
+ s.force_encoding(::Encoding::UTF_8)
73
+ }
74
+ string.force_encoding(::Encoding::UTF_8)
75
+ string
76
+ rescue => e
77
+ raise GeneratorError.wrap(e)
78
+ end
103
79
 
104
- def valid_utf8?(string)
105
- string =~
106
- /\A( [\x09\x0a\x0d\x20-\x7e] # ASCII
107
- | [\xc2-\xdf][\x80-\xbf] # non-overlong 2-byte
108
- | \xe0[\xa0-\xbf][\x80-\xbf] # excluding overlongs
109
- | [\xe1-\xec\xee\xef][\x80-\xbf]{2} # straight 3-byte
110
- | \xed[\x80-\x9f][\x80-\xbf] # excluding surrogates
111
- | \xf0[\x90-\xbf][\x80-\xbf]{2} # planes 1-3
112
- | [\xf1-\xf3][\x80-\xbf]{3} # planes 4-15
113
- | \xf4[\x80-\x8f][\x80-\xbf]{2} # plane 16
114
- )*\z/nx
115
- end
80
+ def valid_utf8?(string)
81
+ encoding = string.encoding
82
+ (encoding == Encoding::UTF_8 || encoding == Encoding::ASCII) &&
83
+ string.valid_encoding?
116
84
  end
117
85
  module_function :utf8_to_json, :utf8_to_json_ascii, :valid_utf8?
118
86
 
119
-
120
87
  module Pure
121
88
  module Generator
122
89
  # This class is used to create State instances, that are use to hold data
@@ -148,14 +115,13 @@ module JSON
148
115
  # * *space_before*: a string that is put before a : pair delimiter (default: ''),
149
116
  # * *object_nl*: a string that is put at the end of a JSON object (default: ''),
150
117
  # * *array_nl*: a string that is put at the end of a JSON array (default: ''),
118
+ # * *escape_slash*: true if forward slash (/) should be escaped (default: false)
151
119
  # * *check_circular*: is deprecated now, use the :max_nesting option instead,
152
120
  # * *max_nesting*: sets the maximum level of data structure nesting in
153
121
  # the generated JSON, max_nesting = 0 if no maximum should be checked.
154
122
  # * *allow_nan*: true if NaN, Infinity, and -Infinity should be
155
123
  # generated, otherwise an exception is thrown, if these values are
156
124
  # encountered. This options defaults to false.
157
- # * *quirks_mode*: Enables quirks_mode for parser, that is for example
158
- # generating single JSON values instead of documents is possible.
159
125
  def initialize(opts = {})
160
126
  @indent = ''
161
127
  @space = ''
@@ -164,7 +130,7 @@ module JSON
164
130
  @array_nl = ''
165
131
  @allow_nan = false
166
132
  @ascii_only = false
167
- @quirks_mode = false
133
+ @escape_slash = false
168
134
  @buffer_initial_length = 1024
169
135
  configure opts
170
136
  end
@@ -190,9 +156,9 @@ module JSON
190
156
  # the generated JSON, max_nesting = 0 if no maximum is checked.
191
157
  attr_accessor :max_nesting
192
158
 
193
- # If this attribute is set to true, quirks mode is enabled, otherwise
194
- # it's disabled.
195
- attr_accessor :quirks_mode
159
+ # If this attribute is set to true, forward slashes will be escaped in
160
+ # all json strings.
161
+ attr_accessor :escape_slash
196
162
 
197
163
  # :stopdoc:
198
164
  attr_reader :buffer_initial_length
@@ -233,9 +199,9 @@ module JSON
233
199
  @ascii_only
234
200
  end
235
201
 
236
- # Returns true, if quirks mode is enabled. Otherwise returns false.
237
- def quirks_mode?
238
- @quirks_mode
202
+ # Returns true, if forward slashes are escaped. Otherwise returns false.
203
+ def escape_slash?
204
+ @escape_slash
239
205
  end
240
206
 
241
207
  # Configure this State instance with the Hash _opts_, and return
@@ -259,8 +225,8 @@ module JSON
259
225
  @allow_nan = !!opts[:allow_nan] if opts.key?(:allow_nan)
260
226
  @ascii_only = opts[:ascii_only] if opts.key?(:ascii_only)
261
227
  @depth = opts[:depth] || 0
262
- @quirks_mode = opts[:quirks_mode] if opts.key?(:quirks_mode)
263
228
  @buffer_initial_length ||= opts[:buffer_initial_length]
229
+ @escape_slash = !!opts[:escape_slash] if opts.key?(:escape_slash)
264
230
 
265
231
  if !opts.key?(:max_nesting) # defaults to 100
266
232
  @max_nesting = 100
@@ -286,20 +252,14 @@ module JSON
286
252
 
287
253
  alias to_hash to_h
288
254
 
289
- # Generates a valid JSON document from object +obj+ and returns the
290
- # result. If no valid JSON document can be created this method raises a
255
+ # Generates a valid JSON document from object +obj+ and
256
+ # returns the result. If no valid JSON document can be
257
+ # created this method raises a
291
258
  # GeneratorError exception.
292
259
  def generate(obj)
293
260
  result = obj.to_json(self)
294
261
  JSON.valid_utf8?(result) or raise GeneratorError,
295
262
  "source sequence #{result.inspect} is illegal/malformed utf-8"
296
- unless @quirks_mode
297
- unless result =~ /\A\s*\[/ && result =~ /\]\s*\Z/ ||
298
- result =~ /\A\s*\{/ && result =~ /\}\s*\Z/
299
- then
300
- raise GeneratorError, "only generation of JSON objects or arrays allowed"
301
- end
302
- end
303
263
  result
304
264
  end
305
265
 
@@ -308,7 +268,8 @@ module JSON
308
268
  if respond_to?(name)
309
269
  __send__(name)
310
270
  else
311
- instance_variable_get("@#{name}")
271
+ instance_variable_get("@#{name}") if
272
+ instance_variables.include?("@#{name}".to_sym) # avoid warning
312
273
  end
313
274
  end
314
275
 
@@ -363,12 +324,18 @@ module JSON
363
324
  result << state.space_before
364
325
  result << ':'
365
326
  result << state.space
366
- result << value.to_json(state)
327
+ if value.respond_to?(:to_json)
328
+ result << value.to_json(state)
329
+ else
330
+ result << %{"#{String(value)}"}
331
+ end
367
332
  first = false
368
333
  }
369
334
  depth = state.depth -= 1
370
- result << state.object_nl
371
- result << state.indent * depth if indent
335
+ unless first
336
+ result << state.object_nl
337
+ result << state.indent * depth if indent
338
+ end
372
339
  result << '}'
373
340
  result
374
341
  end
@@ -398,7 +365,11 @@ module JSON
398
365
  each { |value|
399
366
  result << delim unless first
400
367
  result << state.indent * depth if indent
401
- result << value.to_json(state)
368
+ if value.respond_to?(:to_json)
369
+ result << value.to_json(state)
370
+ else
371
+ result << %{"#{String(value)}"}
372
+ end
402
373
  first = false
403
374
  }
404
375
  depth = state.depth -= 1
@@ -437,38 +408,24 @@ module JSON
437
408
  end
438
409
 
439
410
  module String
440
- if defined?(::Encoding)
441
- # This string should be encoded with UTF-8 A call to this method
442
- # returns a JSON string encoded with UTF16 big endian characters as
443
- # \u????.
444
- def to_json(state = nil, *args)
445
- state = State.from_state(state)
446
- if encoding == ::Encoding::UTF_8
447
- string = self
448
- else
449
- string = encode(::Encoding::UTF_8)
450
- end
451
- if state.ascii_only?
452
- '"' << JSON.utf8_to_json_ascii(string) << '"'
453
- else
454
- '"' << JSON.utf8_to_json(string) << '"'
455
- end
411
+ # This string should be encoded with UTF-8 A call to this method
412
+ # returns a JSON string encoded with UTF16 big endian characters as
413
+ # \u????.
414
+ def to_json(state = nil, *args)
415
+ state = State.from_state(state)
416
+ if encoding == ::Encoding::UTF_8
417
+ string = self
418
+ else
419
+ string = encode(::Encoding::UTF_8)
456
420
  end
457
- else
458
- # This string should be encoded with UTF-8 A call to this method
459
- # returns a JSON string encoded with UTF16 big endian characters as
460
- # \u????.
461
- def to_json(state = nil, *args)
462
- state = State.from_state(state)
463
- if state.ascii_only?
464
- '"' << JSON.utf8_to_json_ascii(self) << '"'
465
- else
466
- '"' << JSON.utf8_to_json(self) << '"'
467
- end
421
+ if state.ascii_only?
422
+ '"' << JSON.utf8_to_json_ascii(string, state.escape_slash) << '"'
423
+ else
424
+ '"' << JSON.utf8_to_json(string, state.escape_slash) << '"'
468
425
  end
469
426
  end
470
427
 
471
- # Module that holds the extinding methods if, the String module is
428
+ # Module that holds the extending methods if, the String module is
472
429
  # included.
473
430
  module Extend
474
431
  # Raw Strings are JSON Objects (the raw bytes are stored in an
@@ -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
  #
@@ -58,23 +59,25 @@ module JSON
58
59
  # structures. Disable depth checking with :max_nesting => false|nil|0,
59
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.
64
+ # * *freeze*: If set to true, all parsed objects will be frozen. Parsed
65
+ # string will be deduplicated if possible.
63
66
  # * *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.
67
+ # (keys) in a JSON object. Otherwise strings are returned, which is
68
+ # also the default. It's not possible to use this option in
69
+ # conjunction with the *create_additions* option.
66
70
  # * *create_additions*: If set to true, the Parser creates
67
- # additions when if a matching class and create_id was found. This
71
+ # additions when a matching class and create_id are found. This
68
72
  # option defaults to false.
69
73
  # * *object_class*: Defaults to Hash
70
74
  # * *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.
75
+ # * *decimal_class*: Specifies which class to use instead of the default
76
+ # (Float) when parsing decimal numbers. This class must accept a single
77
+ # string argument in its constructor.
73
78
  def initialize(source, opts = {})
74
79
  opts ||= {}
75
- unless @quirks_mode = opts[:quirks_mode]
76
- source = convert_encoding source
77
- end
80
+ source = convert_encoding source
78
81
  super source
79
82
  if !opts.key?(:max_nesting) # defaults to 100
80
83
  @max_nesting = 100
@@ -85,61 +88,45 @@ module JSON
85
88
  end
86
89
  @allow_nan = !!opts[:allow_nan]
87
90
  @symbolize_names = !!opts[:symbolize_names]
91
+ @freeze = !!opts[:freeze]
88
92
  if opts.key?(:create_additions)
89
93
  @create_additions = !!opts[:create_additions]
90
94
  else
91
95
  @create_additions = false
92
96
  end
97
+ @symbolize_names && @create_additions and raise ArgumentError,
98
+ 'options :symbolize_names and :create_additions cannot be used '\
99
+ 'in conjunction'
93
100
  @create_id = @create_additions ? JSON.create_id : nil
94
101
  @object_class = opts[:object_class] || Hash
95
102
  @array_class = opts[:array_class] || Array
103
+ @decimal_class = opts[:decimal_class]
96
104
  @match_string = opts[:match_string]
97
105
  end
98
106
 
99
107
  alias source string
100
108
 
101
- def quirks_mode?
102
- !!@quirks_mode
103
- end
104
-
105
109
  def reset
106
110
  super
107
111
  @current_nesting = 0
108
112
  end
109
113
 
110
- # Parses the current JSON string _source_ and returns the complete data
111
- # structure as a result.
114
+ # Parses the current JSON string _source_ and returns the
115
+ # complete data structure as a result.
112
116
  def parse
113
117
  reset
114
118
  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
119
+ while !eos? && skip(IGNORE) do end
120
+ if eos?
121
+ raise ParserError, "source is not valid JSON!"
124
122
  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!"
123
+ obj = parse_value
124
+ UNPARSED.equal?(obj) and raise ParserError,
125
+ "source is not valid JSON!"
126
+ obj.freeze if @freeze
142
127
  end
128
+ while !eos? && skip(IGNORE) do end
129
+ eos? or raise ParserError, "source is not valid JSON!"
143
130
  obj
144
131
  end
145
132
 
@@ -149,43 +136,12 @@ module JSON
149
136
  if source.respond_to?(:to_str)
150
137
  source = source.to_str
151
138
  else
152
- raise TypeError, "#{source.inspect} is not like a string"
139
+ raise TypeError,
140
+ "#{source.inspect} is not like a string"
153
141
  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
142
+ if source.encoding != ::Encoding::ASCII_8BIT
143
+ source = source.encode(::Encoding::UTF_8)
173
144
  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
145
  end
190
146
  source
191
147
  end
@@ -209,6 +165,7 @@ module JSON
209
165
  EMPTY_8BIT_STRING.force_encoding Encoding::ASCII_8BIT
210
166
  end
211
167
 
168
+ STR_UMINUS = ''.respond_to?(:-@)
212
169
  def parse_string
213
170
  if scan(STRING)
214
171
  return '' if self[1].empty?
@@ -228,6 +185,15 @@ module JSON
228
185
  if string.respond_to?(:force_encoding)
229
186
  string.force_encoding(::Encoding::UTF_8)
230
187
  end
188
+
189
+ if @freeze
190
+ if STR_UMINUS
191
+ string = -string
192
+ else
193
+ string.freeze
194
+ end
195
+ end
196
+
231
197
  if @create_additions and @match_string
232
198
  for (regexp, klass) in @match_string
233
199
  klass.json_creatable? or next
@@ -245,7 +211,15 @@ module JSON
245
211
  def parse_value
246
212
  case
247
213
  when scan(FLOAT)
248
- Float(self[1])
214
+ if @decimal_class then
215
+ if @decimal_class == BigDecimal then
216
+ BigDecimal(self[1])
217
+ else
218
+ @decimal_class.new(self[1]) || Float(self[1])
219
+ end
220
+ else
221
+ Float(self[1])
222
+ end
249
223
  when scan(INTEGER)
250
224
  Integer(self[1])
251
225
  when scan(TRUE)
@@ -254,7 +228,7 @@ module JSON
254
228
  false
255
229
  when scan(NULL)
256
230
  nil
257
- when (string = parse_string) != UNPARSED
231
+ when !UNPARSED.equal?(string = parse_string)
258
232
  string
259
233
  when scan(ARRAY_OPEN)
260
234
  @current_nesting += 1
@@ -282,9 +256,11 @@ module JSON
282
256
  @max_nesting.nonzero? && @current_nesting > @max_nesting
283
257
  result = @array_class.new
284
258
  delim = false
285
- until eos?
259
+ loop do
286
260
  case
287
- when (value = parse_value) != UNPARSED
261
+ when eos?
262
+ raise ParserError, "unexpected end of string while parsing array"
263
+ when !UNPARSED.equal?(value = parse_value)
288
264
  delim = false
289
265
  result << value
290
266
  skip(IGNORE)
@@ -314,15 +290,17 @@ module JSON
314
290
  @max_nesting.nonzero? && @current_nesting > @max_nesting
315
291
  result = @object_class.new
316
292
  delim = false
317
- until eos?
293
+ loop do
318
294
  case
319
- when (string = parse_string) != UNPARSED
295
+ when eos?
296
+ raise ParserError, "unexpected end of string while parsing object"
297
+ when !UNPARSED.equal?(string = parse_string)
320
298
  skip(IGNORE)
321
299
  unless scan(PAIR_DELIMITER)
322
300
  raise ParserError, "expected ':' in object at '#{peek(20)}'!"
323
301
  end
324
302
  skip(IGNORE)
325
- unless (value = parse_value).equal? UNPARSED
303
+ unless UNPARSED.equal?(value = parse_value)
326
304
  result[@symbolize_names ? string.to_sym : string] = value
327
305
  delim = false
328
306
  skip(IGNORE)