json 2.2.0 → 2.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +5 -2
- data/CHANGES.md +33 -0
- data/README.md +17 -1
- data/Rakefile +17 -91
- data/VERSION +1 -1
- data/ext/json/ext/generator/generator.c +165 -40
- data/ext/json/ext/parser/parser.c +83 -77
- data/ext/json/ext/parser/parser.rl +13 -7
- data/java/src/json/ext/Generator.java +33 -10
- data/json-java.gemspec +4 -5
- data/json.gemspec +0 -0
- data/json_pure.gemspec +9 -14
- data/lib/json.rb +378 -29
- data/lib/json/add/bigdecimal.rb +2 -2
- data/lib/json/add/complex.rb +2 -2
- data/lib/json/add/rational.rb +2 -2
- data/lib/json/add/regexp.rb +2 -2
- data/lib/json/common.rb +326 -91
- data/lib/json/pure/generator.rb +3 -2
- data/lib/json/pure/parser.rb +11 -3
- data/lib/json/version.rb +1 -1
- data/tests/json_common_interface_test.rb +4 -4
- data/tests/json_fixtures_test.rb +6 -1
- data/tests/json_generator_test.rb +44 -0
- data/tests/json_parser_test.rb +14 -14
- metadata +23 -12
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 80444509bc162d6df8e9cc3e7af2fc28507c06aef49cbfc1dd9e5990af42b14f
|
4
|
+
data.tar.gz: 8541be9708b44604eeeecac22f89c47933d32c90606f23c1d37e70c8b2d3e9db
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1df7b5ee2bf58103f0b5776c4a581aa3b013ad4b3a85a442d37bb72dc62aaf04dc42ed1080fb307fec1d1e9128c9f21e43827c7f15494cb0f9f310f7189bdc5e
|
7
|
+
data.tar.gz: 15ba56ce5d0e04c5326feb9e9faf2627628a715fa4bbeaec5c4aadeab5f27a65135f4f24f142b361f62ca37bbf36380f671d7ae35d46991737e4fc62423a6f9b
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
@@ -4,7 +4,6 @@ language: ruby
|
|
4
4
|
|
5
5
|
# Specify which ruby versions you wish to run your tests on, each version will be used
|
6
6
|
rvm:
|
7
|
-
- 1.9.3
|
8
7
|
- 2.0.0
|
9
8
|
- 2.1
|
10
9
|
- 2.2
|
@@ -12,12 +11,16 @@ rvm:
|
|
12
11
|
- 2.4
|
13
12
|
- 2.5
|
14
13
|
- 2.6
|
14
|
+
- 2.7.0-preview3
|
15
15
|
- ruby-head
|
16
16
|
- jruby
|
17
|
+
- jruby-9.2.7.0
|
18
|
+
- truffleruby
|
17
19
|
matrix:
|
18
20
|
allow_failures:
|
19
|
-
- rvm: 1.9.3
|
20
21
|
- rvm: ruby-head
|
21
22
|
- rvm: jruby
|
23
|
+
- rvm: jruby-9.2.7.0
|
24
|
+
- rvm: truffleruby
|
22
25
|
script: "bundle exec rake"
|
23
26
|
sudo: false
|
data/CHANGES.md
CHANGED
@@ -1,5 +1,38 @@
|
|
1
1
|
# Changes
|
2
2
|
|
3
|
+
## 2020-06-30 (2.3.1)
|
4
|
+
|
5
|
+
* Spelling and grammar fixes for comments. Pull request #191 by Josh
|
6
|
+
Kline.
|
7
|
+
* Enhance generic JSON and #generate docs. Pull request #347 by Victor
|
8
|
+
Shepelev.
|
9
|
+
* Add :nodoc: for GeneratorMethods. Pull request #349 by Victor Shepelev.
|
10
|
+
* Baseline changes to help (JRuby) development. Pull request #371 by Karol
|
11
|
+
Bucek.
|
12
|
+
* Add metadata for rubygems.org. Pull request #379 by Alexandre ZANNI.
|
13
|
+
* Remove invalid JSON.generate description from JSON module rdoc. Pull
|
14
|
+
request #384 by Jeremy Evans.
|
15
|
+
* Test with TruffleRuby in CI. Pull request #402 by Benoit Daloze.
|
16
|
+
* Rdoc enhancements. Pull request #413 by Burdette Lamar.
|
17
|
+
* Fixtures/ are not being tested... Pull request #416 by Marc-André
|
18
|
+
Lafortune.
|
19
|
+
* Use frozen string for hash key. Pull request #420 by Marc-André
|
20
|
+
Lafortune.
|
21
|
+
* Added :call-seq: to RDoc for some methods. Pull request #422 by Burdette
|
22
|
+
Lamar.
|
23
|
+
* Small typo fix. Pull request #423 by Marc-André Lafortune.
|
24
|
+
|
25
|
+
## 2019-12-11 (2.3.0)
|
26
|
+
* Fix default of `create_additions` to always be `false` for `JSON(user_input)`
|
27
|
+
and `JSON.parse(user_input, nil)`.
|
28
|
+
Note that `JSON.load` remains with default `true` and is meant for internal
|
29
|
+
serialization of trusted data. [CVE-2020-10663]
|
30
|
+
* Fix passing args all #to_json in json/add/*.
|
31
|
+
* Fix encoding issues
|
32
|
+
* Fix issues of keyword vs positional parameter
|
33
|
+
* Fix JSON::Parser against bigdecimal updates
|
34
|
+
* Bug fixes to JRuby port
|
35
|
+
|
3
36
|
## 2019-02-21 (2.2.0)
|
4
37
|
* Adds support for 2.6 BigDecimal and ruby standard library Set datetype.
|
5
38
|
|
data/README.md
CHANGED
@@ -390,6 +390,22 @@ Here are the median comparisons for completeness' sake:
|
|
390
390
|
secs/call
|
391
391
|
```
|
392
392
|
|
393
|
+
## Development
|
394
|
+
|
395
|
+
### Release
|
396
|
+
|
397
|
+
Update the json.gemspec and json-java.gemspec.
|
398
|
+
|
399
|
+
```
|
400
|
+
rbenv shell 2.6.5
|
401
|
+
rake build
|
402
|
+
gem push pkg/json-2.3.0.gem
|
403
|
+
|
404
|
+
rbenv shell jruby-9.2.9.0
|
405
|
+
rake build
|
406
|
+
gem push pkg/json-2.3.0-java.gem
|
407
|
+
```
|
408
|
+
|
393
409
|
## Author
|
394
410
|
|
395
411
|
Florian Frank <mailto:flori@ping.de>
|
@@ -406,4 +422,4 @@ The latest version of this library can be downloaded at
|
|
406
422
|
|
407
423
|
Online Documentation should be located at
|
408
424
|
|
409
|
-
*
|
425
|
+
* https://www.rubydoc.info/gems/json
|
data/Rakefile
CHANGED
@@ -23,8 +23,13 @@ class UndocumentedTestTask < Rake::TestTask
|
|
23
23
|
def desc(*) end
|
24
24
|
end
|
25
25
|
|
26
|
-
|
27
|
-
|
26
|
+
which = lambda { |c|
|
27
|
+
w = `which #{c}`
|
28
|
+
break w.chomp unless w.empty?
|
29
|
+
}
|
30
|
+
|
31
|
+
MAKE = ENV['MAKE'] || %w[gmake make].find(&which)
|
32
|
+
BUNDLE = ENV['BUNDLE'] || %w[bundle].find(&which)
|
28
33
|
PKG_NAME = 'json'
|
29
34
|
PKG_TITLE = 'JSON Implementation for Ruby'
|
30
35
|
PKG_VERSION = File.read('VERSION').chomp
|
@@ -47,8 +52,8 @@ JAVA_CLASSES = []
|
|
47
52
|
JRUBY_PARSER_JAR = File.expand_path("lib/json/ext/parser.jar")
|
48
53
|
JRUBY_GENERATOR_JAR = File.expand_path("lib/json/ext/generator.jar")
|
49
54
|
|
50
|
-
RAGEL_CODEGEN = %w[rlcodegen rlgen-cd ragel].find
|
51
|
-
RAGEL_DOTGEN = %w[rlgen-dot rlgen-cd ragel].find
|
55
|
+
RAGEL_CODEGEN = %w[rlcodegen rlgen-cd ragel].find(&which)
|
56
|
+
RAGEL_DOTGEN = %w[rlgen-dot rlgen-cd ragel].find(&which)
|
52
57
|
|
53
58
|
desc "Installing library (pure)"
|
54
59
|
task :install_pure => :version do
|
@@ -73,86 +78,6 @@ task :install_ext => [ :compile, :install_pure, :install_ext_really ]
|
|
73
78
|
desc "Installing library (extension)"
|
74
79
|
task :install => :install_ext
|
75
80
|
|
76
|
-
if defined?(Gem) and defined?(Gem::PackageTask)
|
77
|
-
spec_pure = Gem::Specification.new do |s|
|
78
|
-
s.name = 'json_pure'
|
79
|
-
s.version = PKG_VERSION
|
80
|
-
s.summary = PKG_TITLE
|
81
|
-
s.description = "This is a JSON implementation in pure Ruby."
|
82
|
-
|
83
|
-
s.files = PKG_FILES
|
84
|
-
|
85
|
-
s.require_path = 'lib'
|
86
|
-
s.add_development_dependency 'rake'
|
87
|
-
s.add_development_dependency 'test-unit', '~> 2.0'
|
88
|
-
|
89
|
-
s.extra_rdoc_files << 'README.md'
|
90
|
-
s.rdoc_options <<
|
91
|
-
'--title' << 'JSON implemention for ruby' << '--main' << 'README.md'
|
92
|
-
s.test_files.concat Dir['./tests/test_*.rb']
|
93
|
-
|
94
|
-
s.author = "Florian Frank"
|
95
|
-
s.email = "flori@ping.de"
|
96
|
-
s.homepage = "http://flori.github.com/#{PKG_NAME}"
|
97
|
-
s.license = 'Ruby'
|
98
|
-
s.required_ruby_version = '>= 1.9'
|
99
|
-
end
|
100
|
-
|
101
|
-
desc 'Creates a json_pure.gemspec file'
|
102
|
-
task :gemspec_pure => :version do
|
103
|
-
File.open('json_pure.gemspec', 'w') do |gemspec|
|
104
|
-
gemspec.write spec_pure.to_ruby
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
|
-
Gem::PackageTask.new(spec_pure) do |pkg|
|
109
|
-
pkg.need_tar = true
|
110
|
-
pkg.package_files = PKG_FILES
|
111
|
-
end
|
112
|
-
|
113
|
-
spec_ext = Gem::Specification.new do |s|
|
114
|
-
s.name = 'json'
|
115
|
-
s.version = PKG_VERSION
|
116
|
-
s.summary = PKG_TITLE
|
117
|
-
s.description = "This is a JSON implementation as a Ruby extension in C."
|
118
|
-
|
119
|
-
s.files = PKG_FILES
|
120
|
-
|
121
|
-
s.extensions = FileList['ext/**/extconf.rb']
|
122
|
-
|
123
|
-
s.require_path = 'lib'
|
124
|
-
s.add_development_dependency 'rake'
|
125
|
-
s.add_development_dependency 'test-unit', '~> 2.0'
|
126
|
-
|
127
|
-
s.extra_rdoc_files << 'README.md'
|
128
|
-
s.rdoc_options <<
|
129
|
-
'--title' << 'JSON implemention for Ruby' << '--main' << 'README.md'
|
130
|
-
s.test_files.concat Dir['./tests/test_*.rb']
|
131
|
-
|
132
|
-
s.author = "Florian Frank"
|
133
|
-
s.email = "flori@ping.de"
|
134
|
-
s.homepage = "http://flori.github.com/#{PKG_NAME}"
|
135
|
-
s.license = 'Ruby'
|
136
|
-
s.required_ruby_version = '>= 1.9'
|
137
|
-
end
|
138
|
-
|
139
|
-
desc 'Creates a json.gemspec file'
|
140
|
-
task :gemspec_ext => :version do
|
141
|
-
File.open('json.gemspec', 'w') do |gemspec|
|
142
|
-
gemspec.write spec_ext.to_ruby
|
143
|
-
end
|
144
|
-
end
|
145
|
-
|
146
|
-
Gem::PackageTask.new(spec_ext) do |pkg|
|
147
|
-
pkg.need_tar = true
|
148
|
-
pkg.package_files = PKG_FILES
|
149
|
-
end
|
150
|
-
|
151
|
-
|
152
|
-
desc 'Create all gemspec files'
|
153
|
-
task :gemspec => [ :gemspec_pure, :gemspec_ext ]
|
154
|
-
end
|
155
|
-
|
156
81
|
desc m = "Writing version information for #{PKG_VERSION}"
|
157
82
|
task :version do
|
158
83
|
puts m
|
@@ -176,7 +101,8 @@ task :check_env do
|
|
176
101
|
end
|
177
102
|
|
178
103
|
desc "Testing library (pure ruby)"
|
179
|
-
task :test_pure => [ :
|
104
|
+
task :test_pure => [ :set_env_pure, :check_env, :do_test_pure ]
|
105
|
+
task(:set_env_pure) { ENV['JSON'] = 'pure' }
|
180
106
|
|
181
107
|
UndocumentedTestTask.new do |t|
|
182
108
|
t.name = 'do_test_pure'
|
@@ -187,10 +113,7 @@ UndocumentedTestTask.new do |t|
|
|
187
113
|
end
|
188
114
|
|
189
115
|
desc "Testing library (pure ruby and extension)"
|
190
|
-
task :test
|
191
|
-
sh "env JSON=pure #{BUNDLE} exec rake test_pure" or exit 1
|
192
|
-
sh "env JSON=ext #{BUNDLE} exec rake test_ext" or exit 1
|
193
|
-
end
|
116
|
+
task :test => [ :test_pure, :test_ext ]
|
194
117
|
|
195
118
|
namespace :gems do
|
196
119
|
desc 'Install all development gems'
|
@@ -257,7 +180,8 @@ if defined?(RUBY_ENGINE) and RUBY_ENGINE == 'jruby'
|
|
257
180
|
end
|
258
181
|
|
259
182
|
desc "Testing library (jruby)"
|
260
|
-
task :test_ext => [ :
|
183
|
+
task :test_ext => [ :set_env_ext, :create_jar, :check_env, :do_test_ext ]
|
184
|
+
task(:set_env_ext) { ENV['JSON'] = 'ext' }
|
261
185
|
|
262
186
|
UndocumentedTestTask.new do |t|
|
263
187
|
t.name = 'do_test_ext'
|
@@ -363,6 +287,8 @@ else
|
|
363
287
|
end
|
364
288
|
src = File.read("parser.c").gsub(/[ \t]+$/, '')
|
365
289
|
src.gsub!(/^static const int (JSON_.*=.*);$/, 'enum {\1};')
|
290
|
+
src.gsub!(/0 <= \(\*p\) && \(\*p\) <= 31/, "0 <= (signed char)(*p) && (*p) <= 31")
|
291
|
+
src[0, 0] = "/* This file is automatically generated from parser.rl by using ragel */"
|
366
292
|
File.open("parser.c", "w") {|f| f.print src}
|
367
293
|
end
|
368
294
|
end
|
@@ -405,4 +331,4 @@ else
|
|
405
331
|
end
|
406
332
|
|
407
333
|
desc "Compile in the the source directory"
|
408
|
-
task :default => [ :clean, :
|
334
|
+
task :default => [ :clean, :test ]
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.
|
1
|
+
2.3.1
|
@@ -15,7 +15,7 @@ static VALUE mJSON, mExt, mGenerator, cState, mGeneratorMethods, mObject,
|
|
15
15
|
#endif
|
16
16
|
mFloat, mString, mString_Extend,
|
17
17
|
mTrueClass, mFalseClass, mNilClass, eGeneratorError,
|
18
|
-
eNestingError,
|
18
|
+
eNestingError,
|
19
19
|
i_SAFE_STATE_PROTOTYPE;
|
20
20
|
|
21
21
|
static ID i_to_s, i_to_json, i_new, i_indent, i_space, i_space_before,
|
@@ -237,6 +237,7 @@ static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string)
|
|
237
237
|
int escape_len;
|
238
238
|
unsigned char c;
|
239
239
|
char buf[6] = { '\\', 'u' };
|
240
|
+
int ascii_only = rb_enc_str_asciionly_p(string);
|
240
241
|
|
241
242
|
for (start = 0, end = 0; end < len;) {
|
242
243
|
p = ptr + end;
|
@@ -281,14 +282,17 @@ static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string)
|
|
281
282
|
break;
|
282
283
|
default:
|
283
284
|
{
|
284
|
-
unsigned short clen =
|
285
|
-
if (
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
285
|
+
unsigned short clen = 1;
|
286
|
+
if (!ascii_only) {
|
287
|
+
clen += trailingBytesForUTF8[c];
|
288
|
+
if (end + clen > len) {
|
289
|
+
rb_raise(rb_path2class("JSON::GeneratorError"),
|
290
|
+
"partial character in source, but hit end");
|
291
|
+
}
|
292
|
+
if (!isLegalUTF8((UTF8 *) p, clen)) {
|
293
|
+
rb_raise(rb_path2class("JSON::GeneratorError"),
|
294
|
+
"source sequence is illegal/malformed utf-8");
|
295
|
+
}
|
292
296
|
}
|
293
297
|
end += clen;
|
294
298
|
}
|
@@ -324,6 +328,76 @@ static char *fstrndup(const char *ptr, unsigned long len) {
|
|
324
328
|
*
|
325
329
|
*/
|
326
330
|
|
331
|
+
/* Explanation of the following: that's the only way to not pollute
|
332
|
+
* standard library's docs with GeneratorMethods::<ClassName> which
|
333
|
+
* are uninformative and take a large place in a list of classes
|
334
|
+
*/
|
335
|
+
|
336
|
+
/*
|
337
|
+
* Document-module: JSON::Ext::Generator::GeneratorMethods
|
338
|
+
* :nodoc:
|
339
|
+
*/
|
340
|
+
|
341
|
+
/*
|
342
|
+
* Document-module: JSON::Ext::Generator::GeneratorMethods::Array
|
343
|
+
* :nodoc:
|
344
|
+
*/
|
345
|
+
|
346
|
+
/*
|
347
|
+
* Document-module: JSON::Ext::Generator::GeneratorMethods::Bignum
|
348
|
+
* :nodoc:
|
349
|
+
*/
|
350
|
+
|
351
|
+
/*
|
352
|
+
* Document-module: JSON::Ext::Generator::GeneratorMethods::FalseClass
|
353
|
+
* :nodoc:
|
354
|
+
*/
|
355
|
+
|
356
|
+
/*
|
357
|
+
* Document-module: JSON::Ext::Generator::GeneratorMethods::Fixnum
|
358
|
+
* :nodoc:
|
359
|
+
*/
|
360
|
+
|
361
|
+
/*
|
362
|
+
* Document-module: JSON::Ext::Generator::GeneratorMethods::Float
|
363
|
+
* :nodoc:
|
364
|
+
*/
|
365
|
+
|
366
|
+
/*
|
367
|
+
* Document-module: JSON::Ext::Generator::GeneratorMethods::Hash
|
368
|
+
* :nodoc:
|
369
|
+
*/
|
370
|
+
|
371
|
+
/*
|
372
|
+
* Document-module: JSON::Ext::Generator::GeneratorMethods::Integer
|
373
|
+
* :nodoc:
|
374
|
+
*/
|
375
|
+
|
376
|
+
/*
|
377
|
+
* Document-module: JSON::Ext::Generator::GeneratorMethods::NilClass
|
378
|
+
* :nodoc:
|
379
|
+
*/
|
380
|
+
|
381
|
+
/*
|
382
|
+
* Document-module: JSON::Ext::Generator::GeneratorMethods::Object
|
383
|
+
* :nodoc:
|
384
|
+
*/
|
385
|
+
|
386
|
+
/*
|
387
|
+
* Document-module: JSON::Ext::Generator::GeneratorMethods::String
|
388
|
+
* :nodoc:
|
389
|
+
*/
|
390
|
+
|
391
|
+
/*
|
392
|
+
* Document-module: JSON::Ext::Generator::GeneratorMethods::String::Extend
|
393
|
+
* :nodoc:
|
394
|
+
*/
|
395
|
+
|
396
|
+
/*
|
397
|
+
* Document-module: JSON::Ext::Generator::GeneratorMethods::TrueClass
|
398
|
+
* :nodoc:
|
399
|
+
*/
|
400
|
+
|
327
401
|
/*
|
328
402
|
* call-seq: to_json(state = nil)
|
329
403
|
*
|
@@ -692,7 +766,7 @@ static VALUE cState_aref(VALUE self, VALUE name)
|
|
692
766
|
if (RTEST(rb_funcall(self, i_respond_to_p, 1, name))) {
|
693
767
|
return rb_funcall(self, i_send, 1, name);
|
694
768
|
} else {
|
695
|
-
return
|
769
|
+
return rb_attr_get(self, rb_intern_str(rb_str_concat(rb_str_new2("@"), name)));
|
696
770
|
}
|
697
771
|
}
|
698
772
|
|
@@ -715,43 +789,83 @@ static VALUE cState_aset(VALUE self, VALUE name, VALUE value)
|
|
715
789
|
return Qnil;
|
716
790
|
}
|
717
791
|
|
718
|
-
|
792
|
+
struct hash_foreach_arg {
|
793
|
+
FBuffer *buffer;
|
794
|
+
JSON_Generator_State *state;
|
795
|
+
VALUE Vstate;
|
796
|
+
int iter;
|
797
|
+
};
|
798
|
+
|
799
|
+
static int
|
800
|
+
json_object_i(VALUE key, VALUE val, VALUE _arg)
|
719
801
|
{
|
802
|
+
struct hash_foreach_arg *arg = (struct hash_foreach_arg *)_arg;
|
803
|
+
FBuffer *buffer = arg->buffer;
|
804
|
+
JSON_Generator_State *state = arg->state;
|
805
|
+
VALUE Vstate = arg->Vstate;
|
806
|
+
|
720
807
|
char *object_nl = state->object_nl;
|
721
808
|
long object_nl_len = state->object_nl_len;
|
722
809
|
char *indent = state->indent;
|
723
810
|
long indent_len = state->indent_len;
|
724
|
-
long max_nesting = state->max_nesting;
|
725
811
|
char *delim = FBUFFER_PTR(state->object_delim);
|
726
812
|
long delim_len = FBUFFER_LEN(state->object_delim);
|
727
813
|
char *delim2 = FBUFFER_PTR(state->object_delim2);
|
728
814
|
long delim2_len = FBUFFER_LEN(state->object_delim2);
|
815
|
+
long depth = state->depth;
|
816
|
+
int j;
|
817
|
+
VALUE klass, key_to_s;
|
818
|
+
|
819
|
+
if (arg->iter > 0) fbuffer_append(buffer, delim, delim_len);
|
820
|
+
if (object_nl) {
|
821
|
+
fbuffer_append(buffer, object_nl, object_nl_len);
|
822
|
+
}
|
823
|
+
if (indent) {
|
824
|
+
for (j = 0; j < depth; j++) {
|
825
|
+
fbuffer_append(buffer, indent, indent_len);
|
826
|
+
}
|
827
|
+
}
|
828
|
+
|
829
|
+
klass = CLASS_OF(key);
|
830
|
+
if (klass == rb_cString) {
|
831
|
+
key_to_s = key;
|
832
|
+
} else if (klass == rb_cSymbol) {
|
833
|
+
key_to_s = rb_id2str(SYM2ID(key));
|
834
|
+
} else {
|
835
|
+
key_to_s = rb_funcall(key, i_to_s, 0);
|
836
|
+
}
|
837
|
+
Check_Type(key_to_s, T_STRING);
|
838
|
+
generate_json(buffer, Vstate, state, key_to_s);
|
839
|
+
fbuffer_append(buffer, delim2, delim2_len);
|
840
|
+
generate_json(buffer, Vstate, state, val);
|
841
|
+
|
842
|
+
arg->iter++;
|
843
|
+
return ST_CONTINUE;
|
844
|
+
}
|
845
|
+
|
846
|
+
static void generate_json_object(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
|
847
|
+
{
|
848
|
+
char *object_nl = state->object_nl;
|
849
|
+
long object_nl_len = state->object_nl_len;
|
850
|
+
char *indent = state->indent;
|
851
|
+
long indent_len = state->indent_len;
|
852
|
+
long max_nesting = state->max_nesting;
|
729
853
|
long depth = ++state->depth;
|
730
|
-
int
|
731
|
-
|
854
|
+
int j;
|
855
|
+
struct hash_foreach_arg arg;
|
856
|
+
|
732
857
|
if (max_nesting != 0 && depth > max_nesting) {
|
733
858
|
fbuffer_free(buffer);
|
734
859
|
rb_raise(eNestingError, "nesting of %ld is too deep", --state->depth);
|
735
860
|
}
|
736
861
|
fbuffer_append_char(buffer, '{');
|
737
|
-
|
738
|
-
|
739
|
-
|
740
|
-
|
741
|
-
|
742
|
-
|
743
|
-
|
744
|
-
for (j = 0; j < depth; j++) {
|
745
|
-
fbuffer_append(buffer, indent, indent_len);
|
746
|
-
}
|
747
|
-
}
|
748
|
-
key = rb_ary_entry(keys, i);
|
749
|
-
key_to_s = rb_funcall(key, i_to_s, 0);
|
750
|
-
Check_Type(key_to_s, T_STRING);
|
751
|
-
generate_json(buffer, Vstate, state, key_to_s);
|
752
|
-
fbuffer_append(buffer, delim2, delim2_len);
|
753
|
-
generate_json(buffer, Vstate, state, rb_hash_aref(obj, key));
|
754
|
-
}
|
862
|
+
|
863
|
+
arg.buffer = buffer;
|
864
|
+
arg.state = state;
|
865
|
+
arg.Vstate = Vstate;
|
866
|
+
arg.iter = 0;
|
867
|
+
rb_hash_foreach(obj, json_object_i, (VALUE)&arg);
|
868
|
+
|
755
869
|
depth = --state->depth;
|
756
870
|
if (object_nl) {
|
757
871
|
fbuffer_append(buffer, object_nl, object_nl_len);
|
@@ -802,11 +916,22 @@ static void generate_json_array(FBuffer *buffer, VALUE Vstate, JSON_Generator_St
|
|
802
916
|
fbuffer_append_char(buffer, ']');
|
803
917
|
}
|
804
918
|
|
919
|
+
#ifdef HAVE_RUBY_ENCODING_H
|
920
|
+
static int enc_utf8_compatible_p(rb_encoding *enc)
|
921
|
+
{
|
922
|
+
if (enc == rb_usascii_encoding()) return 1;
|
923
|
+
if (enc == rb_utf8_encoding()) return 1;
|
924
|
+
return 0;
|
925
|
+
}
|
926
|
+
#endif
|
927
|
+
|
805
928
|
static void generate_json_string(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
|
806
929
|
{
|
807
930
|
fbuffer_append_char(buffer, '"');
|
808
931
|
#ifdef HAVE_RUBY_ENCODING_H
|
809
|
-
|
932
|
+
if (!enc_utf8_compatible_p(rb_enc_get(obj))) {
|
933
|
+
obj = rb_str_encode(obj, CEncoding_UTF_8, 0, Qnil);
|
934
|
+
}
|
810
935
|
#endif
|
811
936
|
if (state->ascii_only) {
|
812
937
|
convert_UTF8_to_JSON_ASCII(buffer, obj);
|
@@ -970,6 +1095,8 @@ static VALUE cState_generate(VALUE self, VALUE obj)
|
|
970
1095
|
* * *allow_nan*: true if NaN, Infinity, and -Infinity should be
|
971
1096
|
* generated, otherwise an exception is thrown, if these values are
|
972
1097
|
* encountered. This options defaults to false.
|
1098
|
+
* * *ascii_only*: true if only ASCII characters should be generated. This
|
1099
|
+
* option defaults to false.
|
973
1100
|
* * *buffer_initial_length*: sets the initial length of the generator's
|
974
1101
|
* internal buffer.
|
975
1102
|
*/
|
@@ -1025,10 +1152,8 @@ static VALUE cState_from_state_s(VALUE self, VALUE opts)
|
|
1025
1152
|
} else if (rb_obj_is_kind_of(opts, rb_cHash)) {
|
1026
1153
|
return rb_funcall(self, i_new, 1, opts);
|
1027
1154
|
} else {
|
1028
|
-
|
1029
|
-
|
1030
|
-
}
|
1031
|
-
return rb_funcall(CJSON_SAFE_STATE_PROTOTYPE, i_dup, 0);
|
1155
|
+
VALUE prototype = rb_const_get(mJSON, i_SAFE_STATE_PROTOTYPE);
|
1156
|
+
return rb_funcall(prototype, i_dup, 0);
|
1032
1157
|
}
|
1033
1158
|
}
|
1034
1159
|
|
@@ -1267,7 +1392,7 @@ static VALUE cState_allow_nan_p(VALUE self)
|
|
1267
1392
|
/*
|
1268
1393
|
* call-seq: ascii_only?
|
1269
1394
|
*
|
1270
|
-
* Returns true, if
|
1395
|
+
* Returns true, if only ASCII characters should be generated. Otherwise
|
1271
1396
|
* returns false.
|
1272
1397
|
*/
|
1273
1398
|
static VALUE cState_ascii_only_p(VALUE self)
|
@@ -1344,6 +1469,8 @@ void Init_generator(void)
|
|
1344
1469
|
|
1345
1470
|
eGeneratorError = rb_path2class("JSON::GeneratorError");
|
1346
1471
|
eNestingError = rb_path2class("JSON::NestingError");
|
1472
|
+
rb_gc_register_mark_object(eGeneratorError);
|
1473
|
+
rb_gc_register_mark_object(eNestingError);
|
1347
1474
|
|
1348
1475
|
cState = rb_define_class_under(mGenerator, "State", rb_cObject);
|
1349
1476
|
rb_define_alloc_func(cState, cState_s_allocate);
|
@@ -1409,7 +1536,6 @@ void Init_generator(void)
|
|
1409
1536
|
mNilClass = rb_define_module_under(mGeneratorMethods, "NilClass");
|
1410
1537
|
rb_define_method(mNilClass, "to_json", mNilClass_to_json, -1);
|
1411
1538
|
|
1412
|
-
CRegexp_MULTILINE = rb_const_get(rb_cRegexp, rb_intern("MULTILINE"));
|
1413
1539
|
i_to_s = rb_intern("to_s");
|
1414
1540
|
i_to_json = rb_intern("to_json");
|
1415
1541
|
i_new = rb_intern("new");
|
@@ -1440,5 +1566,4 @@ void Init_generator(void)
|
|
1440
1566
|
i_encode = rb_intern("encode");
|
1441
1567
|
#endif
|
1442
1568
|
i_SAFE_STATE_PROTOTYPE = rb_intern("SAFE_STATE_PROTOTYPE");
|
1443
|
-
CJSON_SAFE_STATE_PROTOTYPE = Qnil;
|
1444
1569
|
}
|