json 2.18.1 → 2.20.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 +4 -4
- data/CHANGES.md +65 -0
- data/LEGAL +3 -3
- data/README.md +11 -2
- data/ext/json/ext/fbuffer/fbuffer.h +46 -36
- data/ext/json/ext/generator/extconf.rb +3 -0
- data/ext/json/ext/generator/generator.c +98 -325
- data/ext/json/ext/json.h +78 -0
- data/ext/json/ext/parser/extconf.rb +37 -0
- data/ext/json/ext/parser/parser.c +1535 -380
- data/ext/json/ext/simd/simd.h +0 -10
- data/ext/json/ext/vendor/fast_float_parser.h +814 -0
- data/lib/json/common.rb +41 -10
- data/lib/json/ext/generator/state.rb +1 -1
- data/lib/json/truffle_ruby/generator.rb +24 -9
- data/lib/json/version.rb +1 -1
- data/lib/json.rb +30 -4
- metadata +3 -3
- data/ext/json/ext/vendor/ryu.h +0 -819
|
@@ -74,9 +74,6 @@ static void generate_json_string(FBuffer *buffer, struct generate_json_data *dat
|
|
|
74
74
|
static void generate_json_null(FBuffer *buffer, struct generate_json_data *data, VALUE obj);
|
|
75
75
|
static void generate_json_false(FBuffer *buffer, struct generate_json_data *data, VALUE obj);
|
|
76
76
|
static void generate_json_true(FBuffer *buffer, struct generate_json_data *data, VALUE obj);
|
|
77
|
-
#ifdef RUBY_INTEGER_UNIFICATION
|
|
78
|
-
static void generate_json_integer(FBuffer *buffer, struct generate_json_data *data, VALUE obj);
|
|
79
|
-
#endif
|
|
80
77
|
static void generate_json_fixnum(FBuffer *buffer, struct generate_json_data *data, VALUE obj);
|
|
81
78
|
static void generate_json_bignum(FBuffer *buffer, struct generate_json_data *data, VALUE obj);
|
|
82
79
|
static void generate_json_float(FBuffer *buffer, struct generate_json_data *data, VALUE obj);
|
|
@@ -703,233 +700,6 @@ static void convert_UTF8_to_ASCII_only_JSON(search_state *search, const unsigned
|
|
|
703
700
|
}
|
|
704
701
|
}
|
|
705
702
|
|
|
706
|
-
/*
|
|
707
|
-
* Document-module: JSON::Ext::Generator
|
|
708
|
-
*
|
|
709
|
-
* This is the JSON generator implemented as a C extension. It can be
|
|
710
|
-
* configured to be used by setting
|
|
711
|
-
*
|
|
712
|
-
* JSON.generator = JSON::Ext::Generator
|
|
713
|
-
*
|
|
714
|
-
* with the method generator= in JSON.
|
|
715
|
-
*
|
|
716
|
-
*/
|
|
717
|
-
|
|
718
|
-
/* Explanation of the following: that's the only way to not pollute
|
|
719
|
-
* standard library's docs with GeneratorMethods::<ClassName> which
|
|
720
|
-
* are uninformative and take a large place in a list of classes
|
|
721
|
-
*/
|
|
722
|
-
|
|
723
|
-
/*
|
|
724
|
-
* Document-module: JSON::Ext::Generator::GeneratorMethods
|
|
725
|
-
* :nodoc:
|
|
726
|
-
*/
|
|
727
|
-
|
|
728
|
-
/*
|
|
729
|
-
* Document-module: JSON::Ext::Generator::GeneratorMethods::Array
|
|
730
|
-
* :nodoc:
|
|
731
|
-
*/
|
|
732
|
-
|
|
733
|
-
/*
|
|
734
|
-
* Document-module: JSON::Ext::Generator::GeneratorMethods::Bignum
|
|
735
|
-
* :nodoc:
|
|
736
|
-
*/
|
|
737
|
-
|
|
738
|
-
/*
|
|
739
|
-
* Document-module: JSON::Ext::Generator::GeneratorMethods::FalseClass
|
|
740
|
-
* :nodoc:
|
|
741
|
-
*/
|
|
742
|
-
|
|
743
|
-
/*
|
|
744
|
-
* Document-module: JSON::Ext::Generator::GeneratorMethods::Fixnum
|
|
745
|
-
* :nodoc:
|
|
746
|
-
*/
|
|
747
|
-
|
|
748
|
-
/*
|
|
749
|
-
* Document-module: JSON::Ext::Generator::GeneratorMethods::Float
|
|
750
|
-
* :nodoc:
|
|
751
|
-
*/
|
|
752
|
-
|
|
753
|
-
/*
|
|
754
|
-
* Document-module: JSON::Ext::Generator::GeneratorMethods::Hash
|
|
755
|
-
* :nodoc:
|
|
756
|
-
*/
|
|
757
|
-
|
|
758
|
-
/*
|
|
759
|
-
* Document-module: JSON::Ext::Generator::GeneratorMethods::Integer
|
|
760
|
-
* :nodoc:
|
|
761
|
-
*/
|
|
762
|
-
|
|
763
|
-
/*
|
|
764
|
-
* Document-module: JSON::Ext::Generator::GeneratorMethods::NilClass
|
|
765
|
-
* :nodoc:
|
|
766
|
-
*/
|
|
767
|
-
|
|
768
|
-
/*
|
|
769
|
-
* Document-module: JSON::Ext::Generator::GeneratorMethods::Object
|
|
770
|
-
* :nodoc:
|
|
771
|
-
*/
|
|
772
|
-
|
|
773
|
-
/*
|
|
774
|
-
* Document-module: JSON::Ext::Generator::GeneratorMethods::String
|
|
775
|
-
* :nodoc:
|
|
776
|
-
*/
|
|
777
|
-
|
|
778
|
-
/*
|
|
779
|
-
* Document-module: JSON::Ext::Generator::GeneratorMethods::String::Extend
|
|
780
|
-
* :nodoc:
|
|
781
|
-
*/
|
|
782
|
-
|
|
783
|
-
/*
|
|
784
|
-
* Document-module: JSON::Ext::Generator::GeneratorMethods::TrueClass
|
|
785
|
-
* :nodoc:
|
|
786
|
-
*/
|
|
787
|
-
|
|
788
|
-
/*
|
|
789
|
-
* call-seq: to_json(state = nil)
|
|
790
|
-
*
|
|
791
|
-
* Returns a JSON string containing a JSON object, that is generated from
|
|
792
|
-
* this Hash instance.
|
|
793
|
-
* _state_ is a JSON::State object, that can also be used to configure the
|
|
794
|
-
* produced JSON string output further.
|
|
795
|
-
*/
|
|
796
|
-
static VALUE mHash_to_json(int argc, VALUE *argv, VALUE self)
|
|
797
|
-
{
|
|
798
|
-
rb_check_arity(argc, 0, 1);
|
|
799
|
-
VALUE Vstate = cState_from_state_s(cState, argc == 1 ? argv[0] : Qnil);
|
|
800
|
-
return cState_partial_generate(Vstate, self, generate_json_object, Qfalse);
|
|
801
|
-
}
|
|
802
|
-
|
|
803
|
-
/*
|
|
804
|
-
* call-seq: to_json(state = nil)
|
|
805
|
-
*
|
|
806
|
-
* Returns a JSON string containing a JSON array, that is generated from
|
|
807
|
-
* this Array instance.
|
|
808
|
-
* _state_ is a JSON::State object, that can also be used to configure the
|
|
809
|
-
* produced JSON string output further.
|
|
810
|
-
*/
|
|
811
|
-
static VALUE mArray_to_json(int argc, VALUE *argv, VALUE self)
|
|
812
|
-
{
|
|
813
|
-
rb_check_arity(argc, 0, 1);
|
|
814
|
-
VALUE Vstate = cState_from_state_s(cState, argc == 1 ? argv[0] : Qnil);
|
|
815
|
-
return cState_partial_generate(Vstate, self, generate_json_array, Qfalse);
|
|
816
|
-
}
|
|
817
|
-
|
|
818
|
-
#ifdef RUBY_INTEGER_UNIFICATION
|
|
819
|
-
/*
|
|
820
|
-
* call-seq: to_json(*)
|
|
821
|
-
*
|
|
822
|
-
* Returns a JSON string representation for this Integer number.
|
|
823
|
-
*/
|
|
824
|
-
static VALUE mInteger_to_json(int argc, VALUE *argv, VALUE self)
|
|
825
|
-
{
|
|
826
|
-
rb_check_arity(argc, 0, 1);
|
|
827
|
-
VALUE Vstate = cState_from_state_s(cState, argc == 1 ? argv[0] : Qnil);
|
|
828
|
-
return cState_partial_generate(Vstate, self, generate_json_integer, Qfalse);
|
|
829
|
-
}
|
|
830
|
-
|
|
831
|
-
#else
|
|
832
|
-
/*
|
|
833
|
-
* call-seq: to_json(*)
|
|
834
|
-
*
|
|
835
|
-
* Returns a JSON string representation for this Integer number.
|
|
836
|
-
*/
|
|
837
|
-
static VALUE mFixnum_to_json(int argc, VALUE *argv, VALUE self)
|
|
838
|
-
{
|
|
839
|
-
rb_check_arity(argc, 0, 1);
|
|
840
|
-
VALUE Vstate = cState_from_state_s(cState, argc == 1 ? argv[0] : Qnil);
|
|
841
|
-
return cState_partial_generate(Vstate, self, generate_json_fixnum, Qfalse);
|
|
842
|
-
}
|
|
843
|
-
|
|
844
|
-
/*
|
|
845
|
-
* call-seq: to_json(*)
|
|
846
|
-
*
|
|
847
|
-
* Returns a JSON string representation for this Integer number.
|
|
848
|
-
*/
|
|
849
|
-
static VALUE mBignum_to_json(int argc, VALUE *argv, VALUE self)
|
|
850
|
-
{
|
|
851
|
-
rb_check_arity(argc, 0, 1);
|
|
852
|
-
VALUE Vstate = cState_from_state_s(cState, argc == 1 ? argv[0] : Qnil);
|
|
853
|
-
return cState_partial_generate(Vstate, self, generate_json_bignum, Qfalse);
|
|
854
|
-
}
|
|
855
|
-
#endif
|
|
856
|
-
|
|
857
|
-
/*
|
|
858
|
-
* call-seq: to_json(*)
|
|
859
|
-
*
|
|
860
|
-
* Returns a JSON string representation for this Float number.
|
|
861
|
-
*/
|
|
862
|
-
static VALUE mFloat_to_json(int argc, VALUE *argv, VALUE self)
|
|
863
|
-
{
|
|
864
|
-
rb_check_arity(argc, 0, 1);
|
|
865
|
-
VALUE Vstate = cState_from_state_s(cState, argc == 1 ? argv[0] : Qnil);
|
|
866
|
-
return cState_partial_generate(Vstate, self, generate_json_float, Qfalse);
|
|
867
|
-
}
|
|
868
|
-
|
|
869
|
-
/*
|
|
870
|
-
* call-seq: to_json(*)
|
|
871
|
-
*
|
|
872
|
-
* This string should be encoded with UTF-8 A call to this method
|
|
873
|
-
* returns a JSON string encoded with UTF16 big endian characters as
|
|
874
|
-
* \u????.
|
|
875
|
-
*/
|
|
876
|
-
static VALUE mString_to_json(int argc, VALUE *argv, VALUE self)
|
|
877
|
-
{
|
|
878
|
-
rb_check_arity(argc, 0, 1);
|
|
879
|
-
VALUE Vstate = cState_from_state_s(cState, argc == 1 ? argv[0] : Qnil);
|
|
880
|
-
return cState_partial_generate(Vstate, self, generate_json_string, Qfalse);
|
|
881
|
-
}
|
|
882
|
-
|
|
883
|
-
/*
|
|
884
|
-
* call-seq: to_json(*)
|
|
885
|
-
*
|
|
886
|
-
* Returns a JSON string for true: 'true'.
|
|
887
|
-
*/
|
|
888
|
-
static VALUE mTrueClass_to_json(int argc, VALUE *argv, VALUE self)
|
|
889
|
-
{
|
|
890
|
-
rb_check_arity(argc, 0, 1);
|
|
891
|
-
return rb_utf8_str_new("true", 4);
|
|
892
|
-
}
|
|
893
|
-
|
|
894
|
-
/*
|
|
895
|
-
* call-seq: to_json(*)
|
|
896
|
-
*
|
|
897
|
-
* Returns a JSON string for false: 'false'.
|
|
898
|
-
*/
|
|
899
|
-
static VALUE mFalseClass_to_json(int argc, VALUE *argv, VALUE self)
|
|
900
|
-
{
|
|
901
|
-
rb_check_arity(argc, 0, 1);
|
|
902
|
-
return rb_utf8_str_new("false", 5);
|
|
903
|
-
}
|
|
904
|
-
|
|
905
|
-
/*
|
|
906
|
-
* call-seq: to_json(*)
|
|
907
|
-
*
|
|
908
|
-
* Returns a JSON string for nil: 'null'.
|
|
909
|
-
*/
|
|
910
|
-
static VALUE mNilClass_to_json(int argc, VALUE *argv, VALUE self)
|
|
911
|
-
{
|
|
912
|
-
rb_check_arity(argc, 0, 1);
|
|
913
|
-
return rb_utf8_str_new("null", 4);
|
|
914
|
-
}
|
|
915
|
-
|
|
916
|
-
/*
|
|
917
|
-
* call-seq: to_json(*)
|
|
918
|
-
*
|
|
919
|
-
* Converts this object to a string (calling #to_s), converts
|
|
920
|
-
* it to a JSON string, and returns the result. This is a fallback, if no
|
|
921
|
-
* special method #to_json was defined for some object.
|
|
922
|
-
*/
|
|
923
|
-
static VALUE mObject_to_json(int argc, VALUE *argv, VALUE self)
|
|
924
|
-
{
|
|
925
|
-
VALUE state;
|
|
926
|
-
VALUE string = rb_funcall(self, i_to_s, 0);
|
|
927
|
-
rb_scan_args(argc, argv, "01", &state);
|
|
928
|
-
Check_Type(string, T_STRING);
|
|
929
|
-
state = cState_from_state_s(cState, state);
|
|
930
|
-
return cState_partial_generate(state, string, generate_json_string, Qfalse);
|
|
931
|
-
}
|
|
932
|
-
|
|
933
703
|
static void State_mark(void *ptr)
|
|
934
704
|
{
|
|
935
705
|
JSON_Generator_State *state = ptr;
|
|
@@ -952,27 +722,24 @@ static void State_compact(void *ptr)
|
|
|
952
722
|
state->as_json = rb_gc_location(state->as_json);
|
|
953
723
|
}
|
|
954
724
|
|
|
955
|
-
static void State_free(void *ptr)
|
|
956
|
-
{
|
|
957
|
-
JSON_Generator_State *state = ptr;
|
|
958
|
-
ruby_xfree(state);
|
|
959
|
-
}
|
|
960
|
-
|
|
961
725
|
static size_t State_memsize(const void *ptr)
|
|
962
726
|
{
|
|
727
|
+
#ifdef HAVE_RUBY_TYPED_EMBEDDABLE
|
|
728
|
+
return 0;
|
|
729
|
+
#else
|
|
963
730
|
return sizeof(JSON_Generator_State);
|
|
731
|
+
#endif
|
|
964
732
|
}
|
|
965
733
|
|
|
966
734
|
static const rb_data_type_t JSON_Generator_State_type = {
|
|
967
|
-
"JSON/Generator/State",
|
|
968
|
-
{
|
|
735
|
+
.wrap_struct_name = "JSON/Generator/State",
|
|
736
|
+
.function = {
|
|
969
737
|
.dmark = State_mark,
|
|
970
|
-
.dfree =
|
|
738
|
+
.dfree = RUBY_DEFAULT_FREE,
|
|
971
739
|
.dsize = State_memsize,
|
|
972
740
|
.dcompact = State_compact,
|
|
973
741
|
},
|
|
974
|
-
|
|
975
|
-
RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_FROZEN_SHAREABLE,
|
|
742
|
+
.flags = RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_FROZEN_SHAREABLE | RUBY_TYPED_EMBEDDABLE,
|
|
976
743
|
};
|
|
977
744
|
|
|
978
745
|
static void state_init(JSON_Generator_State *state)
|
|
@@ -1056,9 +823,17 @@ static VALUE encode_json_string_rescue(VALUE str, VALUE exception)
|
|
|
1056
823
|
return Qundef;
|
|
1057
824
|
}
|
|
1058
825
|
|
|
826
|
+
static inline int json_str_coderange(VALUE str) {
|
|
827
|
+
int coderange = RB_ENC_CODERANGE(str);
|
|
828
|
+
if (coderange == RUBY_ENC_CODERANGE_UNKNOWN) {
|
|
829
|
+
coderange = rb_enc_str_coderange(str);
|
|
830
|
+
}
|
|
831
|
+
return coderange;
|
|
832
|
+
}
|
|
833
|
+
|
|
1059
834
|
static inline bool valid_json_string_p(VALUE str)
|
|
1060
835
|
{
|
|
1061
|
-
int coderange =
|
|
836
|
+
int coderange = json_str_coderange(str);
|
|
1062
837
|
|
|
1063
838
|
if (RB_LIKELY(coderange == ENC_CODERANGE_7BIT)) {
|
|
1064
839
|
return true;
|
|
@@ -1071,12 +846,8 @@ static inline bool valid_json_string_p(VALUE str)
|
|
|
1071
846
|
return false;
|
|
1072
847
|
}
|
|
1073
848
|
|
|
1074
|
-
static
|
|
849
|
+
NOINLINE(static) VALUE convert_invalid_encoding(struct generate_json_data *data, VALUE str, bool as_json_called, bool is_key)
|
|
1075
850
|
{
|
|
1076
|
-
if (RB_LIKELY(valid_json_string_p(str))) {
|
|
1077
|
-
return str;
|
|
1078
|
-
}
|
|
1079
|
-
|
|
1080
851
|
if (!as_json_called && data->state->strict && RTEST(data->state->as_json)) {
|
|
1081
852
|
VALUE coerced_str = json_call_as_json(data->state, str, Qfalse);
|
|
1082
853
|
if (coerced_str != str) {
|
|
@@ -1112,6 +883,16 @@ static inline VALUE ensure_valid_encoding(struct generate_json_data *data, VALUE
|
|
|
1112
883
|
return rb_rescue(encode_json_string_try, str, encode_json_string_rescue, str);
|
|
1113
884
|
}
|
|
1114
885
|
|
|
886
|
+
ALWAYS_INLINE(static) VALUE ensure_valid_encoding(struct generate_json_data *data, VALUE str, bool as_json_called, bool is_key)
|
|
887
|
+
{
|
|
888
|
+
if (RB_LIKELY(valid_json_string_p(str))) {
|
|
889
|
+
return str;
|
|
890
|
+
}
|
|
891
|
+
else {
|
|
892
|
+
return convert_invalid_encoding(data, str, as_json_called, is_key);
|
|
893
|
+
}
|
|
894
|
+
}
|
|
895
|
+
|
|
1115
896
|
static void raw_generate_json_string(FBuffer *buffer, struct generate_json_data *data, VALUE obj)
|
|
1116
897
|
{
|
|
1117
898
|
fbuffer_append_char(buffer, '"');
|
|
@@ -1130,7 +911,7 @@ static void raw_generate_json_string(FBuffer *buffer, struct generate_json_data
|
|
|
1130
911
|
search.chunk_end = NULL;
|
|
1131
912
|
#endif /* HAVE_SIMD */
|
|
1132
913
|
|
|
1133
|
-
switch (
|
|
914
|
+
switch (json_str_coderange(obj)) {
|
|
1134
915
|
case ENC_CODERANGE_7BIT:
|
|
1135
916
|
case ENC_CODERANGE_VALID:
|
|
1136
917
|
if (RB_UNLIKELY(data->state->ascii_only)) {
|
|
@@ -1377,16 +1158,6 @@ static void generate_json_bignum(FBuffer *buffer, struct generate_json_data *dat
|
|
|
1377
1158
|
fbuffer_append_str(buffer, StringValue(tmp));
|
|
1378
1159
|
}
|
|
1379
1160
|
|
|
1380
|
-
#ifdef RUBY_INTEGER_UNIFICATION
|
|
1381
|
-
static void generate_json_integer(FBuffer *buffer, struct generate_json_data *data, VALUE obj)
|
|
1382
|
-
{
|
|
1383
|
-
if (FIXNUM_P(obj))
|
|
1384
|
-
generate_json_fixnum(buffer, data, obj);
|
|
1385
|
-
else
|
|
1386
|
-
generate_json_bignum(buffer, data, obj);
|
|
1387
|
-
}
|
|
1388
|
-
#endif
|
|
1389
|
-
|
|
1390
1161
|
static void generate_json_float(FBuffer *buffer, struct generate_json_data *data, VALUE obj)
|
|
1391
1162
|
{
|
|
1392
1163
|
double value = RFLOAT_VALUE(obj);
|
|
@@ -1430,7 +1201,7 @@ static void generate_json_fragment(FBuffer *buffer, struct generate_json_data *d
|
|
|
1430
1201
|
fbuffer_append_str(buffer, fragment);
|
|
1431
1202
|
}
|
|
1432
1203
|
|
|
1433
|
-
static void
|
|
1204
|
+
static inline void generate_json_general(FBuffer *buffer, struct generate_json_data *data, VALUE obj, bool fallback)
|
|
1434
1205
|
{
|
|
1435
1206
|
bool as_json_called = false;
|
|
1436
1207
|
start:
|
|
@@ -1457,15 +1228,15 @@ start:
|
|
|
1457
1228
|
generate_json_bignum(buffer, data, obj);
|
|
1458
1229
|
break;
|
|
1459
1230
|
case T_HASH:
|
|
1460
|
-
if (klass != rb_cHash) goto general;
|
|
1231
|
+
if (fallback && klass != rb_cHash) goto general;
|
|
1461
1232
|
generate_json_object(buffer, data, obj);
|
|
1462
1233
|
break;
|
|
1463
1234
|
case T_ARRAY:
|
|
1464
|
-
if (klass != rb_cArray) goto general;
|
|
1235
|
+
if (fallback && klass != rb_cArray) goto general;
|
|
1465
1236
|
generate_json_array(buffer, data, obj);
|
|
1466
1237
|
break;
|
|
1467
1238
|
case T_STRING:
|
|
1468
|
-
if (klass != rb_cString) goto general;
|
|
1239
|
+
if (fallback && klass != rb_cString) goto general;
|
|
1469
1240
|
|
|
1470
1241
|
if (RB_LIKELY(valid_json_string_p(obj))) {
|
|
1471
1242
|
raw_generate_json_string(buffer, data, obj);
|
|
@@ -1481,7 +1252,7 @@ start:
|
|
|
1481
1252
|
generate_json_symbol(buffer, data, obj);
|
|
1482
1253
|
break;
|
|
1483
1254
|
case T_FLOAT:
|
|
1484
|
-
if (klass != rb_cFloat) goto general;
|
|
1255
|
+
if (fallback && klass != rb_cFloat) goto general;
|
|
1485
1256
|
generate_json_float(buffer, data, obj);
|
|
1486
1257
|
break;
|
|
1487
1258
|
case T_STRUCT:
|
|
@@ -1505,6 +1276,16 @@ start:
|
|
|
1505
1276
|
}
|
|
1506
1277
|
}
|
|
1507
1278
|
|
|
1279
|
+
static void generate_json(FBuffer *buffer, struct generate_json_data *data, VALUE obj)
|
|
1280
|
+
{
|
|
1281
|
+
generate_json_general(buffer, data, obj, true);
|
|
1282
|
+
}
|
|
1283
|
+
|
|
1284
|
+
static void generate_json_no_fallback(FBuffer *buffer, struct generate_json_data *data, VALUE obj)
|
|
1285
|
+
{
|
|
1286
|
+
generate_json_general(buffer, data, obj, false);
|
|
1287
|
+
}
|
|
1288
|
+
|
|
1508
1289
|
static VALUE generate_json_try(VALUE d)
|
|
1509
1290
|
{
|
|
1510
1291
|
struct generate_json_data *data = (struct generate_json_data *)d;
|
|
@@ -1522,15 +1303,13 @@ static VALUE generate_json_ensure(VALUE d)
|
|
|
1522
1303
|
return Qundef;
|
|
1523
1304
|
}
|
|
1524
1305
|
|
|
1525
|
-
static VALUE cState_partial_generate(VALUE self, VALUE obj, generator_func func, VALUE io)
|
|
1306
|
+
static inline VALUE cState_partial_generate(VALUE self, VALUE obj, generator_func func, VALUE io)
|
|
1526
1307
|
{
|
|
1527
1308
|
GET_STATE(self);
|
|
1528
1309
|
|
|
1529
1310
|
char stack_buffer[FBUFFER_STACK_SIZE];
|
|
1530
|
-
FBuffer buffer = {
|
|
1531
|
-
|
|
1532
|
-
};
|
|
1533
|
-
fbuffer_stack_init(&buffer, state->buffer_initial_length, stack_buffer, FBUFFER_STACK_SIZE);
|
|
1311
|
+
FBuffer buffer = { 0 };
|
|
1312
|
+
fbuffer_init(&buffer, state->buffer_initial_length, io, stack_buffer, FBUFFER_STACK_SIZE);
|
|
1534
1313
|
|
|
1535
1314
|
struct generate_json_data data = {
|
|
1536
1315
|
.buffer = &buffer,
|
|
@@ -1540,9 +1319,7 @@ static VALUE cState_partial_generate(VALUE self, VALUE obj, generator_func func,
|
|
|
1540
1319
|
.obj = obj,
|
|
1541
1320
|
.func = func
|
|
1542
1321
|
};
|
|
1543
|
-
|
|
1544
|
-
RB_GC_GUARD(self);
|
|
1545
|
-
return result;
|
|
1322
|
+
return rb_ensure(generate_json_try, (VALUE)&data, generate_json_ensure, (VALUE)&data);
|
|
1546
1323
|
}
|
|
1547
1324
|
|
|
1548
1325
|
/* call-seq:
|
|
@@ -1561,6 +1338,15 @@ static VALUE cState_generate(int argc, VALUE *argv, VALUE self)
|
|
|
1561
1338
|
return cState_partial_generate(self, obj, generate_json, io);
|
|
1562
1339
|
}
|
|
1563
1340
|
|
|
1341
|
+
/* :nodoc: */
|
|
1342
|
+
static VALUE cState_generate_no_fallback(int argc, VALUE *argv, VALUE self)
|
|
1343
|
+
{
|
|
1344
|
+
rb_check_arity(argc, 1, 2);
|
|
1345
|
+
VALUE obj = argv[0];
|
|
1346
|
+
VALUE io = argc > 1 ? argv[1] : Qnil;
|
|
1347
|
+
return cState_partial_generate(self, obj, generate_json_no_fallback, io);
|
|
1348
|
+
}
|
|
1349
|
+
|
|
1564
1350
|
static VALUE cState_initialize(int argc, VALUE *argv, VALUE self)
|
|
1565
1351
|
{
|
|
1566
1352
|
rb_warn("The json gem extension was loaded with the stdlib ruby code. You should upgrade rubygems with `gem update --system`");
|
|
@@ -1583,12 +1369,14 @@ static VALUE cState_init_copy(VALUE obj, VALUE orig)
|
|
|
1583
1369
|
if (!objState) rb_raise(rb_eArgError, "unallocated JSON::State");
|
|
1584
1370
|
|
|
1585
1371
|
MEMCPY(objState, origState, JSON_Generator_State, 1);
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1372
|
+
|
|
1373
|
+
RB_OBJ_WRITTEN(obj, Qundef, objState->indent);
|
|
1374
|
+
RB_OBJ_WRITTEN(obj, Qundef, objState->space);
|
|
1375
|
+
RB_OBJ_WRITTEN(obj, Qundef, objState->space_before);
|
|
1376
|
+
RB_OBJ_WRITTEN(obj, Qundef, objState->object_nl);
|
|
1377
|
+
RB_OBJ_WRITTEN(obj, Qundef, objState->array_nl);
|
|
1378
|
+
RB_OBJ_WRITTEN(obj, Qundef, objState->as_json);
|
|
1379
|
+
|
|
1592
1380
|
return obj;
|
|
1593
1381
|
}
|
|
1594
1382
|
|
|
@@ -1795,7 +1583,21 @@ static VALUE cState_max_nesting(VALUE self)
|
|
|
1795
1583
|
|
|
1796
1584
|
static long long_config(VALUE num)
|
|
1797
1585
|
{
|
|
1798
|
-
return RTEST(num) ?
|
|
1586
|
+
return RTEST(num) ? NUM2LONG(num) : 0;
|
|
1587
|
+
}
|
|
1588
|
+
|
|
1589
|
+
// depth must never be negative; reject early with a clear error.
|
|
1590
|
+
static long depth_config(VALUE num)
|
|
1591
|
+
{
|
|
1592
|
+
if (!RTEST(num)) return 0;
|
|
1593
|
+
long d = NUM2LONG(num);
|
|
1594
|
+
if (RB_UNLIKELY(d < 0)) {
|
|
1595
|
+
rb_raise(rb_eArgError, "depth must be >= 0 (got %ld)", d);
|
|
1596
|
+
}
|
|
1597
|
+
if (RB_UNLIKELY(d > INT_MAX)) {
|
|
1598
|
+
rb_raise(rb_eArgError, "depth is too large (got %ld)", d);
|
|
1599
|
+
}
|
|
1600
|
+
return d;
|
|
1799
1601
|
}
|
|
1800
1602
|
|
|
1801
1603
|
/*
|
|
@@ -1954,7 +1756,7 @@ static VALUE cState_depth_set(VALUE self, VALUE depth)
|
|
|
1954
1756
|
{
|
|
1955
1757
|
rb_check_frozen(self);
|
|
1956
1758
|
GET_STATE(self);
|
|
1957
|
-
state->depth =
|
|
1759
|
+
state->depth = depth_config(depth);
|
|
1958
1760
|
return Qnil;
|
|
1959
1761
|
}
|
|
1960
1762
|
|
|
@@ -2019,7 +1821,7 @@ static int configure_state_i(VALUE key, VALUE val, VALUE _arg)
|
|
|
2019
1821
|
else if (key == sym_max_nesting) { state->max_nesting = long_config(val); }
|
|
2020
1822
|
else if (key == sym_allow_nan) { state->allow_nan = RTEST(val); }
|
|
2021
1823
|
else if (key == sym_ascii_only) { state->ascii_only = RTEST(val); }
|
|
2022
|
-
else if (key == sym_depth) { state->depth =
|
|
1824
|
+
else if (key == sym_depth) { state->depth = depth_config(val); }
|
|
2023
1825
|
else if (key == sym_buffer_initial_length) { buffer_initial_length_set(state, val); }
|
|
2024
1826
|
else if (key == sym_script_safe) { state->script_safe = RTEST(val); }
|
|
2025
1827
|
else if (key == sym_escape_slash) { state->script_safe = RTEST(val); }
|
|
@@ -2059,17 +1861,15 @@ static VALUE cState_configure(VALUE self, VALUE opts)
|
|
|
2059
1861
|
return self;
|
|
2060
1862
|
}
|
|
2061
1863
|
|
|
2062
|
-
static VALUE
|
|
1864
|
+
static VALUE cState_m_do_generate(VALUE klass, VALUE obj, VALUE opts, VALUE io, generator_func func)
|
|
2063
1865
|
{
|
|
2064
1866
|
JSON_Generator_State state = {0};
|
|
2065
1867
|
state_init(&state);
|
|
2066
1868
|
configure_state(&state, Qfalse, opts);
|
|
2067
1869
|
|
|
2068
1870
|
char stack_buffer[FBUFFER_STACK_SIZE];
|
|
2069
|
-
FBuffer buffer = {
|
|
2070
|
-
|
|
2071
|
-
};
|
|
2072
|
-
fbuffer_stack_init(&buffer, state.buffer_initial_length, stack_buffer, FBUFFER_STACK_SIZE);
|
|
1871
|
+
FBuffer buffer = { 0 };
|
|
1872
|
+
fbuffer_init(&buffer, state.buffer_initial_length, io, stack_buffer, FBUFFER_STACK_SIZE);
|
|
2073
1873
|
|
|
2074
1874
|
struct generate_json_data data = {
|
|
2075
1875
|
.buffer = &buffer,
|
|
@@ -2077,14 +1877,21 @@ static VALUE cState_m_generate(VALUE klass, VALUE obj, VALUE opts, VALUE io)
|
|
|
2077
1877
|
.state = &state,
|
|
2078
1878
|
.depth = state.depth,
|
|
2079
1879
|
.obj = obj,
|
|
2080
|
-
.func =
|
|
1880
|
+
.func = func,
|
|
2081
1881
|
};
|
|
2082
1882
|
return rb_ensure(generate_json_try, (VALUE)&data, generate_json_ensure, (VALUE)&data);
|
|
2083
1883
|
}
|
|
2084
1884
|
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
1885
|
+
static VALUE cState_m_generate(VALUE klass, VALUE obj, VALUE opts, VALUE io)
|
|
1886
|
+
{
|
|
1887
|
+
return cState_m_do_generate(klass, obj, opts, io, generate_json);
|
|
1888
|
+
}
|
|
1889
|
+
|
|
1890
|
+
static VALUE cState_m_generate_no_fallback(VALUE klass, VALUE obj, VALUE opts, VALUE io)
|
|
1891
|
+
{
|
|
1892
|
+
return cState_m_do_generate(klass, obj, opts, io, generate_json_no_fallback);
|
|
1893
|
+
}
|
|
1894
|
+
|
|
2088
1895
|
void Init_generator(void)
|
|
2089
1896
|
{
|
|
2090
1897
|
#ifdef HAVE_RB_EXT_RACTOR_SAFE
|
|
@@ -2149,46 +1956,12 @@ void Init_generator(void)
|
|
|
2149
1956
|
rb_define_method(cState, "buffer_initial_length", cState_buffer_initial_length, 0);
|
|
2150
1957
|
rb_define_method(cState, "buffer_initial_length=", cState_buffer_initial_length_set, 1);
|
|
2151
1958
|
rb_define_method(cState, "generate", cState_generate, -1);
|
|
1959
|
+
rb_define_method(cState, "_generate_no_fallback", cState_generate_no_fallback, -1);
|
|
2152
1960
|
|
|
2153
1961
|
rb_define_private_method(cState, "allow_duplicate_key?", cState_allow_duplicate_key_p, 0);
|
|
2154
1962
|
|
|
2155
1963
|
rb_define_singleton_method(cState, "generate", cState_m_generate, 3);
|
|
2156
|
-
|
|
2157
|
-
VALUE mGeneratorMethods = rb_define_module_under(mGenerator, "GeneratorMethods");
|
|
2158
|
-
|
|
2159
|
-
VALUE mObject = rb_define_module_under(mGeneratorMethods, "Object");
|
|
2160
|
-
rb_define_method(mObject, "to_json", mObject_to_json, -1);
|
|
2161
|
-
|
|
2162
|
-
VALUE mHash = rb_define_module_under(mGeneratorMethods, "Hash");
|
|
2163
|
-
rb_define_method(mHash, "to_json", mHash_to_json, -1);
|
|
2164
|
-
|
|
2165
|
-
VALUE mArray = rb_define_module_under(mGeneratorMethods, "Array");
|
|
2166
|
-
rb_define_method(mArray, "to_json", mArray_to_json, -1);
|
|
2167
|
-
|
|
2168
|
-
#ifdef RUBY_INTEGER_UNIFICATION
|
|
2169
|
-
VALUE mInteger = rb_define_module_under(mGeneratorMethods, "Integer");
|
|
2170
|
-
rb_define_method(mInteger, "to_json", mInteger_to_json, -1);
|
|
2171
|
-
#else
|
|
2172
|
-
VALUE mFixnum = rb_define_module_under(mGeneratorMethods, "Fixnum");
|
|
2173
|
-
rb_define_method(mFixnum, "to_json", mFixnum_to_json, -1);
|
|
2174
|
-
|
|
2175
|
-
VALUE mBignum = rb_define_module_under(mGeneratorMethods, "Bignum");
|
|
2176
|
-
rb_define_method(mBignum, "to_json", mBignum_to_json, -1);
|
|
2177
|
-
#endif
|
|
2178
|
-
VALUE mFloat = rb_define_module_under(mGeneratorMethods, "Float");
|
|
2179
|
-
rb_define_method(mFloat, "to_json", mFloat_to_json, -1);
|
|
2180
|
-
|
|
2181
|
-
VALUE mString = rb_define_module_under(mGeneratorMethods, "String");
|
|
2182
|
-
rb_define_method(mString, "to_json", mString_to_json, -1);
|
|
2183
|
-
|
|
2184
|
-
VALUE mTrueClass = rb_define_module_under(mGeneratorMethods, "TrueClass");
|
|
2185
|
-
rb_define_method(mTrueClass, "to_json", mTrueClass_to_json, -1);
|
|
2186
|
-
|
|
2187
|
-
VALUE mFalseClass = rb_define_module_under(mGeneratorMethods, "FalseClass");
|
|
2188
|
-
rb_define_method(mFalseClass, "to_json", mFalseClass_to_json, -1);
|
|
2189
|
-
|
|
2190
|
-
VALUE mNilClass = rb_define_module_under(mGeneratorMethods, "NilClass");
|
|
2191
|
-
rb_define_method(mNilClass, "to_json", mNilClass_to_json, -1);
|
|
1964
|
+
rb_define_singleton_method(cState, "_generate_no_fallback", cState_m_generate_no_fallback, 3);
|
|
2192
1965
|
|
|
2193
1966
|
rb_global_variable(&Encoding_UTF_8);
|
|
2194
1967
|
Encoding_UTF_8 = rb_const_get(rb_path2class("Encoding"), rb_intern("UTF_8"));
|