scout 5.1.2 → 5.1.3

Sign up to get free protection for your applications and to get access to all the features.
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