json 1.8.6 → 2.3.0
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 +5 -5
- data/.gitignore +1 -0
- data/.travis.yml +11 -5
- data/{CHANGES → CHANGES.md} +179 -95
- data/Gemfile +10 -3
- data/LICENSE +56 -0
- data/{README-json-jruby.markdown → README-json-jruby.md} +0 -0
- data/README.md +171 -107
- data/Rakefile +33 -22
- data/VERSION +1 -1
- data/ext/json/ext/fbuffer/fbuffer.h +0 -3
- data/ext/json/ext/generator/generator.c +105 -98
- data/ext/json/ext/generator/generator.h +0 -6
- data/ext/json/ext/parser/extconf.rb +3 -0
- data/ext/json/ext/parser/parser.c +376 -480
- data/ext/json/ext/parser/parser.h +4 -5
- data/ext/json/ext/parser/parser.rl +108 -175
- data/ext/json/extconf.rb +0 -1
- data/java/src/json/ext/Generator.java +35 -15
- data/java/src/json/ext/GeneratorState.java +2 -54
- data/java/src/json/ext/OptionsReader.java +1 -1
- data/java/src/json/ext/Parser.java +131 -413
- data/java/src/json/ext/Parser.rl +47 -122
- data/java/src/json/ext/RuntimeInfo.java +0 -4
- data/json-java.gemspec +1 -2
- data/json.gemspec +0 -0
- data/json_pure.gemspec +8 -7
- data/lib/json.rb +1 -0
- data/lib/json/add/bigdecimal.rb +3 -2
- data/lib/json/add/complex.rb +4 -3
- data/lib/json/add/core.rb +1 -0
- data/lib/json/add/date.rb +1 -1
- data/lib/json/add/date_time.rb +1 -1
- data/lib/json/add/exception.rb +1 -1
- data/lib/json/add/ostruct.rb +3 -3
- data/lib/json/add/range.rb +1 -1
- data/lib/json/add/rational.rb +3 -2
- data/lib/json/add/regexp.rb +3 -3
- data/lib/json/add/set.rb +29 -0
- data/lib/json/add/struct.rb +1 -1
- data/lib/json/add/symbol.rb +1 -1
- data/lib/json/add/time.rb +1 -1
- data/lib/json/common.rb +26 -54
- data/lib/json/ext.rb +0 -6
- data/lib/json/generic_object.rb +5 -4
- data/lib/json/pure.rb +2 -8
- data/lib/json/pure/generator.rb +53 -124
- data/lib/json/pure/parser.rb +41 -81
- data/lib/json/version.rb +2 -1
- data/references/rfc7159.txt +899 -0
- data/tests/fixtures/obsolete_fail1.json +1 -0
- data/tests/{test_json_addition.rb → json_addition_test.rb} +32 -25
- data/tests/json_common_interface_test.rb +126 -0
- data/tests/json_encoding_test.rb +107 -0
- data/tests/json_ext_parser_test.rb +15 -0
- data/tests/{test_json_fixtures.rb → json_fixtures_test.rb} +5 -8
- data/tests/{test_json_generate.rb → json_generator_test.rb} +112 -39
- data/tests/{test_json_generic_object.rb → json_generic_object_test.rb} +15 -8
- data/tests/json_parser_test.rb +472 -0
- data/tests/json_string_matching_test.rb +38 -0
- data/tests/{setup_variant.rb → test_helper.rb} +6 -0
- data/tools/fuzz.rb +1 -9
- metadata +22 -37
- data/TODO +0 -1
- data/data/example.json +0 -1
- data/data/index.html +0 -38
- data/data/prototype.js +0 -4184
- data/tests/fixtures/fail1.json +0 -1
- data/tests/test_json.rb +0 -519
- data/tests/test_json_encoding.rb +0 -65
- data/tests/test_json_string_matching.rb +0 -39
- data/tests/test_json_unicode.rb +0 -72
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
|
@@ -88,13 +93,14 @@ if defined?(Gem) and defined?(Gem::PackageTask)
|
|
88
93
|
|
89
94
|
s.extra_rdoc_files << 'README.md'
|
90
95
|
s.rdoc_options <<
|
91
|
-
'--title' << 'JSON implemention for
|
96
|
+
'--title' << 'JSON implemention for ruby' << '--main' << 'README.md'
|
92
97
|
s.test_files.concat Dir['./tests/test_*.rb']
|
93
98
|
|
94
99
|
s.author = "Florian Frank"
|
95
100
|
s.email = "flori@ping.de"
|
96
101
|
s.homepage = "http://flori.github.com/#{PKG_NAME}"
|
97
102
|
s.license = 'Ruby'
|
103
|
+
s.required_ruby_version = '>= 1.9'
|
98
104
|
end
|
99
105
|
|
100
106
|
desc 'Creates a json_pure.gemspec file'
|
@@ -132,6 +138,7 @@ if defined?(Gem) and defined?(Gem::PackageTask)
|
|
132
138
|
s.email = "flori@ping.de"
|
133
139
|
s.homepage = "http://flori.github.com/#{PKG_NAME}"
|
134
140
|
s.license = 'Ruby'
|
141
|
+
s.required_ruby_version = '>= 1.9'
|
135
142
|
end
|
136
143
|
|
137
144
|
desc 'Creates a json.gemspec file'
|
@@ -156,6 +163,7 @@ task :version do
|
|
156
163
|
puts m
|
157
164
|
File.open(File.join('lib', 'json', 'version.rb'), 'w') do |v|
|
158
165
|
v.puts <<EOT
|
166
|
+
# frozen_string_literal: false
|
159
167
|
module JSON
|
160
168
|
# JSON version
|
161
169
|
VERSION = '#{PKG_VERSION}'
|
@@ -168,13 +176,17 @@ EOT
|
|
168
176
|
end
|
169
177
|
end
|
170
178
|
|
179
|
+
task :check_env do
|
180
|
+
ENV.key?('JSON') or fail "JSON env var is required"
|
181
|
+
end
|
182
|
+
|
171
183
|
desc "Testing library (pure ruby)"
|
172
|
-
task :test_pure => [ :clean, :do_test_pure ]
|
184
|
+
task :test_pure => [ :clean, :check_env, :do_test_pure ]
|
173
185
|
|
174
186
|
UndocumentedTestTask.new do |t|
|
175
187
|
t.name = 'do_test_pure'
|
176
|
-
t.libs << 'lib'
|
177
|
-
t.test_files = FileList['tests
|
188
|
+
t.libs << 'lib' << 'tests'
|
189
|
+
t.test_files = FileList['tests/*_test.rb']
|
178
190
|
t.verbose = true
|
179
191
|
t.options = '-v'
|
180
192
|
end
|
@@ -193,13 +205,11 @@ namespace :gems do
|
|
193
205
|
end
|
194
206
|
|
195
207
|
if defined?(RUBY_ENGINE) and RUBY_ENGINE == 'jruby'
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
ENV['JAVA_HOME'] = local_java
|
202
|
-
end
|
208
|
+
ENV['JAVA_HOME'] ||= [
|
209
|
+
'/usr/local/java/jdk',
|
210
|
+
'/usr/lib/jvm/java-6-openjdk',
|
211
|
+
'/Library/Java/Home',
|
212
|
+
].find { |c| File.directory?(c) }
|
203
213
|
if ENV['JAVA_HOME']
|
204
214
|
warn " *** JAVA_HOME is set to #{ENV['JAVA_HOME'].inspect}"
|
205
215
|
ENV['PATH'] = ENV['PATH'].split(/:/).unshift(java_path = "#{ENV['JAVA_HOME']}/bin") * ':'
|
@@ -233,7 +243,7 @@ if defined?(RUBY_ENGINE) and RUBY_ENGINE == 'jruby'
|
|
233
243
|
classpath = (Dir['java/lib/*.jar'] << 'java/src' << JRUBY_JAR) * ':'
|
234
244
|
obj = src.sub(/\.java\Z/, '.class')
|
235
245
|
file obj => src do
|
236
|
-
sh 'javac', '-classpath', classpath, '-source', '1.
|
246
|
+
sh 'javac', '-classpath', classpath, '-source', '1.6', '-target', '1.6', src
|
237
247
|
end
|
238
248
|
JAVA_CLASSES << obj
|
239
249
|
end
|
@@ -252,12 +262,12 @@ if defined?(RUBY_ENGINE) and RUBY_ENGINE == 'jruby'
|
|
252
262
|
end
|
253
263
|
|
254
264
|
desc "Testing library (jruby)"
|
255
|
-
task :test_ext => [ :create_jar, :do_test_ext ]
|
265
|
+
task :test_ext => [ :check_env, :create_jar, :do_test_ext ]
|
256
266
|
|
257
267
|
UndocumentedTestTask.new do |t|
|
258
268
|
t.name = 'do_test_ext'
|
259
|
-
t.libs << 'lib'
|
260
|
-
t.test_files = FileList['tests
|
269
|
+
t.libs << 'lib' << 'tests'
|
270
|
+
t.test_files = FileList['tests/*_test.rb']
|
261
271
|
t.verbose = true
|
262
272
|
t.options = '-v'
|
263
273
|
end
|
@@ -326,12 +336,12 @@ else
|
|
326
336
|
end
|
327
337
|
|
328
338
|
desc "Testing library (extension)"
|
329
|
-
task :test_ext => [ :compile, :do_test_ext ]
|
339
|
+
task :test_ext => [ :check_env, :compile, :do_test_ext ]
|
330
340
|
|
331
341
|
UndocumentedTestTask.new do |t|
|
332
342
|
t.name = 'do_test_ext'
|
333
|
-
t.libs << 'ext' << 'lib'
|
334
|
-
t.test_files = FileList['tests
|
343
|
+
t.libs << 'ext' << 'lib' << 'tests'
|
344
|
+
t.test_files = FileList['tests/*_test.rb']
|
335
345
|
t.verbose = true
|
336
346
|
t.options = '-v'
|
337
347
|
end
|
@@ -357,6 +367,7 @@ else
|
|
357
367
|
sh "ragel -x parser.rl | #{RAGEL_CODEGEN} -G2"
|
358
368
|
end
|
359
369
|
src = File.read("parser.c").gsub(/[ \t]+$/, '')
|
370
|
+
src.gsub!(/^static const int (JSON_.*=.*);$/, 'enum {\1};')
|
360
371
|
File.open("parser.c", "w") {|f| f.print src}
|
361
372
|
end
|
362
373
|
end
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
2.3.0
|
@@ -15,12 +15,12 @@ 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,
|
22
22
|
i_object_nl, i_array_nl, i_max_nesting, i_allow_nan, i_ascii_only,
|
23
|
-
|
23
|
+
i_pack, i_unpack, i_create_id, i_extend, i_key_p,
|
24
24
|
i_aref, i_send, i_respond_to_p, i_match, i_keys, i_depth,
|
25
25
|
i_buffer_initial_length, i_dup;
|
26
26
|
|
@@ -222,6 +222,7 @@ static void convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string)
|
|
222
222
|
unicode_escape_to_buffer(buffer, buf, (UTF16)((ch & halfMask) + UNI_SUR_LOW_START));
|
223
223
|
}
|
224
224
|
}
|
225
|
+
RB_GC_GUARD(string);
|
225
226
|
}
|
226
227
|
|
227
228
|
/* Converts string to a JSON string in FBuffer buffer, where only the
|
@@ -236,6 +237,7 @@ static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string)
|
|
236
237
|
int escape_len;
|
237
238
|
unsigned char c;
|
238
239
|
char buf[6] = { '\\', 'u' };
|
240
|
+
int ascii_only = rb_enc_str_asciionly_p(string);
|
239
241
|
|
240
242
|
for (start = 0, end = 0; end < len;) {
|
241
243
|
p = ptr + end;
|
@@ -280,14 +282,17 @@ static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string)
|
|
280
282
|
break;
|
281
283
|
default:
|
282
284
|
{
|
283
|
-
unsigned short clen =
|
284
|
-
if (
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
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
|
+
}
|
291
296
|
}
|
292
297
|
end += clen;
|
293
298
|
}
|
@@ -307,7 +312,7 @@ static char *fstrndup(const char *ptr, unsigned long len) {
|
|
307
312
|
char *result;
|
308
313
|
if (len <= 0) return NULL;
|
309
314
|
result = ALLOC_N(char, len);
|
310
|
-
|
315
|
+
memcpy(result, ptr, len);
|
311
316
|
return result;
|
312
317
|
}
|
313
318
|
|
@@ -641,8 +646,6 @@ static VALUE cState_configure(VALUE self, VALUE opts)
|
|
641
646
|
state->allow_nan = RTEST(tmp);
|
642
647
|
tmp = rb_hash_aref(opts, ID2SYM(i_ascii_only));
|
643
648
|
state->ascii_only = RTEST(tmp);
|
644
|
-
tmp = rb_hash_aref(opts, ID2SYM(i_quirks_mode));
|
645
|
-
state->quirks_mode = RTEST(tmp);
|
646
649
|
return self;
|
647
650
|
}
|
648
651
|
|
@@ -676,7 +679,6 @@ static VALUE cState_to_h(VALUE self)
|
|
676
679
|
rb_hash_aset(result, ID2SYM(i_array_nl), rb_str_new(state->array_nl, state->array_nl_len));
|
677
680
|
rb_hash_aset(result, ID2SYM(i_allow_nan), state->allow_nan ? Qtrue : Qfalse);
|
678
681
|
rb_hash_aset(result, ID2SYM(i_ascii_only), state->ascii_only ? Qtrue : Qfalse);
|
679
|
-
rb_hash_aset(result, ID2SYM(i_quirks_mode), state->quirks_mode ? Qtrue : Qfalse);
|
680
682
|
rb_hash_aset(result, ID2SYM(i_max_nesting), LONG2FIX(state->max_nesting));
|
681
683
|
rb_hash_aset(result, ID2SYM(i_depth), LONG2FIX(state->depth));
|
682
684
|
rb_hash_aset(result, ID2SYM(i_buffer_initial_length), LONG2FIX(state->buffer_initial_length));
|
@@ -694,7 +696,7 @@ static VALUE cState_aref(VALUE self, VALUE name)
|
|
694
696
|
if (RTEST(rb_funcall(self, i_respond_to_p, 1, name))) {
|
695
697
|
return rb_funcall(self, i_send, 1, name);
|
696
698
|
} else {
|
697
|
-
return
|
699
|
+
return rb_attr_get(self, rb_intern_str(rb_str_concat(rb_str_new2("@"), name)));
|
698
700
|
}
|
699
701
|
}
|
700
702
|
|
@@ -717,43 +719,83 @@ static VALUE cState_aset(VALUE self, VALUE name, VALUE value)
|
|
717
719
|
return Qnil;
|
718
720
|
}
|
719
721
|
|
720
|
-
|
722
|
+
struct hash_foreach_arg {
|
723
|
+
FBuffer *buffer;
|
724
|
+
JSON_Generator_State *state;
|
725
|
+
VALUE Vstate;
|
726
|
+
int iter;
|
727
|
+
};
|
728
|
+
|
729
|
+
static int
|
730
|
+
json_object_i(VALUE key, VALUE val, VALUE _arg)
|
721
731
|
{
|
732
|
+
struct hash_foreach_arg *arg = (struct hash_foreach_arg *)_arg;
|
733
|
+
FBuffer *buffer = arg->buffer;
|
734
|
+
JSON_Generator_State *state = arg->state;
|
735
|
+
VALUE Vstate = arg->Vstate;
|
736
|
+
|
722
737
|
char *object_nl = state->object_nl;
|
723
738
|
long object_nl_len = state->object_nl_len;
|
724
739
|
char *indent = state->indent;
|
725
740
|
long indent_len = state->indent_len;
|
726
|
-
long max_nesting = state->max_nesting;
|
727
741
|
char *delim = FBUFFER_PTR(state->object_delim);
|
728
742
|
long delim_len = FBUFFER_LEN(state->object_delim);
|
729
743
|
char *delim2 = FBUFFER_PTR(state->object_delim2);
|
730
744
|
long delim2_len = FBUFFER_LEN(state->object_delim2);
|
745
|
+
long depth = state->depth;
|
746
|
+
int j;
|
747
|
+
VALUE klass, key_to_s;
|
748
|
+
|
749
|
+
if (arg->iter > 0) fbuffer_append(buffer, delim, delim_len);
|
750
|
+
if (object_nl) {
|
751
|
+
fbuffer_append(buffer, object_nl, object_nl_len);
|
752
|
+
}
|
753
|
+
if (indent) {
|
754
|
+
for (j = 0; j < depth; j++) {
|
755
|
+
fbuffer_append(buffer, indent, indent_len);
|
756
|
+
}
|
757
|
+
}
|
758
|
+
|
759
|
+
klass = CLASS_OF(key);
|
760
|
+
if (klass == rb_cString) {
|
761
|
+
key_to_s = key;
|
762
|
+
} else if (klass == rb_cSymbol) {
|
763
|
+
key_to_s = rb_id2str(SYM2ID(key));
|
764
|
+
} else {
|
765
|
+
key_to_s = rb_funcall(key, i_to_s, 0);
|
766
|
+
}
|
767
|
+
Check_Type(key_to_s, T_STRING);
|
768
|
+
generate_json(buffer, Vstate, state, key_to_s);
|
769
|
+
fbuffer_append(buffer, delim2, delim2_len);
|
770
|
+
generate_json(buffer, Vstate, state, val);
|
771
|
+
|
772
|
+
arg->iter++;
|
773
|
+
return ST_CONTINUE;
|
774
|
+
}
|
775
|
+
|
776
|
+
static void generate_json_object(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
|
777
|
+
{
|
778
|
+
char *object_nl = state->object_nl;
|
779
|
+
long object_nl_len = state->object_nl_len;
|
780
|
+
char *indent = state->indent;
|
781
|
+
long indent_len = state->indent_len;
|
782
|
+
long max_nesting = state->max_nesting;
|
731
783
|
long depth = ++state->depth;
|
732
|
-
int
|
733
|
-
|
784
|
+
int j;
|
785
|
+
struct hash_foreach_arg arg;
|
786
|
+
|
734
787
|
if (max_nesting != 0 && depth > max_nesting) {
|
735
788
|
fbuffer_free(buffer);
|
736
789
|
rb_raise(eNestingError, "nesting of %ld is too deep", --state->depth);
|
737
790
|
}
|
738
791
|
fbuffer_append_char(buffer, '{');
|
739
|
-
|
740
|
-
|
741
|
-
|
742
|
-
|
743
|
-
|
744
|
-
|
745
|
-
|
746
|
-
for (j = 0; j < depth; j++) {
|
747
|
-
fbuffer_append(buffer, indent, indent_len);
|
748
|
-
}
|
749
|
-
}
|
750
|
-
key = rb_ary_entry(keys, i);
|
751
|
-
key_to_s = rb_funcall(key, i_to_s, 0);
|
752
|
-
Check_Type(key_to_s, T_STRING);
|
753
|
-
generate_json(buffer, Vstate, state, key_to_s);
|
754
|
-
fbuffer_append(buffer, delim2, delim2_len);
|
755
|
-
generate_json(buffer, Vstate, state, rb_hash_aref(obj, key));
|
756
|
-
}
|
792
|
+
|
793
|
+
arg.buffer = buffer;
|
794
|
+
arg.state = state;
|
795
|
+
arg.Vstate = Vstate;
|
796
|
+
arg.iter = 0;
|
797
|
+
rb_hash_foreach(obj, json_object_i, (VALUE)&arg);
|
798
|
+
|
757
799
|
depth = --state->depth;
|
758
800
|
if (object_nl) {
|
759
801
|
fbuffer_append(buffer, object_nl, object_nl_len);
|
@@ -804,11 +846,22 @@ static void generate_json_array(FBuffer *buffer, VALUE Vstate, JSON_Generator_St
|
|
804
846
|
fbuffer_append_char(buffer, ']');
|
805
847
|
}
|
806
848
|
|
849
|
+
#ifdef HAVE_RUBY_ENCODING_H
|
850
|
+
static int enc_utf8_compatible_p(rb_encoding *enc)
|
851
|
+
{
|
852
|
+
if (enc == rb_usascii_encoding()) return 1;
|
853
|
+
if (enc == rb_utf8_encoding()) return 1;
|
854
|
+
return 0;
|
855
|
+
}
|
856
|
+
#endif
|
857
|
+
|
807
858
|
static void generate_json_string(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
|
808
859
|
{
|
809
860
|
fbuffer_append_char(buffer, '"');
|
810
861
|
#ifdef HAVE_RUBY_ENCODING_H
|
811
|
-
|
862
|
+
if (!enc_utf8_compatible_p(rb_enc_get(obj))) {
|
863
|
+
obj = rb_str_encode(obj, CEncoding_UTF_8, 0, Qnil);
|
864
|
+
}
|
812
865
|
#endif
|
813
866
|
if (state->ascii_only) {
|
814
867
|
convert_UTF8_to_JSON_ASCII(buffer, obj);
|
@@ -853,7 +906,6 @@ static void generate_json_integer(FBuffer *buffer, VALUE Vstate, JSON_Generator_
|
|
853
906
|
generate_json_bignum(buffer, Vstate, state, obj);
|
854
907
|
}
|
855
908
|
#endif
|
856
|
-
|
857
909
|
static void generate_json_float(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
|
858
910
|
{
|
859
911
|
double value = RFLOAT_VALUE(obj);
|
@@ -943,21 +995,6 @@ static VALUE cState_partial_generate(VALUE self, VALUE obj)
|
|
943
995
|
return fbuffer_to_s(buffer);
|
944
996
|
}
|
945
997
|
|
946
|
-
/*
|
947
|
-
* This function returns true if string is either a JSON array or JSON object.
|
948
|
-
* It might suffer from false positives, e. g. syntactically incorrect JSON in
|
949
|
-
* the string or certain UTF-8 characters on the right hand side.
|
950
|
-
*/
|
951
|
-
static int isArrayOrObject(VALUE string)
|
952
|
-
{
|
953
|
-
long string_len = RSTRING_LEN(string);
|
954
|
-
char *p = RSTRING_PTR(string), *q = p + string_len - 1;
|
955
|
-
if (string_len < 2) return 0;
|
956
|
-
for (; p < q && isspace((unsigned char)*p); p++);
|
957
|
-
for (; q > p && isspace((unsigned char)*q); q--);
|
958
|
-
return (*p == '[' && *q == ']') || (*p == '{' && *q == '}');
|
959
|
-
}
|
960
|
-
|
961
998
|
/*
|
962
999
|
* call-seq: generate(obj)
|
963
1000
|
*
|
@@ -969,9 +1006,7 @@ static VALUE cState_generate(VALUE self, VALUE obj)
|
|
969
1006
|
{
|
970
1007
|
VALUE result = cState_partial_generate(self, obj);
|
971
1008
|
GET_STATE(self);
|
972
|
-
|
973
|
-
rb_raise(eGeneratorError, "only generation of JSON objects or arrays allowed");
|
974
|
-
}
|
1009
|
+
(void)state;
|
975
1010
|
return result;
|
976
1011
|
}
|
977
1012
|
|
@@ -990,8 +1025,8 @@ static VALUE cState_generate(VALUE self, VALUE obj)
|
|
990
1025
|
* * *allow_nan*: true if NaN, Infinity, and -Infinity should be
|
991
1026
|
* generated, otherwise an exception is thrown, if these values are
|
992
1027
|
* encountered. This options defaults to false.
|
993
|
-
* * *
|
994
|
-
*
|
1028
|
+
* * *ascii_only*: true if only ASCII characters should be generated. This
|
1029
|
+
* ontions defaults to false.
|
995
1030
|
* * *buffer_initial_length*: sets the initial length of the generator's
|
996
1031
|
* internal buffer.
|
997
1032
|
*/
|
@@ -1047,10 +1082,8 @@ static VALUE cState_from_state_s(VALUE self, VALUE opts)
|
|
1047
1082
|
} else if (rb_obj_is_kind_of(opts, rb_cHash)) {
|
1048
1083
|
return rb_funcall(self, i_new, 1, opts);
|
1049
1084
|
} else {
|
1050
|
-
|
1051
|
-
|
1052
|
-
}
|
1053
|
-
return rb_funcall(CJSON_SAFE_STATE_PROTOTYPE, i_dup, 0);
|
1085
|
+
VALUE prototype = rb_const_get(mJSON, i_SAFE_STATE_PROTOTYPE);
|
1086
|
+
return rb_funcall(prototype, i_dup, 0);
|
1054
1087
|
}
|
1055
1088
|
}
|
1056
1089
|
|
@@ -1084,7 +1117,7 @@ static VALUE cState_indent_set(VALUE self, VALUE indent)
|
|
1084
1117
|
}
|
1085
1118
|
} else {
|
1086
1119
|
if (state->indent) ruby_xfree(state->indent);
|
1087
|
-
state->indent =
|
1120
|
+
state->indent = fstrndup(RSTRING_PTR(indent), len);
|
1088
1121
|
state->indent_len = len;
|
1089
1122
|
}
|
1090
1123
|
return Qnil;
|
@@ -1122,7 +1155,7 @@ static VALUE cState_space_set(VALUE self, VALUE space)
|
|
1122
1155
|
}
|
1123
1156
|
} else {
|
1124
1157
|
if (state->space) ruby_xfree(state->space);
|
1125
|
-
state->space =
|
1158
|
+
state->space = fstrndup(RSTRING_PTR(space), len);
|
1126
1159
|
state->space_len = len;
|
1127
1160
|
}
|
1128
1161
|
return Qnil;
|
@@ -1158,7 +1191,7 @@ static VALUE cState_space_before_set(VALUE self, VALUE space_before)
|
|
1158
1191
|
}
|
1159
1192
|
} else {
|
1160
1193
|
if (state->space_before) ruby_xfree(state->space_before);
|
1161
|
-
state->space_before =
|
1194
|
+
state->space_before = fstrndup(RSTRING_PTR(space_before), len);
|
1162
1195
|
state->space_before_len = len;
|
1163
1196
|
}
|
1164
1197
|
return Qnil;
|
@@ -1195,7 +1228,7 @@ static VALUE cState_object_nl_set(VALUE self, VALUE object_nl)
|
|
1195
1228
|
}
|
1196
1229
|
} else {
|
1197
1230
|
if (state->object_nl) ruby_xfree(state->object_nl);
|
1198
|
-
state->object_nl =
|
1231
|
+
state->object_nl = fstrndup(RSTRING_PTR(object_nl), len);
|
1199
1232
|
state->object_nl_len = len;
|
1200
1233
|
}
|
1201
1234
|
return Qnil;
|
@@ -1230,7 +1263,7 @@ static VALUE cState_array_nl_set(VALUE self, VALUE array_nl)
|
|
1230
1263
|
}
|
1231
1264
|
} else {
|
1232
1265
|
if (state->array_nl) ruby_xfree(state->array_nl);
|
1233
|
-
state->array_nl =
|
1266
|
+
state->array_nl = fstrndup(RSTRING_PTR(array_nl), len);
|
1234
1267
|
state->array_nl_len = len;
|
1235
1268
|
}
|
1236
1269
|
return Qnil;
|
@@ -1289,7 +1322,7 @@ static VALUE cState_allow_nan_p(VALUE self)
|
|
1289
1322
|
/*
|
1290
1323
|
* call-seq: ascii_only?
|
1291
1324
|
*
|
1292
|
-
* Returns true, if
|
1325
|
+
* Returns true, if only ASCII characters should be generated. Otherwise
|
1293
1326
|
* returns false.
|
1294
1327
|
*/
|
1295
1328
|
static VALUE cState_ascii_only_p(VALUE self)
|
@@ -1298,29 +1331,6 @@ static VALUE cState_ascii_only_p(VALUE self)
|
|
1298
1331
|
return state->ascii_only ? Qtrue : Qfalse;
|
1299
1332
|
}
|
1300
1333
|
|
1301
|
-
/*
|
1302
|
-
* call-seq: quirks_mode?
|
1303
|
-
*
|
1304
|
-
* Returns true, if quirks mode is enabled. Otherwise returns false.
|
1305
|
-
*/
|
1306
|
-
static VALUE cState_quirks_mode_p(VALUE self)
|
1307
|
-
{
|
1308
|
-
GET_STATE(self);
|
1309
|
-
return state->quirks_mode ? Qtrue : Qfalse;
|
1310
|
-
}
|
1311
|
-
|
1312
|
-
/*
|
1313
|
-
* call-seq: quirks_mode=(enable)
|
1314
|
-
*
|
1315
|
-
* If set to true, enables the quirks_mode mode.
|
1316
|
-
*/
|
1317
|
-
static VALUE cState_quirks_mode_set(VALUE self, VALUE enable)
|
1318
|
-
{
|
1319
|
-
GET_STATE(self);
|
1320
|
-
state->quirks_mode = RTEST(enable);
|
1321
|
-
return Qnil;
|
1322
|
-
}
|
1323
|
-
|
1324
1334
|
/*
|
1325
1335
|
* call-seq: depth
|
1326
1336
|
*
|
@@ -1380,6 +1390,7 @@ static VALUE cState_buffer_initial_length_set(VALUE self, VALUE buffer_initial_l
|
|
1380
1390
|
*/
|
1381
1391
|
void Init_generator(void)
|
1382
1392
|
{
|
1393
|
+
#undef rb_intern
|
1383
1394
|
rb_require("json/common");
|
1384
1395
|
|
1385
1396
|
mJSON = rb_define_module("JSON");
|
@@ -1388,6 +1399,8 @@ void Init_generator(void)
|
|
1388
1399
|
|
1389
1400
|
eGeneratorError = rb_path2class("JSON::GeneratorError");
|
1390
1401
|
eNestingError = rb_path2class("JSON::NestingError");
|
1402
|
+
rb_gc_register_mark_object(eGeneratorError);
|
1403
|
+
rb_gc_register_mark_object(eNestingError);
|
1391
1404
|
|
1392
1405
|
cState = rb_define_class_under(mGenerator, "State", rb_cObject);
|
1393
1406
|
rb_define_alloc_func(cState, cState_s_allocate);
|
@@ -1409,9 +1422,6 @@ void Init_generator(void)
|
|
1409
1422
|
rb_define_method(cState, "check_circular?", cState_check_circular_p, 0);
|
1410
1423
|
rb_define_method(cState, "allow_nan?", cState_allow_nan_p, 0);
|
1411
1424
|
rb_define_method(cState, "ascii_only?", cState_ascii_only_p, 0);
|
1412
|
-
rb_define_method(cState, "quirks_mode?", cState_quirks_mode_p, 0);
|
1413
|
-
rb_define_method(cState, "quirks_mode", cState_quirks_mode_p, 0);
|
1414
|
-
rb_define_method(cState, "quirks_mode=", cState_quirks_mode_set, 1);
|
1415
1425
|
rb_define_method(cState, "depth", cState_depth, 0);
|
1416
1426
|
rb_define_method(cState, "depth=", cState_depth_set, 1);
|
1417
1427
|
rb_define_method(cState, "buffer_initial_length", cState_buffer_initial_length, 0);
|
@@ -1456,7 +1466,6 @@ void Init_generator(void)
|
|
1456
1466
|
mNilClass = rb_define_module_under(mGeneratorMethods, "NilClass");
|
1457
1467
|
rb_define_method(mNilClass, "to_json", mNilClass_to_json, -1);
|
1458
1468
|
|
1459
|
-
CRegexp_MULTILINE = rb_const_get(rb_cRegexp, rb_intern("MULTILINE"));
|
1460
1469
|
i_to_s = rb_intern("to_s");
|
1461
1470
|
i_to_json = rb_intern("to_json");
|
1462
1471
|
i_new = rb_intern("new");
|
@@ -1468,7 +1477,6 @@ void Init_generator(void)
|
|
1468
1477
|
i_max_nesting = rb_intern("max_nesting");
|
1469
1478
|
i_allow_nan = rb_intern("allow_nan");
|
1470
1479
|
i_ascii_only = rb_intern("ascii_only");
|
1471
|
-
i_quirks_mode = rb_intern("quirks_mode");
|
1472
1480
|
i_depth = rb_intern("depth");
|
1473
1481
|
i_buffer_initial_length = rb_intern("buffer_initial_length");
|
1474
1482
|
i_pack = rb_intern("pack");
|
@@ -1488,5 +1496,4 @@ void Init_generator(void)
|
|
1488
1496
|
i_encode = rb_intern("encode");
|
1489
1497
|
#endif
|
1490
1498
|
i_SAFE_STATE_PROTOTYPE = rb_intern("SAFE_STATE_PROTOTYPE");
|
1491
|
-
CJSON_SAFE_STATE_PROTOTYPE = Qnil;
|
1492
1499
|
}
|