json 2.10.2 → 2.11.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -31,28 +31,15 @@ typedef unsigned char _Bool;
31
31
  static VALUE mJSON, eNestingError, Encoding_UTF_8;
32
32
  static VALUE CNaN, CInfinity, CMinusInfinity;
33
33
 
34
- static ID i_json_creatable_p, i_json_create, i_create_id,
35
- i_chr, i_deep_const_get, i_match, i_aset, i_aref,
34
+ static ID i_chr, i_aset, i_aref,
36
35
  i_leftshift, i_new, i_try_convert, i_uminus, i_encode;
37
36
 
38
37
  static VALUE sym_max_nesting, sym_allow_nan, sym_allow_trailing_comma, sym_symbolize_names, sym_freeze,
39
- sym_create_additions, sym_create_id, sym_object_class, sym_array_class,
40
- sym_decimal_class, sym_match_string;
38
+ sym_decimal_class, sym_on_load;
41
39
 
42
40
  static int binary_encindex;
43
41
  static int utf8_encindex;
44
42
 
45
- #ifdef HAVE_RB_CATEGORY_WARN
46
- # define json_deprecated(message) rb_category_warn(RB_WARN_CATEGORY_DEPRECATED, message)
47
- #else
48
- # define json_deprecated(message) rb_warn(message)
49
- #endif
50
-
51
- static const char deprecated_create_additions_warning[] =
52
- "JSON.load implicit support for `create_additions: true` is deprecated "
53
- "and will be removed in 3.0, use JSON.unsafe_load or explicitly "
54
- "pass `create_additions: true`";
55
-
56
43
  #ifndef HAVE_RB_HASH_BULK_INSERT
57
44
  // For TruffleRuby
58
45
  void
@@ -444,20 +431,15 @@ static int convert_UTF32_to_UTF8(char *buf, uint32_t ch)
444
431
  }
445
432
 
446
433
  typedef struct JSON_ParserStruct {
447
- VALUE create_id;
448
- VALUE object_class;
449
- VALUE array_class;
434
+ VALUE on_load_proc;
450
435
  VALUE decimal_class;
451
436
  ID decimal_method_id;
452
- VALUE match_string;
453
437
  int max_nesting;
454
438
  bool allow_nan;
455
439
  bool allow_trailing_comma;
456
440
  bool parsing_name;
457
441
  bool symbolize_names;
458
442
  bool freeze;
459
- bool create_additions;
460
- bool deprecated_create_additions;
461
443
  } JSON_ParserConfig;
462
444
 
463
445
  typedef struct JSON_ParserStateStruct {
@@ -769,18 +751,7 @@ static VALUE json_decode_float(JSON_ParserConfig *config, const char *start, con
769
751
 
770
752
  static inline VALUE json_decode_array(JSON_ParserState *state, JSON_ParserConfig *config, long count)
771
753
  {
772
- VALUE array;
773
- if (RB_UNLIKELY(config->array_class)) {
774
- array = rb_class_new_instance(0, 0, config->array_class);
775
- VALUE *items = rvalue_stack_peek(state->stack, count);
776
- long index;
777
- for (index = 0; index < count; index++) {
778
- rb_funcall(array, i_leftshift, 1, items[index]);
779
- }
780
- } else {
781
- array = rb_ary_new_from_values(count, rvalue_stack_peek(state->stack, count));
782
- }
783
-
754
+ VALUE array = rb_ary_new_from_values(count, rvalue_stack_peek(state->stack, count));
784
755
  rvalue_stack_pop(state->stack, count);
785
756
 
786
757
  if (config->freeze) {
@@ -792,41 +763,11 @@ static inline VALUE json_decode_array(JSON_ParserState *state, JSON_ParserConfig
792
763
 
793
764
  static inline VALUE json_decode_object(JSON_ParserState *state, JSON_ParserConfig *config, long count)
794
765
  {
795
- VALUE object;
796
- if (RB_UNLIKELY(config->object_class)) {
797
- object = rb_class_new_instance(0, 0, config->object_class);
798
- long index = 0;
799
- VALUE *items = rvalue_stack_peek(state->stack, count);
800
- while (index < count) {
801
- VALUE name = items[index++];
802
- VALUE value = items[index++];
803
- rb_funcall(object, i_aset, 2, name, value);
804
- }
805
- } else {
806
- object = rb_hash_new_capa(count);
807
- rb_hash_bulk_insert(count, rvalue_stack_peek(state->stack, count), object);
808
- }
766
+ VALUE object = rb_hash_new_capa(count);
767
+ rb_hash_bulk_insert(count, rvalue_stack_peek(state->stack, count), object);
809
768
 
810
769
  rvalue_stack_pop(state->stack, count);
811
770
 
812
- if (RB_UNLIKELY(config->create_additions)) {
813
- VALUE klassname;
814
- if (config->object_class) {
815
- klassname = rb_funcall(object, i_aref, 1, config->create_id);
816
- } else {
817
- klassname = rb_hash_aref(object, config->create_id);
818
- }
819
- if (!NIL_P(klassname)) {
820
- VALUE klass = rb_funcall(mJSON, i_deep_const_get, 1, klassname);
821
- if (RTEST(rb_funcall(klass, i_json_creatable_p, 0))) {
822
- if (config->deprecated_create_additions) {
823
- json_deprecated(deprecated_create_additions_warning);
824
- }
825
- object = rb_funcall(klass, i_json_create, 1, object);
826
- }
827
- }
828
- }
829
-
830
771
  if (config->freeze) {
831
772
  RB_OBJ_FREEZE(object);
832
773
  }
@@ -834,17 +775,6 @@ static inline VALUE json_decode_object(JSON_ParserState *state, JSON_ParserConfi
834
775
  return object;
835
776
  }
836
777
 
837
- static int match_i(VALUE regexp, VALUE klass, VALUE memo)
838
- {
839
- if (regexp == Qundef) return ST_STOP;
840
- if (RTEST(rb_funcall(klass, i_json_creatable_p, 0)) &&
841
- RTEST(rb_funcall(regexp, i_match, 1, rb_ary_entry(memo, 0)))) {
842
- rb_ary_push(memo, klass);
843
- return ST_STOP;
844
- }
845
- return ST_CONTINUE;
846
- }
847
-
848
778
  static inline VALUE json_decode_string(JSON_ParserState *state, JSON_ParserConfig *config, const char *start, const char *end, bool escaped, bool is_name)
849
779
  {
850
780
  VALUE string;
@@ -856,21 +786,17 @@ static inline VALUE json_decode_string(JSON_ParserState *state, JSON_ParserConfi
856
786
  string = json_string_fastpath(state, start, end, is_name, intern, symbolize);
857
787
  }
858
788
 
859
- if (RB_UNLIKELY(config->create_additions && RTEST(config->match_string))) {
860
- VALUE klass;
861
- VALUE memo = rb_ary_new2(2);
862
- rb_ary_push(memo, string);
863
- rb_hash_foreach(config->match_string, match_i, memo);
864
- klass = rb_ary_entry(memo, 1);
865
- if (RTEST(klass)) {
866
- string = rb_funcall(klass, i_json_create, 1, string);
867
- }
868
- }
869
-
870
789
  return string;
871
790
  }
872
791
 
873
- #define PUSH(result) rvalue_stack_push(state->stack, result, &state->stack_handle, &state->stack)
792
+ static inline VALUE json_push_value(JSON_ParserState *state, JSON_ParserConfig *config, VALUE value)
793
+ {
794
+ if (RB_UNLIKELY(config->on_load_proc)) {
795
+ value = rb_proc_call_with_block(config->on_load_proc, 1, &value, Qnil);
796
+ }
797
+ rvalue_stack_push(state->stack, value, &state->stack_handle, &state->stack);
798
+ return value;
799
+ }
874
800
 
875
801
  static const bool string_scan[256] = {
876
802
  // ASCII Control Characters
@@ -897,7 +823,7 @@ static inline VALUE json_parse_string(JSON_ParserState *state, JSON_ParserConfig
897
823
  case '"': {
898
824
  VALUE string = json_decode_string(state, config, start, state->cursor, escaped, is_name);
899
825
  state->cursor++;
900
- return PUSH(string);
826
+ return json_push_value(state, config, string);
901
827
  }
902
828
  case '\\': {
903
829
  state->cursor++;
@@ -931,7 +857,7 @@ static VALUE json_parse_any(JSON_ParserState *state, JSON_ParserConfig *config)
931
857
  case 'n':
932
858
  if ((state->end - state->cursor >= 4) && (memcmp(state->cursor, "null", 4) == 0)) {
933
859
  state->cursor += 4;
934
- return PUSH(Qnil);
860
+ return json_push_value(state, config, Qnil);
935
861
  }
936
862
 
937
863
  raise_parse_error("unexpected token at '%s'", state->cursor);
@@ -939,7 +865,7 @@ static VALUE json_parse_any(JSON_ParserState *state, JSON_ParserConfig *config)
939
865
  case 't':
940
866
  if ((state->end - state->cursor >= 4) && (memcmp(state->cursor, "true", 4) == 0)) {
941
867
  state->cursor += 4;
942
- return PUSH(Qtrue);
868
+ return json_push_value(state, config, Qtrue);
943
869
  }
944
870
 
945
871
  raise_parse_error("unexpected token at '%s'", state->cursor);
@@ -948,7 +874,7 @@ static VALUE json_parse_any(JSON_ParserState *state, JSON_ParserConfig *config)
948
874
  // Note: memcmp with a small power of two compile to an integer comparison
949
875
  if ((state->end - state->cursor >= 5) && (memcmp(state->cursor + 1, "alse", 4) == 0)) {
950
876
  state->cursor += 5;
951
- return PUSH(Qfalse);
877
+ return json_push_value(state, config, Qfalse);
952
878
  }
953
879
 
954
880
  raise_parse_error("unexpected token at '%s'", state->cursor);
@@ -957,7 +883,7 @@ static VALUE json_parse_any(JSON_ParserState *state, JSON_ParserConfig *config)
957
883
  // Note: memcmp with a small power of two compile to an integer comparison
958
884
  if (config->allow_nan && (state->end - state->cursor >= 3) && (memcmp(state->cursor + 1, "aN", 2) == 0)) {
959
885
  state->cursor += 3;
960
- return PUSH(CNaN);
886
+ return json_push_value(state, config, CNaN);
961
887
  }
962
888
 
963
889
  raise_parse_error("unexpected token at '%s'", state->cursor);
@@ -965,7 +891,7 @@ static VALUE json_parse_any(JSON_ParserState *state, JSON_ParserConfig *config)
965
891
  case 'I':
966
892
  if (config->allow_nan && (state->end - state->cursor >= 8) && (memcmp(state->cursor, "Infinity", 8) == 0)) {
967
893
  state->cursor += 8;
968
- return PUSH(CInfinity);
894
+ return json_push_value(state, config, CInfinity);
969
895
  }
970
896
 
971
897
  raise_parse_error("unexpected token at '%s'", state->cursor);
@@ -975,7 +901,7 @@ static VALUE json_parse_any(JSON_ParserState *state, JSON_ParserConfig *config)
975
901
  if ((state->end - state->cursor >= 9) && (memcmp(state->cursor + 1, "Infinity", 8) == 0)) {
976
902
  if (config->allow_nan) {
977
903
  state->cursor += 9;
978
- return PUSH(CMinusInfinity);
904
+ return json_push_value(state, config, CMinusInfinity);
979
905
  } else {
980
906
  raise_parse_error("unexpected token at '%s'", state->cursor);
981
907
  }
@@ -1032,9 +958,9 @@ static VALUE json_parse_any(JSON_ParserState *state, JSON_ParserConfig *config)
1032
958
  }
1033
959
 
1034
960
  if (integer) {
1035
- return PUSH(json_decode_integer(start, state->cursor));
961
+ return json_push_value(state, config, json_decode_integer(start, state->cursor));
1036
962
  }
1037
- return PUSH(json_decode_float(config, start, state->cursor));
963
+ return json_push_value(state, config, json_decode_float(config, start, state->cursor));
1038
964
  }
1039
965
  case '"': {
1040
966
  // %r{\A"[^"\\\t\n\x00]*(?:\\[bfnrtu\\/"][^"\\]*)*"}
@@ -1048,7 +974,7 @@ static VALUE json_parse_any(JSON_ParserState *state, JSON_ParserConfig *config)
1048
974
 
1049
975
  if ((state->cursor < state->end) && (*state->cursor == ']')) {
1050
976
  state->cursor++;
1051
- return PUSH(json_decode_array(state, config, 0));
977
+ return json_push_value(state, config, json_decode_array(state, config, 0));
1052
978
  } else {
1053
979
  state->current_nesting++;
1054
980
  if (RB_UNLIKELY(config->max_nesting && (config->max_nesting < state->current_nesting))) {
@@ -1067,7 +993,7 @@ static VALUE json_parse_any(JSON_ParserState *state, JSON_ParserConfig *config)
1067
993
  long count = state->stack->head - stack_head;
1068
994
  state->current_nesting--;
1069
995
  state->in_array--;
1070
- return PUSH(json_decode_array(state, config, count));
996
+ return json_push_value(state, config, json_decode_array(state, config, count));
1071
997
  }
1072
998
 
1073
999
  if (*state->cursor == ',') {
@@ -1094,7 +1020,7 @@ static VALUE json_parse_any(JSON_ParserState *state, JSON_ParserConfig *config)
1094
1020
 
1095
1021
  if ((state->cursor < state->end) && (*state->cursor == '}')) {
1096
1022
  state->cursor++;
1097
- return PUSH(json_decode_object(state, config, 0));
1023
+ return json_push_value(state, config, json_decode_object(state, config, 0));
1098
1024
  } else {
1099
1025
  state->current_nesting++;
1100
1026
  if (RB_UNLIKELY(config->max_nesting && (config->max_nesting < state->current_nesting))) {
@@ -1123,7 +1049,7 @@ static VALUE json_parse_any(JSON_ParserState *state, JSON_ParserConfig *config)
1123
1049
  state->cursor++;
1124
1050
  state->current_nesting--;
1125
1051
  long count = state->stack->head - stack_head;
1126
- return PUSH(json_decode_object(state, config, count));
1052
+ return json_push_value(state, config, json_decode_object(state, config, count));
1127
1053
  }
1128
1054
 
1129
1055
  if (*state->cursor == ',') {
@@ -1211,10 +1137,7 @@ static int parser_config_init_i(VALUE key, VALUE val, VALUE data)
1211
1137
  else if (key == sym_allow_trailing_comma) { config->allow_trailing_comma = RTEST(val); }
1212
1138
  else if (key == sym_symbolize_names) { config->symbolize_names = RTEST(val); }
1213
1139
  else if (key == sym_freeze) { config->freeze = RTEST(val); }
1214
- else if (key == sym_create_id) { config->create_id = RTEST(val) ? val : Qfalse; }
1215
- else if (key == sym_object_class) { config->object_class = RTEST(val) ? val : Qfalse; }
1216
- else if (key == sym_array_class) { config->array_class = RTEST(val) ? val : Qfalse; }
1217
- else if (key == sym_match_string) { config->match_string = RTEST(val) ? val : Qfalse; }
1140
+ else if (key == sym_on_load) { config->on_load_proc = RTEST(val) ? val : Qfalse; }
1218
1141
  else if (key == sym_decimal_class) {
1219
1142
  if (RTEST(val)) {
1220
1143
  if (rb_respond_to(val, i_try_convert)) {
@@ -1244,15 +1167,6 @@ static int parser_config_init_i(VALUE key, VALUE val, VALUE data)
1244
1167
  }
1245
1168
  }
1246
1169
  }
1247
- else if (key == sym_create_additions) {
1248
- if (NIL_P(val)) {
1249
- config->create_additions = true;
1250
- config->deprecated_create_additions = true;
1251
- } else {
1252
- config->create_additions = RTEST(val);
1253
- config->deprecated_create_additions = false;
1254
- }
1255
- }
1256
1170
 
1257
1171
  return ST_CONTINUE;
1258
1172
  }
@@ -1267,16 +1181,6 @@ static void parser_config_init(JSON_ParserConfig *config, VALUE opts)
1267
1181
  // We assume in most cases few keys are set so it's faster to go over
1268
1182
  // the provided keys than to check all possible keys.
1269
1183
  rb_hash_foreach(opts, parser_config_init_i, (VALUE)config);
1270
-
1271
- if (config->symbolize_names && config->create_additions) {
1272
- rb_raise(rb_eArgError,
1273
- "options :symbolize_names and :create_additions cannot be "
1274
- " used in conjunction");
1275
- }
1276
-
1277
- if (config->create_additions && !config->create_id) {
1278
- config->create_id = rb_funcall(mJSON, i_create_id, 0);
1279
- }
1280
1184
  }
1281
1185
 
1282
1186
  }
@@ -1301,15 +1205,6 @@ static void parser_config_init(JSON_ParserConfig *config, VALUE opts)
1301
1205
  * (keys) in a JSON object. Otherwise strings are returned, which is
1302
1206
  * also the default. It's not possible to use this option in
1303
1207
  * conjunction with the *create_additions* option.
1304
- * * *create_additions*: If set to false, the Parser doesn't create
1305
- * additions even if a matching class and create_id was found. This option
1306
- * defaults to false.
1307
- * * *object_class*: Defaults to Hash. If another type is provided, it will be used
1308
- * instead of Hash to represent JSON objects. The type must respond to
1309
- * +new+ without arguments, and return an object that respond to +[]=+.
1310
- * * *array_class*: Defaults to Array If another type is provided, it will be used
1311
- * instead of Hash to represent JSON arrays. The type must respond to
1312
- * +new+ without arguments, and return an object that respond to +<<+.
1313
1208
  * * *decimal_class*: Specifies which class to use instead of the default
1314
1209
  * (Float) when parsing decimal numbers. This class must accept a single
1315
1210
  * string argument in its constructor.
@@ -1320,11 +1215,7 @@ static VALUE cParserConfig_initialize(VALUE self, VALUE opts)
1320
1215
 
1321
1216
  parser_config_init(config, opts);
1322
1217
 
1323
- RB_OBJ_WRITTEN(self, Qundef, config->create_id);
1324
- RB_OBJ_WRITTEN(self, Qundef, config->object_class);
1325
- RB_OBJ_WRITTEN(self, Qundef, config->array_class);
1326
1218
  RB_OBJ_WRITTEN(self, Qundef, config->decimal_class);
1327
- RB_OBJ_WRITTEN(self, Qundef, config->match_string);
1328
1219
 
1329
1220
  return self;
1330
1221
  }
@@ -1387,11 +1278,8 @@ static VALUE cParser_m_parse(VALUE klass, VALUE Vsource, VALUE opts)
1387
1278
  static void JSON_ParserConfig_mark(void *ptr)
1388
1279
  {
1389
1280
  JSON_ParserConfig *config = ptr;
1390
- rb_gc_mark(config->create_id);
1391
- rb_gc_mark(config->object_class);
1392
- rb_gc_mark(config->array_class);
1281
+ rb_gc_mark(config->on_load_proc);
1393
1282
  rb_gc_mark(config->decimal_class);
1394
- rb_gc_mark(config->match_string);
1395
1283
  }
1396
1284
 
1397
1285
  static void JSON_ParserConfig_free(void *ptr)
@@ -1459,19 +1347,10 @@ void Init_parser(void)
1459
1347
  sym_allow_trailing_comma = ID2SYM(rb_intern("allow_trailing_comma"));
1460
1348
  sym_symbolize_names = ID2SYM(rb_intern("symbolize_names"));
1461
1349
  sym_freeze = ID2SYM(rb_intern("freeze"));
1462
- sym_create_additions = ID2SYM(rb_intern("create_additions"));
1463
- sym_create_id = ID2SYM(rb_intern("create_id"));
1464
- sym_object_class = ID2SYM(rb_intern("object_class"));
1465
- sym_array_class = ID2SYM(rb_intern("array_class"));
1350
+ sym_on_load = ID2SYM(rb_intern("on_load"));
1466
1351
  sym_decimal_class = ID2SYM(rb_intern("decimal_class"));
1467
- sym_match_string = ID2SYM(rb_intern("match_string"));
1468
1352
 
1469
- i_create_id = rb_intern("create_id");
1470
- i_json_creatable_p = rb_intern("json_creatable?");
1471
- i_json_create = rb_intern("json_create");
1472
1353
  i_chr = rb_intern("chr");
1473
- i_match = rb_intern("match");
1474
- i_deep_const_get = rb_intern("deep_const_get");
1475
1354
  i_aset = rb_intern("[]=");
1476
1355
  i_aref = rb_intern("[]");
1477
1356
  i_leftshift = rb_intern("<<");