json_pure 1.1.3 → 1.1.4
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +9 -0
- data/Rakefile +47 -53
- data/VERSION +1 -1
- data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkComparison.log +52 -0
- data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_fast-autocorrelation.dat +1000 -0
- data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_fast.dat +1001 -0
- data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_pretty-autocorrelation.dat +900 -0
- data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_pretty.dat +901 -0
- data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_safe-autocorrelation.dat +1000 -0
- data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_safe.dat +1001 -0
- data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt.log +261 -0
- data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_fast-autocorrelation.dat +1000 -0
- data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_fast.dat +1001 -0
- data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_pretty-autocorrelation.dat +1000 -0
- data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_pretty.dat +1001 -0
- data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_safe-autocorrelation.dat +1000 -0
- data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_safe.dat +1001 -0
- data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure.log +262 -0
- data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkRails#generator-autocorrelation.dat +1000 -0
- data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkRails#generator.dat +1001 -0
- data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkRails.log +82 -0
- data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkComparison.log +34 -0
- data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkExt#parser-autocorrelation.dat +900 -0
- data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkExt#parser.dat +901 -0
- data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkExt.log +81 -0
- data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkPure#parser-autocorrelation.dat +1000 -0
- data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkPure#parser.dat +1001 -0
- data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkPure.log +82 -0
- data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkRails#parser-autocorrelation.dat +1000 -0
- data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkRails#parser.dat +1001 -0
- data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkRails.log +82 -0
- data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkYAML#parser-autocorrelation.dat +1000 -0
- data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkYAML#parser.dat +1001 -0
- data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkYAML.log +82 -0
- data/benchmarks/generator_benchmark.rb +162 -0
- data/benchmarks/parser_benchmark.rb +193 -0
- data/bin/edit_json.rb +0 -1
- data/bin/prettify_json.rb +0 -1
- data/doc-templates/main.txt +284 -0
- data/ext/json/ext/generator/extconf.rb +2 -0
- data/ext/json/ext/generator/generator.c +62 -18
- data/ext/json/ext/parser/extconf.rb +2 -0
- data/ext/json/ext/parser/parser.c +128 -81
- data/ext/json/ext/parser/parser.rl +31 -7
- data/ext/json/ext/parser/unicode.c +4 -4
- data/lib/json/add/core.rb +1 -1
- data/lib/json/editor.rb +11 -2
- data/lib/json/ext.rb +2 -0
- data/lib/json/pure/generator.rb +77 -41
- data/lib/json/pure/parser.rb +6 -2
- data/lib/json/pure.rb +2 -0
- data/lib/json/version.rb +1 -1
- data/lib/json.rb +0 -221
- data/tests/test_json.rb +7 -4
- data/tests/test_json_addition.rb +8 -5
- data/tests/test_json_fixtures.rb +6 -2
- data/tests/test_json_generate.rb +8 -2
- data/tests/test_json_rails.rb +30 -2
- data/tests/test_json_unicode.rb +8 -7
- data/tools/fuzz.rb +0 -1
- data/tools/server.rb +0 -1
- metadata +46 -9
- data/benchmarks/benchmark.txt +0 -133
- data/benchmarks/benchmark_generator.rb +0 -48
- data/benchmarks/benchmark_parser.rb +0 -26
- data/benchmarks/benchmark_rails.rb +0 -26
- data/tests/runner.rb +0 -25
@@ -0,0 +1,284 @@
|
|
1
|
+
# = json - JSON for Ruby
|
2
|
+
#
|
3
|
+
# == Description
|
4
|
+
#
|
5
|
+
# This is a implementation of the JSON specification according to RFC 4627
|
6
|
+
# (http://www.ietf.org/rfc/rfc4627.txt). Starting from version 1.0.0 on there
|
7
|
+
# will be two variants available:
|
8
|
+
#
|
9
|
+
# * A pure ruby variant, that relies on the iconv and the stringscan
|
10
|
+
# extensions, which are both part of the ruby standard library.
|
11
|
+
# * The quite a bit faster C extension variant, which is in parts implemented
|
12
|
+
# in C and comes with its own unicode conversion functions and a parser
|
13
|
+
# generated by the ragel state machine compiler
|
14
|
+
# (http://www.cs.queensu.ca/~thurston/ragel).
|
15
|
+
#
|
16
|
+
# Both variants of the JSON generator escape all non-ASCII an control
|
17
|
+
# characters with \uXXXX escape sequences, and support UTF-16 surrogate pairs
|
18
|
+
# in order to be able to generate the whole range of unicode code points. This
|
19
|
+
# means that generated JSON text is encoded as UTF-8 (because ASCII is a subset
|
20
|
+
# of UTF-8) and at the same time avoids decoding problems for receiving
|
21
|
+
# endpoints, that don't expect UTF-8 encoded texts. On the negative side this
|
22
|
+
# may lead to a bit longer strings than necessarry.
|
23
|
+
#
|
24
|
+
# All strings, that are to be encoded as JSON strings, should be UTF-8 byte
|
25
|
+
# sequences on the Ruby side. To encode raw binary strings, that aren't UTF-8
|
26
|
+
# encoded, please use the to_json_raw_object method of String (which produces
|
27
|
+
# an object, that contains a byte array) and decode the result on the receiving
|
28
|
+
# endpoint.
|
29
|
+
#
|
30
|
+
# == Author
|
31
|
+
#
|
32
|
+
# Florian Frank <mailto:flori@ping.de>
|
33
|
+
#
|
34
|
+
# == License
|
35
|
+
#
|
36
|
+
# This software is distributed under the same license as Ruby itself, see
|
37
|
+
# http://www.ruby-lang.org/en/LICENSE.txt.
|
38
|
+
#
|
39
|
+
# == Download
|
40
|
+
#
|
41
|
+
# The latest version of this library can be downloaded at
|
42
|
+
#
|
43
|
+
# * http://rubyforge.org/frs?group_id=953
|
44
|
+
#
|
45
|
+
# Online Documentation should be located at
|
46
|
+
#
|
47
|
+
# * http://json.rubyforge.org
|
48
|
+
#
|
49
|
+
# == Usage
|
50
|
+
#
|
51
|
+
# To use JSON you can
|
52
|
+
# require 'json'
|
53
|
+
# to load the installed variant (either the extension 'json' or the pure
|
54
|
+
# variant 'json_pure'). If you have installed the extension variant, you can
|
55
|
+
# pick either the extension variant or the pure variant by typing
|
56
|
+
# require 'json/ext'
|
57
|
+
# or
|
58
|
+
# require 'json/pure'
|
59
|
+
#
|
60
|
+
# You can choose to load a set of common additions to ruby core's objects if
|
61
|
+
# you
|
62
|
+
# require 'json/add/core'
|
63
|
+
#
|
64
|
+
# After requiring this you can, e. g., serialise/deserialise Ruby ranges:
|
65
|
+
#
|
66
|
+
# JSON JSON(1..10) # => 1..10
|
67
|
+
#
|
68
|
+
# To find out how to add JSON support to other or your own classes, read the
|
69
|
+
# Examples section below.
|
70
|
+
#
|
71
|
+
# To get the best compatibility to rails' JSON implementation, you can
|
72
|
+
# require 'json/add/rails'
|
73
|
+
#
|
74
|
+
# Both of the additions attempt to require 'json' (like above) first, if it has
|
75
|
+
# not been required yet.
|
76
|
+
#
|
77
|
+
# == Speed Comparisons
|
78
|
+
#
|
79
|
+
# I have created some benchmark results on on ruby 1.8.6 (2008-08-11
|
80
|
+
# patchlevel 287) [i686-linux] (see the benchmarks/data-p4-3Ghz-ruby18
|
81
|
+
# subdir of the package) for the JSON-parser to estimate the speed up in the C
|
82
|
+
# extension:
|
83
|
+
#
|
84
|
+
# Comparing times (call_time_mean):
|
85
|
+
# 1 ParserBenchmarkExt#parser 900 repeats:
|
86
|
+
# 553.922304770 ( real) -> 21.500x
|
87
|
+
# 0.001805307
|
88
|
+
# 2 ParserBenchmarkYAML#parser 1000 repeats:
|
89
|
+
# 224.513358139 ( real) -> 8.714x
|
90
|
+
# 0.004454078
|
91
|
+
# 3 ParserBenchmarkPure#parser 1000 repeats:
|
92
|
+
# 26.755020642 ( real) -> 1.038x
|
93
|
+
# 0.037376163
|
94
|
+
# 4 ParserBenchmarkRails#parser 1000 repeats:
|
95
|
+
# 25.763381731 ( real) -> 1.000x
|
96
|
+
# 0.038814780
|
97
|
+
# calls/sec ( time) -> speed covers
|
98
|
+
# secs/call
|
99
|
+
#
|
100
|
+
# In the table above 1 is JSON::Ext::Parser, 2 is YAML.load with YAML
|
101
|
+
# compatbile JSON document, 3 is is JSON::Pure::Parser, and 4 is
|
102
|
+
# ActiveSupport::JSON.decode. The ActiveSupport JSON-decoder converts the
|
103
|
+
# input first to YAML and then uses the YAML-parser, the conversion seems to
|
104
|
+
# slow it down so much that it is only as fast as the JSON::Pure::Parser!
|
105
|
+
#
|
106
|
+
# If you look at the benchmark data you can see that this is mostly caused by
|
107
|
+
# the frequent high outliers - the median of the Rails-parser runs is still
|
108
|
+
# overall smaller than the median of the JSON::Pure::Parser runs:
|
109
|
+
#
|
110
|
+
# Comparing times (call_time_median):
|
111
|
+
# 1 ParserBenchmarkExt#parser 900 repeats:
|
112
|
+
# 800.592479481 ( real) -> 26.936x
|
113
|
+
# 0.001249075
|
114
|
+
# 2 ParserBenchmarkYAML#parser 1000 repeats:
|
115
|
+
# 271.002390644 ( real) -> 9.118x
|
116
|
+
# 0.003690004
|
117
|
+
# 3 ParserBenchmarkRails#parser 1000 repeats:
|
118
|
+
# 30.227910865 ( real) -> 1.017x
|
119
|
+
# 0.033082008
|
120
|
+
# 4 ParserBenchmarkPure#parser 1000 repeats:
|
121
|
+
# 29.722384421 ( real) -> 1.000x
|
122
|
+
# 0.033644676
|
123
|
+
# calls/sec ( time) -> speed covers
|
124
|
+
# secs/call
|
125
|
+
#
|
126
|
+
# I have benchmarked the JSON-Generator as well. This generated a few more
|
127
|
+
# values, because there are different modes that also influence the achieved
|
128
|
+
# speed:
|
129
|
+
#
|
130
|
+
# Comparing times (call_time_mean):
|
131
|
+
# 1 GeneratorBenchmarkExt#generator_fast 1000 repeats:
|
132
|
+
# 547.354332608 ( real) -> 15.090x
|
133
|
+
# 0.001826970
|
134
|
+
# 2 GeneratorBenchmarkExt#generator_safe 1000 repeats:
|
135
|
+
# 443.968212317 ( real) -> 12.240x
|
136
|
+
# 0.002252414
|
137
|
+
# 3 GeneratorBenchmarkExt#generator_pretty 900 repeats:
|
138
|
+
# 375.104545883 ( real) -> 10.341x
|
139
|
+
# 0.002665923
|
140
|
+
# 4 GeneratorBenchmarkPure#generator_fast 1000 repeats:
|
141
|
+
# 49.978706968 ( real) -> 1.378x
|
142
|
+
# 0.020008521
|
143
|
+
# 5 GeneratorBenchmarkRails#generator 1000 repeats:
|
144
|
+
# 38.531868759 ( real) -> 1.062x
|
145
|
+
# 0.025952543
|
146
|
+
# 6 GeneratorBenchmarkPure#generator_safe 1000 repeats:
|
147
|
+
# 36.927649925 ( real) -> 1.018x 7 (>=3859)
|
148
|
+
# 0.027079979
|
149
|
+
# 7 GeneratorBenchmarkPure#generator_pretty 1000 repeats:
|
150
|
+
# 36.272134441 ( real) -> 1.000x 6 (>=3859)
|
151
|
+
# 0.027569373
|
152
|
+
# calls/sec ( time) -> speed covers
|
153
|
+
# secs/call
|
154
|
+
#
|
155
|
+
# In the table above 1-3 are JSON::Ext::Generator methods. 4, 6, and 7 are
|
156
|
+
# JSON::Pure::Generator methods and 5 is the Rails JSON generator. It is now a
|
157
|
+
# bit faster than the generator_safe and generator_pretty methods of the pure
|
158
|
+
# variant but slower than the others.
|
159
|
+
#
|
160
|
+
# To achieve the fastest JSON text output, you can use the fast_generate
|
161
|
+
# method. Beware, that this will disable the checking for circular Ruby data
|
162
|
+
# structures, which may cause JSON to go into an infinite loop.
|
163
|
+
#
|
164
|
+
# Here are the median comparisons for completeness' sake:
|
165
|
+
#
|
166
|
+
# Comparing times (call_time_median):
|
167
|
+
# 1 GeneratorBenchmarkExt#generator_fast 1000 repeats:
|
168
|
+
# 708.258020939 ( real) -> 16.547x
|
169
|
+
# 0.001411915
|
170
|
+
# 2 GeneratorBenchmarkExt#generator_safe 1000 repeats:
|
171
|
+
# 569.105020353 ( real) -> 13.296x
|
172
|
+
# 0.001757145
|
173
|
+
# 3 GeneratorBenchmarkExt#generator_pretty 900 repeats:
|
174
|
+
# 482.825371244 ( real) -> 11.280x
|
175
|
+
# 0.002071142
|
176
|
+
# 4 GeneratorBenchmarkPure#generator_fast 1000 repeats:
|
177
|
+
# 62.717626652 ( real) -> 1.465x
|
178
|
+
# 0.015944481
|
179
|
+
# 5 GeneratorBenchmarkRails#generator 1000 repeats:
|
180
|
+
# 43.965681162 ( real) -> 1.027x
|
181
|
+
# 0.022745013
|
182
|
+
# 6 GeneratorBenchmarkPure#generator_safe 1000 repeats:
|
183
|
+
# 43.929073409 ( real) -> 1.026x 7 (>=3859)
|
184
|
+
# 0.022763968
|
185
|
+
# 7 GeneratorBenchmarkPure#generator_pretty 1000 repeats:
|
186
|
+
# 42.802514491 ( real) -> 1.000x 6 (>=3859)
|
187
|
+
# 0.023363113
|
188
|
+
# calls/sec ( time) -> speed covers
|
189
|
+
# secs/call
|
190
|
+
#
|
191
|
+
# == Examples
|
192
|
+
#
|
193
|
+
# To create a JSON text from a ruby data structure, you can call JSON.generate
|
194
|
+
# like that:
|
195
|
+
#
|
196
|
+
# json = JSON.generate [1, 2, {"a"=>3.141}, false, true, nil, 4..10]
|
197
|
+
# # => "[1,2,{\"a\":3.141},false,true,null,\"4..10\"]"
|
198
|
+
#
|
199
|
+
# To create a valid JSON text you have to make sure, that the output is
|
200
|
+
# embedded in either a JSON array [] or a JSON object {}. The easiest way to do
|
201
|
+
# this, is by putting your values in a Ruby Array or Hash instance.
|
202
|
+
#
|
203
|
+
# To get back a ruby data structure from a JSON text, you have to call
|
204
|
+
# JSON.parse on it:
|
205
|
+
#
|
206
|
+
# JSON.parse json
|
207
|
+
# # => [1, 2, {"a"=>3.141}, false, true, nil, "4..10"]
|
208
|
+
#
|
209
|
+
# Note, that the range from the original data structure is a simple
|
210
|
+
# string now. The reason for this is, that JSON doesn't support ranges
|
211
|
+
# or arbitrary classes. In this case the json library falls back to call
|
212
|
+
# Object#to_json, which is the same as #to_s.to_json.
|
213
|
+
#
|
214
|
+
# It's possible to add JSON support serialization to arbitrary classes by
|
215
|
+
# simply implementing a more specialized version of the #to_json method, that
|
216
|
+
# should return a JSON object (a hash converted to JSON with #to_json) like
|
217
|
+
# this (don't forget the *a for all the arguments):
|
218
|
+
#
|
219
|
+
# class Range
|
220
|
+
# def to_json(*a)
|
221
|
+
# {
|
222
|
+
# 'json_class' => self.class.name, # = 'Range'
|
223
|
+
# 'data' => [ first, last, exclude_end? ]
|
224
|
+
# }.to_json(*a)
|
225
|
+
# end
|
226
|
+
# end
|
227
|
+
#
|
228
|
+
# The hash key 'json_class' is the class, that will be asked to deserialise the
|
229
|
+
# JSON representation later. In this case it's 'Range', but any namespace of
|
230
|
+
# the form 'A::B' or '::A::B' will do. All other keys are arbitrary and can be
|
231
|
+
# used to store the necessary data to configure the object to be deserialised.
|
232
|
+
#
|
233
|
+
# If a the key 'json_class' is found in a JSON object, the JSON parser checks
|
234
|
+
# if the given class responds to the json_create class method. If so, it is
|
235
|
+
# called with the JSON object converted to a Ruby hash. So a range can
|
236
|
+
# be deserialised by implementing Range.json_create like this:
|
237
|
+
#
|
238
|
+
# class Range
|
239
|
+
# def self.json_create(o)
|
240
|
+
# new(*o['data'])
|
241
|
+
# end
|
242
|
+
# end
|
243
|
+
#
|
244
|
+
# Now it possible to serialise/deserialise ranges as well:
|
245
|
+
#
|
246
|
+
# json = JSON.generate [1, 2, {"a"=>3.141}, false, true, nil, 4..10]
|
247
|
+
# # => "[1,2,{\"a\":3.141},false,true,null,{\"json_class\":\"Range\",\"data\":[4,10,false]}]"
|
248
|
+
# JSON.parse json
|
249
|
+
# # => [1, 2, {"a"=>3.141}, false, true, nil, 4..10]
|
250
|
+
#
|
251
|
+
# JSON.generate always creates the shortest possible string representation of a
|
252
|
+
# ruby data structure in one line. This good for data storage or network
|
253
|
+
# protocols, but not so good for humans to read. Fortunately there's also
|
254
|
+
# JSON.pretty_generate (or JSON.pretty_generate) that creates a more
|
255
|
+
# readable output:
|
256
|
+
#
|
257
|
+
# puts JSON.pretty_generate([1, 2, {"a"=>3.141}, false, true, nil, 4..10])
|
258
|
+
# [
|
259
|
+
# 1,
|
260
|
+
# 2,
|
261
|
+
# {
|
262
|
+
# "a": 3.141
|
263
|
+
# },
|
264
|
+
# false,
|
265
|
+
# true,
|
266
|
+
# null,
|
267
|
+
# {
|
268
|
+
# "json_class": "Range",
|
269
|
+
# "data": [
|
270
|
+
# 4,
|
271
|
+
# 10,
|
272
|
+
# false
|
273
|
+
# ]
|
274
|
+
# }
|
275
|
+
# ]
|
276
|
+
#
|
277
|
+
# There are also the methods Kernel#j for generate, and Kernel#jj for
|
278
|
+
# pretty_generate output to the console, that work analogous to Core Ruby's p
|
279
|
+
# and the pp library's pp methods.
|
280
|
+
#
|
281
|
+
# The script tools/server.rb contains a small example if you want to test, how
|
282
|
+
# receiving a JSON object from a webrick server in your browser with the
|
283
|
+
# javasript prototype library (http://www.prototypejs.org) works.
|
284
|
+
#
|
@@ -1,9 +1,33 @@
|
|
1
1
|
#include <string.h>
|
2
2
|
#include "ruby.h"
|
3
|
+
#if HAVE_RUBY_ST_H
|
4
|
+
#include "ruby/st.h"
|
5
|
+
#endif
|
6
|
+
#if HAVE_ST_H
|
3
7
|
#include "st.h"
|
8
|
+
#endif
|
4
9
|
#include "unicode.h"
|
5
10
|
#include <math.h>
|
6
11
|
|
12
|
+
#ifndef RHASH_TBL
|
13
|
+
#define RHASH_TBL(hsh) (RHASH(hsh)->tbl)
|
14
|
+
#endif
|
15
|
+
|
16
|
+
#ifndef RHASH_SIZE
|
17
|
+
#define RHASH_SIZE(hsh) (RHASH(hsh)->tbl->num_entries)
|
18
|
+
#endif
|
19
|
+
|
20
|
+
#ifndef RFLOAT_VALUE
|
21
|
+
#define RFLOAT_VALUE(val) (RFLOAT(val)->value)
|
22
|
+
#endif
|
23
|
+
|
24
|
+
#ifdef HAVE_RUBY_ENCODING_H
|
25
|
+
#include "ruby/encoding.h"
|
26
|
+
#define FORCE_UTF8(obj) rb_enc_associate((obj), rb_utf8_encoding())
|
27
|
+
#else
|
28
|
+
#define FORCE_UTF8(obj)
|
29
|
+
#endif
|
30
|
+
|
7
31
|
#define check_max_nesting(state, depth) do { \
|
8
32
|
long current_nesting = 1 + depth; \
|
9
33
|
if (state->max_nesting != 0 && current_nesting > state->max_nesting) \
|
@@ -86,7 +110,7 @@ static int hash_to_json_state_i(VALUE key, VALUE value, VALUE Vstate)
|
|
86
110
|
}
|
87
111
|
|
88
112
|
inline static VALUE mHash_json_transfrom(VALUE self, VALUE Vstate, VALUE Vdepth) {
|
89
|
-
long depth, len =
|
113
|
+
long depth, len = RHASH_SIZE(self);
|
90
114
|
VALUE result;
|
91
115
|
GET_STATE(Vstate);
|
92
116
|
|
@@ -142,7 +166,7 @@ static VALUE mHash_to_json(int argc, VALUE *argv, VALUE self)
|
|
142
166
|
rb_scan_args(argc, argv, "02", &Vstate, &Vdepth);
|
143
167
|
depth = NIL_P(Vdepth) ? 0 : FIX2LONG(Vdepth);
|
144
168
|
if (NIL_P(Vstate)) {
|
145
|
-
long len =
|
169
|
+
long len = RHASH_SIZE(self);
|
146
170
|
result = rb_str_buf_new(len);
|
147
171
|
rb_str_buf_cat2(result, "{");
|
148
172
|
rb_hash_foreach(self, hash_to_json_i, result);
|
@@ -164,6 +188,7 @@ static VALUE mHash_to_json(int argc, VALUE *argv, VALUE self)
|
|
164
188
|
}
|
165
189
|
}
|
166
190
|
OBJ_INFECT(result, self);
|
191
|
+
FORCE_UTF8(result);
|
167
192
|
return result;
|
168
193
|
}
|
169
194
|
|
@@ -261,6 +286,7 @@ static VALUE mArray_to_json(int argc, VALUE *argv, VALUE self) {
|
|
261
286
|
result = mArray_json_transfrom(self, Vstate, Vdepth);
|
262
287
|
}
|
263
288
|
OBJ_INFECT(result, self);
|
289
|
+
FORCE_UTF8(result);
|
264
290
|
return result;
|
265
291
|
}
|
266
292
|
|
@@ -271,7 +297,9 @@ static VALUE mArray_to_json(int argc, VALUE *argv, VALUE self) {
|
|
271
297
|
*/
|
272
298
|
static VALUE mInteger_to_json(int argc, VALUE *argv, VALUE self)
|
273
299
|
{
|
274
|
-
|
300
|
+
VALUE result = rb_funcall(self, i_to_s, 0);
|
301
|
+
FORCE_UTF8(result);
|
302
|
+
return result;
|
275
303
|
}
|
276
304
|
|
277
305
|
/*
|
@@ -282,27 +310,29 @@ static VALUE mInteger_to_json(int argc, VALUE *argv, VALUE self)
|
|
282
310
|
static VALUE mFloat_to_json(int argc, VALUE *argv, VALUE self)
|
283
311
|
{
|
284
312
|
JSON_Generator_State *state = NULL;
|
285
|
-
VALUE Vstate, rest, tmp;
|
286
|
-
double value =
|
313
|
+
VALUE Vstate, rest, tmp, result;
|
314
|
+
double value = RFLOAT_VALUE(self);
|
287
315
|
rb_scan_args(argc, argv, "01*", &Vstate, &rest);
|
288
316
|
if (!NIL_P(Vstate)) Data_Get_Struct(Vstate, JSON_Generator_State, state);
|
289
317
|
if (isinf(value)) {
|
290
318
|
if (!state || state->allow_nan) {
|
291
|
-
|
319
|
+
result = rb_funcall(self, i_to_s, 0);
|
292
320
|
} else {
|
293
321
|
tmp = rb_funcall(self, i_to_s, 0);
|
294
322
|
rb_raise(eGeneratorError, "%u: %s not allowed in JSON", __LINE__, StringValueCStr(tmp));
|
295
323
|
}
|
296
324
|
} else if (isnan(value)) {
|
297
325
|
if (!state || state->allow_nan) {
|
298
|
-
|
326
|
+
result = rb_funcall(self, i_to_s, 0);
|
299
327
|
} else {
|
300
328
|
tmp = rb_funcall(self, i_to_s, 0);
|
301
329
|
rb_raise(eGeneratorError, "%u: %s not allowed in JSON", __LINE__, StringValueCStr(tmp));
|
302
330
|
}
|
303
331
|
} else {
|
304
|
-
|
332
|
+
result = rb_funcall(self, i_to_s, 0);
|
305
333
|
}
|
334
|
+
FORCE_UTF8(result);
|
335
|
+
return result;
|
306
336
|
}
|
307
337
|
|
308
338
|
/*
|
@@ -311,7 +341,9 @@ static VALUE mFloat_to_json(int argc, VALUE *argv, VALUE self)
|
|
311
341
|
* Extends _modul_ with the String::Extend module.
|
312
342
|
*/
|
313
343
|
static VALUE mString_included_s(VALUE self, VALUE modul) {
|
314
|
-
|
344
|
+
VALUE result = rb_funcall(modul, i_extend, 1, mString_Extend);
|
345
|
+
FORCE_UTF8(result);
|
346
|
+
return result;
|
315
347
|
}
|
316
348
|
|
317
349
|
/*
|
@@ -327,6 +359,7 @@ static VALUE mString_to_json(int argc, VALUE *argv, VALUE self)
|
|
327
359
|
rb_str_buf_cat2(result, "\"");
|
328
360
|
JSON_convert_UTF8_to_JSON(result, self, strictConversion);
|
329
361
|
rb_str_buf_cat2(result, "\"");
|
362
|
+
FORCE_UTF8(result);
|
330
363
|
return result;
|
331
364
|
}
|
332
365
|
|
@@ -344,6 +377,7 @@ static VALUE mString_to_json_raw_object(VALUE self) {
|
|
344
377
|
rb_hash_aset(result, rb_funcall(mJSON, i_create_id, 0), rb_class_name(rb_obj_class(self)));
|
345
378
|
ary = rb_funcall(self, i_unpack, 1, rb_str_new2("C*"));
|
346
379
|
rb_hash_aset(result, rb_str_new2("raw"), ary);
|
380
|
+
FORCE_UTF8(result);
|
347
381
|
return result;
|
348
382
|
}
|
349
383
|
|
@@ -354,9 +388,11 @@ static VALUE mString_to_json_raw_object(VALUE self) {
|
|
354
388
|
* to_json_raw_object of this String.
|
355
389
|
*/
|
356
390
|
static VALUE mString_to_json_raw(int argc, VALUE *argv, VALUE self) {
|
357
|
-
VALUE obj = mString_to_json_raw_object(self);
|
391
|
+
VALUE result, obj = mString_to_json_raw_object(self);
|
358
392
|
Check_Type(obj, T_HASH);
|
359
|
-
|
393
|
+
result = mHash_to_json(argc, argv, obj);
|
394
|
+
FORCE_UTF8(result);
|
395
|
+
return result;
|
360
396
|
}
|
361
397
|
|
362
398
|
/*
|
@@ -379,7 +415,9 @@ static VALUE mString_Extend_json_create(VALUE self, VALUE o) {
|
|
379
415
|
*/
|
380
416
|
static VALUE mTrueClass_to_json(int argc, VALUE *argv, VALUE self)
|
381
417
|
{
|
382
|
-
|
418
|
+
VALUE result = rb_str_new2("true");
|
419
|
+
FORCE_UTF8(result);
|
420
|
+
return result;
|
383
421
|
}
|
384
422
|
|
385
423
|
/*
|
@@ -389,7 +427,9 @@ static VALUE mTrueClass_to_json(int argc, VALUE *argv, VALUE self)
|
|
389
427
|
*/
|
390
428
|
static VALUE mFalseClass_to_json(int argc, VALUE *argv, VALUE self)
|
391
429
|
{
|
392
|
-
|
430
|
+
VALUE result = rb_str_new2("false");
|
431
|
+
FORCE_UTF8(result);
|
432
|
+
return result;
|
393
433
|
}
|
394
434
|
|
395
435
|
/*
|
@@ -398,7 +438,9 @@ static VALUE mFalseClass_to_json(int argc, VALUE *argv, VALUE self)
|
|
398
438
|
*/
|
399
439
|
static VALUE mNilClass_to_json(int argc, VALUE *argv, VALUE self)
|
400
440
|
{
|
401
|
-
|
441
|
+
VALUE result = rb_str_new2("null");
|
442
|
+
FORCE_UTF8(result);
|
443
|
+
return result;
|
402
444
|
}
|
403
445
|
|
404
446
|
/*
|
@@ -410,9 +452,11 @@ static VALUE mNilClass_to_json(int argc, VALUE *argv, VALUE self)
|
|
410
452
|
*/
|
411
453
|
static VALUE mObject_to_json(int argc, VALUE *argv, VALUE self)
|
412
454
|
{
|
413
|
-
VALUE string = rb_funcall(self, i_to_s, 0);
|
455
|
+
VALUE result, string = rb_funcall(self, i_to_s, 0);
|
414
456
|
Check_Type(string, T_STRING);
|
415
|
-
|
457
|
+
result = mString_to_json(argc, argv, string);
|
458
|
+
FORCE_UTF8(result);
|
459
|
+
return result;
|
416
460
|
}
|
417
461
|
|
418
462
|
/*
|
@@ -488,7 +532,7 @@ static inline VALUE cState_configure(VALUE self, VALUE opts)
|
|
488
532
|
state->object_nl = tmp;
|
489
533
|
}
|
490
534
|
tmp = ID2SYM(i_check_circular);
|
491
|
-
if (st_lookup(
|
535
|
+
if (st_lookup(RHASH_TBL(opts), tmp, 0)) {
|
492
536
|
tmp = rb_hash_aref(opts, ID2SYM(i_check_circular));
|
493
537
|
state->check_circular = RTEST(tmp);
|
494
538
|
} else {
|
@@ -496,7 +540,7 @@ static inline VALUE cState_configure(VALUE self, VALUE opts)
|
|
496
540
|
}
|
497
541
|
tmp = ID2SYM(i_max_nesting);
|
498
542
|
state->max_nesting = 19;
|
499
|
-
if (st_lookup(
|
543
|
+
if (st_lookup(RHASH_TBL(opts), tmp, 0)) {
|
500
544
|
VALUE max_nesting = rb_hash_aref(opts, tmp);
|
501
545
|
if (RTEST(max_nesting)) {
|
502
546
|
Check_Type(max_nesting, T_FIXNUM);
|