json 2.18.1 → 3.0.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 +127 -0
- data/LEGAL +3 -3
- data/README.md +19 -90
- 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 +200 -364
- data/ext/json/ext/json.h +95 -0
- data/ext/json/ext/parser/extconf.rb +27 -0
- data/ext/json/ext/parser/parser.c +1654 -406
- 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 +184 -411
- data/lib/json/ext/generator/state.rb +2 -28
- data/lib/json/ext.rb +25 -1
- data/lib/json/truffle_ruby/generator.rb +89 -81
- data/lib/json/version.rb +1 -1
- data/lib/json.rb +53 -264
- metadata +3 -19
- data/ext/json/ext/vendor/ryu.h +0 -819
- data/lib/json/add/bigdecimal.rb +0 -58
- data/lib/json/add/complex.rb +0 -51
- data/lib/json/add/core.rb +0 -13
- data/lib/json/add/date.rb +0 -54
- data/lib/json/add/date_time.rb +0 -67
- data/lib/json/add/exception.rb +0 -49
- data/lib/json/add/ostruct.rb +0 -54
- data/lib/json/add/range.rb +0 -54
- data/lib/json/add/rational.rb +0 -49
- data/lib/json/add/regexp.rb +0 -48
- data/lib/json/add/set.rb +0 -48
- data/lib/json/add/string.rb +0 -35
- data/lib/json/add/struct.rb +0 -52
- data/lib/json/add/symbol.rb +0 -52
- data/lib/json/add/time.rb +0 -52
- data/lib/json/generic_object.rb +0 -67
|
@@ -9,12 +9,6 @@
|
|
|
9
9
|
|
|
10
10
|
/* ruby api and some helpers */
|
|
11
11
|
|
|
12
|
-
enum duplicate_key_action {
|
|
13
|
-
JSON_DEPRECATED = 0,
|
|
14
|
-
JSON_IGNORE,
|
|
15
|
-
JSON_RAISE,
|
|
16
|
-
};
|
|
17
|
-
|
|
18
12
|
typedef struct JSON_Generator_StateStruct {
|
|
19
13
|
VALUE indent;
|
|
20
14
|
VALUE space;
|
|
@@ -27,20 +21,20 @@ typedef struct JSON_Generator_StateStruct {
|
|
|
27
21
|
long depth;
|
|
28
22
|
long buffer_initial_length;
|
|
29
23
|
|
|
30
|
-
|
|
31
|
-
|
|
24
|
+
bool allow_duplicate_key;
|
|
32
25
|
bool as_json_single_arg;
|
|
33
26
|
bool allow_nan;
|
|
34
27
|
bool ascii_only;
|
|
35
28
|
bool script_safe;
|
|
36
29
|
bool strict;
|
|
30
|
+
VALUE sort_keys;
|
|
37
31
|
} JSON_Generator_State;
|
|
38
32
|
|
|
39
|
-
static VALUE mJSON, cState, cFragment, eGeneratorError, eNestingError, Encoding_UTF_8;
|
|
33
|
+
static VALUE mJSON, cState, cFragment, eGeneratorError, eNestingError, Encoding_UTF_8, default_sort_keys_proc;
|
|
40
34
|
|
|
41
35
|
static ID i_to_s, i_to_json, i_new, i_encode;
|
|
42
36
|
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
|
-
sym_ascii_only, sym_depth, sym_buffer_initial_length, sym_script_safe,
|
|
37
|
+
sym_ascii_only, sym_depth, sym_buffer_initial_length, sym_script_safe, sym_strict, sym_as_json, sym_sort_keys;
|
|
44
38
|
|
|
45
39
|
|
|
46
40
|
#define GET_STATE_TO(self, state) \
|
|
@@ -74,9 +68,6 @@ static void generate_json_string(FBuffer *buffer, struct generate_json_data *dat
|
|
|
74
68
|
static void generate_json_null(FBuffer *buffer, struct generate_json_data *data, VALUE obj);
|
|
75
69
|
static void generate_json_false(FBuffer *buffer, struct generate_json_data *data, VALUE obj);
|
|
76
70
|
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
71
|
static void generate_json_fixnum(FBuffer *buffer, struct generate_json_data *data, VALUE obj);
|
|
81
72
|
static void generate_json_bignum(FBuffer *buffer, struct generate_json_data *data, VALUE obj);
|
|
82
73
|
static void generate_json_float(FBuffer *buffer, struct generate_json_data *data, VALUE obj);
|
|
@@ -703,233 +694,6 @@ static void convert_UTF8_to_ASCII_only_JSON(search_state *search, const unsigned
|
|
|
703
694
|
}
|
|
704
695
|
}
|
|
705
696
|
|
|
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
697
|
static void State_mark(void *ptr)
|
|
934
698
|
{
|
|
935
699
|
JSON_Generator_State *state = ptr;
|
|
@@ -939,6 +703,7 @@ static void State_mark(void *ptr)
|
|
|
939
703
|
rb_gc_mark_movable(state->object_nl);
|
|
940
704
|
rb_gc_mark_movable(state->array_nl);
|
|
941
705
|
rb_gc_mark_movable(state->as_json);
|
|
706
|
+
rb_gc_mark_movable(state->sort_keys);
|
|
942
707
|
}
|
|
943
708
|
|
|
944
709
|
static void State_compact(void *ptr)
|
|
@@ -950,29 +715,27 @@ static void State_compact(void *ptr)
|
|
|
950
715
|
state->object_nl = rb_gc_location(state->object_nl);
|
|
951
716
|
state->array_nl = rb_gc_location(state->array_nl);
|
|
952
717
|
state->as_json = rb_gc_location(state->as_json);
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
static void State_free(void *ptr)
|
|
956
|
-
{
|
|
957
|
-
JSON_Generator_State *state = ptr;
|
|
958
|
-
ruby_xfree(state);
|
|
718
|
+
state->sort_keys = rb_gc_location(state->sort_keys);
|
|
959
719
|
}
|
|
960
720
|
|
|
961
721
|
static size_t State_memsize(const void *ptr)
|
|
962
722
|
{
|
|
723
|
+
#ifdef HAVE_RUBY_TYPED_EMBEDDABLE
|
|
724
|
+
return 0;
|
|
725
|
+
#else
|
|
963
726
|
return sizeof(JSON_Generator_State);
|
|
727
|
+
#endif
|
|
964
728
|
}
|
|
965
729
|
|
|
966
730
|
static const rb_data_type_t JSON_Generator_State_type = {
|
|
967
|
-
"JSON/Generator/State",
|
|
968
|
-
{
|
|
731
|
+
.wrap_struct_name = "JSON/Generator/State",
|
|
732
|
+
.function = {
|
|
969
733
|
.dmark = State_mark,
|
|
970
|
-
.dfree =
|
|
734
|
+
.dfree = RUBY_DEFAULT_FREE,
|
|
971
735
|
.dsize = State_memsize,
|
|
972
736
|
.dcompact = State_compact,
|
|
973
737
|
},
|
|
974
|
-
|
|
975
|
-
RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_FROZEN_SHAREABLE,
|
|
738
|
+
.flags = RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_THREAD_SAFE_FREE | RUBY_TYPED_FROZEN_SHAREABLE | RUBY_TYPED_EMBEDDABLE,
|
|
976
739
|
};
|
|
977
740
|
|
|
978
741
|
static void state_init(JSON_Generator_State *state)
|
|
@@ -1002,6 +765,7 @@ static void vstate_spill(struct generate_json_data *data)
|
|
|
1002
765
|
RB_OBJ_WRITTEN(vstate, Qundef, state->object_nl);
|
|
1003
766
|
RB_OBJ_WRITTEN(vstate, Qundef, state->array_nl);
|
|
1004
767
|
RB_OBJ_WRITTEN(vstate, Qundef, state->as_json);
|
|
768
|
+
RB_OBJ_WRITTEN(vstate, Qundef, state->sort_keys);
|
|
1005
769
|
}
|
|
1006
770
|
|
|
1007
771
|
static inline VALUE json_call_to_json(struct generate_json_data *data, VALUE obj)
|
|
@@ -1056,9 +820,17 @@ static VALUE encode_json_string_rescue(VALUE str, VALUE exception)
|
|
|
1056
820
|
return Qundef;
|
|
1057
821
|
}
|
|
1058
822
|
|
|
823
|
+
static inline int json_str_coderange(VALUE str) {
|
|
824
|
+
int coderange = RB_ENC_CODERANGE(str);
|
|
825
|
+
if (coderange == RUBY_ENC_CODERANGE_UNKNOWN) {
|
|
826
|
+
coderange = rb_enc_str_coderange(str);
|
|
827
|
+
}
|
|
828
|
+
return coderange;
|
|
829
|
+
}
|
|
830
|
+
|
|
1059
831
|
static inline bool valid_json_string_p(VALUE str)
|
|
1060
832
|
{
|
|
1061
|
-
int coderange =
|
|
833
|
+
int coderange = json_str_coderange(str);
|
|
1062
834
|
|
|
1063
835
|
if (RB_LIKELY(coderange == ENC_CODERANGE_7BIT)) {
|
|
1064
836
|
return true;
|
|
@@ -1071,12 +843,8 @@ static inline bool valid_json_string_p(VALUE str)
|
|
|
1071
843
|
return false;
|
|
1072
844
|
}
|
|
1073
845
|
|
|
1074
|
-
static
|
|
846
|
+
NOINLINE(static) VALUE convert_invalid_encoding(struct generate_json_data *data, VALUE str, bool as_json_called, bool is_key)
|
|
1075
847
|
{
|
|
1076
|
-
if (RB_LIKELY(valid_json_string_p(str))) {
|
|
1077
|
-
return str;
|
|
1078
|
-
}
|
|
1079
|
-
|
|
1080
848
|
if (!as_json_called && data->state->strict && RTEST(data->state->as_json)) {
|
|
1081
849
|
VALUE coerced_str = json_call_as_json(data->state, str, Qfalse);
|
|
1082
850
|
if (coerced_str != str) {
|
|
@@ -1112,6 +880,16 @@ static inline VALUE ensure_valid_encoding(struct generate_json_data *data, VALUE
|
|
|
1112
880
|
return rb_rescue(encode_json_string_try, str, encode_json_string_rescue, str);
|
|
1113
881
|
}
|
|
1114
882
|
|
|
883
|
+
ALWAYS_INLINE(static) VALUE ensure_valid_encoding(struct generate_json_data *data, VALUE str, bool as_json_called, bool is_key)
|
|
884
|
+
{
|
|
885
|
+
if (RB_LIKELY(valid_json_string_p(str))) {
|
|
886
|
+
return str;
|
|
887
|
+
}
|
|
888
|
+
else {
|
|
889
|
+
return convert_invalid_encoding(data, str, as_json_called, is_key);
|
|
890
|
+
}
|
|
891
|
+
}
|
|
892
|
+
|
|
1115
893
|
static void raw_generate_json_string(FBuffer *buffer, struct generate_json_data *data, VALUE obj)
|
|
1116
894
|
{
|
|
1117
895
|
fbuffer_append_char(buffer, '"');
|
|
@@ -1130,7 +908,7 @@ static void raw_generate_json_string(FBuffer *buffer, struct generate_json_data
|
|
|
1130
908
|
search.chunk_end = NULL;
|
|
1131
909
|
#endif /* HAVE_SIMD */
|
|
1132
910
|
|
|
1133
|
-
switch (
|
|
911
|
+
switch (json_str_coderange(obj)) {
|
|
1134
912
|
case ENC_CODERANGE_7BIT:
|
|
1135
913
|
case ENC_CODERANGE_VALID:
|
|
1136
914
|
if (RB_UNLIKELY(data->state->ascii_only)) {
|
|
@@ -1171,9 +949,8 @@ json_inspect_hash_with_mixed_keys(struct hash_foreach_arg *arg)
|
|
|
1171
949
|
arg->mixed_keys_encountered = true;
|
|
1172
950
|
|
|
1173
951
|
JSON_Generator_State *state = arg->data->state;
|
|
1174
|
-
if (state->
|
|
1175
|
-
|
|
1176
|
-
rb_funcall(mJSON, rb_intern("on_mixed_keys_hash"), 2, arg->hash, do_raise);
|
|
952
|
+
if (!state->allow_duplicate_key) {
|
|
953
|
+
rb_funcall(mJSON, rb_intern("on_mixed_keys_hash"), 1, arg->hash);
|
|
1177
954
|
}
|
|
1178
955
|
}
|
|
1179
956
|
|
|
@@ -1269,6 +1046,11 @@ static inline long increase_depth(struct generate_json_data *data)
|
|
|
1269
1046
|
|
|
1270
1047
|
static void generate_json_object(FBuffer *buffer, struct generate_json_data *data, VALUE obj)
|
|
1271
1048
|
{
|
|
1049
|
+
if (RB_UNLIKELY(data->state->sort_keys)) {
|
|
1050
|
+
obj = rb_proc_call_with_block(data->state->sort_keys, 1, &obj, Qnil);
|
|
1051
|
+
Check_Type(obj, T_HASH);
|
|
1052
|
+
}
|
|
1053
|
+
|
|
1272
1054
|
long depth = increase_depth(data);
|
|
1273
1055
|
|
|
1274
1056
|
if (RHASH_SIZE(obj) == 0) {
|
|
@@ -1342,15 +1124,6 @@ static void generate_json_fallback(FBuffer *buffer, struct generate_json_data *d
|
|
|
1342
1124
|
}
|
|
1343
1125
|
}
|
|
1344
1126
|
|
|
1345
|
-
static inline void generate_json_symbol(FBuffer *buffer, struct generate_json_data *data, VALUE obj)
|
|
1346
|
-
{
|
|
1347
|
-
if (data->state->strict) {
|
|
1348
|
-
generate_json_string(buffer, data, rb_sym2str(obj));
|
|
1349
|
-
} else {
|
|
1350
|
-
generate_json_fallback(buffer, data, obj);
|
|
1351
|
-
}
|
|
1352
|
-
}
|
|
1353
|
-
|
|
1354
1127
|
static void generate_json_null(FBuffer *buffer, struct generate_json_data *data, VALUE obj)
|
|
1355
1128
|
{
|
|
1356
1129
|
fbuffer_append(buffer, "null", 4);
|
|
@@ -1377,16 +1150,6 @@ static void generate_json_bignum(FBuffer *buffer, struct generate_json_data *dat
|
|
|
1377
1150
|
fbuffer_append_str(buffer, StringValue(tmp));
|
|
1378
1151
|
}
|
|
1379
1152
|
|
|
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
1153
|
static void generate_json_float(FBuffer *buffer, struct generate_json_data *data, VALUE obj)
|
|
1391
1154
|
{
|
|
1392
1155
|
double value = RFLOAT_VALUE(obj);
|
|
@@ -1430,7 +1193,7 @@ static void generate_json_fragment(FBuffer *buffer, struct generate_json_data *d
|
|
|
1430
1193
|
fbuffer_append_str(buffer, fragment);
|
|
1431
1194
|
}
|
|
1432
1195
|
|
|
1433
|
-
static void
|
|
1196
|
+
static inline void generate_json_general(FBuffer *buffer, struct generate_json_data *data, VALUE obj, bool fallback)
|
|
1434
1197
|
{
|
|
1435
1198
|
bool as_json_called = false;
|
|
1436
1199
|
start:
|
|
@@ -1446,7 +1209,13 @@ start:
|
|
|
1446
1209
|
} else if (RB_FLONUM_P(obj)) {
|
|
1447
1210
|
generate_json_float(buffer, data, obj);
|
|
1448
1211
|
} else if (RB_STATIC_SYM_P(obj)) {
|
|
1449
|
-
|
|
1212
|
+
if (data->state->strict) {
|
|
1213
|
+
obj = rb_sym2str(obj);
|
|
1214
|
+
JSON_ASSERT(RBASIC_CLASS(obj) == rb_cString);
|
|
1215
|
+
goto generate_string;
|
|
1216
|
+
}
|
|
1217
|
+
|
|
1218
|
+
generate_json_fallback(buffer, data, obj);
|
|
1450
1219
|
} else {
|
|
1451
1220
|
goto general;
|
|
1452
1221
|
}
|
|
@@ -1457,16 +1226,17 @@ start:
|
|
|
1457
1226
|
generate_json_bignum(buffer, data, obj);
|
|
1458
1227
|
break;
|
|
1459
1228
|
case T_HASH:
|
|
1460
|
-
if (klass != rb_cHash) goto general;
|
|
1229
|
+
if (fallback && klass != rb_cHash) goto general;
|
|
1461
1230
|
generate_json_object(buffer, data, obj);
|
|
1462
1231
|
break;
|
|
1463
1232
|
case T_ARRAY:
|
|
1464
|
-
if (klass != rb_cArray) goto general;
|
|
1233
|
+
if (fallback && klass != rb_cArray) goto general;
|
|
1465
1234
|
generate_json_array(buffer, data, obj);
|
|
1466
1235
|
break;
|
|
1467
1236
|
case T_STRING:
|
|
1468
|
-
if (klass != rb_cString) goto general;
|
|
1237
|
+
if (fallback && klass != rb_cString) goto general;
|
|
1469
1238
|
|
|
1239
|
+
generate_string:
|
|
1470
1240
|
if (RB_LIKELY(valid_json_string_p(obj))) {
|
|
1471
1241
|
raw_generate_json_string(buffer, data, obj);
|
|
1472
1242
|
} else if (as_json_called) {
|
|
@@ -1478,10 +1248,16 @@ start:
|
|
|
1478
1248
|
}
|
|
1479
1249
|
break;
|
|
1480
1250
|
case T_SYMBOL:
|
|
1481
|
-
|
|
1251
|
+
if (data->state->strict) {
|
|
1252
|
+
obj = rb_sym2str(obj);
|
|
1253
|
+
JSON_ASSERT(RBASIC_CLASS(obj) == rb_cString);
|
|
1254
|
+
goto generate_string;
|
|
1255
|
+
}
|
|
1256
|
+
|
|
1257
|
+
generate_json_fallback(buffer, data, obj);
|
|
1482
1258
|
break;
|
|
1483
1259
|
case T_FLOAT:
|
|
1484
|
-
if (klass != rb_cFloat) goto general;
|
|
1260
|
+
if (fallback && klass != rb_cFloat) goto general;
|
|
1485
1261
|
generate_json_float(buffer, data, obj);
|
|
1486
1262
|
break;
|
|
1487
1263
|
case T_STRUCT:
|
|
@@ -1505,6 +1281,16 @@ start:
|
|
|
1505
1281
|
}
|
|
1506
1282
|
}
|
|
1507
1283
|
|
|
1284
|
+
static void generate_json(FBuffer *buffer, struct generate_json_data *data, VALUE obj)
|
|
1285
|
+
{
|
|
1286
|
+
generate_json_general(buffer, data, obj, true);
|
|
1287
|
+
}
|
|
1288
|
+
|
|
1289
|
+
static void generate_json_no_fallback(FBuffer *buffer, struct generate_json_data *data, VALUE obj)
|
|
1290
|
+
{
|
|
1291
|
+
generate_json_general(buffer, data, obj, false);
|
|
1292
|
+
}
|
|
1293
|
+
|
|
1508
1294
|
static VALUE generate_json_try(VALUE d)
|
|
1509
1295
|
{
|
|
1510
1296
|
struct generate_json_data *data = (struct generate_json_data *)d;
|
|
@@ -1522,15 +1308,13 @@ static VALUE generate_json_ensure(VALUE d)
|
|
|
1522
1308
|
return Qundef;
|
|
1523
1309
|
}
|
|
1524
1310
|
|
|
1525
|
-
static VALUE cState_partial_generate(VALUE self, VALUE obj, generator_func func, VALUE io)
|
|
1311
|
+
static inline VALUE cState_partial_generate(VALUE self, VALUE obj, generator_func func, VALUE io)
|
|
1526
1312
|
{
|
|
1527
1313
|
GET_STATE(self);
|
|
1528
1314
|
|
|
1529
1315
|
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);
|
|
1316
|
+
FBuffer buffer = { 0 };
|
|
1317
|
+
fbuffer_init(&buffer, state->buffer_initial_length, io, stack_buffer, FBUFFER_STACK_SIZE);
|
|
1534
1318
|
|
|
1535
1319
|
struct generate_json_data data = {
|
|
1536
1320
|
.buffer = &buffer,
|
|
@@ -1540,9 +1324,7 @@ static VALUE cState_partial_generate(VALUE self, VALUE obj, generator_func func,
|
|
|
1540
1324
|
.obj = obj,
|
|
1541
1325
|
.func = func
|
|
1542
1326
|
};
|
|
1543
|
-
|
|
1544
|
-
RB_GC_GUARD(self);
|
|
1545
|
-
return result;
|
|
1327
|
+
return rb_ensure(generate_json_try, (VALUE)&data, generate_json_ensure, (VALUE)&data);
|
|
1546
1328
|
}
|
|
1547
1329
|
|
|
1548
1330
|
/* call-seq:
|
|
@@ -1561,6 +1343,15 @@ static VALUE cState_generate(int argc, VALUE *argv, VALUE self)
|
|
|
1561
1343
|
return cState_partial_generate(self, obj, generate_json, io);
|
|
1562
1344
|
}
|
|
1563
1345
|
|
|
1346
|
+
/* :nodoc: */
|
|
1347
|
+
static VALUE cState_generate_no_fallback(int argc, VALUE *argv, VALUE self)
|
|
1348
|
+
{
|
|
1349
|
+
rb_check_arity(argc, 1, 2);
|
|
1350
|
+
VALUE obj = argv[0];
|
|
1351
|
+
VALUE io = argc > 1 ? argv[1] : Qnil;
|
|
1352
|
+
return cState_partial_generate(self, obj, generate_json_no_fallback, io);
|
|
1353
|
+
}
|
|
1354
|
+
|
|
1564
1355
|
static VALUE cState_initialize(int argc, VALUE *argv, VALUE self)
|
|
1565
1356
|
{
|
|
1566
1357
|
rb_warn("The json gem extension was loaded with the stdlib ruby code. You should upgrade rubygems with `gem update --system`");
|
|
@@ -1583,12 +1374,15 @@ static VALUE cState_init_copy(VALUE obj, VALUE orig)
|
|
|
1583
1374
|
if (!objState) rb_raise(rb_eArgError, "unallocated JSON::State");
|
|
1584
1375
|
|
|
1585
1376
|
MEMCPY(objState, origState, JSON_Generator_State, 1);
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1377
|
+
|
|
1378
|
+
RB_OBJ_WRITTEN(obj, Qundef, objState->indent);
|
|
1379
|
+
RB_OBJ_WRITTEN(obj, Qundef, objState->space);
|
|
1380
|
+
RB_OBJ_WRITTEN(obj, Qundef, objState->space_before);
|
|
1381
|
+
RB_OBJ_WRITTEN(obj, Qundef, objState->object_nl);
|
|
1382
|
+
RB_OBJ_WRITTEN(obj, Qundef, objState->array_nl);
|
|
1383
|
+
RB_OBJ_WRITTEN(obj, Qundef, objState->as_json);
|
|
1384
|
+
RB_OBJ_WRITTEN(obj, Qundef, objState->sort_keys);
|
|
1385
|
+
|
|
1592
1386
|
return obj;
|
|
1593
1387
|
}
|
|
1594
1388
|
|
|
@@ -1795,7 +1589,21 @@ static VALUE cState_max_nesting(VALUE self)
|
|
|
1795
1589
|
|
|
1796
1590
|
static long long_config(VALUE num)
|
|
1797
1591
|
{
|
|
1798
|
-
return RTEST(num) ?
|
|
1592
|
+
return RTEST(num) ? NUM2LONG(num) : 0;
|
|
1593
|
+
}
|
|
1594
|
+
|
|
1595
|
+
// depth must never be negative; reject early with a clear error.
|
|
1596
|
+
static long depth_config(VALUE num)
|
|
1597
|
+
{
|
|
1598
|
+
if (!RTEST(num)) return 0;
|
|
1599
|
+
long d = NUM2LONG(num);
|
|
1600
|
+
if (RB_UNLIKELY(d < 0)) {
|
|
1601
|
+
rb_raise(rb_eArgError, "depth must be >= 0 (got %ld)", d);
|
|
1602
|
+
}
|
|
1603
|
+
if (RB_UNLIKELY(d > INT_MAX)) {
|
|
1604
|
+
rb_raise(rb_eArgError, "depth is too large (got %ld)", d);
|
|
1605
|
+
}
|
|
1606
|
+
return d;
|
|
1799
1607
|
}
|
|
1800
1608
|
|
|
1801
1609
|
/*
|
|
@@ -1920,17 +1728,59 @@ static VALUE cState_ascii_only_set(VALUE self, VALUE enable)
|
|
|
1920
1728
|
return Qnil;
|
|
1921
1729
|
}
|
|
1922
1730
|
|
|
1731
|
+
static VALUE cState_set_default_sort_keys_proc(VALUE self, VALUE proc)
|
|
1732
|
+
{
|
|
1733
|
+
if (!rb_obj_is_proc(proc)) {
|
|
1734
|
+
rb_raise(rb_eTypeError, "sort_key_proc must be a Proc");
|
|
1735
|
+
}
|
|
1736
|
+
return default_sort_keys_proc = proc;
|
|
1737
|
+
}
|
|
1738
|
+
|
|
1739
|
+
static VALUE normalize_sort_keys(VALUE value)
|
|
1740
|
+
{
|
|
1741
|
+
if (rb_obj_is_proc(value)) {
|
|
1742
|
+
return value;
|
|
1743
|
+
} else if (value == Qtrue) {
|
|
1744
|
+
return default_sort_keys_proc;
|
|
1745
|
+
} else if (RTEST(value)) {
|
|
1746
|
+
rb_raise(rb_eTypeError, "The `sort_keys` argument must be a boolean or a Proc");
|
|
1747
|
+
} else {
|
|
1748
|
+
return Qfalse;
|
|
1749
|
+
}
|
|
1750
|
+
}
|
|
1751
|
+
|
|
1752
|
+
/*
|
|
1753
|
+
* call-seq: sort_keys
|
|
1754
|
+
*
|
|
1755
|
+
* Get the value of sort_keys.
|
|
1756
|
+
*/
|
|
1757
|
+
static VALUE cState_sort_keys_p(VALUE self)
|
|
1758
|
+
{
|
|
1759
|
+
GET_STATE(self);
|
|
1760
|
+
return state->sort_keys;
|
|
1761
|
+
}
|
|
1762
|
+
|
|
1763
|
+
/*
|
|
1764
|
+
* call-seq: sort_keys=(value)
|
|
1765
|
+
*
|
|
1766
|
+
* value is a boolean or a proc. If the value is the boolean true, object keys
|
|
1767
|
+
* will be sorted lexicographically in ascending order.
|
|
1768
|
+
*
|
|
1769
|
+
* If the value is a proc, it receives the entire Hash and must return a Hash
|
|
1770
|
+
* with its pairs in the desired order, allowing for arbitrary sorting.
|
|
1771
|
+
*/
|
|
1772
|
+
static VALUE cState_sort_keys_set(VALUE self, VALUE value)
|
|
1773
|
+
{
|
|
1774
|
+
rb_check_frozen(self);
|
|
1775
|
+
GET_STATE(self);
|
|
1776
|
+
RB_OBJ_WRITE(self, &state->sort_keys, normalize_sort_keys(value));
|
|
1777
|
+
return Qnil;
|
|
1778
|
+
}
|
|
1779
|
+
|
|
1923
1780
|
static VALUE cState_allow_duplicate_key_p(VALUE self)
|
|
1924
1781
|
{
|
|
1925
1782
|
GET_STATE(self);
|
|
1926
|
-
|
|
1927
|
-
case JSON_IGNORE:
|
|
1928
|
-
return Qtrue;
|
|
1929
|
-
case JSON_DEPRECATED:
|
|
1930
|
-
return Qnil;
|
|
1931
|
-
default:
|
|
1932
|
-
return Qfalse;
|
|
1933
|
-
}
|
|
1783
|
+
return state->allow_duplicate_key ? Qtrue : Qfalse;
|
|
1934
1784
|
}
|
|
1935
1785
|
|
|
1936
1786
|
/*
|
|
@@ -1954,7 +1804,7 @@ static VALUE cState_depth_set(VALUE self, VALUE depth)
|
|
|
1954
1804
|
{
|
|
1955
1805
|
rb_check_frozen(self);
|
|
1956
1806
|
GET_STATE(self);
|
|
1957
|
-
state->depth =
|
|
1807
|
+
state->depth = depth_config(depth);
|
|
1958
1808
|
return Qnil;
|
|
1959
1809
|
}
|
|
1960
1810
|
|
|
@@ -1995,6 +1845,7 @@ static VALUE cState_buffer_initial_length_set(VALUE self, VALUE buffer_initial_l
|
|
|
1995
1845
|
struct configure_state_data {
|
|
1996
1846
|
JSON_Generator_State *state;
|
|
1997
1847
|
VALUE vstate; // Ruby object that owns the state, or Qfalse if stack-allocated
|
|
1848
|
+
VALUE unknown_keywords;
|
|
1998
1849
|
};
|
|
1999
1850
|
|
|
2000
1851
|
static inline void state_write_value(struct configure_state_data *data, VALUE *field, VALUE value)
|
|
@@ -2019,17 +1870,25 @@ static int configure_state_i(VALUE key, VALUE val, VALUE _arg)
|
|
|
2019
1870
|
else if (key == sym_max_nesting) { state->max_nesting = long_config(val); }
|
|
2020
1871
|
else if (key == sym_allow_nan) { state->allow_nan = RTEST(val); }
|
|
2021
1872
|
else if (key == sym_ascii_only) { state->ascii_only = RTEST(val); }
|
|
2022
|
-
else if (key == sym_depth) { state->depth =
|
|
1873
|
+
else if (key == sym_depth) { state->depth = depth_config(val); }
|
|
2023
1874
|
else if (key == sym_buffer_initial_length) { buffer_initial_length_set(state, val); }
|
|
2024
1875
|
else if (key == sym_script_safe) { state->script_safe = RTEST(val); }
|
|
2025
|
-
else if (key == sym_escape_slash) { state->script_safe = RTEST(val); }
|
|
2026
1876
|
else if (key == sym_strict) { state->strict = RTEST(val); }
|
|
2027
|
-
else if (key == sym_allow_duplicate_key) { state->
|
|
1877
|
+
else if (key == sym_allow_duplicate_key) { state->allow_duplicate_key = RTEST(val); }
|
|
2028
1878
|
else if (key == sym_as_json) {
|
|
2029
1879
|
VALUE proc = RTEST(val) ? rb_convert_type(val, T_DATA, "Proc", "to_proc") : Qfalse;
|
|
2030
1880
|
state->as_json_single_arg = proc && rb_proc_arity(proc) == 1;
|
|
2031
1881
|
state_write_value(data, &state->as_json, proc);
|
|
2032
1882
|
}
|
|
1883
|
+
else if (key == sym_sort_keys) {
|
|
1884
|
+
state_write_value(data, &state->sort_keys, normalize_sort_keys(val));
|
|
1885
|
+
}
|
|
1886
|
+
else {
|
|
1887
|
+
if (!data->unknown_keywords) {
|
|
1888
|
+
data->unknown_keywords = rb_obj_hide(rb_ary_new());
|
|
1889
|
+
}
|
|
1890
|
+
rb_ary_push(data->unknown_keywords, key);
|
|
1891
|
+
}
|
|
2033
1892
|
return ST_CONTINUE;
|
|
2034
1893
|
}
|
|
2035
1894
|
|
|
@@ -2043,12 +1902,15 @@ static void configure_state(JSON_Generator_State *state, VALUE vstate, VALUE con
|
|
|
2043
1902
|
|
|
2044
1903
|
struct configure_state_data data = {
|
|
2045
1904
|
.state = state,
|
|
2046
|
-
.vstate = vstate
|
|
1905
|
+
.vstate = vstate,
|
|
1906
|
+
.unknown_keywords = Qfalse,
|
|
2047
1907
|
};
|
|
2048
1908
|
|
|
2049
1909
|
// We assume in most cases few keys are set so it's faster to go over
|
|
2050
1910
|
// the provided keys than to check all possible keys.
|
|
2051
1911
|
rb_hash_foreach(config, configure_state_i, (VALUE)&data);
|
|
1912
|
+
|
|
1913
|
+
raise_argument_error_on_unknown_keywords(data.unknown_keywords);
|
|
2052
1914
|
}
|
|
2053
1915
|
|
|
2054
1916
|
static VALUE cState_configure(VALUE self, VALUE opts)
|
|
@@ -2059,17 +1921,15 @@ static VALUE cState_configure(VALUE self, VALUE opts)
|
|
|
2059
1921
|
return self;
|
|
2060
1922
|
}
|
|
2061
1923
|
|
|
2062
|
-
static VALUE
|
|
1924
|
+
static VALUE cState_m_do_generate(VALUE klass, VALUE obj, VALUE opts, VALUE io, generator_func func)
|
|
2063
1925
|
{
|
|
2064
1926
|
JSON_Generator_State state = {0};
|
|
2065
1927
|
state_init(&state);
|
|
2066
1928
|
configure_state(&state, Qfalse, opts);
|
|
2067
1929
|
|
|
2068
1930
|
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);
|
|
1931
|
+
FBuffer buffer = { 0 };
|
|
1932
|
+
fbuffer_init(&buffer, state.buffer_initial_length, io, stack_buffer, FBUFFER_STACK_SIZE);
|
|
2073
1933
|
|
|
2074
1934
|
struct generate_json_data data = {
|
|
2075
1935
|
.buffer = &buffer,
|
|
@@ -2077,14 +1937,21 @@ static VALUE cState_m_generate(VALUE klass, VALUE obj, VALUE opts, VALUE io)
|
|
|
2077
1937
|
.state = &state,
|
|
2078
1938
|
.depth = state.depth,
|
|
2079
1939
|
.obj = obj,
|
|
2080
|
-
.func =
|
|
1940
|
+
.func = func,
|
|
2081
1941
|
};
|
|
2082
1942
|
return rb_ensure(generate_json_try, (VALUE)&data, generate_json_ensure, (VALUE)&data);
|
|
2083
1943
|
}
|
|
2084
1944
|
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
1945
|
+
static VALUE cState_m_generate(VALUE klass, VALUE obj, VALUE opts, VALUE io)
|
|
1946
|
+
{
|
|
1947
|
+
return cState_m_do_generate(klass, obj, opts, io, generate_json);
|
|
1948
|
+
}
|
|
1949
|
+
|
|
1950
|
+
static VALUE cState_m_generate_no_fallback(VALUE klass, VALUE obj, VALUE opts, VALUE io)
|
|
1951
|
+
{
|
|
1952
|
+
return cState_m_do_generate(klass, obj, opts, io, generate_json_no_fallback);
|
|
1953
|
+
}
|
|
1954
|
+
|
|
2088
1955
|
void Init_generator(void)
|
|
2089
1956
|
{
|
|
2090
1957
|
#ifdef HAVE_RB_EXT_RACTOR_SAFE
|
|
@@ -2102,6 +1969,8 @@ void Init_generator(void)
|
|
|
2102
1969
|
VALUE mExt = rb_define_module_under(mJSON, "Ext");
|
|
2103
1970
|
VALUE mGenerator = rb_define_module_under(mExt, "Generator");
|
|
2104
1971
|
|
|
1972
|
+
rb_global_variable(&default_sort_keys_proc);
|
|
1973
|
+
|
|
2105
1974
|
rb_global_variable(&eGeneratorError);
|
|
2106
1975
|
eGeneratorError = rb_path2class("JSON::GeneratorError");
|
|
2107
1976
|
|
|
@@ -2111,6 +1980,8 @@ void Init_generator(void)
|
|
|
2111
1980
|
cState = rb_define_class_under(mGenerator, "State", rb_cObject);
|
|
2112
1981
|
rb_define_alloc_func(cState, cState_s_allocate);
|
|
2113
1982
|
rb_define_singleton_method(cState, "from_state", cState_from_state_s, 1);
|
|
1983
|
+
rb_define_singleton_method(cState, "default_sort_keys_proc=", cState_set_default_sort_keys_proc, 1);
|
|
1984
|
+
|
|
2114
1985
|
rb_define_method(cState, "initialize", cState_initialize, -1);
|
|
2115
1986
|
rb_define_alias(cState, "initialize", "initialize"); // avoid method redefinition warnings
|
|
2116
1987
|
rb_define_private_method(cState, "_configure", cState_configure, 1);
|
|
@@ -2133,9 +2004,6 @@ void Init_generator(void)
|
|
|
2133
2004
|
rb_define_method(cState, "script_safe", cState_script_safe, 0);
|
|
2134
2005
|
rb_define_method(cState, "script_safe?", cState_script_safe, 0);
|
|
2135
2006
|
rb_define_method(cState, "script_safe=", cState_script_safe_set, 1);
|
|
2136
|
-
rb_define_alias(cState, "escape_slash", "script_safe");
|
|
2137
|
-
rb_define_alias(cState, "escape_slash?", "script_safe?");
|
|
2138
|
-
rb_define_alias(cState, "escape_slash=", "script_safe=");
|
|
2139
2007
|
rb_define_method(cState, "strict", cState_strict, 0);
|
|
2140
2008
|
rb_define_method(cState, "strict?", cState_strict, 0);
|
|
2141
2009
|
rb_define_method(cState, "strict=", cState_strict_set, 1);
|
|
@@ -2149,46 +2017,14 @@ void Init_generator(void)
|
|
|
2149
2017
|
rb_define_method(cState, "buffer_initial_length", cState_buffer_initial_length, 0);
|
|
2150
2018
|
rb_define_method(cState, "buffer_initial_length=", cState_buffer_initial_length_set, 1);
|
|
2151
2019
|
rb_define_method(cState, "generate", cState_generate, -1);
|
|
2020
|
+
rb_define_method(cState, "_generate_no_fallback", cState_generate_no_fallback, -1);
|
|
2021
|
+
rb_define_method(cState, "sort_keys", cState_sort_keys_p, 0);
|
|
2022
|
+
rb_define_method(cState, "sort_keys=", cState_sort_keys_set, 1);
|
|
2152
2023
|
|
|
2153
2024
|
rb_define_private_method(cState, "allow_duplicate_key?", cState_allow_duplicate_key_p, 0);
|
|
2154
2025
|
|
|
2155
2026
|
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);
|
|
2027
|
+
rb_define_singleton_method(cState, "_generate_no_fallback", cState_m_generate_no_fallback, 3);
|
|
2192
2028
|
|
|
2193
2029
|
rb_global_variable(&Encoding_UTF_8);
|
|
2194
2030
|
Encoding_UTF_8 = rb_const_get(rb_path2class("Encoding"), rb_intern("UTF_8"));
|
|
@@ -2209,10 +2045,10 @@ void Init_generator(void)
|
|
|
2209
2045
|
sym_depth = ID2SYM(rb_intern("depth"));
|
|
2210
2046
|
sym_buffer_initial_length = ID2SYM(rb_intern("buffer_initial_length"));
|
|
2211
2047
|
sym_script_safe = ID2SYM(rb_intern("script_safe"));
|
|
2212
|
-
sym_escape_slash = ID2SYM(rb_intern("escape_slash"));
|
|
2213
2048
|
sym_strict = ID2SYM(rb_intern("strict"));
|
|
2214
2049
|
sym_as_json = ID2SYM(rb_intern("as_json"));
|
|
2215
2050
|
sym_allow_duplicate_key = ID2SYM(rb_intern("allow_duplicate_key"));
|
|
2051
|
+
sym_sort_keys = ID2SYM(rb_intern("sort_keys"));
|
|
2216
2052
|
|
|
2217
2053
|
usascii_encindex = rb_usascii_encindex();
|
|
2218
2054
|
utf8_encindex = rb_utf8_encindex();
|