json 2.1.0 → 2.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (96) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGES.md +63 -5
  3. data/LICENSE +56 -0
  4. data/README.md +56 -23
  5. data/VERSION +1 -1
  6. data/ext/json/ext/generator/generator.c +223 -58
  7. data/ext/json/ext/generator/generator.h +5 -2
  8. data/ext/json/ext/parser/extconf.rb +26 -0
  9. data/ext/json/ext/parser/parser.c +2973 -1744
  10. data/ext/json/ext/parser/parser.h +6 -1
  11. data/ext/json/ext/parser/parser.rl +130 -22
  12. data/ext/json/extconf.rb +1 -0
  13. data/json.gemspec +0 -0
  14. data/lib/json/add/bigdecimal.rb +2 -2
  15. data/lib/json/add/complex.rb +2 -3
  16. data/lib/json/add/ostruct.rb +1 -1
  17. data/lib/json/add/rational.rb +2 -3
  18. data/lib/json/add/regexp.rb +2 -2
  19. data/lib/json/add/set.rb +29 -0
  20. data/lib/json/common.rb +372 -125
  21. data/lib/json/pure/generator.rb +31 -10
  22. data/lib/json/pure/parser.rb +32 -6
  23. data/lib/json/version.rb +1 -1
  24. data/lib/json.rb +549 -29
  25. metadata +19 -113
  26. data/.gitignore +0 -17
  27. data/.travis.yml +0 -19
  28. data/Gemfile +0 -16
  29. data/README-json-jruby.md +0 -33
  30. data/Rakefile +0 -408
  31. data/data/example.json +0 -1
  32. data/data/index.html +0 -38
  33. data/data/prototype.js +0 -4184
  34. data/diagrams/.keep +0 -0
  35. data/install.rb +0 -23
  36. data/java/src/json/ext/ByteListTranscoder.java +0 -166
  37. data/java/src/json/ext/Generator.java +0 -443
  38. data/java/src/json/ext/GeneratorMethods.java +0 -231
  39. data/java/src/json/ext/GeneratorService.java +0 -42
  40. data/java/src/json/ext/GeneratorState.java +0 -490
  41. data/java/src/json/ext/OptionsReader.java +0 -113
  42. data/java/src/json/ext/Parser.java +0 -2362
  43. data/java/src/json/ext/Parser.rl +0 -893
  44. data/java/src/json/ext/ParserService.java +0 -34
  45. data/java/src/json/ext/RuntimeInfo.java +0 -116
  46. data/java/src/json/ext/StringDecoder.java +0 -166
  47. data/java/src/json/ext/StringEncoder.java +0 -111
  48. data/java/src/json/ext/Utils.java +0 -88
  49. data/json-java.gemspec +0 -38
  50. data/json_pure.gemspec +0 -38
  51. data/lib/json/ext/.keep +0 -0
  52. data/references/rfc7159.txt +0 -899
  53. data/tests/fixtures/fail10.json +0 -1
  54. data/tests/fixtures/fail11.json +0 -1
  55. data/tests/fixtures/fail12.json +0 -1
  56. data/tests/fixtures/fail13.json +0 -1
  57. data/tests/fixtures/fail14.json +0 -1
  58. data/tests/fixtures/fail18.json +0 -1
  59. data/tests/fixtures/fail19.json +0 -1
  60. data/tests/fixtures/fail2.json +0 -1
  61. data/tests/fixtures/fail20.json +0 -1
  62. data/tests/fixtures/fail21.json +0 -1
  63. data/tests/fixtures/fail22.json +0 -1
  64. data/tests/fixtures/fail23.json +0 -1
  65. data/tests/fixtures/fail24.json +0 -1
  66. data/tests/fixtures/fail25.json +0 -1
  67. data/tests/fixtures/fail27.json +0 -2
  68. data/tests/fixtures/fail28.json +0 -2
  69. data/tests/fixtures/fail3.json +0 -1
  70. data/tests/fixtures/fail4.json +0 -1
  71. data/tests/fixtures/fail5.json +0 -1
  72. data/tests/fixtures/fail6.json +0 -1
  73. data/tests/fixtures/fail7.json +0 -1
  74. data/tests/fixtures/fail8.json +0 -1
  75. data/tests/fixtures/fail9.json +0 -1
  76. data/tests/fixtures/obsolete_fail1.json +0 -1
  77. data/tests/fixtures/pass1.json +0 -56
  78. data/tests/fixtures/pass15.json +0 -1
  79. data/tests/fixtures/pass16.json +0 -1
  80. data/tests/fixtures/pass17.json +0 -1
  81. data/tests/fixtures/pass2.json +0 -1
  82. data/tests/fixtures/pass26.json +0 -1
  83. data/tests/fixtures/pass3.json +0 -6
  84. data/tests/json_addition_test.rb +0 -193
  85. data/tests/json_common_interface_test.rb +0 -126
  86. data/tests/json_encoding_test.rb +0 -107
  87. data/tests/json_ext_parser_test.rb +0 -15
  88. data/tests/json_fixtures_test.rb +0 -32
  89. data/tests/json_generator_test.rb +0 -377
  90. data/tests/json_generic_object_test.rb +0 -82
  91. data/tests/json_parser_test.rb +0 -471
  92. data/tests/json_string_matching_test.rb +0 -38
  93. data/tests/test_helper.rb +0 -21
  94. data/tools/diff.sh +0 -18
  95. data/tools/fuzz.rb +0 -131
  96. data/tools/server.rb +0 -62
@@ -37,20 +37,26 @@ module JSON
37
37
  '\\' => '\\\\',
38
38
  } # :nodoc:
39
39
 
40
+ ESCAPE_SLASH_MAP = MAP.merge(
41
+ '/' => '\\/',
42
+ )
43
+
40
44
  # Convert a UTF8 encoded Ruby string _string_ to a JSON string, encoded with
41
45
  # UTF16 big endian characters as \u????, and return it.
42
- def utf8_to_json(string) # :nodoc:
46
+ def utf8_to_json(string, escape_slash = false) # :nodoc:
43
47
  string = string.dup
44
48
  string.force_encoding(::Encoding::ASCII_8BIT)
45
- string.gsub!(/["\\\x0-\x1f]/) { MAP[$&] }
49
+ map = escape_slash ? ESCAPE_SLASH_MAP : MAP
50
+ string.gsub!(/[\/"\\\x0-\x1f]/) { map[$&] || $& }
46
51
  string.force_encoding(::Encoding::UTF_8)
47
52
  string
48
53
  end
49
54
 
50
- def utf8_to_json_ascii(string) # :nodoc:
55
+ def utf8_to_json_ascii(string, escape_slash = false) # :nodoc:
51
56
  string = string.dup
52
57
  string.force_encoding(::Encoding::ASCII_8BIT)
53
- string.gsub!(/["\\\x0-\x1f]/n) { MAP[$&] }
58
+ map = escape_slash ? ESCAPE_SLASH_MAP : MAP
59
+ string.gsub!(/[\/"\\\x0-\x1f]/n) { map[$&] || $& }
54
60
  string.gsub!(/(
55
61
  (?:
56
62
  [\xc2-\xdf][\x80-\xbf] |
@@ -109,6 +115,7 @@ module JSON
109
115
  # * *space_before*: a string that is put before a : pair delimiter (default: ''),
110
116
  # * *object_nl*: a string that is put at the end of a JSON object (default: ''),
111
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)
112
119
  # * *check_circular*: is deprecated now, use the :max_nesting option instead,
113
120
  # * *max_nesting*: sets the maximum level of data structure nesting in
114
121
  # the generated JSON, max_nesting = 0 if no maximum should be checked.
@@ -123,6 +130,7 @@ module JSON
123
130
  @array_nl = ''
124
131
  @allow_nan = false
125
132
  @ascii_only = false
133
+ @escape_slash = false
126
134
  @buffer_initial_length = 1024
127
135
  configure opts
128
136
  end
@@ -148,6 +156,10 @@ module JSON
148
156
  # the generated JSON, max_nesting = 0 if no maximum is checked.
149
157
  attr_accessor :max_nesting
150
158
 
159
+ # If this attribute is set to true, forward slashes will be escaped in
160
+ # all json strings.
161
+ attr_accessor :escape_slash
162
+
151
163
  # :stopdoc:
152
164
  attr_reader :buffer_initial_length
153
165
 
@@ -187,6 +199,11 @@ module JSON
187
199
  @ascii_only
188
200
  end
189
201
 
202
+ # Returns true, if forward slashes are escaped. Otherwise returns false.
203
+ def escape_slash?
204
+ @escape_slash
205
+ end
206
+
190
207
  # Configure this State instance with the Hash _opts_, and return
191
208
  # itself.
192
209
  def configure(opts)
@@ -209,6 +226,7 @@ module JSON
209
226
  @ascii_only = opts[:ascii_only] if opts.key?(:ascii_only)
210
227
  @depth = opts[:depth] || 0
211
228
  @buffer_initial_length ||= opts[:buffer_initial_length]
229
+ @escape_slash = !!opts[:escape_slash] if opts.key?(:escape_slash)
212
230
 
213
231
  if !opts.key?(:max_nesting) # defaults to 100
214
232
  @max_nesting = 100
@@ -250,7 +268,8 @@ module JSON
250
268
  if respond_to?(name)
251
269
  __send__(name)
252
270
  else
253
- instance_variable_get("@#{name}")
271
+ instance_variable_get("@#{name}") if
272
+ instance_variables.include?("@#{name}".to_sym) # avoid warning
254
273
  end
255
274
  end
256
275
 
@@ -313,8 +332,10 @@ module JSON
313
332
  first = false
314
333
  }
315
334
  depth = state.depth -= 1
316
- result << state.object_nl
317
- result << state.indent * depth if indent
335
+ unless first
336
+ result << state.object_nl
337
+ result << state.indent * depth if indent
338
+ end
318
339
  result << '}'
319
340
  result
320
341
  end
@@ -398,13 +419,13 @@ module JSON
398
419
  string = encode(::Encoding::UTF_8)
399
420
  end
400
421
  if state.ascii_only?
401
- '"' << JSON.utf8_to_json_ascii(string) << '"'
422
+ '"' << JSON.utf8_to_json_ascii(string, state.escape_slash) << '"'
402
423
  else
403
- '"' << JSON.utf8_to_json(string) << '"'
424
+ '"' << JSON.utf8_to_json(string, state.escape_slash) << '"'
404
425
  end
405
426
  end
406
427
 
407
- # Module that holds the extinding methods if, the String module is
428
+ # Module that holds the extending methods if, the String module is
408
429
  # included.
409
430
  module Extend
410
431
  # Raw Strings are JSON Objects (the raw bytes are stored in an
@@ -45,11 +45,11 @@ module JSON
45
45
  /(?=\*/) # single slash before this comment's end
46
46
  )*
47
47
  \*/ # the End of this comment
48
- |[ \t\r\n]+ # whitespaces: space, horicontal tab, lf, cr
48
+ |[ \t\r\n]+ # whitespaces: space, horizontal tab, lf, cr
49
49
  )+
50
50
  )mx
51
51
 
52
- UNPARSED = Object.new.freeze
52
+ UNPARSED = Object.new.freeze
53
53
 
54
54
  # Creates a new JSON::Pure::Parser instance for the string _source_.
55
55
  #
@@ -61,12 +61,14 @@ module JSON
61
61
  # * *allow_nan*: If set to true, allow NaN, Infinity and -Infinity in
62
62
  # defiance of RFC 7159 to be parsed by the Parser. This option defaults
63
63
  # to false.
64
+ # * *freeze*: If set to true, all parsed objects will be frozen. Parsed
65
+ # string will be deduplicated if possible.
64
66
  # * *symbolize_names*: If set to true, returns symbols for the names
65
67
  # (keys) in a JSON object. Otherwise strings are returned, which is
66
68
  # also the default. It's not possible to use this option in
67
69
  # conjunction with the *create_additions* option.
68
70
  # * *create_additions*: If set to true, the Parser creates
69
- # additions when if a matching class and create_id was found. This
71
+ # additions when a matching class and create_id are found. This
70
72
  # option defaults to false.
71
73
  # * *object_class*: Defaults to Hash
72
74
  # * *array_class*: Defaults to Array
@@ -86,6 +88,7 @@ module JSON
86
88
  end
87
89
  @allow_nan = !!opts[:allow_nan]
88
90
  @symbolize_names = !!opts[:symbolize_names]
91
+ @freeze = !!opts[:freeze]
89
92
  if opts.key?(:create_additions)
90
93
  @create_additions = !!opts[:create_additions]
91
94
  else
@@ -120,6 +123,7 @@ module JSON
120
123
  obj = parse_value
121
124
  UNPARSED.equal?(obj) and raise ParserError,
122
125
  "source is not valid JSON!"
126
+ obj.freeze if @freeze
123
127
  end
124
128
  while !eos? && skip(IGNORE) do end
125
129
  eos? or raise ParserError, "source is not valid JSON!"
@@ -161,6 +165,7 @@ module JSON
161
165
  EMPTY_8BIT_STRING.force_encoding Encoding::ASCII_8BIT
162
166
  end
163
167
 
168
+ STR_UMINUS = ''.respond_to?(:-@)
164
169
  def parse_string
165
170
  if scan(STRING)
166
171
  return '' if self[1].empty?
@@ -180,6 +185,15 @@ module JSON
180
185
  if string.respond_to?(:force_encoding)
181
186
  string.force_encoding(::Encoding::UTF_8)
182
187
  end
188
+
189
+ if @freeze
190
+ if STR_UMINUS
191
+ string = -string
192
+ else
193
+ string.freeze
194
+ end
195
+ end
196
+
183
197
  if @create_additions and @match_string
184
198
  for (regexp, klass) in @match_string
185
199
  klass.json_creatable? or next
@@ -197,7 +211,15 @@ module JSON
197
211
  def parse_value
198
212
  case
199
213
  when scan(FLOAT)
200
- @decimal_class && @decimal_class.new(self[1]) || 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
201
223
  when scan(INTEGER)
202
224
  Integer(self[1])
203
225
  when scan(TRUE)
@@ -234,8 +256,10 @@ module JSON
234
256
  @max_nesting.nonzero? && @current_nesting > @max_nesting
235
257
  result = @array_class.new
236
258
  delim = false
237
- until eos?
259
+ loop do
238
260
  case
261
+ when eos?
262
+ raise ParserError, "unexpected end of string while parsing array"
239
263
  when !UNPARSED.equal?(value = parse_value)
240
264
  delim = false
241
265
  result << value
@@ -266,8 +290,10 @@ module JSON
266
290
  @max_nesting.nonzero? && @current_nesting > @max_nesting
267
291
  result = @object_class.new
268
292
  delim = false
269
- until eos?
293
+ loop do
270
294
  case
295
+ when eos?
296
+ raise ParserError, "unexpected end of string while parsing object"
271
297
  when !UNPARSED.equal?(string = parse_string)
272
298
  skip(IGNORE)
273
299
  unless scan(PAIR_DELIMITER)
data/lib/json/version.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: false
2
2
  module JSON
3
3
  # JSON version
4
- VERSION = '2.1.0'
4
+ VERSION = '2.6.0'
5
5
  VERSION_ARRAY = VERSION.split(/\./).map { |x| x.to_i } # :nodoc:
6
6
  VERSION_MAJOR = VERSION_ARRAY[0] # :nodoc:
7
7
  VERSION_MINOR = VERSION_ARRAY[1] # :nodoc: