json 2.6.2 → 2.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/BSDL +22 -0
  3. data/CHANGES.md +144 -17
  4. data/LEGAL +8 -0
  5. data/README.md +67 -224
  6. data/ext/json/ext/fbuffer/fbuffer.h +110 -92
  7. data/ext/json/ext/generator/extconf.rb +8 -2
  8. data/ext/json/ext/generator/generator.c +1020 -806
  9. data/ext/json/ext/parser/extconf.rb +7 -27
  10. data/ext/json/ext/parser/parser.c +1343 -3212
  11. data/json.gemspec +48 -52
  12. data/lib/json/add/bigdecimal.rb +39 -10
  13. data/lib/json/add/complex.rb +29 -6
  14. data/lib/json/add/core.rb +1 -1
  15. data/lib/json/add/date.rb +27 -7
  16. data/lib/json/add/date_time.rb +26 -9
  17. data/lib/json/add/exception.rb +25 -7
  18. data/lib/json/add/ostruct.rb +32 -9
  19. data/lib/json/add/range.rb +33 -8
  20. data/lib/json/add/rational.rb +28 -6
  21. data/lib/json/add/regexp.rb +26 -8
  22. data/lib/json/add/set.rb +25 -6
  23. data/lib/json/add/struct.rb +29 -7
  24. data/lib/json/add/symbol.rb +34 -7
  25. data/lib/json/add/time.rb +29 -15
  26. data/lib/json/common.rb +418 -128
  27. data/lib/json/ext/generator/state.rb +106 -0
  28. data/lib/json/ext.rb +34 -4
  29. data/lib/json/generic_object.rb +7 -3
  30. data/lib/json/truffle_ruby/generator.rb +690 -0
  31. data/lib/json/version.rb +3 -7
  32. data/lib/json.rb +25 -21
  33. metadata +15 -26
  34. data/VERSION +0 -1
  35. data/ext/json/ext/generator/depend +0 -1
  36. data/ext/json/ext/generator/generator.h +0 -174
  37. data/ext/json/ext/parser/depend +0 -1
  38. data/ext/json/ext/parser/parser.h +0 -96
  39. data/ext/json/ext/parser/parser.rl +0 -986
  40. data/ext/json/extconf.rb +0 -3
  41. data/lib/json/pure/generator.rb +0 -479
  42. data/lib/json/pure/parser.rb +0 -337
  43. data/lib/json/pure.rb +0 -15
  44. /data/{LICENSE → COPYING} +0 -0
data/ext/json/extconf.rb DELETED
@@ -1,3 +0,0 @@
1
- require 'mkmf'
2
-
3
- create_makefile('json')
@@ -1,479 +0,0 @@
1
- #frozen_string_literal: false
2
- module JSON
3
- MAP = {
4
- "\x0" => '\u0000',
5
- "\x1" => '\u0001',
6
- "\x2" => '\u0002',
7
- "\x3" => '\u0003',
8
- "\x4" => '\u0004',
9
- "\x5" => '\u0005',
10
- "\x6" => '\u0006',
11
- "\x7" => '\u0007',
12
- "\b" => '\b',
13
- "\t" => '\t',
14
- "\n" => '\n',
15
- "\xb" => '\u000b',
16
- "\f" => '\f',
17
- "\r" => '\r',
18
- "\xe" => '\u000e',
19
- "\xf" => '\u000f',
20
- "\x10" => '\u0010',
21
- "\x11" => '\u0011',
22
- "\x12" => '\u0012',
23
- "\x13" => '\u0013',
24
- "\x14" => '\u0014',
25
- "\x15" => '\u0015',
26
- "\x16" => '\u0016',
27
- "\x17" => '\u0017',
28
- "\x18" => '\u0018',
29
- "\x19" => '\u0019',
30
- "\x1a" => '\u001a',
31
- "\x1b" => '\u001b',
32
- "\x1c" => '\u001c',
33
- "\x1d" => '\u001d',
34
- "\x1e" => '\u001e',
35
- "\x1f" => '\u001f',
36
- '"' => '\"',
37
- '\\' => '\\\\',
38
- } # :nodoc:
39
-
40
- ESCAPE_SLASH_MAP = MAP.merge(
41
- '/' => '\\/',
42
- )
43
-
44
- # Convert a UTF8 encoded Ruby string _string_ to a JSON string, encoded with
45
- # UTF16 big endian characters as \u????, and return it.
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
54
-
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
79
-
80
- def valid_utf8?(string)
81
- encoding = string.encoding
82
- (encoding == Encoding::UTF_8 || encoding == Encoding::ASCII) &&
83
- string.valid_encoding?
84
- end
85
- module_function :utf8_to_json, :utf8_to_json_ascii, :valid_utf8?
86
-
87
- module Pure
88
- module Generator
89
- # This class is used to create State instances, that are use to hold data
90
- # while generating a JSON text from a Ruby data structure.
91
- class State
92
- # Creates a State object from _opts_, which ought to be Hash to create
93
- # a new State instance configured by _opts_, something else to create
94
- # an unconfigured instance. If _opts_ is a State object, it is just
95
- # returned.
96
- def self.from_state(opts)
97
- case
98
- when self === opts
99
- opts
100
- when opts.respond_to?(:to_hash)
101
- new(opts.to_hash)
102
- when opts.respond_to?(:to_h)
103
- new(opts.to_h)
104
- else
105
- SAFE_STATE_PROTOTYPE.dup
106
- end
107
- end
108
-
109
- # Instantiates a new State object, configured by _opts_.
110
- #
111
- # _opts_ can have the following keys:
112
- #
113
- # * *indent*: a string used to indent levels (default: ''),
114
- # * *space*: a string that is put after, a : or , delimiter (default: ''),
115
- # * *space_before*: a string that is put before a : pair delimiter (default: ''),
116
- # * *object_nl*: a string that is put at the end of a JSON object (default: ''),
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)
119
- # * *check_circular*: is deprecated now, use the :max_nesting option instead,
120
- # * *max_nesting*: sets the maximum level of data structure nesting in
121
- # the generated JSON, max_nesting = 0 if no maximum should be checked.
122
- # * *allow_nan*: true if NaN, Infinity, and -Infinity should be
123
- # generated, otherwise an exception is thrown, if these values are
124
- # encountered. This options defaults to false.
125
- def initialize(opts = {})
126
- @indent = ''
127
- @space = ''
128
- @space_before = ''
129
- @object_nl = ''
130
- @array_nl = ''
131
- @allow_nan = false
132
- @ascii_only = false
133
- @escape_slash = false
134
- @buffer_initial_length = 1024
135
- configure opts
136
- end
137
-
138
- # This string is used to indent levels in the JSON text.
139
- attr_accessor :indent
140
-
141
- # This string is used to insert a space between the tokens in a JSON
142
- # string.
143
- attr_accessor :space
144
-
145
- # This string is used to insert a space before the ':' in JSON objects.
146
- attr_accessor :space_before
147
-
148
- # This string is put at the end of a line that holds a JSON object (or
149
- # Hash).
150
- attr_accessor :object_nl
151
-
152
- # This string is put at the end of a line that holds a JSON array.
153
- attr_accessor :array_nl
154
-
155
- # This integer returns the maximum level of data structure nesting in
156
- # the generated JSON, max_nesting = 0 if no maximum is checked.
157
- attr_accessor :max_nesting
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
-
163
- # :stopdoc:
164
- attr_reader :buffer_initial_length
165
-
166
- def buffer_initial_length=(length)
167
- if length > 0
168
- @buffer_initial_length = length
169
- end
170
- end
171
- # :startdoc:
172
-
173
- # This integer returns the current depth data structure nesting in the
174
- # generated JSON.
175
- attr_accessor :depth
176
-
177
- def check_max_nesting # :nodoc:
178
- return if @max_nesting.zero?
179
- current_nesting = depth + 1
180
- current_nesting > @max_nesting and
181
- raise NestingError, "nesting of #{current_nesting} is too deep"
182
- end
183
-
184
- # Returns true, if circular data structures are checked,
185
- # otherwise returns false.
186
- def check_circular?
187
- !@max_nesting.zero?
188
- end
189
-
190
- # Returns true if NaN, Infinity, and -Infinity should be considered as
191
- # valid JSON and output.
192
- def allow_nan?
193
- @allow_nan
194
- end
195
-
196
- # Returns true, if only ASCII characters should be generated. Otherwise
197
- # returns false.
198
- def ascii_only?
199
- @ascii_only
200
- end
201
-
202
- # Returns true, if forward slashes are escaped. Otherwise returns false.
203
- def escape_slash?
204
- @escape_slash
205
- end
206
-
207
- # Configure this State instance with the Hash _opts_, and return
208
- # itself.
209
- def configure(opts)
210
- if opts.respond_to?(:to_hash)
211
- opts = opts.to_hash
212
- elsif opts.respond_to?(:to_h)
213
- opts = opts.to_h
214
- else
215
- raise TypeError, "can't convert #{opts.class} into Hash"
216
- end
217
- for key, value in opts
218
- instance_variable_set "@#{key}", value
219
- end
220
- @indent = opts[:indent] if opts.key?(:indent)
221
- @space = opts[:space] if opts.key?(:space)
222
- @space_before = opts[:space_before] if opts.key?(:space_before)
223
- @object_nl = opts[:object_nl] if opts.key?(:object_nl)
224
- @array_nl = opts[:array_nl] if opts.key?(:array_nl)
225
- @allow_nan = !!opts[:allow_nan] if opts.key?(:allow_nan)
226
- @ascii_only = opts[:ascii_only] if opts.key?(:ascii_only)
227
- @depth = opts[:depth] || 0
228
- @buffer_initial_length ||= opts[:buffer_initial_length]
229
- @escape_slash = !!opts[:escape_slash] if opts.key?(:escape_slash)
230
-
231
- if !opts.key?(:max_nesting) # defaults to 100
232
- @max_nesting = 100
233
- elsif opts[:max_nesting]
234
- @max_nesting = opts[:max_nesting]
235
- else
236
- @max_nesting = 0
237
- end
238
- self
239
- end
240
- alias merge configure
241
-
242
- # Returns the configuration instance variables as a hash, that can be
243
- # passed to the configure method.
244
- def to_h
245
- result = {}
246
- for iv in instance_variables
247
- iv = iv.to_s[1..-1]
248
- result[iv.to_sym] = self[iv]
249
- end
250
- result
251
- end
252
-
253
- alias to_hash to_h
254
-
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
258
- # GeneratorError exception.
259
- def generate(obj)
260
- result = obj.to_json(self)
261
- JSON.valid_utf8?(result) or raise GeneratorError,
262
- "source sequence #{result.inspect} is illegal/malformed utf-8"
263
- result
264
- end
265
-
266
- # Return the value returned by method +name+.
267
- def [](name)
268
- if respond_to?(name)
269
- __send__(name)
270
- else
271
- instance_variable_get("@#{name}") if
272
- instance_variables.include?("@#{name}".to_sym) # avoid warning
273
- end
274
- end
275
-
276
- def []=(name, value)
277
- if respond_to?(name_writer = "#{name}=")
278
- __send__ name_writer, value
279
- else
280
- instance_variable_set "@#{name}", value
281
- end
282
- end
283
- end
284
-
285
- module GeneratorMethods
286
- module Object
287
- # Converts this object to a string (calling #to_s), converts
288
- # it to a JSON string, and returns the result. This is a fallback, if no
289
- # special method #to_json was defined for some object.
290
- def to_json(*) to_s.to_json end
291
- end
292
-
293
- module Hash
294
- # Returns a JSON string containing a JSON object, that is unparsed from
295
- # this Hash instance.
296
- # _state_ is a JSON::State object, that can also be used to configure the
297
- # produced JSON string output further.
298
- # _depth_ is used to find out nesting depth, to indent accordingly.
299
- def to_json(state = nil, *)
300
- state = State.from_state(state)
301
- state.check_max_nesting
302
- json_transform(state)
303
- end
304
-
305
- private
306
-
307
- def json_shift(state)
308
- state.object_nl.empty? or return ''
309
- state.indent * state.depth
310
- end
311
-
312
- def json_transform(state)
313
- delim = ','
314
- delim << state.object_nl
315
- result = '{'
316
- result << state.object_nl
317
- depth = state.depth += 1
318
- first = true
319
- indent = !state.object_nl.empty?
320
- each { |key,value|
321
- result << delim unless first
322
- result << state.indent * depth if indent
323
- result << key.to_s.to_json(state)
324
- result << state.space_before
325
- result << ':'
326
- result << state.space
327
- if value.respond_to?(:to_json)
328
- result << value.to_json(state)
329
- else
330
- result << %{"#{String(value)}"}
331
- end
332
- first = false
333
- }
334
- depth = state.depth -= 1
335
- unless first
336
- result << state.object_nl
337
- result << state.indent * depth if indent
338
- end
339
- result << '}'
340
- result
341
- end
342
- end
343
-
344
- module Array
345
- # Returns a JSON string containing a JSON array, that is unparsed from
346
- # this Array instance.
347
- # _state_ is a JSON::State object, that can also be used to configure the
348
- # produced JSON string output further.
349
- def to_json(state = nil, *)
350
- state = State.from_state(state)
351
- state.check_max_nesting
352
- json_transform(state)
353
- end
354
-
355
- private
356
-
357
- def json_transform(state)
358
- delim = ','
359
- delim << state.array_nl
360
- result = '['
361
- result << state.array_nl
362
- depth = state.depth += 1
363
- first = true
364
- indent = !state.array_nl.empty?
365
- each { |value|
366
- result << delim unless first
367
- result << state.indent * depth if indent
368
- if value.respond_to?(:to_json)
369
- result << value.to_json(state)
370
- else
371
- result << %{"#{String(value)}"}
372
- end
373
- first = false
374
- }
375
- depth = state.depth -= 1
376
- result << state.array_nl
377
- result << state.indent * depth if indent
378
- result << ']'
379
- end
380
- end
381
-
382
- module Integer
383
- # Returns a JSON string representation for this Integer number.
384
- def to_json(*) to_s end
385
- end
386
-
387
- module Float
388
- # Returns a JSON string representation for this Float number.
389
- def to_json(state = nil, *)
390
- state = State.from_state(state)
391
- case
392
- when infinite?
393
- if state.allow_nan?
394
- to_s
395
- else
396
- raise GeneratorError, "#{self} not allowed in JSON"
397
- end
398
- when nan?
399
- if state.allow_nan?
400
- to_s
401
- else
402
- raise GeneratorError, "#{self} not allowed in JSON"
403
- end
404
- else
405
- to_s
406
- end
407
- end
408
- end
409
-
410
- module String
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)
420
- 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) << '"'
425
- end
426
- end
427
-
428
- # Module that holds the extending methods if, the String module is
429
- # included.
430
- module Extend
431
- # Raw Strings are JSON Objects (the raw bytes are stored in an
432
- # array for the key "raw"). The Ruby String can be created by this
433
- # module method.
434
- def json_create(o)
435
- o['raw'].pack('C*')
436
- end
437
- end
438
-
439
- # Extends _modul_ with the String::Extend module.
440
- def self.included(modul)
441
- modul.extend Extend
442
- end
443
-
444
- # This method creates a raw object hash, that can be nested into
445
- # other data structures and will be unparsed as a raw string. This
446
- # method should be used, if you want to convert raw strings to JSON
447
- # instead of UTF-8 strings, e. g. binary data.
448
- def to_json_raw_object
449
- {
450
- JSON.create_id => self.class.name,
451
- 'raw' => self.unpack('C*'),
452
- }
453
- end
454
-
455
- # This method creates a JSON text from the result of
456
- # a call to to_json_raw_object of this String.
457
- def to_json_raw(*args)
458
- to_json_raw_object.to_json(*args)
459
- end
460
- end
461
-
462
- module TrueClass
463
- # Returns a JSON string for true: 'true'.
464
- def to_json(*) 'true' end
465
- end
466
-
467
- module FalseClass
468
- # Returns a JSON string for false: 'false'.
469
- def to_json(*) 'false' end
470
- end
471
-
472
- module NilClass
473
- # Returns a JSON string for nil: 'null'.
474
- def to_json(*) 'null' end
475
- end
476
- end
477
- end
478
- end
479
- end