scout 5.1.2 → 5.1.3
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.
- data/CHANGELOG +5 -0
- data/lib/scout.rb +1 -1
- data/lib/scout/server.rb +4 -1
- data/vendor/json_pure/CHANGES +43 -0
- data/vendor/json_pure/{RUBY → COPYING} +1 -1
- data/vendor/json_pure/GPL +7 -7
- data/vendor/json_pure/README +319 -39
- data/vendor/json_pure/Rakefile +69 -47
- data/vendor/json_pure/VERSION +1 -1
- data/vendor/json_pure/benchmarks/generator2_benchmark.rb +222 -0
- data/vendor/json_pure/benchmarks/generator_benchmark.rb +64 -5
- data/vendor/json_pure/benchmarks/ohai.json +1216 -0
- data/vendor/json_pure/benchmarks/ohai.ruby +1 -0
- data/vendor/json_pure/benchmarks/parser2_benchmark.rb +251 -0
- data/vendor/json_pure/benchmarks/parser_benchmark.rb +67 -5
- data/vendor/json_pure/ext/json/ext/generator/extconf.rb +9 -4
- data/vendor/json_pure/ext/json/ext/generator/generator.c +831 -409
- data/vendor/json_pure/ext/json/ext/generator/generator.h +170 -0
- data/vendor/json_pure/ext/json/ext/parser/extconf.rb +8 -4
- data/vendor/json_pure/ext/json/ext/parser/parser.c +292 -186
- data/vendor/json_pure/ext/json/ext/parser/parser.h +71 -0
- data/vendor/json_pure/ext/json/ext/parser/parser.rl +218 -112
- data/vendor/json_pure/lib/json/add/core.rb +20 -7
- data/vendor/json_pure/lib/json/add/rails.rb +2 -2
- data/vendor/json_pure/lib/json/common.rb +85 -42
- data/vendor/json_pure/lib/json/pure.rb +3 -3
- data/vendor/json_pure/lib/json/pure/generator.rb +112 -90
- data/vendor/json_pure/lib/json/pure/parser.rb +42 -4
- data/vendor/json_pure/lib/json/version.rb +1 -1
- data/vendor/json_pure/tests/test_json.rb +46 -18
- data/vendor/json_pure/tests/test_json_addition.rb +4 -6
- data/vendor/json_pure/tests/test_json_encoding.rb +68 -0
- data/vendor/json_pure/tests/test_json_generate.rb +30 -14
- data/vendor/json_pure/tests/test_json_rails.rb +5 -7
- data/vendor/json_pure/tests/test_json_unicode.rb +20 -6
- metadata +26 -15
- data/vendor/json_pure/doc-templates/main.txt +0 -283
- data/vendor/json_pure/ext/json/ext/generator/unicode.c +0 -182
- data/vendor/json_pure/ext/json/ext/generator/unicode.h +0 -53
- data/vendor/json_pure/ext/json/ext/parser/unicode.c +0 -154
- data/vendor/json_pure/ext/json/ext/parser/unicode.h +0 -58
@@ -7,6 +7,19 @@ unless Object.const_defined?(:JSON) and ::JSON.const_defined?(:JSON_LOADED) and
|
|
7
7
|
end
|
8
8
|
require 'date'
|
9
9
|
|
10
|
+
class Symbol
|
11
|
+
def to_json(*a)
|
12
|
+
{
|
13
|
+
JSON.create_id => self.class.name,
|
14
|
+
's' => to_s,
|
15
|
+
}.to_json(*a)
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.json_create(o)
|
19
|
+
o['s'].to_sym
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
10
23
|
class Time
|
11
24
|
def self.json_create(object)
|
12
25
|
if usec = object.delete('u') # used to be tv_usec -> tv_nsec
|
@@ -21,7 +34,7 @@ class Time
|
|
21
34
|
|
22
35
|
def to_json(*args)
|
23
36
|
{
|
24
|
-
|
37
|
+
JSON.create_id => self.class.name,
|
25
38
|
's' => tv_sec,
|
26
39
|
'n' => respond_to?(:tv_nsec) ? tv_nsec : tv_usec * 1000
|
27
40
|
}.to_json(*args)
|
@@ -37,7 +50,7 @@ class Date
|
|
37
50
|
|
38
51
|
def to_json(*args)
|
39
52
|
{
|
40
|
-
|
53
|
+
JSON.create_id => self.class.name,
|
41
54
|
'y' => year,
|
42
55
|
'm' => month,
|
43
56
|
'd' => day,
|
@@ -63,7 +76,7 @@ class DateTime
|
|
63
76
|
|
64
77
|
def to_json(*args)
|
65
78
|
{
|
66
|
-
|
79
|
+
JSON.create_id => self.class.name,
|
67
80
|
'y' => year,
|
68
81
|
'm' => month,
|
69
82
|
'd' => day,
|
@@ -83,7 +96,7 @@ class Range
|
|
83
96
|
|
84
97
|
def to_json(*args)
|
85
98
|
{
|
86
|
-
|
99
|
+
JSON.create_id => self.class.name,
|
87
100
|
'a' => [ first, last, exclude_end? ]
|
88
101
|
}.to_json(*args)
|
89
102
|
end
|
@@ -98,7 +111,7 @@ class Struct
|
|
98
111
|
klass = self.class.name
|
99
112
|
klass.to_s.empty? and raise JSON::JSONError, "Only named structs are supported!"
|
100
113
|
{
|
101
|
-
|
114
|
+
JSON.create_id => klass,
|
102
115
|
'v' => values,
|
103
116
|
}.to_json(*args)
|
104
117
|
end
|
@@ -113,7 +126,7 @@ class Exception
|
|
113
126
|
|
114
127
|
def to_json(*args)
|
115
128
|
{
|
116
|
-
|
129
|
+
JSON.create_id => self.class.name,
|
117
130
|
'm' => message,
|
118
131
|
'b' => backtrace,
|
119
132
|
}.to_json(*args)
|
@@ -127,7 +140,7 @@ class Regexp
|
|
127
140
|
|
128
141
|
def to_json(*)
|
129
142
|
{
|
130
|
-
|
143
|
+
JSON.create_id => self.class.name,
|
131
144
|
'o' => options,
|
132
145
|
's' => source,
|
133
146
|
}.to_json
|
@@ -10,7 +10,7 @@ class Object
|
|
10
10
|
def self.json_create(object)
|
11
11
|
obj = new
|
12
12
|
for key, value in object
|
13
|
-
next if key ==
|
13
|
+
next if key == JSON.create_id
|
14
14
|
instance_variable_set "@#{key}", value
|
15
15
|
end
|
16
16
|
obj
|
@@ -18,7 +18,7 @@ class Object
|
|
18
18
|
|
19
19
|
def to_json(*a)
|
20
20
|
result = {
|
21
|
-
|
21
|
+
JSON.create_id => self.class.name
|
22
22
|
}
|
23
23
|
instance_variables.inject(result) do |r, name|
|
24
24
|
r[name[1..-1]] = instance_variable_get name
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'json/version'
|
2
|
+
require 'iconv'
|
2
3
|
|
3
4
|
module JSON
|
4
5
|
class << self
|
@@ -32,12 +33,16 @@ module JSON
|
|
32
33
|
# level (absolute namespace path?). If there doesn't exist a constant at
|
33
34
|
# the given path, an ArgumentError is raised.
|
34
35
|
def deep_const_get(path) # :nodoc:
|
35
|
-
path
|
36
|
-
path.split(/::/).inject(Object) do |p, c|
|
36
|
+
path.to_s.split(/::/).inject(Object) do |p, c|
|
37
37
|
case
|
38
38
|
when c.empty? then p
|
39
39
|
when p.const_defined?(c) then p.const_get(c)
|
40
|
-
else
|
40
|
+
else
|
41
|
+
begin
|
42
|
+
p.const_missing(c)
|
43
|
+
rescue NameError
|
44
|
+
raise ArgumentError, "can't find const #{path}"
|
45
|
+
end
|
41
46
|
end
|
42
47
|
end
|
43
48
|
end
|
@@ -58,6 +63,20 @@ module JSON
|
|
58
63
|
end
|
59
64
|
self.state = generator::State
|
60
65
|
const_set :State, self.state
|
66
|
+
const_set :SAFE_STATE_PROTOTYPE, State.new.freeze
|
67
|
+
const_set :FAST_STATE_PROTOTYPE, State.new(
|
68
|
+
:indent => '',
|
69
|
+
:space => '',
|
70
|
+
:object_nl => "",
|
71
|
+
:array_nl => "",
|
72
|
+
:max_nesting => false
|
73
|
+
).freeze
|
74
|
+
const_set :PRETTY_STATE_PROTOTYPE, State.new(
|
75
|
+
:indent => ' ',
|
76
|
+
:space => ' ',
|
77
|
+
:object_nl => "\n",
|
78
|
+
:array_nl => "\n"
|
79
|
+
).freeze
|
61
80
|
end
|
62
81
|
|
63
82
|
# Returns the JSON generator modul, that is used by JSON. This might be
|
@@ -74,7 +93,7 @@ module JSON
|
|
74
93
|
end
|
75
94
|
self.create_id = 'json_class'
|
76
95
|
|
77
|
-
NaN =
|
96
|
+
NaN = 0.0/0
|
78
97
|
|
79
98
|
Infinity = 1.0/0
|
80
99
|
|
@@ -90,22 +109,22 @@ module JSON
|
|
90
109
|
# deep.
|
91
110
|
class NestingError < ParserError; end
|
92
111
|
|
112
|
+
# :stopdoc:
|
113
|
+
class CircularDatastructure < NestingError; end
|
114
|
+
# :startdoc:
|
115
|
+
|
93
116
|
# This exception is raised, if a generator or unparser error occurs.
|
94
117
|
class GeneratorError < JSONError; end
|
95
118
|
# For backwards compatibility
|
96
119
|
UnparserError = GeneratorError
|
97
120
|
|
98
|
-
# If a circular data structure is encountered while unparsing
|
99
|
-
# this exception is raised.
|
100
|
-
class CircularDatastructure < GeneratorError; end
|
101
|
-
|
102
121
|
# This exception is raised, if the required unicode support is missing on the
|
103
122
|
# system. Usually this means, that the iconv library is not installed.
|
104
123
|
class MissingUnicodeSupport < JSONError; end
|
105
124
|
|
106
125
|
module_function
|
107
126
|
|
108
|
-
# Parse the JSON
|
127
|
+
# Parse the JSON document _source_ into a Ruby data structure and return it.
|
109
128
|
#
|
110
129
|
# _opts_ can have the following
|
111
130
|
# keys:
|
@@ -115,16 +134,21 @@ module JSON
|
|
115
134
|
# * *allow_nan*: If set to true, allow NaN, Infinity and -Infinity in
|
116
135
|
# defiance of RFC 4627 to be parsed by the Parser. This option defaults
|
117
136
|
# to false.
|
137
|
+
# * *symbolize_names*: If set to true, returns symbols for the names
|
138
|
+
# (keys) in a JSON object. Otherwise strings are returned, which is also
|
139
|
+
# the default.
|
118
140
|
# * *create_additions*: If set to false, the Parser doesn't create
|
119
141
|
# additions even if a matchin class and create_id was found. This option
|
120
142
|
# defaults to true.
|
143
|
+
# * *object_class*: Defaults to Hash
|
144
|
+
# * *array_class*: Defaults to Array
|
121
145
|
def parse(source, opts = {})
|
122
|
-
|
146
|
+
Parser.new(source, opts).parse
|
123
147
|
end
|
124
148
|
|
125
|
-
# Parse the JSON
|
149
|
+
# Parse the JSON document _source_ into a Ruby data structure and return it.
|
126
150
|
# The bang version of the parse method, defaults to the more dangerous values
|
127
|
-
# for the _opts_ hash, so be sure only to parse trusted _source_
|
151
|
+
# for the _opts_ hash, so be sure only to parse trusted _source_ documents.
|
128
152
|
#
|
129
153
|
# _opts_ can have the following keys:
|
130
154
|
# * *max_nesting*: The maximum depth of nesting allowed in the parsed data
|
@@ -139,15 +163,14 @@ module JSON
|
|
139
163
|
# defaults to true.
|
140
164
|
def parse!(source, opts = {})
|
141
165
|
opts = {
|
142
|
-
:max_nesting
|
143
|
-
:allow_nan
|
166
|
+
:max_nesting => false,
|
167
|
+
:allow_nan => true
|
144
168
|
}.update(opts)
|
145
|
-
|
169
|
+
Parser.new(source, opts).parse
|
146
170
|
end
|
147
171
|
|
148
|
-
#
|
149
|
-
#
|
150
|
-
# * a JSON::State object,
|
172
|
+
# Generate a JSON document from the Ruby data structure _obj_ and return
|
173
|
+
# it. _state_ is * a JSON::State object,
|
151
174
|
# * or a Hash like object (responding to to_hash),
|
152
175
|
# * an object convertible into a hash by a to_h method,
|
153
176
|
# that is used as or to configure a State object.
|
@@ -162,8 +185,6 @@ module JSON
|
|
162
185
|
# * *space_before*: a string that is put before a : pair delimiter (default: ''),
|
163
186
|
# * *object_nl*: a string that is put at the end of a JSON object (default: ''),
|
164
187
|
# * *array_nl*: a string that is put at the end of a JSON array (default: ''),
|
165
|
-
# * *check_circular*: true if checking for circular data structures
|
166
|
-
# should be done (the default), false otherwise.
|
167
188
|
# * *allow_nan*: true if NaN, Infinity, and -Infinity should be
|
168
189
|
# generated, otherwise an exception is thrown, if these values are
|
169
190
|
# encountered. This options defaults to false.
|
@@ -174,13 +195,21 @@ module JSON
|
|
174
195
|
# See also the fast_generate for the fastest creation method with the least
|
175
196
|
# amount of sanity checks, and the pretty_generate method for some
|
176
197
|
# defaults for a pretty output.
|
177
|
-
def generate(obj,
|
178
|
-
if
|
179
|
-
|
198
|
+
def generate(obj, opts = nil)
|
199
|
+
if opts
|
200
|
+
if opts.respond_to? :to_hash
|
201
|
+
opts = opts.to_hash
|
202
|
+
elsif opts.respond_to? :to_h
|
203
|
+
opts = opts.to_h
|
204
|
+
else
|
205
|
+
raise TypeError, "can't convert #{opts.class} into Hash"
|
206
|
+
end
|
207
|
+
state = SAFE_STATE_PROTOTYPE.dup
|
208
|
+
state = state.configure(opts)
|
180
209
|
else
|
181
|
-
state =
|
210
|
+
state = SAFE_STATE_PROTOTYPE
|
182
211
|
end
|
183
|
-
|
212
|
+
state.generate(obj)
|
184
213
|
end
|
185
214
|
|
186
215
|
# :stopdoc:
|
@@ -190,14 +219,26 @@ module JSON
|
|
190
219
|
module_function :unparse
|
191
220
|
# :startdoc:
|
192
221
|
|
193
|
-
#
|
194
|
-
#
|
195
|
-
# also generates NaN, Infinity, and, -Infinity float values.
|
222
|
+
# Generate a JSON document from the Ruby data structure _obj_ and return it.
|
223
|
+
# This method disables the checks for circles in Ruby objects.
|
196
224
|
#
|
197
225
|
# *WARNING*: Be careful not to pass any Ruby data structures with circles as
|
198
226
|
# _obj_ argument, because this will cause JSON to go into an infinite loop.
|
199
|
-
def fast_generate(obj)
|
200
|
-
|
227
|
+
def fast_generate(obj, opts = nil)
|
228
|
+
if opts
|
229
|
+
if opts.respond_to? :to_hash
|
230
|
+
opts = opts.to_hash
|
231
|
+
elsif opts.respond_to? :to_h
|
232
|
+
opts = opts.to_h
|
233
|
+
else
|
234
|
+
raise TypeError, "can't convert #{opts.class} into Hash"
|
235
|
+
end
|
236
|
+
state = FAST_STATE_PROTOTYPE.dup
|
237
|
+
state.configure(opts)
|
238
|
+
else
|
239
|
+
state = FAST_STATE_PROTOTYPE
|
240
|
+
end
|
241
|
+
state.generate(obj)
|
201
242
|
end
|
202
243
|
|
203
244
|
# :stopdoc:
|
@@ -206,19 +247,13 @@ module JSON
|
|
206
247
|
module_function :fast_unparse
|
207
248
|
# :startdoc:
|
208
249
|
|
209
|
-
#
|
210
|
-
# returned
|
250
|
+
# Generate a JSON document from the Ruby data structure _obj_ and return it.
|
251
|
+
# The returned document is a prettier form of the document returned by
|
252
|
+
# #unparse.
|
211
253
|
#
|
212
254
|
# The _opts_ argument can be used to configure the generator, see the
|
213
255
|
# generate method for a more detailed explanation.
|
214
256
|
def pretty_generate(obj, opts = nil)
|
215
|
-
state = JSON.state.new(
|
216
|
-
:indent => ' ',
|
217
|
-
:space => ' ',
|
218
|
-
:object_nl => "\n",
|
219
|
-
:array_nl => "\n",
|
220
|
-
:check_circular => true
|
221
|
-
)
|
222
257
|
if opts
|
223
258
|
if opts.respond_to? :to_hash
|
224
259
|
opts = opts.to_hash
|
@@ -227,9 +262,12 @@ module JSON
|
|
227
262
|
else
|
228
263
|
raise TypeError, "can't convert #{opts.class} into Hash"
|
229
264
|
end
|
265
|
+
state = PRETTY_STATE_PROTOTYPE.dup
|
230
266
|
state.configure(opts)
|
267
|
+
else
|
268
|
+
state = PRETTY_STATE_PROTOTYPE
|
231
269
|
end
|
232
|
-
|
270
|
+
state.generate(obj)
|
233
271
|
end
|
234
272
|
|
235
273
|
# :stopdoc:
|
@@ -270,8 +308,6 @@ module JSON
|
|
270
308
|
proc.call result
|
271
309
|
end
|
272
310
|
end
|
273
|
-
private :recurse_proc
|
274
|
-
module_function :recurse_proc
|
275
311
|
|
276
312
|
alias restore load
|
277
313
|
module_function :restore
|
@@ -307,9 +343,16 @@ module JSON
|
|
307
343
|
rescue JSON::NestingError
|
308
344
|
raise ArgumentError, "exceed depth limit"
|
309
345
|
end
|
346
|
+
|
347
|
+
# Shortuct for iconv.
|
348
|
+
def self.iconv(to, from, string)
|
349
|
+
Iconv.iconv(to, from, string).first
|
350
|
+
end
|
310
351
|
end
|
311
352
|
|
312
353
|
module ::Kernel
|
354
|
+
private
|
355
|
+
|
313
356
|
# Outputs _objs_ to STDOUT as JSON strings in the shortest form, that is in
|
314
357
|
# one line.
|
315
358
|
def j(*objs)
|
@@ -10,6 +10,9 @@ module JSON
|
|
10
10
|
# An iconv instance to convert from UTF16 Big Endian to UTF8.
|
11
11
|
UTF8toUTF16 = Iconv.new('utf-16be', 'utf-8') # :nodoc:
|
12
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"
|
13
16
|
rescue Errno::EINVAL, Iconv::InvalidEncoding
|
14
17
|
# Iconv doesn't support big endian utf-16. Let's try to hack this manually
|
15
18
|
# into the converters.
|
@@ -51,9 +54,6 @@ module JSON
|
|
51
54
|
ensure
|
52
55
|
$VERBOSE = old_verbose
|
53
56
|
end
|
54
|
-
rescue LoadError
|
55
|
-
raise MissingUnicodeSupport,
|
56
|
-
"iconv couldn't be loaded, which is required for UTF-8/UTF-16 conversions"
|
57
57
|
end
|
58
58
|
|
59
59
|
# Swap consecutive bytes of _string_ in place.
|
@@ -34,17 +34,25 @@ module JSON
|
|
34
34
|
"\x1f" => '\u001f',
|
35
35
|
'"' => '\"',
|
36
36
|
'\\' => '\\\\',
|
37
|
-
'/' => '\/',
|
38
37
|
} # :nodoc:
|
39
38
|
|
40
39
|
# Convert a UTF8 encoded Ruby string _string_ to a JSON string, encoded with
|
41
40
|
# UTF16 big endian characters as \u????, and return it.
|
42
|
-
if
|
41
|
+
if defined?(::Encoding)
|
43
42
|
def utf8_to_json(string) # :nodoc:
|
44
43
|
string = string.dup
|
45
44
|
string << '' # XXX workaround: avoid buffer sharing
|
46
|
-
string.force_encoding(Encoding::ASCII_8BIT)
|
47
|
-
string.gsub!(/["
|
45
|
+
string.force_encoding(::Encoding::ASCII_8BIT)
|
46
|
+
string.gsub!(/["\\\x0-\x1f]/) { MAP[$&] }
|
47
|
+
string.force_encoding(::Encoding::UTF_8)
|
48
|
+
string
|
49
|
+
end
|
50
|
+
|
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[$&] }
|
48
56
|
string.gsub!(/(
|
49
57
|
(?:
|
50
58
|
[\xc2-\xdf][\x80-\xbf] |
|
@@ -57,14 +65,18 @@ module JSON
|
|
57
65
|
s = JSON::UTF8toUTF16.iconv(c).unpack('H*')[0]
|
58
66
|
s.gsub!(/.{4}/n, '\\\\u\&')
|
59
67
|
}
|
60
|
-
string.force_encoding(Encoding::UTF_8)
|
68
|
+
string.force_encoding(::Encoding::UTF_8)
|
61
69
|
string
|
62
70
|
rescue Iconv::Failure => e
|
63
71
|
raise GeneratorError, "Caught #{e.class}: #{e}"
|
64
72
|
end
|
65
73
|
else
|
66
74
|
def utf8_to_json(string) # :nodoc:
|
67
|
-
string
|
75
|
+
string.gsub(/["\\\x0-\x1f]/) { MAP[$&] }
|
76
|
+
end
|
77
|
+
|
78
|
+
def utf8_to_json_ascii(string) # :nodoc:
|
79
|
+
string = string.gsub(/["\\\x0-\x1f]/) { MAP[$&] }
|
68
80
|
string.gsub!(/(
|
69
81
|
(?:
|
70
82
|
[\xc2-\xdf][\x80-\xbf] |
|
@@ -82,7 +94,7 @@ module JSON
|
|
82
94
|
raise GeneratorError, "Caught #{e.class}: #{e}"
|
83
95
|
end
|
84
96
|
end
|
85
|
-
module_function :utf8_to_json
|
97
|
+
module_function :utf8_to_json, :utf8_to_json_ascii
|
86
98
|
|
87
99
|
module Pure
|
88
100
|
module Generator
|
@@ -100,7 +112,7 @@ module JSON
|
|
100
112
|
when Hash
|
101
113
|
new(opts)
|
102
114
|
else
|
103
|
-
|
115
|
+
SAFE_STATE_PROTOTYPE
|
104
116
|
end
|
105
117
|
end
|
106
118
|
|
@@ -113,22 +125,20 @@ module JSON
|
|
113
125
|
# * *space_before*: a string that is put before a : pair delimiter (default: ''),
|
114
126
|
# * *object_nl*: a string that is put at the end of a JSON object (default: ''),
|
115
127
|
# * *array_nl*: a string that is put at the end of a JSON array (default: ''),
|
116
|
-
# * *check_circular*:
|
117
|
-
#
|
118
|
-
#
|
119
|
-
# should be done, false (the default) otherwise.
|
128
|
+
# * *check_circular*: is deprecated now, use the :max_nesting option instead,
|
129
|
+
# * *max_nesting*: sets the maximum level of data structure nesting in
|
130
|
+
# the generated JSON, max_nesting = 0 if no maximum should be checked.
|
120
131
|
# * *allow_nan*: true if NaN, Infinity, and -Infinity should be
|
121
132
|
# generated, otherwise an exception is thrown, if these values are
|
122
133
|
# encountered. This options defaults to false.
|
123
134
|
def initialize(opts = {})
|
124
|
-
@seen = {}
|
125
135
|
@indent = ''
|
126
136
|
@space = ''
|
127
137
|
@space_before = ''
|
128
138
|
@object_nl = ''
|
129
139
|
@array_nl = ''
|
130
|
-
@check_circular = true
|
131
140
|
@allow_nan = false
|
141
|
+
@ascii_only = false
|
132
142
|
configure opts
|
133
143
|
end
|
134
144
|
|
@@ -160,10 +170,10 @@ module JSON
|
|
160
170
|
raise NestingError, "nesting of #{current_nesting} is too deep"
|
161
171
|
end
|
162
172
|
|
163
|
-
# Returns true, if circular data structures
|
173
|
+
# Returns true, if circular data structures are checked,
|
164
174
|
# otherwise returns false.
|
165
175
|
def check_circular?
|
166
|
-
|
176
|
+
!@max_nesting.zero?
|
167
177
|
end
|
168
178
|
|
169
179
|
# Returns true if NaN, Infinity, and -Infinity should be considered as
|
@@ -172,21 +182,8 @@ module JSON
|
|
172
182
|
@allow_nan
|
173
183
|
end
|
174
184
|
|
175
|
-
|
176
|
-
|
177
|
-
def seen?(object)
|
178
|
-
@seen.key?(object.__id__)
|
179
|
-
end
|
180
|
-
|
181
|
-
# Remember _object_, to find out if it was already encountered (if a
|
182
|
-
# cyclic data structure is if a cyclic data structure is rendered).
|
183
|
-
def remember(object)
|
184
|
-
@seen[object.__id__] = true
|
185
|
-
end
|
186
|
-
|
187
|
-
# Forget _object_ for this generating run.
|
188
|
-
def forget(object)
|
189
|
-
@seen.delete object.__id__
|
185
|
+
def ascii_only?
|
186
|
+
@ascii_only
|
190
187
|
end
|
191
188
|
|
192
189
|
# Configure this State instance with the Hash _opts_, and return
|
@@ -197,8 +194,8 @@ module JSON
|
|
197
194
|
@space_before = opts[:space_before] if opts.key?(:space_before)
|
198
195
|
@object_nl = opts[:object_nl] if opts.key?(:object_nl)
|
199
196
|
@array_nl = opts[:array_nl] if opts.key?(:array_nl)
|
200
|
-
@check_circular = !!opts[:check_circular] if opts.key?(:check_circular)
|
201
197
|
@allow_nan = !!opts[:allow_nan] if opts.key?(:allow_nan)
|
198
|
+
@ascii_only = opts[:ascii_only] if opts.key?(:ascii_only)
|
202
199
|
if !opts.key?(:max_nesting) # defaults to 19
|
203
200
|
@max_nesting = 19
|
204
201
|
elsif opts[:max_nesting]
|
@@ -213,11 +210,27 @@ module JSON
|
|
213
210
|
# passed to the configure method.
|
214
211
|
def to_h
|
215
212
|
result = {}
|
216
|
-
for iv in %w[indent space space_before object_nl array_nl
|
213
|
+
for iv in %w[indent space space_before object_nl array_nl allow_nan max_nesting]
|
217
214
|
result[iv.intern] = instance_variable_get("@#{iv}")
|
218
215
|
end
|
219
216
|
result
|
220
217
|
end
|
218
|
+
|
219
|
+
# Generates a valid JSON document from object +obj+ and returns the
|
220
|
+
# result. If no valid JSON document can be created this method raises a
|
221
|
+
# GeneratorError exception.
|
222
|
+
def generate(obj)
|
223
|
+
result = obj.to_json(self)
|
224
|
+
if result !~ /\A\s*(?:\[.*\]|\{.*\})\s*\Z/m
|
225
|
+
raise GeneratorError, "only generation of JSON objects or arrays allowed"
|
226
|
+
end
|
227
|
+
result
|
228
|
+
end
|
229
|
+
|
230
|
+
# Return the value returned by method +name+.
|
231
|
+
def [](name)
|
232
|
+
__send__ name
|
233
|
+
end
|
221
234
|
end
|
222
235
|
|
223
236
|
module GeneratorMethods
|
@@ -236,27 +249,14 @@ module JSON
|
|
236
249
|
# _depth_ is used to find out nesting depth, to indent accordingly.
|
237
250
|
def to_json(state = nil, depth = 0, *)
|
238
251
|
if state
|
239
|
-
state =
|
252
|
+
state = State.from_state(state)
|
240
253
|
state.check_max_nesting(depth)
|
241
|
-
json_check_circular(state) { json_transform(state, depth) }
|
242
|
-
else
|
243
|
-
json_transform(state, depth)
|
244
254
|
end
|
255
|
+
json_transform(state, depth)
|
245
256
|
end
|
246
257
|
|
247
258
|
private
|
248
259
|
|
249
|
-
def json_check_circular(state)
|
250
|
-
if state and state.check_circular?
|
251
|
-
state.seen?(self) and raise JSON::CircularDatastructure,
|
252
|
-
"circular data structures not supported!"
|
253
|
-
state.remember self
|
254
|
-
end
|
255
|
-
yield
|
256
|
-
ensure
|
257
|
-
state and state.forget self
|
258
|
-
end
|
259
|
-
|
260
260
|
def json_shift(state, depth)
|
261
261
|
state and not state.object_nl.empty? or return ''
|
262
262
|
state.indent * depth
|
@@ -268,16 +268,22 @@ module JSON
|
|
268
268
|
delim << state.object_nl
|
269
269
|
result = '{'
|
270
270
|
result << state.object_nl
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
271
|
+
depth += 1
|
272
|
+
first = true
|
273
|
+
indent = state && !state.object_nl.empty?
|
274
|
+
each { |key,value|
|
275
|
+
result << delim unless first
|
276
|
+
result << state.indent * depth if indent
|
277
|
+
result << key.to_s.to_json(state, depth)
|
278
|
+
result << state.space_before
|
279
|
+
result << ':'
|
280
|
+
result << state.space
|
281
|
+
result << value.to_json(state, depth)
|
282
|
+
first = false
|
283
|
+
}
|
284
|
+
depth -= 1
|
279
285
|
result << state.object_nl
|
280
|
-
result <<
|
286
|
+
result << state.indent * depth if indent if indent
|
281
287
|
result << '}'
|
282
288
|
else
|
283
289
|
result = '{'
|
@@ -298,43 +304,32 @@ module JSON
|
|
298
304
|
# _depth_ is used to find out nesting depth, to indent accordingly.
|
299
305
|
def to_json(state = nil, depth = 0, *)
|
300
306
|
if state
|
301
|
-
state =
|
307
|
+
state = State.from_state(state)
|
302
308
|
state.check_max_nesting(depth)
|
303
|
-
json_check_circular(state) { json_transform(state, depth) }
|
304
|
-
else
|
305
|
-
json_transform(state, depth)
|
306
309
|
end
|
310
|
+
json_transform(state, depth)
|
307
311
|
end
|
308
312
|
|
309
313
|
private
|
310
314
|
|
311
|
-
def json_check_circular(state)
|
312
|
-
if state and state.check_circular?
|
313
|
-
state.seen?(self) and raise JSON::CircularDatastructure,
|
314
|
-
"circular data structures not supported!"
|
315
|
-
state.remember self
|
316
|
-
end
|
317
|
-
yield
|
318
|
-
ensure
|
319
|
-
state and state.forget self
|
320
|
-
end
|
321
|
-
|
322
|
-
def json_shift(state, depth)
|
323
|
-
state and not state.array_nl.empty? or return ''
|
324
|
-
state.indent * depth
|
325
|
-
end
|
326
|
-
|
327
315
|
def json_transform(state, depth)
|
328
316
|
delim = ','
|
329
317
|
if state
|
330
318
|
delim << state.array_nl
|
331
319
|
result = '['
|
332
320
|
result << state.array_nl
|
333
|
-
|
334
|
-
|
335
|
-
|
321
|
+
depth += 1
|
322
|
+
first = true
|
323
|
+
indent = state && !state.array_nl.empty?
|
324
|
+
each { |value|
|
325
|
+
result << delim unless first
|
326
|
+
result << state.indent * depth if indent
|
327
|
+
result << value.to_json(state, depth)
|
328
|
+
first = false
|
329
|
+
}
|
330
|
+
depth -= 1
|
336
331
|
result << state.array_nl
|
337
|
-
result <<
|
332
|
+
result << state.indent * depth if indent
|
338
333
|
result << ']'
|
339
334
|
else
|
340
335
|
'[' << map { |value| value.to_json }.join(delim) << ']'
|
@@ -352,13 +347,13 @@ module JSON
|
|
352
347
|
def to_json(state = nil, *)
|
353
348
|
case
|
354
349
|
when infinite?
|
355
|
-
if
|
350
|
+
if state && state.allow_nan?
|
356
351
|
to_s
|
357
352
|
else
|
358
353
|
raise GeneratorError, "#{self} not allowed in JSON"
|
359
354
|
end
|
360
355
|
when nan?
|
361
|
-
if
|
356
|
+
if state && state.allow_nan?
|
362
357
|
to_s
|
363
358
|
else
|
364
359
|
raise GeneratorError, "#{self} not allowed in JSON"
|
@@ -370,18 +365,45 @@ module JSON
|
|
370
365
|
end
|
371
366
|
|
372
367
|
module String
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
368
|
+
if defined?(::Encoding)
|
369
|
+
# This string should be encoded with UTF-8 A call to this method
|
370
|
+
# returns a JSON string encoded with UTF16 big endian characters as
|
371
|
+
# \u????.
|
372
|
+
def to_json(*args)
|
373
|
+
state, = *args
|
374
|
+
state ||= State.from_state(state)
|
375
|
+
if encoding == ::Encoding::UTF_8
|
376
|
+
string = self
|
377
|
+
else
|
378
|
+
string = encode(::Encoding::UTF_8)
|
379
|
+
end
|
380
|
+
if state.ascii_only?
|
381
|
+
'"' << JSON.utf8_to_json_ascii(string) << '"'
|
382
|
+
else
|
383
|
+
'"' << JSON.utf8_to_json(string) << '"'
|
384
|
+
end
|
385
|
+
end
|
386
|
+
else
|
387
|
+
# This string should be encoded with UTF-8 A call to this method
|
388
|
+
# returns a JSON string encoded with UTF16 big endian characters as
|
389
|
+
# \u????.
|
390
|
+
def to_json(*args)
|
391
|
+
state, = *args
|
392
|
+
state ||= State.from_state(state)
|
393
|
+
if state.ascii_only?
|
394
|
+
'"' << JSON.utf8_to_json_ascii(self) << '"'
|
395
|
+
else
|
396
|
+
'"' << JSON.utf8_to_json(self) << '"'
|
397
|
+
end
|
398
|
+
end
|
378
399
|
end
|
379
400
|
|
380
401
|
# Module that holds the extinding methods if, the String module is
|
381
402
|
# included.
|
382
403
|
module Extend
|
383
|
-
# Raw Strings are JSON Objects (the raw bytes are stored in an
|
384
|
-
# key "raw"). The Ruby String can be created by this
|
404
|
+
# Raw Strings are JSON Objects (the raw bytes are stored in an
|
405
|
+
# array for the key "raw"). The Ruby String can be created by this
|
406
|
+
# module method.
|
385
407
|
def json_create(o)
|
386
408
|
o['raw'].pack('C*')
|
387
409
|
end
|