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.
Files changed (41) hide show
  1. data/CHANGELOG +5 -0
  2. data/lib/scout.rb +1 -1
  3. data/lib/scout/server.rb +4 -1
  4. data/vendor/json_pure/CHANGES +43 -0
  5. data/vendor/json_pure/{RUBY → COPYING} +1 -1
  6. data/vendor/json_pure/GPL +7 -7
  7. data/vendor/json_pure/README +319 -39
  8. data/vendor/json_pure/Rakefile +69 -47
  9. data/vendor/json_pure/VERSION +1 -1
  10. data/vendor/json_pure/benchmarks/generator2_benchmark.rb +222 -0
  11. data/vendor/json_pure/benchmarks/generator_benchmark.rb +64 -5
  12. data/vendor/json_pure/benchmarks/ohai.json +1216 -0
  13. data/vendor/json_pure/benchmarks/ohai.ruby +1 -0
  14. data/vendor/json_pure/benchmarks/parser2_benchmark.rb +251 -0
  15. data/vendor/json_pure/benchmarks/parser_benchmark.rb +67 -5
  16. data/vendor/json_pure/ext/json/ext/generator/extconf.rb +9 -4
  17. data/vendor/json_pure/ext/json/ext/generator/generator.c +831 -409
  18. data/vendor/json_pure/ext/json/ext/generator/generator.h +170 -0
  19. data/vendor/json_pure/ext/json/ext/parser/extconf.rb +8 -4
  20. data/vendor/json_pure/ext/json/ext/parser/parser.c +292 -186
  21. data/vendor/json_pure/ext/json/ext/parser/parser.h +71 -0
  22. data/vendor/json_pure/ext/json/ext/parser/parser.rl +218 -112
  23. data/vendor/json_pure/lib/json/add/core.rb +20 -7
  24. data/vendor/json_pure/lib/json/add/rails.rb +2 -2
  25. data/vendor/json_pure/lib/json/common.rb +85 -42
  26. data/vendor/json_pure/lib/json/pure.rb +3 -3
  27. data/vendor/json_pure/lib/json/pure/generator.rb +112 -90
  28. data/vendor/json_pure/lib/json/pure/parser.rb +42 -4
  29. data/vendor/json_pure/lib/json/version.rb +1 -1
  30. data/vendor/json_pure/tests/test_json.rb +46 -18
  31. data/vendor/json_pure/tests/test_json_addition.rb +4 -6
  32. data/vendor/json_pure/tests/test_json_encoding.rb +68 -0
  33. data/vendor/json_pure/tests/test_json_generate.rb +30 -14
  34. data/vendor/json_pure/tests/test_json_rails.rb +5 -7
  35. data/vendor/json_pure/tests/test_json_unicode.rb +20 -6
  36. metadata +26 -15
  37. data/vendor/json_pure/doc-templates/main.txt +0 -283
  38. data/vendor/json_pure/ext/json/ext/generator/unicode.c +0 -182
  39. data/vendor/json_pure/ext/json/ext/generator/unicode.h +0 -53
  40. data/vendor/json_pure/ext/json/ext/parser/unicode.c +0 -154
  41. 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
- 'json_class' => self.class.name,
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
- 'json_class' => self.class.name,
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
- 'json_class' => self.class.name,
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
- 'json_class' => self.class.name,
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
- 'json_class' => klass,
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
- 'json_class' => self.class.name,
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
- 'json_class' => self.class.name,
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 == 'json_class'
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
- 'json_class' => self.class.name
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 = path.to_s
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 raise ArgumentError, "can't find const #{path}"
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 = (-1.0) ** 0.5
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 string _source_ into a Ruby data structure and return it.
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
- JSON.parser.new(source, opts).parse
146
+ Parser.new(source, opts).parse
123
147
  end
124
148
 
125
- # Parse the JSON string _source_ into a Ruby data structure and return it.
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_ strings.
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 => false,
143
- :allow_nan => true
166
+ :max_nesting => false,
167
+ :allow_nan => true
144
168
  }.update(opts)
145
- JSON.parser.new(source, opts).parse
169
+ Parser.new(source, opts).parse
146
170
  end
147
171
 
148
- # Unparse the Ruby data structure _obj_ into a single line JSON string and
149
- # return it. _state_ is
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, state = nil)
178
- if state
179
- state = State.from_state(state)
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 = State.new
210
+ state = SAFE_STATE_PROTOTYPE
182
211
  end
183
- obj.to_json(state)
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
- # Unparse the Ruby data structure _obj_ into a single line JSON string and
194
- # return it. This method disables the checks for circles in Ruby objects, and
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
- obj.to_json(nil)
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
- # Unparse the Ruby data structure _obj_ into a JSON string and return it. The
210
- # returned string is a prettier form of the string returned by #unparse.
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
- obj.to_json(state)
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 String.method_defined?(:force_encoding)
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!(/["\\\/\x0-\x1f]/) { MAP[$&] }
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 = string.gsub(/["\\\/\x0-\x1f]/) { MAP[$&] }
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
- new
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*: true if checking for circular data structures
117
- # should be done (the default), false otherwise.
118
- # * *check_circular*: true if checking for circular data structures
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 should be checked,
173
+ # Returns true, if circular data structures are checked,
164
174
  # otherwise returns false.
165
175
  def check_circular?
166
- @check_circular
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
- # Returns _true_, if _object_ was already seen during this generating
176
- # run.
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 check_circular allow_nan max_nesting]
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 = JSON.state.from_state(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
- result << map { |key,value|
272
- s = json_shift(state, depth + 1)
273
- s << key.to_s.to_json(state, depth + 1)
274
- s << state.space_before
275
- s << ':'
276
- s << state.space
277
- s << value.to_json(state, depth + 1)
278
- }.join(delim)
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 << json_shift(state, depth)
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 = JSON.state.from_state(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
- result << map { |value|
334
- json_shift(state, depth + 1) << value.to_json(state, depth + 1)
335
- }.join(delim)
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 << json_shift(state, depth)
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 !state || state.allow_nan?
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 !state || state.allow_nan?
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
- # This string should be encoded with UTF-8 A call to this method
374
- # returns a JSON string encoded with UTF16 big endian characters as
375
- # \u????.
376
- def to_json(*)
377
- '"' << JSON.utf8_to_json(self) << '"'
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 array for the
384
- # key "raw"). The Ruby String can be created by this module method.
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