json 2.16.0 → 2.19.3
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/CHANGES.md +43 -1
- data/ext/json/ext/fbuffer/fbuffer.h +29 -25
- data/ext/json/ext/generator/extconf.rb +1 -1
- data/ext/json/ext/generator/generator.c +132 -369
- data/ext/json/ext/json.h +13 -0
- data/ext/json/ext/parser/extconf.rb +1 -2
- data/ext/json/ext/parser/parser.c +235 -179
- data/ext/json/ext/simd/simd.h +33 -16
- data/ext/json/ext/vendor/fpconv.c +3 -3
- data/lib/json/common.rb +62 -14
- data/lib/json/ext/generator/state.rb +1 -1
- data/lib/json/truffle_ruby/generator.rb +34 -18
- data/lib/json/version.rb +1 -1
- data/lib/json.rb +33 -0
- metadata +2 -2
|
@@ -38,7 +38,7 @@ typedef struct JSON_Generator_StateStruct {
|
|
|
38
38
|
|
|
39
39
|
static VALUE mJSON, cState, cFragment, eGeneratorError, eNestingError, Encoding_UTF_8;
|
|
40
40
|
|
|
41
|
-
static ID i_to_s, i_to_json, i_new,
|
|
41
|
+
static ID i_to_s, i_to_json, i_new, i_encode;
|
|
42
42
|
static VALUE sym_indent, sym_space, sym_space_before, sym_object_nl, sym_array_nl, sym_max_nesting, sym_allow_nan, sym_allow_duplicate_key,
|
|
43
43
|
sym_ascii_only, sym_depth, sym_buffer_initial_length, sym_script_safe, sym_escape_slash, sym_strict, sym_as_json;
|
|
44
44
|
|
|
@@ -60,8 +60,11 @@ struct generate_json_data {
|
|
|
60
60
|
JSON_Generator_State *state;
|
|
61
61
|
VALUE obj;
|
|
62
62
|
generator_func func;
|
|
63
|
+
long depth;
|
|
63
64
|
};
|
|
64
65
|
|
|
66
|
+
static SIMD_Implementation simd_impl;
|
|
67
|
+
|
|
65
68
|
static VALUE cState_from_state_s(VALUE self, VALUE opts);
|
|
66
69
|
static VALUE cState_partial_generate(VALUE self, VALUE obj, generator_func, VALUE io);
|
|
67
70
|
static void generate_json(FBuffer *buffer, struct generate_json_data *data, VALUE obj);
|
|
@@ -71,9 +74,6 @@ static void generate_json_string(FBuffer *buffer, struct generate_json_data *dat
|
|
|
71
74
|
static void generate_json_null(FBuffer *buffer, struct generate_json_data *data, VALUE obj);
|
|
72
75
|
static void generate_json_false(FBuffer *buffer, struct generate_json_data *data, VALUE obj);
|
|
73
76
|
static void generate_json_true(FBuffer *buffer, struct generate_json_data *data, VALUE obj);
|
|
74
|
-
#ifdef RUBY_INTEGER_UNIFICATION
|
|
75
|
-
static void generate_json_integer(FBuffer *buffer, struct generate_json_data *data, VALUE obj);
|
|
76
|
-
#endif
|
|
77
77
|
static void generate_json_fixnum(FBuffer *buffer, struct generate_json_data *data, VALUE obj);
|
|
78
78
|
static void generate_json_bignum(FBuffer *buffer, struct generate_json_data *data, VALUE obj);
|
|
79
79
|
static void generate_json_float(FBuffer *buffer, struct generate_json_data *data, VALUE obj);
|
|
@@ -127,7 +127,7 @@ typedef struct _search_state {
|
|
|
127
127
|
#endif /* HAVE_SIMD */
|
|
128
128
|
} search_state;
|
|
129
129
|
|
|
130
|
-
|
|
130
|
+
ALWAYS_INLINE(static) void search_flush(search_state *search)
|
|
131
131
|
{
|
|
132
132
|
// Do not remove this conditional without profiling, specifically escape-heavy text.
|
|
133
133
|
// escape_UTF8_char_basic will advance search->ptr and search->cursor (effectively a search_flush).
|
|
@@ -154,8 +154,6 @@ static const unsigned char escape_table_basic[256] = {
|
|
|
154
154
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
155
155
|
};
|
|
156
156
|
|
|
157
|
-
static unsigned char (*search_escape_basic_impl)(search_state *);
|
|
158
|
-
|
|
159
157
|
static inline unsigned char search_escape_basic(search_state *search)
|
|
160
158
|
{
|
|
161
159
|
while (search->ptr < search->end) {
|
|
@@ -170,7 +168,7 @@ static inline unsigned char search_escape_basic(search_state *search)
|
|
|
170
168
|
return 0;
|
|
171
169
|
}
|
|
172
170
|
|
|
173
|
-
|
|
171
|
+
ALWAYS_INLINE(static) void escape_UTF8_char_basic(search_state *search)
|
|
174
172
|
{
|
|
175
173
|
const unsigned char ch = (unsigned char)*search->ptr;
|
|
176
174
|
switch (ch) {
|
|
@@ -211,11 +209,39 @@ static ALWAYS_INLINE() void escape_UTF8_char_basic(search_state *search)
|
|
|
211
209
|
* Everything else (should be UTF-8) is just passed through and
|
|
212
210
|
* appended to the result.
|
|
213
211
|
*/
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
#if defined(HAVE_SIMD_NEON)
|
|
215
|
+
static inline unsigned char search_escape_basic_neon(search_state *search);
|
|
216
|
+
#elif defined(HAVE_SIMD_SSE2)
|
|
217
|
+
static inline unsigned char search_escape_basic_sse2(search_state *search);
|
|
218
|
+
#endif
|
|
219
|
+
|
|
220
|
+
static inline unsigned char search_escape_basic(search_state *search);
|
|
221
|
+
|
|
214
222
|
static inline void convert_UTF8_to_JSON(search_state *search)
|
|
215
223
|
{
|
|
216
|
-
|
|
224
|
+
#ifdef HAVE_SIMD
|
|
225
|
+
#if defined(HAVE_SIMD_NEON)
|
|
226
|
+
while (search_escape_basic_neon(search)) {
|
|
217
227
|
escape_UTF8_char_basic(search);
|
|
218
228
|
}
|
|
229
|
+
#elif defined(HAVE_SIMD_SSE2)
|
|
230
|
+
if (simd_impl == SIMD_SSE2) {
|
|
231
|
+
while (search_escape_basic_sse2(search)) {
|
|
232
|
+
escape_UTF8_char_basic(search);
|
|
233
|
+
}
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
while (search_escape_basic(search)) {
|
|
237
|
+
escape_UTF8_char_basic(search);
|
|
238
|
+
}
|
|
239
|
+
#endif
|
|
240
|
+
#else
|
|
241
|
+
while (search_escape_basic(search)) {
|
|
242
|
+
escape_UTF8_char_basic(search);
|
|
243
|
+
}
|
|
244
|
+
#endif /* HAVE_SIMD */
|
|
219
245
|
}
|
|
220
246
|
|
|
221
247
|
static inline void escape_UTF8_char(search_state *search, unsigned char ch_len)
|
|
@@ -257,8 +283,10 @@ static inline void escape_UTF8_char(search_state *search, unsigned char ch_len)
|
|
|
257
283
|
|
|
258
284
|
#ifdef HAVE_SIMD
|
|
259
285
|
|
|
260
|
-
|
|
286
|
+
ALWAYS_INLINE(static) char *copy_remaining_bytes(search_state *search, unsigned long vec_len, unsigned long len)
|
|
261
287
|
{
|
|
288
|
+
RBIMPL_ASSERT_OR_ASSUME(len < vec_len);
|
|
289
|
+
|
|
262
290
|
// Flush the buffer so everything up until the last 'len' characters are unflushed.
|
|
263
291
|
search_flush(search);
|
|
264
292
|
|
|
@@ -268,19 +296,25 @@ static ALWAYS_INLINE() char *copy_remaining_bytes(search_state *search, unsigned
|
|
|
268
296
|
char *s = (buf->ptr + buf->len);
|
|
269
297
|
|
|
270
298
|
// Pad the buffer with dummy characters that won't need escaping.
|
|
271
|
-
// This seem
|
|
272
|
-
|
|
299
|
+
// This seem wasteful at first sight, but memset of vector length is very fast.
|
|
300
|
+
// This is a space as it can be directly represented as an immediate on AArch64.
|
|
301
|
+
memset(s, ' ', vec_len);
|
|
273
302
|
|
|
274
303
|
// Optimistically copy the remaining 'len' characters to the output FBuffer. If there are no characters
|
|
275
304
|
// to escape, then everything ends up in the correct spot. Otherwise it was convenient temporary storage.
|
|
276
|
-
|
|
305
|
+
if (vec_len == 16) {
|
|
306
|
+
RBIMPL_ASSERT_OR_ASSUME(len >= SIMD_MINIMUM_THRESHOLD);
|
|
307
|
+
json_fast_memcpy16(s, search->ptr, len);
|
|
308
|
+
} else {
|
|
309
|
+
MEMCPY(s, search->ptr, char, len);
|
|
310
|
+
}
|
|
277
311
|
|
|
278
312
|
return s;
|
|
279
313
|
}
|
|
280
314
|
|
|
281
315
|
#ifdef HAVE_SIMD_NEON
|
|
282
316
|
|
|
283
|
-
|
|
317
|
+
ALWAYS_INLINE(static) unsigned char neon_next_match(search_state *search)
|
|
284
318
|
{
|
|
285
319
|
uint64_t mask = search->matches_mask;
|
|
286
320
|
uint32_t index = trailing_zeros64(mask) >> 2;
|
|
@@ -394,7 +428,7 @@ static inline unsigned char search_escape_basic_neon(search_state *search)
|
|
|
394
428
|
|
|
395
429
|
#ifdef HAVE_SIMD_SSE2
|
|
396
430
|
|
|
397
|
-
|
|
431
|
+
ALWAYS_INLINE(static) unsigned char sse2_next_match(search_state *search)
|
|
398
432
|
{
|
|
399
433
|
int mask = search->matches_mask;
|
|
400
434
|
int index = trailing_zeros(mask);
|
|
@@ -418,7 +452,7 @@ static ALWAYS_INLINE() unsigned char sse2_next_match(search_state *search)
|
|
|
418
452
|
#define TARGET_SSE2
|
|
419
453
|
#endif
|
|
420
454
|
|
|
421
|
-
static TARGET_SSE2
|
|
455
|
+
ALWAYS_INLINE(static) TARGET_SSE2 unsigned char search_escape_basic_sse2(search_state *search)
|
|
422
456
|
{
|
|
423
457
|
if (RB_UNLIKELY(search->has_matches)) {
|
|
424
458
|
// There are more matches if search->matches_mask > 0.
|
|
@@ -666,233 +700,6 @@ static void convert_UTF8_to_ASCII_only_JSON(search_state *search, const unsigned
|
|
|
666
700
|
}
|
|
667
701
|
}
|
|
668
702
|
|
|
669
|
-
/*
|
|
670
|
-
* Document-module: JSON::Ext::Generator
|
|
671
|
-
*
|
|
672
|
-
* This is the JSON generator implemented as a C extension. It can be
|
|
673
|
-
* configured to be used by setting
|
|
674
|
-
*
|
|
675
|
-
* JSON.generator = JSON::Ext::Generator
|
|
676
|
-
*
|
|
677
|
-
* with the method generator= in JSON.
|
|
678
|
-
*
|
|
679
|
-
*/
|
|
680
|
-
|
|
681
|
-
/* Explanation of the following: that's the only way to not pollute
|
|
682
|
-
* standard library's docs with GeneratorMethods::<ClassName> which
|
|
683
|
-
* are uninformative and take a large place in a list of classes
|
|
684
|
-
*/
|
|
685
|
-
|
|
686
|
-
/*
|
|
687
|
-
* Document-module: JSON::Ext::Generator::GeneratorMethods
|
|
688
|
-
* :nodoc:
|
|
689
|
-
*/
|
|
690
|
-
|
|
691
|
-
/*
|
|
692
|
-
* Document-module: JSON::Ext::Generator::GeneratorMethods::Array
|
|
693
|
-
* :nodoc:
|
|
694
|
-
*/
|
|
695
|
-
|
|
696
|
-
/*
|
|
697
|
-
* Document-module: JSON::Ext::Generator::GeneratorMethods::Bignum
|
|
698
|
-
* :nodoc:
|
|
699
|
-
*/
|
|
700
|
-
|
|
701
|
-
/*
|
|
702
|
-
* Document-module: JSON::Ext::Generator::GeneratorMethods::FalseClass
|
|
703
|
-
* :nodoc:
|
|
704
|
-
*/
|
|
705
|
-
|
|
706
|
-
/*
|
|
707
|
-
* Document-module: JSON::Ext::Generator::GeneratorMethods::Fixnum
|
|
708
|
-
* :nodoc:
|
|
709
|
-
*/
|
|
710
|
-
|
|
711
|
-
/*
|
|
712
|
-
* Document-module: JSON::Ext::Generator::GeneratorMethods::Float
|
|
713
|
-
* :nodoc:
|
|
714
|
-
*/
|
|
715
|
-
|
|
716
|
-
/*
|
|
717
|
-
* Document-module: JSON::Ext::Generator::GeneratorMethods::Hash
|
|
718
|
-
* :nodoc:
|
|
719
|
-
*/
|
|
720
|
-
|
|
721
|
-
/*
|
|
722
|
-
* Document-module: JSON::Ext::Generator::GeneratorMethods::Integer
|
|
723
|
-
* :nodoc:
|
|
724
|
-
*/
|
|
725
|
-
|
|
726
|
-
/*
|
|
727
|
-
* Document-module: JSON::Ext::Generator::GeneratorMethods::NilClass
|
|
728
|
-
* :nodoc:
|
|
729
|
-
*/
|
|
730
|
-
|
|
731
|
-
/*
|
|
732
|
-
* Document-module: JSON::Ext::Generator::GeneratorMethods::Object
|
|
733
|
-
* :nodoc:
|
|
734
|
-
*/
|
|
735
|
-
|
|
736
|
-
/*
|
|
737
|
-
* Document-module: JSON::Ext::Generator::GeneratorMethods::String
|
|
738
|
-
* :nodoc:
|
|
739
|
-
*/
|
|
740
|
-
|
|
741
|
-
/*
|
|
742
|
-
* Document-module: JSON::Ext::Generator::GeneratorMethods::String::Extend
|
|
743
|
-
* :nodoc:
|
|
744
|
-
*/
|
|
745
|
-
|
|
746
|
-
/*
|
|
747
|
-
* Document-module: JSON::Ext::Generator::GeneratorMethods::TrueClass
|
|
748
|
-
* :nodoc:
|
|
749
|
-
*/
|
|
750
|
-
|
|
751
|
-
/*
|
|
752
|
-
* call-seq: to_json(state = nil)
|
|
753
|
-
*
|
|
754
|
-
* Returns a JSON string containing a JSON object, that is generated from
|
|
755
|
-
* this Hash instance.
|
|
756
|
-
* _state_ is a JSON::State object, that can also be used to configure the
|
|
757
|
-
* produced JSON string output further.
|
|
758
|
-
*/
|
|
759
|
-
static VALUE mHash_to_json(int argc, VALUE *argv, VALUE self)
|
|
760
|
-
{
|
|
761
|
-
rb_check_arity(argc, 0, 1);
|
|
762
|
-
VALUE Vstate = cState_from_state_s(cState, argc == 1 ? argv[0] : Qnil);
|
|
763
|
-
return cState_partial_generate(Vstate, self, generate_json_object, Qfalse);
|
|
764
|
-
}
|
|
765
|
-
|
|
766
|
-
/*
|
|
767
|
-
* call-seq: to_json(state = nil)
|
|
768
|
-
*
|
|
769
|
-
* Returns a JSON string containing a JSON array, that is generated from
|
|
770
|
-
* this Array instance.
|
|
771
|
-
* _state_ is a JSON::State object, that can also be used to configure the
|
|
772
|
-
* produced JSON string output further.
|
|
773
|
-
*/
|
|
774
|
-
static VALUE mArray_to_json(int argc, VALUE *argv, VALUE self)
|
|
775
|
-
{
|
|
776
|
-
rb_check_arity(argc, 0, 1);
|
|
777
|
-
VALUE Vstate = cState_from_state_s(cState, argc == 1 ? argv[0] : Qnil);
|
|
778
|
-
return cState_partial_generate(Vstate, self, generate_json_array, Qfalse);
|
|
779
|
-
}
|
|
780
|
-
|
|
781
|
-
#ifdef RUBY_INTEGER_UNIFICATION
|
|
782
|
-
/*
|
|
783
|
-
* call-seq: to_json(*)
|
|
784
|
-
*
|
|
785
|
-
* Returns a JSON string representation for this Integer number.
|
|
786
|
-
*/
|
|
787
|
-
static VALUE mInteger_to_json(int argc, VALUE *argv, VALUE self)
|
|
788
|
-
{
|
|
789
|
-
rb_check_arity(argc, 0, 1);
|
|
790
|
-
VALUE Vstate = cState_from_state_s(cState, argc == 1 ? argv[0] : Qnil);
|
|
791
|
-
return cState_partial_generate(Vstate, self, generate_json_integer, Qfalse);
|
|
792
|
-
}
|
|
793
|
-
|
|
794
|
-
#else
|
|
795
|
-
/*
|
|
796
|
-
* call-seq: to_json(*)
|
|
797
|
-
*
|
|
798
|
-
* Returns a JSON string representation for this Integer number.
|
|
799
|
-
*/
|
|
800
|
-
static VALUE mFixnum_to_json(int argc, VALUE *argv, VALUE self)
|
|
801
|
-
{
|
|
802
|
-
rb_check_arity(argc, 0, 1);
|
|
803
|
-
VALUE Vstate = cState_from_state_s(cState, argc == 1 ? argv[0] : Qnil);
|
|
804
|
-
return cState_partial_generate(Vstate, self, generate_json_fixnum, Qfalse);
|
|
805
|
-
}
|
|
806
|
-
|
|
807
|
-
/*
|
|
808
|
-
* call-seq: to_json(*)
|
|
809
|
-
*
|
|
810
|
-
* Returns a JSON string representation for this Integer number.
|
|
811
|
-
*/
|
|
812
|
-
static VALUE mBignum_to_json(int argc, VALUE *argv, VALUE self)
|
|
813
|
-
{
|
|
814
|
-
rb_check_arity(argc, 0, 1);
|
|
815
|
-
VALUE Vstate = cState_from_state_s(cState, argc == 1 ? argv[0] : Qnil);
|
|
816
|
-
return cState_partial_generate(Vstate, self, generate_json_bignum, Qfalse);
|
|
817
|
-
}
|
|
818
|
-
#endif
|
|
819
|
-
|
|
820
|
-
/*
|
|
821
|
-
* call-seq: to_json(*)
|
|
822
|
-
*
|
|
823
|
-
* Returns a JSON string representation for this Float number.
|
|
824
|
-
*/
|
|
825
|
-
static VALUE mFloat_to_json(int argc, VALUE *argv, VALUE self)
|
|
826
|
-
{
|
|
827
|
-
rb_check_arity(argc, 0, 1);
|
|
828
|
-
VALUE Vstate = cState_from_state_s(cState, argc == 1 ? argv[0] : Qnil);
|
|
829
|
-
return cState_partial_generate(Vstate, self, generate_json_float, Qfalse);
|
|
830
|
-
}
|
|
831
|
-
|
|
832
|
-
/*
|
|
833
|
-
* call-seq: to_json(*)
|
|
834
|
-
*
|
|
835
|
-
* This string should be encoded with UTF-8 A call to this method
|
|
836
|
-
* returns a JSON string encoded with UTF16 big endian characters as
|
|
837
|
-
* \u????.
|
|
838
|
-
*/
|
|
839
|
-
static VALUE mString_to_json(int argc, VALUE *argv, VALUE self)
|
|
840
|
-
{
|
|
841
|
-
rb_check_arity(argc, 0, 1);
|
|
842
|
-
VALUE Vstate = cState_from_state_s(cState, argc == 1 ? argv[0] : Qnil);
|
|
843
|
-
return cState_partial_generate(Vstate, self, generate_json_string, Qfalse);
|
|
844
|
-
}
|
|
845
|
-
|
|
846
|
-
/*
|
|
847
|
-
* call-seq: to_json(*)
|
|
848
|
-
*
|
|
849
|
-
* Returns a JSON string for true: 'true'.
|
|
850
|
-
*/
|
|
851
|
-
static VALUE mTrueClass_to_json(int argc, VALUE *argv, VALUE self)
|
|
852
|
-
{
|
|
853
|
-
rb_check_arity(argc, 0, 1);
|
|
854
|
-
return rb_utf8_str_new("true", 4);
|
|
855
|
-
}
|
|
856
|
-
|
|
857
|
-
/*
|
|
858
|
-
* call-seq: to_json(*)
|
|
859
|
-
*
|
|
860
|
-
* Returns a JSON string for false: 'false'.
|
|
861
|
-
*/
|
|
862
|
-
static VALUE mFalseClass_to_json(int argc, VALUE *argv, VALUE self)
|
|
863
|
-
{
|
|
864
|
-
rb_check_arity(argc, 0, 1);
|
|
865
|
-
return rb_utf8_str_new("false", 5);
|
|
866
|
-
}
|
|
867
|
-
|
|
868
|
-
/*
|
|
869
|
-
* call-seq: to_json(*)
|
|
870
|
-
*
|
|
871
|
-
* Returns a JSON string for nil: 'null'.
|
|
872
|
-
*/
|
|
873
|
-
static VALUE mNilClass_to_json(int argc, VALUE *argv, VALUE self)
|
|
874
|
-
{
|
|
875
|
-
rb_check_arity(argc, 0, 1);
|
|
876
|
-
return rb_utf8_str_new("null", 4);
|
|
877
|
-
}
|
|
878
|
-
|
|
879
|
-
/*
|
|
880
|
-
* call-seq: to_json(*)
|
|
881
|
-
*
|
|
882
|
-
* Converts this object to a string (calling #to_s), converts
|
|
883
|
-
* it to a JSON string, and returns the result. This is a fallback, if no
|
|
884
|
-
* special method #to_json was defined for some object.
|
|
885
|
-
*/
|
|
886
|
-
static VALUE mObject_to_json(int argc, VALUE *argv, VALUE self)
|
|
887
|
-
{
|
|
888
|
-
VALUE state;
|
|
889
|
-
VALUE string = rb_funcall(self, i_to_s, 0);
|
|
890
|
-
rb_scan_args(argc, argv, "01", &state);
|
|
891
|
-
Check_Type(string, T_STRING);
|
|
892
|
-
state = cState_from_state_s(cState, state);
|
|
893
|
-
return cState_partial_generate(state, string, generate_json_string, Qfalse);
|
|
894
|
-
}
|
|
895
|
-
|
|
896
703
|
static void State_mark(void *ptr)
|
|
897
704
|
{
|
|
898
705
|
JSON_Generator_State *state = ptr;
|
|
@@ -926,11 +733,6 @@ static size_t State_memsize(const void *ptr)
|
|
|
926
733
|
return sizeof(JSON_Generator_State);
|
|
927
734
|
}
|
|
928
735
|
|
|
929
|
-
#ifndef HAVE_RB_EXT_RACTOR_SAFE
|
|
930
|
-
# undef RUBY_TYPED_FROZEN_SHAREABLE
|
|
931
|
-
# define RUBY_TYPED_FROZEN_SHAREABLE 0
|
|
932
|
-
#endif
|
|
933
|
-
|
|
934
736
|
static const rb_data_type_t JSON_Generator_State_type = {
|
|
935
737
|
"JSON/Generator/State",
|
|
936
738
|
{
|
|
@@ -972,12 +774,16 @@ static void vstate_spill(struct generate_json_data *data)
|
|
|
972
774
|
RB_OBJ_WRITTEN(vstate, Qundef, state->as_json);
|
|
973
775
|
}
|
|
974
776
|
|
|
975
|
-
static inline VALUE
|
|
777
|
+
static inline VALUE json_call_to_json(struct generate_json_data *data, VALUE obj)
|
|
976
778
|
{
|
|
977
779
|
if (RB_UNLIKELY(!data->vstate)) {
|
|
978
780
|
vstate_spill(data);
|
|
979
781
|
}
|
|
980
|
-
|
|
782
|
+
GET_STATE(data->vstate);
|
|
783
|
+
state->depth = data->depth;
|
|
784
|
+
VALUE tmp = rb_funcall(obj, i_to_json, 1, data->vstate);
|
|
785
|
+
// no need to restore state->depth, vstate is just a temporary State
|
|
786
|
+
return tmp;
|
|
981
787
|
}
|
|
982
788
|
|
|
983
789
|
static VALUE
|
|
@@ -1091,6 +897,7 @@ static void raw_generate_json_string(FBuffer *buffer, struct generate_json_data
|
|
|
1091
897
|
search.matches_mask = 0;
|
|
1092
898
|
search.has_matches = false;
|
|
1093
899
|
search.chunk_base = NULL;
|
|
900
|
+
search.chunk_end = NULL;
|
|
1094
901
|
#endif /* HAVE_SIMD */
|
|
1095
902
|
|
|
1096
903
|
switch (rb_enc_str_coderange(obj)) {
|
|
@@ -1125,8 +932,7 @@ struct hash_foreach_arg {
|
|
|
1125
932
|
bool mixed_keys_encountered;
|
|
1126
933
|
};
|
|
1127
934
|
|
|
1128
|
-
NOINLINE()
|
|
1129
|
-
static void
|
|
935
|
+
NOINLINE(static) void
|
|
1130
936
|
json_inspect_hash_with_mixed_keys(struct hash_foreach_arg *arg)
|
|
1131
937
|
{
|
|
1132
938
|
if (arg->mixed_keys_encountered) {
|
|
@@ -1150,7 +956,7 @@ json_object_i(VALUE key, VALUE val, VALUE _arg)
|
|
|
1150
956
|
FBuffer *buffer = data->buffer;
|
|
1151
957
|
JSON_Generator_State *state = data->state;
|
|
1152
958
|
|
|
1153
|
-
long depth =
|
|
959
|
+
long depth = data->depth;
|
|
1154
960
|
int key_type = rb_type(key);
|
|
1155
961
|
|
|
1156
962
|
if (arg->first) {
|
|
@@ -1224,9 +1030,9 @@ json_object_i(VALUE key, VALUE val, VALUE _arg)
|
|
|
1224
1030
|
static inline long increase_depth(struct generate_json_data *data)
|
|
1225
1031
|
{
|
|
1226
1032
|
JSON_Generator_State *state = data->state;
|
|
1227
|
-
long depth = ++
|
|
1033
|
+
long depth = ++data->depth;
|
|
1228
1034
|
if (RB_UNLIKELY(depth > state->max_nesting && state->max_nesting)) {
|
|
1229
|
-
rb_raise(eNestingError, "nesting of %ld is too deep. Did you try to serialize objects with circular references?", --
|
|
1035
|
+
rb_raise(eNestingError, "nesting of %ld is too deep. Did you try to serialize objects with circular references?", --data->depth);
|
|
1230
1036
|
}
|
|
1231
1037
|
return depth;
|
|
1232
1038
|
}
|
|
@@ -1237,7 +1043,7 @@ static void generate_json_object(FBuffer *buffer, struct generate_json_data *dat
|
|
|
1237
1043
|
|
|
1238
1044
|
if (RHASH_SIZE(obj) == 0) {
|
|
1239
1045
|
fbuffer_append(buffer, "{}", 2);
|
|
1240
|
-
--data->
|
|
1046
|
+
--data->depth;
|
|
1241
1047
|
return;
|
|
1242
1048
|
}
|
|
1243
1049
|
|
|
@@ -1250,7 +1056,7 @@ static void generate_json_object(FBuffer *buffer, struct generate_json_data *dat
|
|
|
1250
1056
|
};
|
|
1251
1057
|
rb_hash_foreach(obj, json_object_i, (VALUE)&arg);
|
|
1252
1058
|
|
|
1253
|
-
depth = --data->
|
|
1059
|
+
depth = --data->depth;
|
|
1254
1060
|
if (RB_UNLIKELY(data->state->object_nl)) {
|
|
1255
1061
|
fbuffer_append_str(buffer, data->state->object_nl);
|
|
1256
1062
|
if (RB_UNLIKELY(data->state->indent)) {
|
|
@@ -1266,7 +1072,7 @@ static void generate_json_array(FBuffer *buffer, struct generate_json_data *data
|
|
|
1266
1072
|
|
|
1267
1073
|
if (RARRAY_LEN(obj) == 0) {
|
|
1268
1074
|
fbuffer_append(buffer, "[]", 2);
|
|
1269
|
-
--data->
|
|
1075
|
+
--data->depth;
|
|
1270
1076
|
return;
|
|
1271
1077
|
}
|
|
1272
1078
|
|
|
@@ -1282,7 +1088,7 @@ static void generate_json_array(FBuffer *buffer, struct generate_json_data *data
|
|
|
1282
1088
|
}
|
|
1283
1089
|
generate_json(buffer, data, RARRAY_AREF(obj, i));
|
|
1284
1090
|
}
|
|
1285
|
-
data->
|
|
1091
|
+
data->depth = --depth;
|
|
1286
1092
|
if (RB_UNLIKELY(data->state->array_nl)) {
|
|
1287
1093
|
fbuffer_append_str(buffer, data->state->array_nl);
|
|
1288
1094
|
if (RB_UNLIKELY(data->state->indent)) {
|
|
@@ -1296,7 +1102,7 @@ static void generate_json_fallback(FBuffer *buffer, struct generate_json_data *d
|
|
|
1296
1102
|
{
|
|
1297
1103
|
VALUE tmp;
|
|
1298
1104
|
if (rb_respond_to(obj, i_to_json)) {
|
|
1299
|
-
tmp =
|
|
1105
|
+
tmp = json_call_to_json(data, obj);
|
|
1300
1106
|
Check_Type(tmp, T_STRING);
|
|
1301
1107
|
fbuffer_append_str(buffer, tmp);
|
|
1302
1108
|
} else {
|
|
@@ -1338,18 +1144,8 @@ static void generate_json_fixnum(FBuffer *buffer, struct generate_json_data *dat
|
|
|
1338
1144
|
static void generate_json_bignum(FBuffer *buffer, struct generate_json_data *data, VALUE obj)
|
|
1339
1145
|
{
|
|
1340
1146
|
VALUE tmp = rb_funcall(obj, i_to_s, 0);
|
|
1341
|
-
fbuffer_append_str(buffer, tmp);
|
|
1342
|
-
}
|
|
1343
|
-
|
|
1344
|
-
#ifdef RUBY_INTEGER_UNIFICATION
|
|
1345
|
-
static void generate_json_integer(FBuffer *buffer, struct generate_json_data *data, VALUE obj)
|
|
1346
|
-
{
|
|
1347
|
-
if (FIXNUM_P(obj))
|
|
1348
|
-
generate_json_fixnum(buffer, data, obj);
|
|
1349
|
-
else
|
|
1350
|
-
generate_json_bignum(buffer, data, obj);
|
|
1147
|
+
fbuffer_append_str(buffer, StringValue(tmp));
|
|
1351
1148
|
}
|
|
1352
|
-
#endif
|
|
1353
1149
|
|
|
1354
1150
|
static void generate_json_float(FBuffer *buffer, struct generate_json_data *data, VALUE obj)
|
|
1355
1151
|
{
|
|
@@ -1363,7 +1159,7 @@ static void generate_json_float(FBuffer *buffer, struct generate_json_data *data
|
|
|
1363
1159
|
if (casted_obj != obj) {
|
|
1364
1160
|
increase_depth(data);
|
|
1365
1161
|
generate_json(buffer, data, casted_obj);
|
|
1366
|
-
data->
|
|
1162
|
+
data->depth--;
|
|
1367
1163
|
return;
|
|
1368
1164
|
}
|
|
1369
1165
|
}
|
|
@@ -1394,7 +1190,7 @@ static void generate_json_fragment(FBuffer *buffer, struct generate_json_data *d
|
|
|
1394
1190
|
fbuffer_append_str(buffer, fragment);
|
|
1395
1191
|
}
|
|
1396
1192
|
|
|
1397
|
-
static void
|
|
1193
|
+
static inline void generate_json_general(FBuffer *buffer, struct generate_json_data *data, VALUE obj, bool fallback)
|
|
1398
1194
|
{
|
|
1399
1195
|
bool as_json_called = false;
|
|
1400
1196
|
start:
|
|
@@ -1421,15 +1217,15 @@ start:
|
|
|
1421
1217
|
generate_json_bignum(buffer, data, obj);
|
|
1422
1218
|
break;
|
|
1423
1219
|
case T_HASH:
|
|
1424
|
-
if (klass != rb_cHash) goto general;
|
|
1220
|
+
if (fallback && klass != rb_cHash) goto general;
|
|
1425
1221
|
generate_json_object(buffer, data, obj);
|
|
1426
1222
|
break;
|
|
1427
1223
|
case T_ARRAY:
|
|
1428
|
-
if (klass != rb_cArray) goto general;
|
|
1224
|
+
if (fallback && klass != rb_cArray) goto general;
|
|
1429
1225
|
generate_json_array(buffer, data, obj);
|
|
1430
1226
|
break;
|
|
1431
1227
|
case T_STRING:
|
|
1432
|
-
if (klass != rb_cString) goto general;
|
|
1228
|
+
if (fallback && klass != rb_cString) goto general;
|
|
1433
1229
|
|
|
1434
1230
|
if (RB_LIKELY(valid_json_string_p(obj))) {
|
|
1435
1231
|
raw_generate_json_string(buffer, data, obj);
|
|
@@ -1445,7 +1241,7 @@ start:
|
|
|
1445
1241
|
generate_json_symbol(buffer, data, obj);
|
|
1446
1242
|
break;
|
|
1447
1243
|
case T_FLOAT:
|
|
1448
|
-
if (klass != rb_cFloat) goto general;
|
|
1244
|
+
if (fallback && klass != rb_cFloat) goto general;
|
|
1449
1245
|
generate_json_float(buffer, data, obj);
|
|
1450
1246
|
break;
|
|
1451
1247
|
case T_STRUCT:
|
|
@@ -1469,6 +1265,16 @@ start:
|
|
|
1469
1265
|
}
|
|
1470
1266
|
}
|
|
1471
1267
|
|
|
1268
|
+
static void generate_json(FBuffer *buffer, struct generate_json_data *data, VALUE obj)
|
|
1269
|
+
{
|
|
1270
|
+
generate_json_general(buffer, data, obj, true);
|
|
1271
|
+
}
|
|
1272
|
+
|
|
1273
|
+
static void generate_json_no_fallback(FBuffer *buffer, struct generate_json_data *data, VALUE obj)
|
|
1274
|
+
{
|
|
1275
|
+
generate_json_general(buffer, data, obj, false);
|
|
1276
|
+
}
|
|
1277
|
+
|
|
1472
1278
|
static VALUE generate_json_try(VALUE d)
|
|
1473
1279
|
{
|
|
1474
1280
|
struct generate_json_data *data = (struct generate_json_data *)d;
|
|
@@ -1486,7 +1292,7 @@ static VALUE generate_json_ensure(VALUE d)
|
|
|
1486
1292
|
return Qundef;
|
|
1487
1293
|
}
|
|
1488
1294
|
|
|
1489
|
-
static VALUE cState_partial_generate(VALUE self, VALUE obj, generator_func func, VALUE io)
|
|
1295
|
+
static inline VALUE cState_partial_generate(VALUE self, VALUE obj, generator_func func, VALUE io)
|
|
1490
1296
|
{
|
|
1491
1297
|
GET_STATE(self);
|
|
1492
1298
|
|
|
@@ -1498,8 +1304,9 @@ static VALUE cState_partial_generate(VALUE self, VALUE obj, generator_func func,
|
|
|
1498
1304
|
|
|
1499
1305
|
struct generate_json_data data = {
|
|
1500
1306
|
.buffer = &buffer,
|
|
1501
|
-
.vstate = self
|
|
1307
|
+
.vstate = Qfalse, // don't use self as it may be frozen and its depth is mutated when calling to_json
|
|
1502
1308
|
.state = state,
|
|
1309
|
+
.depth = state->depth,
|
|
1503
1310
|
.obj = obj,
|
|
1504
1311
|
.func = func
|
|
1505
1312
|
};
|
|
@@ -1522,34 +1329,13 @@ static VALUE cState_generate(int argc, VALUE *argv, VALUE self)
|
|
|
1522
1329
|
return cState_partial_generate(self, obj, generate_json, io);
|
|
1523
1330
|
}
|
|
1524
1331
|
|
|
1525
|
-
|
|
1332
|
+
/* :nodoc: */
|
|
1333
|
+
static VALUE cState_generate_no_fallback(int argc, VALUE *argv, VALUE self)
|
|
1526
1334
|
{
|
|
1527
1335
|
rb_check_arity(argc, 1, 2);
|
|
1528
1336
|
VALUE obj = argv[0];
|
|
1529
1337
|
VALUE io = argc > 1 ? argv[1] : Qnil;
|
|
1530
|
-
|
|
1531
|
-
GET_STATE(self);
|
|
1532
|
-
|
|
1533
|
-
JSON_Generator_State new_state;
|
|
1534
|
-
MEMCPY(&new_state, state, JSON_Generator_State, 1);
|
|
1535
|
-
|
|
1536
|
-
// FIXME: depth shouldn't be part of JSON_Generator_State, as that prevents it from being used concurrently.
|
|
1537
|
-
new_state.depth = 0;
|
|
1538
|
-
|
|
1539
|
-
char stack_buffer[FBUFFER_STACK_SIZE];
|
|
1540
|
-
FBuffer buffer = {
|
|
1541
|
-
.io = RTEST(io) ? io : Qfalse,
|
|
1542
|
-
};
|
|
1543
|
-
fbuffer_stack_init(&buffer, state->buffer_initial_length, stack_buffer, FBUFFER_STACK_SIZE);
|
|
1544
|
-
|
|
1545
|
-
struct generate_json_data data = {
|
|
1546
|
-
.buffer = &buffer,
|
|
1547
|
-
.vstate = Qfalse,
|
|
1548
|
-
.state = &new_state,
|
|
1549
|
-
.obj = obj,
|
|
1550
|
-
.func = generate_json
|
|
1551
|
-
};
|
|
1552
|
-
return rb_ensure(generate_json_try, (VALUE)&data, generate_json_ensure, (VALUE)&data);
|
|
1338
|
+
return cState_partial_generate(self, obj, generate_json_no_fallback, io);
|
|
1553
1339
|
}
|
|
1554
1340
|
|
|
1555
1341
|
static VALUE cState_initialize(int argc, VALUE *argv, VALUE self)
|
|
@@ -1630,6 +1416,7 @@ static VALUE string_config(VALUE config)
|
|
|
1630
1416
|
*/
|
|
1631
1417
|
static VALUE cState_indent_set(VALUE self, VALUE indent)
|
|
1632
1418
|
{
|
|
1419
|
+
rb_check_frozen(self);
|
|
1633
1420
|
GET_STATE(self);
|
|
1634
1421
|
RB_OBJ_WRITE(self, &state->indent, string_config(indent));
|
|
1635
1422
|
return Qnil;
|
|
@@ -1655,6 +1442,7 @@ static VALUE cState_space(VALUE self)
|
|
|
1655
1442
|
*/
|
|
1656
1443
|
static VALUE cState_space_set(VALUE self, VALUE space)
|
|
1657
1444
|
{
|
|
1445
|
+
rb_check_frozen(self);
|
|
1658
1446
|
GET_STATE(self);
|
|
1659
1447
|
RB_OBJ_WRITE(self, &state->space, string_config(space));
|
|
1660
1448
|
return Qnil;
|
|
@@ -1678,6 +1466,7 @@ static VALUE cState_space_before(VALUE self)
|
|
|
1678
1466
|
*/
|
|
1679
1467
|
static VALUE cState_space_before_set(VALUE self, VALUE space_before)
|
|
1680
1468
|
{
|
|
1469
|
+
rb_check_frozen(self);
|
|
1681
1470
|
GET_STATE(self);
|
|
1682
1471
|
RB_OBJ_WRITE(self, &state->space_before, string_config(space_before));
|
|
1683
1472
|
return Qnil;
|
|
@@ -1703,6 +1492,7 @@ static VALUE cState_object_nl(VALUE self)
|
|
|
1703
1492
|
*/
|
|
1704
1493
|
static VALUE cState_object_nl_set(VALUE self, VALUE object_nl)
|
|
1705
1494
|
{
|
|
1495
|
+
rb_check_frozen(self);
|
|
1706
1496
|
GET_STATE(self);
|
|
1707
1497
|
RB_OBJ_WRITE(self, &state->object_nl, string_config(object_nl));
|
|
1708
1498
|
return Qnil;
|
|
@@ -1726,6 +1516,7 @@ static VALUE cState_array_nl(VALUE self)
|
|
|
1726
1516
|
*/
|
|
1727
1517
|
static VALUE cState_array_nl_set(VALUE self, VALUE array_nl)
|
|
1728
1518
|
{
|
|
1519
|
+
rb_check_frozen(self);
|
|
1729
1520
|
GET_STATE(self);
|
|
1730
1521
|
RB_OBJ_WRITE(self, &state->array_nl, string_config(array_nl));
|
|
1731
1522
|
return Qnil;
|
|
@@ -1749,6 +1540,7 @@ static VALUE cState_as_json(VALUE self)
|
|
|
1749
1540
|
*/
|
|
1750
1541
|
static VALUE cState_as_json_set(VALUE self, VALUE as_json)
|
|
1751
1542
|
{
|
|
1543
|
+
rb_check_frozen(self);
|
|
1752
1544
|
GET_STATE(self);
|
|
1753
1545
|
RB_OBJ_WRITE(self, &state->as_json, rb_convert_type(as_json, T_DATA, "Proc", "to_proc"));
|
|
1754
1546
|
return Qnil;
|
|
@@ -1783,6 +1575,17 @@ static long long_config(VALUE num)
|
|
|
1783
1575
|
return RTEST(num) ? FIX2LONG(num) : 0;
|
|
1784
1576
|
}
|
|
1785
1577
|
|
|
1578
|
+
// depth must never be negative; reject early with a clear error.
|
|
1579
|
+
static long depth_config(VALUE num)
|
|
1580
|
+
{
|
|
1581
|
+
if (!RTEST(num)) return 0;
|
|
1582
|
+
long d = NUM2LONG(num);
|
|
1583
|
+
if (RB_UNLIKELY(d < 0)) {
|
|
1584
|
+
rb_raise(rb_eArgError, "depth must be >= 0 (got %ld)", d);
|
|
1585
|
+
}
|
|
1586
|
+
return d;
|
|
1587
|
+
}
|
|
1588
|
+
|
|
1786
1589
|
/*
|
|
1787
1590
|
* call-seq: max_nesting=(depth)
|
|
1788
1591
|
*
|
|
@@ -1791,6 +1594,7 @@ static long long_config(VALUE num)
|
|
|
1791
1594
|
*/
|
|
1792
1595
|
static VALUE cState_max_nesting_set(VALUE self, VALUE depth)
|
|
1793
1596
|
{
|
|
1597
|
+
rb_check_frozen(self);
|
|
1794
1598
|
GET_STATE(self);
|
|
1795
1599
|
state->max_nesting = long_config(depth);
|
|
1796
1600
|
return Qnil;
|
|
@@ -1816,6 +1620,7 @@ static VALUE cState_script_safe(VALUE self)
|
|
|
1816
1620
|
*/
|
|
1817
1621
|
static VALUE cState_script_safe_set(VALUE self, VALUE enable)
|
|
1818
1622
|
{
|
|
1623
|
+
rb_check_frozen(self);
|
|
1819
1624
|
GET_STATE(self);
|
|
1820
1625
|
state->script_safe = RTEST(enable);
|
|
1821
1626
|
return Qnil;
|
|
@@ -1847,6 +1652,7 @@ static VALUE cState_strict(VALUE self)
|
|
|
1847
1652
|
*/
|
|
1848
1653
|
static VALUE cState_strict_set(VALUE self, VALUE enable)
|
|
1849
1654
|
{
|
|
1655
|
+
rb_check_frozen(self);
|
|
1850
1656
|
GET_STATE(self);
|
|
1851
1657
|
state->strict = RTEST(enable);
|
|
1852
1658
|
return Qnil;
|
|
@@ -1871,6 +1677,7 @@ static VALUE cState_allow_nan_p(VALUE self)
|
|
|
1871
1677
|
*/
|
|
1872
1678
|
static VALUE cState_allow_nan_set(VALUE self, VALUE enable)
|
|
1873
1679
|
{
|
|
1680
|
+
rb_check_frozen(self);
|
|
1874
1681
|
GET_STATE(self);
|
|
1875
1682
|
state->allow_nan = RTEST(enable);
|
|
1876
1683
|
return Qnil;
|
|
@@ -1895,6 +1702,7 @@ static VALUE cState_ascii_only_p(VALUE self)
|
|
|
1895
1702
|
*/
|
|
1896
1703
|
static VALUE cState_ascii_only_set(VALUE self, VALUE enable)
|
|
1897
1704
|
{
|
|
1705
|
+
rb_check_frozen(self);
|
|
1898
1706
|
GET_STATE(self);
|
|
1899
1707
|
state->ascii_only = RTEST(enable);
|
|
1900
1708
|
return Qnil;
|
|
@@ -1932,8 +1740,9 @@ static VALUE cState_depth(VALUE self)
|
|
|
1932
1740
|
*/
|
|
1933
1741
|
static VALUE cState_depth_set(VALUE self, VALUE depth)
|
|
1934
1742
|
{
|
|
1743
|
+
rb_check_frozen(self);
|
|
1935
1744
|
GET_STATE(self);
|
|
1936
|
-
state->depth =
|
|
1745
|
+
state->depth = depth_config(depth);
|
|
1937
1746
|
return Qnil;
|
|
1938
1747
|
}
|
|
1939
1748
|
|
|
@@ -1965,6 +1774,7 @@ static void buffer_initial_length_set(JSON_Generator_State *state, VALUE buffer_
|
|
|
1965
1774
|
*/
|
|
1966
1775
|
static VALUE cState_buffer_initial_length_set(VALUE self, VALUE buffer_initial_length)
|
|
1967
1776
|
{
|
|
1777
|
+
rb_check_frozen(self);
|
|
1968
1778
|
GET_STATE(self);
|
|
1969
1779
|
buffer_initial_length_set(state, buffer_initial_length);
|
|
1970
1780
|
return Qnil;
|
|
@@ -1997,7 +1807,7 @@ static int configure_state_i(VALUE key, VALUE val, VALUE _arg)
|
|
|
1997
1807
|
else if (key == sym_max_nesting) { state->max_nesting = long_config(val); }
|
|
1998
1808
|
else if (key == sym_allow_nan) { state->allow_nan = RTEST(val); }
|
|
1999
1809
|
else if (key == sym_ascii_only) { state->ascii_only = RTEST(val); }
|
|
2000
|
-
else if (key == sym_depth) { state->depth =
|
|
1810
|
+
else if (key == sym_depth) { state->depth = depth_config(val); }
|
|
2001
1811
|
else if (key == sym_buffer_initial_length) { buffer_initial_length_set(state, val); }
|
|
2002
1812
|
else if (key == sym_script_safe) { state->script_safe = RTEST(val); }
|
|
2003
1813
|
else if (key == sym_escape_slash) { state->script_safe = RTEST(val); }
|
|
@@ -2031,12 +1841,13 @@ static void configure_state(JSON_Generator_State *state, VALUE vstate, VALUE con
|
|
|
2031
1841
|
|
|
2032
1842
|
static VALUE cState_configure(VALUE self, VALUE opts)
|
|
2033
1843
|
{
|
|
1844
|
+
rb_check_frozen(self);
|
|
2034
1845
|
GET_STATE(self);
|
|
2035
1846
|
configure_state(state, self, opts);
|
|
2036
1847
|
return self;
|
|
2037
1848
|
}
|
|
2038
1849
|
|
|
2039
|
-
static VALUE
|
|
1850
|
+
static VALUE cState_m_do_generate(VALUE klass, VALUE obj, VALUE opts, VALUE io, generator_func func)
|
|
2040
1851
|
{
|
|
2041
1852
|
JSON_Generator_State state = {0};
|
|
2042
1853
|
state_init(&state);
|
|
@@ -2052,15 +1863,23 @@ static VALUE cState_m_generate(VALUE klass, VALUE obj, VALUE opts, VALUE io)
|
|
|
2052
1863
|
.buffer = &buffer,
|
|
2053
1864
|
.vstate = Qfalse,
|
|
2054
1865
|
.state = &state,
|
|
1866
|
+
.depth = state.depth,
|
|
2055
1867
|
.obj = obj,
|
|
2056
|
-
.func =
|
|
1868
|
+
.func = func,
|
|
2057
1869
|
};
|
|
2058
1870
|
return rb_ensure(generate_json_try, (VALUE)&data, generate_json_ensure, (VALUE)&data);
|
|
2059
1871
|
}
|
|
2060
1872
|
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
1873
|
+
static VALUE cState_m_generate(VALUE klass, VALUE obj, VALUE opts, VALUE io)
|
|
1874
|
+
{
|
|
1875
|
+
return cState_m_do_generate(klass, obj, opts, io, generate_json);
|
|
1876
|
+
}
|
|
1877
|
+
|
|
1878
|
+
static VALUE cState_m_generate_no_fallback(VALUE klass, VALUE obj, VALUE opts, VALUE io)
|
|
1879
|
+
{
|
|
1880
|
+
return cState_m_do_generate(klass, obj, opts, io, generate_json_no_fallback);
|
|
1881
|
+
}
|
|
1882
|
+
|
|
2064
1883
|
void Init_generator(void)
|
|
2065
1884
|
{
|
|
2066
1885
|
#ifdef HAVE_RB_EXT_RACTOR_SAFE
|
|
@@ -2125,47 +1944,12 @@ void Init_generator(void)
|
|
|
2125
1944
|
rb_define_method(cState, "buffer_initial_length", cState_buffer_initial_length, 0);
|
|
2126
1945
|
rb_define_method(cState, "buffer_initial_length=", cState_buffer_initial_length_set, 1);
|
|
2127
1946
|
rb_define_method(cState, "generate", cState_generate, -1);
|
|
2128
|
-
rb_define_method(cState, "
|
|
1947
|
+
rb_define_method(cState, "_generate_no_fallback", cState_generate_no_fallback, -1);
|
|
2129
1948
|
|
|
2130
1949
|
rb_define_private_method(cState, "allow_duplicate_key?", cState_allow_duplicate_key_p, 0);
|
|
2131
1950
|
|
|
2132
1951
|
rb_define_singleton_method(cState, "generate", cState_m_generate, 3);
|
|
2133
|
-
|
|
2134
|
-
VALUE mGeneratorMethods = rb_define_module_under(mGenerator, "GeneratorMethods");
|
|
2135
|
-
|
|
2136
|
-
VALUE mObject = rb_define_module_under(mGeneratorMethods, "Object");
|
|
2137
|
-
rb_define_method(mObject, "to_json", mObject_to_json, -1);
|
|
2138
|
-
|
|
2139
|
-
VALUE mHash = rb_define_module_under(mGeneratorMethods, "Hash");
|
|
2140
|
-
rb_define_method(mHash, "to_json", mHash_to_json, -1);
|
|
2141
|
-
|
|
2142
|
-
VALUE mArray = rb_define_module_under(mGeneratorMethods, "Array");
|
|
2143
|
-
rb_define_method(mArray, "to_json", mArray_to_json, -1);
|
|
2144
|
-
|
|
2145
|
-
#ifdef RUBY_INTEGER_UNIFICATION
|
|
2146
|
-
VALUE mInteger = rb_define_module_under(mGeneratorMethods, "Integer");
|
|
2147
|
-
rb_define_method(mInteger, "to_json", mInteger_to_json, -1);
|
|
2148
|
-
#else
|
|
2149
|
-
VALUE mFixnum = rb_define_module_under(mGeneratorMethods, "Fixnum");
|
|
2150
|
-
rb_define_method(mFixnum, "to_json", mFixnum_to_json, -1);
|
|
2151
|
-
|
|
2152
|
-
VALUE mBignum = rb_define_module_under(mGeneratorMethods, "Bignum");
|
|
2153
|
-
rb_define_method(mBignum, "to_json", mBignum_to_json, -1);
|
|
2154
|
-
#endif
|
|
2155
|
-
VALUE mFloat = rb_define_module_under(mGeneratorMethods, "Float");
|
|
2156
|
-
rb_define_method(mFloat, "to_json", mFloat_to_json, -1);
|
|
2157
|
-
|
|
2158
|
-
VALUE mString = rb_define_module_under(mGeneratorMethods, "String");
|
|
2159
|
-
rb_define_method(mString, "to_json", mString_to_json, -1);
|
|
2160
|
-
|
|
2161
|
-
VALUE mTrueClass = rb_define_module_under(mGeneratorMethods, "TrueClass");
|
|
2162
|
-
rb_define_method(mTrueClass, "to_json", mTrueClass_to_json, -1);
|
|
2163
|
-
|
|
2164
|
-
VALUE mFalseClass = rb_define_module_under(mGeneratorMethods, "FalseClass");
|
|
2165
|
-
rb_define_method(mFalseClass, "to_json", mFalseClass_to_json, -1);
|
|
2166
|
-
|
|
2167
|
-
VALUE mNilClass = rb_define_module_under(mGeneratorMethods, "NilClass");
|
|
2168
|
-
rb_define_method(mNilClass, "to_json", mNilClass_to_json, -1);
|
|
1952
|
+
rb_define_singleton_method(cState, "_generate_no_fallback", cState_m_generate_no_fallback, 3);
|
|
2169
1953
|
|
|
2170
1954
|
rb_global_variable(&Encoding_UTF_8);
|
|
2171
1955
|
Encoding_UTF_8 = rb_const_get(rb_path2class("Encoding"), rb_intern("UTF_8"));
|
|
@@ -2173,10 +1957,6 @@ void Init_generator(void)
|
|
|
2173
1957
|
i_to_s = rb_intern("to_s");
|
|
2174
1958
|
i_to_json = rb_intern("to_json");
|
|
2175
1959
|
i_new = rb_intern("new");
|
|
2176
|
-
i_pack = rb_intern("pack");
|
|
2177
|
-
i_unpack = rb_intern("unpack");
|
|
2178
|
-
i_create_id = rb_intern("create_id");
|
|
2179
|
-
i_extend = rb_intern("extend");
|
|
2180
1960
|
i_encode = rb_intern("encode");
|
|
2181
1961
|
|
|
2182
1962
|
sym_indent = ID2SYM(rb_intern("indent"));
|
|
@@ -2201,22 +1981,5 @@ void Init_generator(void)
|
|
|
2201
1981
|
|
|
2202
1982
|
rb_require("json/ext/generator/state");
|
|
2203
1983
|
|
|
2204
|
-
|
|
2205
|
-
switch (find_simd_implementation()) {
|
|
2206
|
-
#ifdef HAVE_SIMD
|
|
2207
|
-
#ifdef HAVE_SIMD_NEON
|
|
2208
|
-
case SIMD_NEON:
|
|
2209
|
-
search_escape_basic_impl = search_escape_basic_neon;
|
|
2210
|
-
break;
|
|
2211
|
-
#endif /* HAVE_SIMD_NEON */
|
|
2212
|
-
#ifdef HAVE_SIMD_SSE2
|
|
2213
|
-
case SIMD_SSE2:
|
|
2214
|
-
search_escape_basic_impl = search_escape_basic_sse2;
|
|
2215
|
-
break;
|
|
2216
|
-
#endif /* HAVE_SIMD_SSE2 */
|
|
2217
|
-
#endif /* HAVE_SIMD */
|
|
2218
|
-
default:
|
|
2219
|
-
search_escape_basic_impl = search_escape_basic;
|
|
2220
|
-
break;
|
|
2221
|
-
}
|
|
1984
|
+
simd_impl = find_simd_implementation();
|
|
2222
1985
|
}
|