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.
@@ -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
- enum duplicate_key_action on_duplicate_key;
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, sym_escape_slash, sym_strict, sym_as_json;
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 = State_free,
734
+ .dfree = RUBY_DEFAULT_FREE,
971
735
  .dsize = State_memsize,
972
736
  .dcompact = State_compact,
973
737
  },
974
- 0, 0,
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 = rb_enc_str_coderange(str);
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 inline VALUE ensure_valid_encoding(struct generate_json_data *data, VALUE str, bool as_json_called, bool is_key)
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 (rb_enc_str_coderange(obj)) {
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->on_duplicate_key != JSON_IGNORE) {
1175
- VALUE do_raise = state->on_duplicate_key == JSON_RAISE ? Qtrue : Qfalse;
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 generate_json(FBuffer *buffer, struct generate_json_data *data, VALUE obj)
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
- generate_json_symbol(buffer, data, obj);
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
- generate_json_symbol(buffer, data, obj);
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
- .io = RTEST(io) ? io : Qfalse,
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
- VALUE result = rb_ensure(generate_json_try, (VALUE)&data, generate_json_ensure, (VALUE)&data);
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
- objState->indent = origState->indent;
1587
- objState->space = origState->space;
1588
- objState->space_before = origState->space_before;
1589
- objState->object_nl = origState->object_nl;
1590
- objState->array_nl = origState->array_nl;
1591
- objState->as_json = origState->as_json;
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) ? FIX2LONG(num) : 0;
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
- switch (state->on_duplicate_key) {
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 = long_config(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 = long_config(val); }
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->on_duplicate_key = RTEST(val) ? JSON_IGNORE : JSON_RAISE; }
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 cState_m_generate(VALUE klass, VALUE obj, VALUE opts, VALUE io)
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
- .io = RTEST(io) ? io : Qfalse,
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 = generate_json,
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();