json 1.8.6 → 2.5.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 +5 -5
- data/{CHANGES → CHANGES.md} +234 -95
- data/Gemfile +10 -3
- data/LICENSE +56 -0
- data/README.md +187 -107
- data/VERSION +1 -1
- data/ext/json/ext/fbuffer/fbuffer.h +0 -3
- data/ext/json/ext/generator/generator.c +227 -101
- data/ext/json/ext/generator/generator.h +5 -8
- data/ext/json/ext/parser/extconf.rb +28 -0
- data/ext/json/ext/parser/parser.c +420 -481
- data/ext/json/ext/parser/parser.h +5 -5
- data/ext/json/ext/parser/parser.rl +148 -172
- data/ext/json/extconf.rb +1 -1
- data/json.gemspec +0 -0
- data/lib/json.rb +550 -29
- data/lib/json/add/bigdecimal.rb +3 -2
- data/lib/json/add/complex.rb +4 -4
- 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 -3
- 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 +381 -162
- 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 +73 -124
- data/lib/json/pure/parser.rb +62 -84
- data/lib/json/version.rb +2 -1
- data/tests/fixtures/fail29.json +1 -0
- data/tests/fixtures/fail30.json +1 -0
- data/tests/fixtures/fail31.json +1 -0
- data/tests/fixtures/fail32.json +1 -0
- data/tests/fixtures/obsolete_fail1.json +1 -0
- data/tests/{test_json_addition.rb → json_addition_test.rb} +28 -25
- data/tests/json_common_interface_test.rb +169 -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} +13 -8
- data/tests/{test_json_generate.rb → json_generator_test.rb} +98 -47
- data/tests/{test_json_generic_object.rb → json_generic_object_test.rb} +15 -8
- data/tests/json_parser_test.rb +497 -0
- data/tests/json_string_matching_test.rb +38 -0
- data/tests/lib/core_assertions.rb +763 -0
- data/tests/lib/envutil.rb +365 -0
- data/tests/lib/find_executable.rb +22 -0
- data/tests/lib/helper.rb +4 -0
- data/tests/ractor_test.rb +30 -0
- data/tests/test_helper.rb +17 -0
- metadata +43 -69
- data/.gitignore +0 -17
- data/.travis.yml +0 -18
- data/README-json-jruby.markdown +0 -33
- data/Rakefile +0 -402
- data/TODO +0 -1
- data/data/example.json +0 -1
- data/data/index.html +0 -38
- data/data/prototype.js +0 -4184
- data/diagrams/.keep +0 -0
- data/install.rb +0 -23
- data/java/src/json/ext/ByteListTranscoder.java +0 -166
- data/java/src/json/ext/Generator.java +0 -446
- data/java/src/json/ext/GeneratorMethods.java +0 -231
- data/java/src/json/ext/GeneratorService.java +0 -42
- data/java/src/json/ext/GeneratorState.java +0 -542
- data/java/src/json/ext/OptionsReader.java +0 -113
- data/java/src/json/ext/Parser.java +0 -2644
- data/java/src/json/ext/Parser.rl +0 -968
- data/java/src/json/ext/ParserService.java +0 -34
- data/java/src/json/ext/RuntimeInfo.java +0 -120
- data/java/src/json/ext/StringDecoder.java +0 -166
- data/java/src/json/ext/StringEncoder.java +0 -111
- data/java/src/json/ext/Utils.java +0 -88
- data/json-java.gemspec +0 -38
- data/json_pure.gemspec +0 -37
- data/tests/fixtures/fail1.json +0 -1
- data/tests/setup_variant.rb +0 -11
- 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/tools/diff.sh +0 -18
- data/tools/fuzz.rb +0 -139
- data/tools/server.rb +0 -62
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
2.5.1
|
@@ -15,14 +15,13 @@ 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
|
19
|
-
i_SAFE_STATE_PROTOTYPE;
|
18
|
+
eNestingError;
|
20
19
|
|
21
20
|
static ID i_to_s, i_to_json, i_new, i_indent, i_space, i_space_before,
|
22
21
|
i_object_nl, i_array_nl, i_max_nesting, i_allow_nan, i_ascii_only,
|
23
|
-
|
22
|
+
i_pack, i_unpack, i_create_id, i_extend, i_key_p,
|
24
23
|
i_aref, i_send, i_respond_to_p, i_match, i_keys, i_depth,
|
25
|
-
i_buffer_initial_length, i_dup;
|
24
|
+
i_buffer_initial_length, i_dup, i_escape_slash;
|
26
25
|
|
27
26
|
/*
|
28
27
|
* Copyright 2001-2004 Unicode, Inc.
|
@@ -130,7 +129,7 @@ static void unicode_escape_to_buffer(FBuffer *buffer, char buf[6], UTF16
|
|
130
129
|
|
131
130
|
/* Converts string to a JSON string in FBuffer buffer, where all but the ASCII
|
132
131
|
* and control characters are JSON escaped. */
|
133
|
-
static void convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string)
|
132
|
+
static void convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string, char escape_slash)
|
134
133
|
{
|
135
134
|
const UTF8 *source = (UTF8 *) RSTRING_PTR(string);
|
136
135
|
const UTF8 *sourceEnd = source + RSTRING_LEN(string);
|
@@ -180,6 +179,11 @@ static void convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string)
|
|
180
179
|
case '"':
|
181
180
|
fbuffer_append(buffer, "\\\"", 2);
|
182
181
|
break;
|
182
|
+
case '/':
|
183
|
+
if(escape_slash) {
|
184
|
+
fbuffer_append(buffer, "\\/", 2);
|
185
|
+
break;
|
186
|
+
}
|
183
187
|
default:
|
184
188
|
fbuffer_append_char(buffer, (char)ch);
|
185
189
|
break;
|
@@ -222,13 +226,14 @@ static void convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string)
|
|
222
226
|
unicode_escape_to_buffer(buffer, buf, (UTF16)((ch & halfMask) + UNI_SUR_LOW_START));
|
223
227
|
}
|
224
228
|
}
|
229
|
+
RB_GC_GUARD(string);
|
225
230
|
}
|
226
231
|
|
227
232
|
/* Converts string to a JSON string in FBuffer buffer, where only the
|
228
233
|
* characters required by the JSON standard are JSON escaped. The remaining
|
229
234
|
* characters (should be UTF8) are just passed through and appended to the
|
230
235
|
* result. */
|
231
|
-
static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string)
|
236
|
+
static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string, char escape_slash)
|
232
237
|
{
|
233
238
|
const char *ptr = RSTRING_PTR(string), *p;
|
234
239
|
unsigned long len = RSTRING_LEN(string), start = 0, end = 0;
|
@@ -236,6 +241,7 @@ static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string)
|
|
236
241
|
int escape_len;
|
237
242
|
unsigned char c;
|
238
243
|
char buf[6] = { '\\', 'u' };
|
244
|
+
int ascii_only = rb_enc_str_asciionly_p(string);
|
239
245
|
|
240
246
|
for (start = 0, end = 0; end < len;) {
|
241
247
|
p = ptr + end;
|
@@ -278,16 +284,25 @@ static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string)
|
|
278
284
|
escape = "\\\"";
|
279
285
|
escape_len = 2;
|
280
286
|
break;
|
287
|
+
case '/':
|
288
|
+
if(escape_slash) {
|
289
|
+
escape = "\\/";
|
290
|
+
escape_len = 2;
|
291
|
+
break;
|
292
|
+
}
|
281
293
|
default:
|
282
294
|
{
|
283
|
-
unsigned short clen =
|
284
|
-
if (
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
295
|
+
unsigned short clen = 1;
|
296
|
+
if (!ascii_only) {
|
297
|
+
clen += trailingBytesForUTF8[c];
|
298
|
+
if (end + clen > len) {
|
299
|
+
rb_raise(rb_path2class("JSON::GeneratorError"),
|
300
|
+
"partial character in source, but hit end");
|
301
|
+
}
|
302
|
+
if (!isLegalUTF8((UTF8 *) p, clen)) {
|
303
|
+
rb_raise(rb_path2class("JSON::GeneratorError"),
|
304
|
+
"source sequence is illegal/malformed utf-8");
|
305
|
+
}
|
291
306
|
}
|
292
307
|
end += clen;
|
293
308
|
}
|
@@ -307,7 +322,7 @@ static char *fstrndup(const char *ptr, unsigned long len) {
|
|
307
322
|
char *result;
|
308
323
|
if (len <= 0) return NULL;
|
309
324
|
result = ALLOC_N(char, len);
|
310
|
-
|
325
|
+
memcpy(result, ptr, len);
|
311
326
|
return result;
|
312
327
|
}
|
313
328
|
|
@@ -323,6 +338,76 @@ static char *fstrndup(const char *ptr, unsigned long len) {
|
|
323
338
|
*
|
324
339
|
*/
|
325
340
|
|
341
|
+
/* Explanation of the following: that's the only way to not pollute
|
342
|
+
* standard library's docs with GeneratorMethods::<ClassName> which
|
343
|
+
* are uninformative and take a large place in a list of classes
|
344
|
+
*/
|
345
|
+
|
346
|
+
/*
|
347
|
+
* Document-module: JSON::Ext::Generator::GeneratorMethods
|
348
|
+
* :nodoc:
|
349
|
+
*/
|
350
|
+
|
351
|
+
/*
|
352
|
+
* Document-module: JSON::Ext::Generator::GeneratorMethods::Array
|
353
|
+
* :nodoc:
|
354
|
+
*/
|
355
|
+
|
356
|
+
/*
|
357
|
+
* Document-module: JSON::Ext::Generator::GeneratorMethods::Bignum
|
358
|
+
* :nodoc:
|
359
|
+
*/
|
360
|
+
|
361
|
+
/*
|
362
|
+
* Document-module: JSON::Ext::Generator::GeneratorMethods::FalseClass
|
363
|
+
* :nodoc:
|
364
|
+
*/
|
365
|
+
|
366
|
+
/*
|
367
|
+
* Document-module: JSON::Ext::Generator::GeneratorMethods::Fixnum
|
368
|
+
* :nodoc:
|
369
|
+
*/
|
370
|
+
|
371
|
+
/*
|
372
|
+
* Document-module: JSON::Ext::Generator::GeneratorMethods::Float
|
373
|
+
* :nodoc:
|
374
|
+
*/
|
375
|
+
|
376
|
+
/*
|
377
|
+
* Document-module: JSON::Ext::Generator::GeneratorMethods::Hash
|
378
|
+
* :nodoc:
|
379
|
+
*/
|
380
|
+
|
381
|
+
/*
|
382
|
+
* Document-module: JSON::Ext::Generator::GeneratorMethods::Integer
|
383
|
+
* :nodoc:
|
384
|
+
*/
|
385
|
+
|
386
|
+
/*
|
387
|
+
* Document-module: JSON::Ext::Generator::GeneratorMethods::NilClass
|
388
|
+
* :nodoc:
|
389
|
+
*/
|
390
|
+
|
391
|
+
/*
|
392
|
+
* Document-module: JSON::Ext::Generator::GeneratorMethods::Object
|
393
|
+
* :nodoc:
|
394
|
+
*/
|
395
|
+
|
396
|
+
/*
|
397
|
+
* Document-module: JSON::Ext::Generator::GeneratorMethods::String
|
398
|
+
* :nodoc:
|
399
|
+
*/
|
400
|
+
|
401
|
+
/*
|
402
|
+
* Document-module: JSON::Ext::Generator::GeneratorMethods::String::Extend
|
403
|
+
* :nodoc:
|
404
|
+
*/
|
405
|
+
|
406
|
+
/*
|
407
|
+
* Document-module: JSON::Ext::Generator::GeneratorMethods::TrueClass
|
408
|
+
* :nodoc:
|
409
|
+
*/
|
410
|
+
|
326
411
|
/*
|
327
412
|
* call-seq: to_json(state = nil)
|
328
413
|
*
|
@@ -534,13 +619,18 @@ static size_t State_memsize(const void *ptr)
|
|
534
619
|
return size;
|
535
620
|
}
|
536
621
|
|
622
|
+
#ifndef HAVE_RB_EXT_RACTOR_SAFE
|
623
|
+
# undef RUBY_TYPED_FROZEN_SHAREABLE
|
624
|
+
# define RUBY_TYPED_FROZEN_SHAREABLE 0
|
625
|
+
#endif
|
626
|
+
|
537
627
|
#ifdef NEW_TYPEDDATA_WRAPPER
|
538
628
|
static const rb_data_type_t JSON_Generator_State_type = {
|
539
629
|
"JSON/Generator/State",
|
540
630
|
{NULL, State_free, State_memsize,},
|
541
631
|
#ifdef RUBY_TYPED_FREE_IMMEDIATELY
|
542
632
|
0, 0,
|
543
|
-
RUBY_TYPED_FREE_IMMEDIATELY,
|
633
|
+
RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_FROZEN_SHAREABLE,
|
544
634
|
#endif
|
545
635
|
};
|
546
636
|
#endif
|
@@ -641,8 +731,8 @@ static VALUE cState_configure(VALUE self, VALUE opts)
|
|
641
731
|
state->allow_nan = RTEST(tmp);
|
642
732
|
tmp = rb_hash_aref(opts, ID2SYM(i_ascii_only));
|
643
733
|
state->ascii_only = RTEST(tmp);
|
644
|
-
tmp = rb_hash_aref(opts, ID2SYM(
|
645
|
-
state->
|
734
|
+
tmp = rb_hash_aref(opts, ID2SYM(i_escape_slash));
|
735
|
+
state->escape_slash = RTEST(tmp);
|
646
736
|
return self;
|
647
737
|
}
|
648
738
|
|
@@ -676,8 +766,8 @@ static VALUE cState_to_h(VALUE self)
|
|
676
766
|
rb_hash_aset(result, ID2SYM(i_array_nl), rb_str_new(state->array_nl, state->array_nl_len));
|
677
767
|
rb_hash_aset(result, ID2SYM(i_allow_nan), state->allow_nan ? Qtrue : Qfalse);
|
678
768
|
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
769
|
rb_hash_aset(result, ID2SYM(i_max_nesting), LONG2FIX(state->max_nesting));
|
770
|
+
rb_hash_aset(result, ID2SYM(i_escape_slash), state->escape_slash ? Qtrue : Qfalse);
|
681
771
|
rb_hash_aset(result, ID2SYM(i_depth), LONG2FIX(state->depth));
|
682
772
|
rb_hash_aset(result, ID2SYM(i_buffer_initial_length), LONG2FIX(state->buffer_initial_length));
|
683
773
|
return result;
|
@@ -694,7 +784,7 @@ static VALUE cState_aref(VALUE self, VALUE name)
|
|
694
784
|
if (RTEST(rb_funcall(self, i_respond_to_p, 1, name))) {
|
695
785
|
return rb_funcall(self, i_send, 1, name);
|
696
786
|
} else {
|
697
|
-
return
|
787
|
+
return rb_attr_get(self, rb_intern_str(rb_str_concat(rb_str_new2("@"), name)));
|
698
788
|
}
|
699
789
|
}
|
700
790
|
|
@@ -717,43 +807,83 @@ static VALUE cState_aset(VALUE self, VALUE name, VALUE value)
|
|
717
807
|
return Qnil;
|
718
808
|
}
|
719
809
|
|
720
|
-
|
810
|
+
struct hash_foreach_arg {
|
811
|
+
FBuffer *buffer;
|
812
|
+
JSON_Generator_State *state;
|
813
|
+
VALUE Vstate;
|
814
|
+
int iter;
|
815
|
+
};
|
816
|
+
|
817
|
+
static int
|
818
|
+
json_object_i(VALUE key, VALUE val, VALUE _arg)
|
721
819
|
{
|
820
|
+
struct hash_foreach_arg *arg = (struct hash_foreach_arg *)_arg;
|
821
|
+
FBuffer *buffer = arg->buffer;
|
822
|
+
JSON_Generator_State *state = arg->state;
|
823
|
+
VALUE Vstate = arg->Vstate;
|
824
|
+
|
722
825
|
char *object_nl = state->object_nl;
|
723
826
|
long object_nl_len = state->object_nl_len;
|
724
827
|
char *indent = state->indent;
|
725
828
|
long indent_len = state->indent_len;
|
726
|
-
long max_nesting = state->max_nesting;
|
727
829
|
char *delim = FBUFFER_PTR(state->object_delim);
|
728
830
|
long delim_len = FBUFFER_LEN(state->object_delim);
|
729
831
|
char *delim2 = FBUFFER_PTR(state->object_delim2);
|
730
832
|
long delim2_len = FBUFFER_LEN(state->object_delim2);
|
833
|
+
long depth = state->depth;
|
834
|
+
int j;
|
835
|
+
VALUE klass, key_to_s;
|
836
|
+
|
837
|
+
if (arg->iter > 0) fbuffer_append(buffer, delim, delim_len);
|
838
|
+
if (object_nl) {
|
839
|
+
fbuffer_append(buffer, object_nl, object_nl_len);
|
840
|
+
}
|
841
|
+
if (indent) {
|
842
|
+
for (j = 0; j < depth; j++) {
|
843
|
+
fbuffer_append(buffer, indent, indent_len);
|
844
|
+
}
|
845
|
+
}
|
846
|
+
|
847
|
+
klass = CLASS_OF(key);
|
848
|
+
if (klass == rb_cString) {
|
849
|
+
key_to_s = key;
|
850
|
+
} else if (klass == rb_cSymbol) {
|
851
|
+
key_to_s = rb_id2str(SYM2ID(key));
|
852
|
+
} else {
|
853
|
+
key_to_s = rb_funcall(key, i_to_s, 0);
|
854
|
+
}
|
855
|
+
Check_Type(key_to_s, T_STRING);
|
856
|
+
generate_json(buffer, Vstate, state, key_to_s);
|
857
|
+
fbuffer_append(buffer, delim2, delim2_len);
|
858
|
+
generate_json(buffer, Vstate, state, val);
|
859
|
+
|
860
|
+
arg->iter++;
|
861
|
+
return ST_CONTINUE;
|
862
|
+
}
|
863
|
+
|
864
|
+
static void generate_json_object(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
|
865
|
+
{
|
866
|
+
char *object_nl = state->object_nl;
|
867
|
+
long object_nl_len = state->object_nl_len;
|
868
|
+
char *indent = state->indent;
|
869
|
+
long indent_len = state->indent_len;
|
870
|
+
long max_nesting = state->max_nesting;
|
731
871
|
long depth = ++state->depth;
|
732
|
-
int
|
733
|
-
|
872
|
+
int j;
|
873
|
+
struct hash_foreach_arg arg;
|
874
|
+
|
734
875
|
if (max_nesting != 0 && depth > max_nesting) {
|
735
876
|
fbuffer_free(buffer);
|
736
877
|
rb_raise(eNestingError, "nesting of %ld is too deep", --state->depth);
|
737
878
|
}
|
738
879
|
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
|
-
}
|
880
|
+
|
881
|
+
arg.buffer = buffer;
|
882
|
+
arg.state = state;
|
883
|
+
arg.Vstate = Vstate;
|
884
|
+
arg.iter = 0;
|
885
|
+
rb_hash_foreach(obj, json_object_i, (VALUE)&arg);
|
886
|
+
|
757
887
|
depth = --state->depth;
|
758
888
|
if (object_nl) {
|
759
889
|
fbuffer_append(buffer, object_nl, object_nl_len);
|
@@ -804,16 +934,27 @@ static void generate_json_array(FBuffer *buffer, VALUE Vstate, JSON_Generator_St
|
|
804
934
|
fbuffer_append_char(buffer, ']');
|
805
935
|
}
|
806
936
|
|
937
|
+
#ifdef HAVE_RUBY_ENCODING_H
|
938
|
+
static int enc_utf8_compatible_p(rb_encoding *enc)
|
939
|
+
{
|
940
|
+
if (enc == rb_usascii_encoding()) return 1;
|
941
|
+
if (enc == rb_utf8_encoding()) return 1;
|
942
|
+
return 0;
|
943
|
+
}
|
944
|
+
#endif
|
945
|
+
|
807
946
|
static void generate_json_string(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
|
808
947
|
{
|
809
948
|
fbuffer_append_char(buffer, '"');
|
810
949
|
#ifdef HAVE_RUBY_ENCODING_H
|
811
|
-
|
950
|
+
if (!enc_utf8_compatible_p(rb_enc_get(obj))) {
|
951
|
+
obj = rb_str_encode(obj, CEncoding_UTF_8, 0, Qnil);
|
952
|
+
}
|
812
953
|
#endif
|
813
954
|
if (state->ascii_only) {
|
814
|
-
convert_UTF8_to_JSON_ASCII(buffer, obj);
|
955
|
+
convert_UTF8_to_JSON_ASCII(buffer, obj, state->escape_slash);
|
815
956
|
} else {
|
816
|
-
convert_UTF8_to_JSON(buffer, obj);
|
957
|
+
convert_UTF8_to_JSON(buffer, obj, state->escape_slash);
|
817
958
|
}
|
818
959
|
fbuffer_append_char(buffer, '"');
|
819
960
|
}
|
@@ -853,7 +994,6 @@ static void generate_json_integer(FBuffer *buffer, VALUE Vstate, JSON_Generator_
|
|
853
994
|
generate_json_bignum(buffer, Vstate, state, obj);
|
854
995
|
}
|
855
996
|
#endif
|
856
|
-
|
857
997
|
static void generate_json_float(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
|
858
998
|
{
|
859
999
|
double value = RFLOAT_VALUE(obj);
|
@@ -943,21 +1083,6 @@ static VALUE cState_partial_generate(VALUE self, VALUE obj)
|
|
943
1083
|
return fbuffer_to_s(buffer);
|
944
1084
|
}
|
945
1085
|
|
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
1086
|
/*
|
962
1087
|
* call-seq: generate(obj)
|
963
1088
|
*
|
@@ -969,9 +1094,7 @@ static VALUE cState_generate(VALUE self, VALUE obj)
|
|
969
1094
|
{
|
970
1095
|
VALUE result = cState_partial_generate(self, obj);
|
971
1096
|
GET_STATE(self);
|
972
|
-
|
973
|
-
rb_raise(eGeneratorError, "only generation of JSON objects or arrays allowed");
|
974
|
-
}
|
1097
|
+
(void)state;
|
975
1098
|
return result;
|
976
1099
|
}
|
977
1100
|
|
@@ -990,8 +1113,8 @@ static VALUE cState_generate(VALUE self, VALUE obj)
|
|
990
1113
|
* * *allow_nan*: true if NaN, Infinity, and -Infinity should be
|
991
1114
|
* generated, otherwise an exception is thrown, if these values are
|
992
1115
|
* encountered. This options defaults to false.
|
993
|
-
* * *
|
994
|
-
*
|
1116
|
+
* * *ascii_only*: true if only ASCII characters should be generated. This
|
1117
|
+
* option defaults to false.
|
995
1118
|
* * *buffer_initial_length*: sets the initial length of the generator's
|
996
1119
|
* internal buffer.
|
997
1120
|
*/
|
@@ -1047,10 +1170,7 @@ static VALUE cState_from_state_s(VALUE self, VALUE opts)
|
|
1047
1170
|
} else if (rb_obj_is_kind_of(opts, rb_cHash)) {
|
1048
1171
|
return rb_funcall(self, i_new, 1, opts);
|
1049
1172
|
} else {
|
1050
|
-
|
1051
|
-
CJSON_SAFE_STATE_PROTOTYPE = rb_const_get(mJSON, i_SAFE_STATE_PROTOTYPE);
|
1052
|
-
}
|
1053
|
-
return rb_funcall(CJSON_SAFE_STATE_PROTOTYPE, i_dup, 0);
|
1173
|
+
return rb_class_new_instance(0, NULL, cState);
|
1054
1174
|
}
|
1055
1175
|
}
|
1056
1176
|
|
@@ -1084,7 +1204,7 @@ static VALUE cState_indent_set(VALUE self, VALUE indent)
|
|
1084
1204
|
}
|
1085
1205
|
} else {
|
1086
1206
|
if (state->indent) ruby_xfree(state->indent);
|
1087
|
-
state->indent =
|
1207
|
+
state->indent = fstrndup(RSTRING_PTR(indent), len);
|
1088
1208
|
state->indent_len = len;
|
1089
1209
|
}
|
1090
1210
|
return Qnil;
|
@@ -1122,7 +1242,7 @@ static VALUE cState_space_set(VALUE self, VALUE space)
|
|
1122
1242
|
}
|
1123
1243
|
} else {
|
1124
1244
|
if (state->space) ruby_xfree(state->space);
|
1125
|
-
state->space =
|
1245
|
+
state->space = fstrndup(RSTRING_PTR(space), len);
|
1126
1246
|
state->space_len = len;
|
1127
1247
|
}
|
1128
1248
|
return Qnil;
|
@@ -1158,7 +1278,7 @@ static VALUE cState_space_before_set(VALUE self, VALUE space_before)
|
|
1158
1278
|
}
|
1159
1279
|
} else {
|
1160
1280
|
if (state->space_before) ruby_xfree(state->space_before);
|
1161
|
-
state->space_before =
|
1281
|
+
state->space_before = fstrndup(RSTRING_PTR(space_before), len);
|
1162
1282
|
state->space_before_len = len;
|
1163
1283
|
}
|
1164
1284
|
return Qnil;
|
@@ -1195,7 +1315,7 @@ static VALUE cState_object_nl_set(VALUE self, VALUE object_nl)
|
|
1195
1315
|
}
|
1196
1316
|
} else {
|
1197
1317
|
if (state->object_nl) ruby_xfree(state->object_nl);
|
1198
|
-
state->object_nl =
|
1318
|
+
state->object_nl = fstrndup(RSTRING_PTR(object_nl), len);
|
1199
1319
|
state->object_nl_len = len;
|
1200
1320
|
}
|
1201
1321
|
return Qnil;
|
@@ -1230,7 +1350,7 @@ static VALUE cState_array_nl_set(VALUE self, VALUE array_nl)
|
|
1230
1350
|
}
|
1231
1351
|
} else {
|
1232
1352
|
if (state->array_nl) ruby_xfree(state->array_nl);
|
1233
|
-
state->array_nl =
|
1353
|
+
state->array_nl = fstrndup(RSTRING_PTR(array_nl), len);
|
1234
1354
|
state->array_nl_len = len;
|
1235
1355
|
}
|
1236
1356
|
return Qnil;
|
@@ -1275,50 +1395,52 @@ static VALUE cState_max_nesting_set(VALUE self, VALUE depth)
|
|
1275
1395
|
}
|
1276
1396
|
|
1277
1397
|
/*
|
1278
|
-
* call-seq:
|
1398
|
+
* call-seq: escape_slash
|
1279
1399
|
*
|
1280
|
-
*
|
1281
|
-
*
|
1400
|
+
* If this boolean is true, the forward slashes will be escaped in
|
1401
|
+
* the json output.
|
1282
1402
|
*/
|
1283
|
-
static VALUE
|
1403
|
+
static VALUE cState_escape_slash(VALUE self)
|
1284
1404
|
{
|
1285
1405
|
GET_STATE(self);
|
1286
|
-
return state->
|
1406
|
+
return state->escape_slash ? Qtrue : Qfalse;
|
1287
1407
|
}
|
1288
1408
|
|
1289
1409
|
/*
|
1290
|
-
* call-seq:
|
1410
|
+
* call-seq: escape_slash=(depth)
|
1291
1411
|
*
|
1292
|
-
*
|
1293
|
-
*
|
1412
|
+
* This sets whether or not the forward slashes will be escaped in
|
1413
|
+
* the json output.
|
1294
1414
|
*/
|
1295
|
-
static VALUE
|
1415
|
+
static VALUE cState_escape_slash_set(VALUE self, VALUE enable)
|
1296
1416
|
{
|
1297
1417
|
GET_STATE(self);
|
1298
|
-
|
1418
|
+
state->escape_slash = RTEST(enable);
|
1419
|
+
return Qnil;
|
1299
1420
|
}
|
1300
1421
|
|
1301
1422
|
/*
|
1302
|
-
* call-seq:
|
1423
|
+
* call-seq: allow_nan?
|
1303
1424
|
*
|
1304
|
-
* Returns true, if
|
1425
|
+
* Returns true, if NaN, Infinity, and -Infinity should be generated, otherwise
|
1426
|
+
* returns false.
|
1305
1427
|
*/
|
1306
|
-
static VALUE
|
1428
|
+
static VALUE cState_allow_nan_p(VALUE self)
|
1307
1429
|
{
|
1308
1430
|
GET_STATE(self);
|
1309
|
-
return state->
|
1431
|
+
return state->allow_nan ? Qtrue : Qfalse;
|
1310
1432
|
}
|
1311
1433
|
|
1312
1434
|
/*
|
1313
|
-
* call-seq:
|
1435
|
+
* call-seq: ascii_only?
|
1314
1436
|
*
|
1315
|
-
*
|
1437
|
+
* Returns true, if only ASCII characters should be generated. Otherwise
|
1438
|
+
* returns false.
|
1316
1439
|
*/
|
1317
|
-
static VALUE
|
1440
|
+
static VALUE cState_ascii_only_p(VALUE self)
|
1318
1441
|
{
|
1319
1442
|
GET_STATE(self);
|
1320
|
-
state->
|
1321
|
-
return Qnil;
|
1443
|
+
return state->ascii_only ? Qtrue : Qfalse;
|
1322
1444
|
}
|
1323
1445
|
|
1324
1446
|
/*
|
@@ -1380,6 +1502,11 @@ static VALUE cState_buffer_initial_length_set(VALUE self, VALUE buffer_initial_l
|
|
1380
1502
|
*/
|
1381
1503
|
void Init_generator(void)
|
1382
1504
|
{
|
1505
|
+
#ifdef HAVE_RB_EXT_RACTOR_SAFE
|
1506
|
+
rb_ext_ractor_safe(true);
|
1507
|
+
#endif
|
1508
|
+
|
1509
|
+
#undef rb_intern
|
1383
1510
|
rb_require("json/common");
|
1384
1511
|
|
1385
1512
|
mJSON = rb_define_module("JSON");
|
@@ -1388,6 +1515,8 @@ void Init_generator(void)
|
|
1388
1515
|
|
1389
1516
|
eGeneratorError = rb_path2class("JSON::GeneratorError");
|
1390
1517
|
eNestingError = rb_path2class("JSON::NestingError");
|
1518
|
+
rb_gc_register_mark_object(eGeneratorError);
|
1519
|
+
rb_gc_register_mark_object(eNestingError);
|
1391
1520
|
|
1392
1521
|
cState = rb_define_class_under(mGenerator, "State", rb_cObject);
|
1393
1522
|
rb_define_alloc_func(cState, cState_s_allocate);
|
@@ -1406,12 +1535,12 @@ void Init_generator(void)
|
|
1406
1535
|
rb_define_method(cState, "array_nl=", cState_array_nl_set, 1);
|
1407
1536
|
rb_define_method(cState, "max_nesting", cState_max_nesting, 0);
|
1408
1537
|
rb_define_method(cState, "max_nesting=", cState_max_nesting_set, 1);
|
1538
|
+
rb_define_method(cState, "escape_slash", cState_escape_slash, 0);
|
1539
|
+
rb_define_method(cState, "escape_slash?", cState_escape_slash, 0);
|
1540
|
+
rb_define_method(cState, "escape_slash=", cState_escape_slash_set, 1);
|
1409
1541
|
rb_define_method(cState, "check_circular?", cState_check_circular_p, 0);
|
1410
1542
|
rb_define_method(cState, "allow_nan?", cState_allow_nan_p, 0);
|
1411
1543
|
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
1544
|
rb_define_method(cState, "depth", cState_depth, 0);
|
1416
1545
|
rb_define_method(cState, "depth=", cState_depth_set, 1);
|
1417
1546
|
rb_define_method(cState, "buffer_initial_length", cState_buffer_initial_length, 0);
|
@@ -1456,7 +1585,6 @@ void Init_generator(void)
|
|
1456
1585
|
mNilClass = rb_define_module_under(mGeneratorMethods, "NilClass");
|
1457
1586
|
rb_define_method(mNilClass, "to_json", mNilClass_to_json, -1);
|
1458
1587
|
|
1459
|
-
CRegexp_MULTILINE = rb_const_get(rb_cRegexp, rb_intern("MULTILINE"));
|
1460
1588
|
i_to_s = rb_intern("to_s");
|
1461
1589
|
i_to_json = rb_intern("to_json");
|
1462
1590
|
i_new = rb_intern("new");
|
@@ -1466,9 +1594,9 @@ void Init_generator(void)
|
|
1466
1594
|
i_object_nl = rb_intern("object_nl");
|
1467
1595
|
i_array_nl = rb_intern("array_nl");
|
1468
1596
|
i_max_nesting = rb_intern("max_nesting");
|
1597
|
+
i_escape_slash = rb_intern("escape_slash");
|
1469
1598
|
i_allow_nan = rb_intern("allow_nan");
|
1470
1599
|
i_ascii_only = rb_intern("ascii_only");
|
1471
|
-
i_quirks_mode = rb_intern("quirks_mode");
|
1472
1600
|
i_depth = rb_intern("depth");
|
1473
1601
|
i_buffer_initial_length = rb_intern("buffer_initial_length");
|
1474
1602
|
i_pack = rb_intern("pack");
|
@@ -1487,6 +1615,4 @@ void Init_generator(void)
|
|
1487
1615
|
i_encoding = rb_intern("encoding");
|
1488
1616
|
i_encode = rb_intern("encode");
|
1489
1617
|
#endif
|
1490
|
-
i_SAFE_STATE_PROTOTYPE = rb_intern("SAFE_STATE_PROTOTYPE");
|
1491
|
-
CJSON_SAFE_STATE_PROTOTYPE = Qnil;
|
1492
1618
|
}
|