oj 3.16.0 → 3.17.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.
Files changed (137) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +107 -0
  3. data/README.md +0 -16
  4. data/ext/oj/cache.c +4 -2
  5. data/ext/oj/cache.h +3 -2
  6. data/ext/oj/compat.c +3 -3
  7. data/ext/oj/custom.c +17 -11
  8. data/ext/oj/dump.c +624 -90
  9. data/ext/oj/dump.h +9 -2
  10. data/ext/oj/dump_compat.c +15 -9
  11. data/ext/oj/dump_leaf.c +1 -1
  12. data/ext/oj/dump_object.c +32 -17
  13. data/ext/oj/dump_strict.c +20 -14
  14. data/ext/oj/extconf.rb +11 -9
  15. data/ext/oj/fast.c +50 -32
  16. data/ext/oj/intern.c +24 -7
  17. data/ext/oj/mimic_json.c +17 -11
  18. data/ext/oj/object.c +21 -13
  19. data/ext/oj/oj.c +387 -140
  20. data/ext/oj/oj.h +59 -55
  21. data/ext/oj/parse.c +248 -47
  22. data/ext/oj/parser.c +179 -89
  23. data/ext/oj/parser.h +4 -2
  24. data/ext/oj/rails.c +64 -42
  25. data/ext/oj/reader.c +1 -1
  26. data/ext/oj/rxclass.c +1 -1
  27. data/ext/oj/rxclass.h +1 -1
  28. data/ext/oj/safe.c +230 -0
  29. data/ext/oj/safe.h +79 -0
  30. data/ext/oj/saj.c +15 -10
  31. data/ext/oj/scp.c +3 -6
  32. data/ext/oj/simd.h +219 -0
  33. data/ext/oj/sparse.c +6 -3
  34. data/ext/oj/stream_writer.c +38 -28
  35. data/ext/oj/strict.c +2 -4
  36. data/ext/oj/string_writer.c +54 -22
  37. data/ext/oj/usual.c +57 -35
  38. data/ext/oj/usual.h +1 -0
  39. data/ext/oj/val_stack.c +13 -2
  40. data/ext/oj/wab.c +5 -4
  41. data/lib/oj/mimic.rb +1 -5
  42. data/lib/oj/schandler.rb +5 -4
  43. data/lib/oj/version.rb +1 -1
  44. data/pages/Encoding.md +1 -1
  45. metadata +36 -100
  46. data/test/_test_active.rb +0 -75
  47. data/test/_test_active_mimic.rb +0 -95
  48. data/test/_test_mimic_rails.rb +0 -123
  49. data/test/activerecord/result_test.rb +0 -31
  50. data/test/activesupport6/abstract_unit.rb +0 -44
  51. data/test/activesupport6/decoding_test.rb +0 -133
  52. data/test/activesupport6/encoding_test.rb +0 -507
  53. data/test/activesupport6/encoding_test_cases.rb +0 -98
  54. data/test/activesupport6/test_common.rb +0 -17
  55. data/test/activesupport6/test_helper.rb +0 -163
  56. data/test/activesupport6/time_zone_test_helpers.rb +0 -39
  57. data/test/activesupport7/abstract_unit.rb +0 -49
  58. data/test/activesupport7/decoding_test.rb +0 -125
  59. data/test/activesupport7/encoding_test.rb +0 -486
  60. data/test/activesupport7/encoding_test_cases.rb +0 -104
  61. data/test/activesupport7/time_zone_test_helpers.rb +0 -47
  62. data/test/files.rb +0 -29
  63. data/test/foo.rb +0 -14
  64. data/test/helper.rb +0 -39
  65. data/test/isolated/shared.rb +0 -309
  66. data/test/isolated/test_mimic_after.rb +0 -13
  67. data/test/isolated/test_mimic_alone.rb +0 -12
  68. data/test/isolated/test_mimic_as_json.rb +0 -45
  69. data/test/isolated/test_mimic_before.rb +0 -13
  70. data/test/isolated/test_mimic_define.rb +0 -28
  71. data/test/isolated/test_mimic_rails_after.rb +0 -22
  72. data/test/isolated/test_mimic_rails_before.rb +0 -21
  73. data/test/isolated/test_mimic_redefine.rb +0 -15
  74. data/test/json_gem/json_addition_test.rb +0 -216
  75. data/test/json_gem/json_common_interface_test.rb +0 -155
  76. data/test/json_gem/json_encoding_test.rb +0 -107
  77. data/test/json_gem/json_ext_parser_test.rb +0 -21
  78. data/test/json_gem/json_fixtures_test.rb +0 -36
  79. data/test/json_gem/json_generator_test.rb +0 -407
  80. data/test/json_gem/json_generic_object_test.rb +0 -90
  81. data/test/json_gem/json_parser_test.rb +0 -477
  82. data/test/json_gem/json_string_matching_test.rb +0 -42
  83. data/test/json_gem/test_helper.rb +0 -30
  84. data/test/mem.rb +0 -34
  85. data/test/perf.rb +0 -102
  86. data/test/perf_compat.rb +0 -128
  87. data/test/perf_dump.rb +0 -50
  88. data/test/perf_fast.rb +0 -162
  89. data/test/perf_file.rb +0 -62
  90. data/test/perf_object.rb +0 -134
  91. data/test/perf_once.rb +0 -59
  92. data/test/perf_parser.rb +0 -183
  93. data/test/perf_saj.rb +0 -101
  94. data/test/perf_scp.rb +0 -140
  95. data/test/perf_simple.rb +0 -289
  96. data/test/perf_strict.rb +0 -137
  97. data/test/perf_wab.rb +0 -129
  98. data/test/prec.rb +0 -23
  99. data/test/sample/change.rb +0 -13
  100. data/test/sample/dir.rb +0 -18
  101. data/test/sample/doc.rb +0 -35
  102. data/test/sample/file.rb +0 -47
  103. data/test/sample/group.rb +0 -15
  104. data/test/sample/hasprops.rb +0 -15
  105. data/test/sample/layer.rb +0 -11
  106. data/test/sample/line.rb +0 -20
  107. data/test/sample/oval.rb +0 -10
  108. data/test/sample/rect.rb +0 -9
  109. data/test/sample/shape.rb +0 -34
  110. data/test/sample/text.rb +0 -19
  111. data/test/sample.rb +0 -54
  112. data/test/sample_json.rb +0 -37
  113. data/test/test_compat.rb +0 -567
  114. data/test/test_custom.rb +0 -554
  115. data/test/test_debian.rb +0 -50
  116. data/test/test_fast.rb +0 -526
  117. data/test/test_file.rb +0 -250
  118. data/test/test_gc.rb +0 -60
  119. data/test/test_generate.rb +0 -21
  120. data/test/test_hash.rb +0 -39
  121. data/test/test_integer_range.rb +0 -72
  122. data/test/test_null.rb +0 -376
  123. data/test/test_object.rb +0 -1016
  124. data/test/test_parser.rb +0 -11
  125. data/test/test_parser_debug.rb +0 -27
  126. data/test/test_parser_saj.rb +0 -337
  127. data/test/test_parser_usual.rb +0 -217
  128. data/test/test_rails.rb +0 -35
  129. data/test/test_saj.rb +0 -188
  130. data/test/test_scp.rb +0 -431
  131. data/test/test_strict.rb +0 -431
  132. data/test/test_various.rb +0 -801
  133. data/test/test_wab.rb +0 -311
  134. data/test/test_writer.rb +0 -380
  135. data/test/tests.rb +0 -33
  136. data/test/tests_mimic.rb +0 -23
  137. data/test/tests_mimic_addition.rb +0 -16
data/ext/oj/intern.c CHANGED
@@ -69,7 +69,7 @@ static VALUE form_attr(const char *str, size_t len) {
69
69
  memcpy(b + 1, str, len);
70
70
  b[len + 1] = '\0';
71
71
  }
72
- id = rb_intern3(buf, len + 1, oj_utf8_encoding);
72
+ id = rb_intern3(b, len + 1, oj_utf8_encoding);
73
73
  OJ_R_FREE(b);
74
74
  return id;
75
75
  }
@@ -85,20 +85,31 @@ static VALUE form_attr(const char *str, size_t len) {
85
85
  return (VALUE)rb_intern3(buf, len + 1, oj_utf8_encoding);
86
86
  }
87
87
 
88
+ static const rb_data_type_t oj_cache_type = {
89
+ "Oj/cache",
90
+ {
91
+ cache_mark,
92
+ cache_free,
93
+ NULL,
94
+ },
95
+ 0,
96
+ 0,
97
+ };
98
+
88
99
  void oj_hash_init(void) {
89
100
  VALUE cache_class = rb_define_class_under(Oj, "Cache", rb_cObject);
90
101
  rb_undef_alloc_func(cache_class);
91
102
 
92
103
  struct _cache *str_cache = cache_create(0, form_str, true, true);
93
- str_cache_obj = Data_Wrap_Struct(cache_class, cache_mark, cache_free, str_cache);
104
+ str_cache_obj = TypedData_Wrap_Struct(cache_class, &oj_cache_type, str_cache);
94
105
  rb_gc_register_address(&str_cache_obj);
95
106
 
96
107
  struct _cache *sym_cache = cache_create(0, form_sym, true, true);
97
- sym_cache_obj = Data_Wrap_Struct(cache_class, cache_mark, cache_free, sym_cache);
108
+ sym_cache_obj = TypedData_Wrap_Struct(cache_class, &oj_cache_type, sym_cache);
98
109
  rb_gc_register_address(&sym_cache_obj);
99
110
 
100
111
  struct _cache *attr_cache = cache_create(0, form_attr, false, true);
101
- attr_cache_obj = Data_Wrap_Struct(cache_class, cache_mark, cache_free, attr_cache);
112
+ attr_cache_obj = TypedData_Wrap_Struct(cache_class, &oj_cache_type, attr_cache);
102
113
  rb_gc_register_address(&attr_cache_obj);
103
114
 
104
115
  memset(class_hash.slots, 0, sizeof(class_hash.slots));
@@ -118,17 +129,23 @@ oj_str_intern(const char *key, size_t len) {
118
129
  #if HAVE_RB_ENC_INTERNED_STR && 0
119
130
  return rb_enc_interned_str(key, len, rb_utf8_encoding());
120
131
  #else
121
- return cache_intern(DATA_PTR(str_cache_obj), key, len);
132
+ Cache c;
133
+ TypedData_Get_Struct(str_cache_obj, struct _cache, &oj_cache_type, c);
134
+ return cache_intern(c, key, len);
122
135
  #endif
123
136
  }
124
137
 
125
138
  VALUE
126
139
  oj_sym_intern(const char *key, size_t len) {
127
- return cache_intern(DATA_PTR(sym_cache_obj), key, len);
140
+ Cache c;
141
+ TypedData_Get_Struct(sym_cache_obj, struct _cache, &oj_cache_type, c);
142
+ return cache_intern(c, key, len);
128
143
  }
129
144
 
130
145
  ID oj_attr_intern(const char *key, size_t len) {
131
- return cache_intern(DATA_PTR(attr_cache_obj), key, len);
146
+ Cache c;
147
+ TypedData_Get_Struct(attr_cache_obj, struct _cache, &oj_cache_type, c);
148
+ return cache_intern(c, key, len);
132
149
  }
133
150
 
134
151
  static uint64_t hash_calc(const uint8_t *key, size_t len) {
data/ext/oj/mimic_json.c CHANGED
@@ -246,8 +246,7 @@ static VALUE mimic_dump(int argc, VALUE *argv, VALUE self) {
246
246
  if (0 == out.buf) {
247
247
  rb_raise(rb_eNoMemError, "Not enough memory.");
248
248
  }
249
- rstr = rb_str_new2(out.buf);
250
- rstr = oj_encode(rstr);
249
+ rstr = rb_utf8_str_new_cstr(out.buf);
251
250
  if (2 <= argc && Qnil != argv[1] && rb_respond_to(argv[1], oj_write_id)) {
252
251
  VALUE io = argv[1];
253
252
  VALUE args[1];
@@ -396,8 +395,7 @@ static VALUE mimic_generate_core(int argc, VALUE *argv, Options copts) {
396
395
  if (0 == out.buf) {
397
396
  rb_raise(rb_eNoMemError, "Not enough memory.");
398
397
  }
399
- rstr = rb_str_new2(out.buf);
400
- rstr = oj_encode(rstr);
398
+ rstr = rb_utf8_str_new_cstr(out.buf);
401
399
 
402
400
  oj_out_free(&out);
403
401
 
@@ -425,7 +423,7 @@ static VALUE mimic_generate_core(int argc, VALUE *argv, Options copts) {
425
423
  * - *:object_nl* [_String_] String placed after a JSON object
426
424
  * - *:array_nl* [_String_] String placed after a JSON array
427
425
  * - *:ascii_only* [_Boolean_] if not nil or false then use only ascii characters in the output.
428
- * Note JSON.generate does support this even if it is not documented.
426
+ * Note JSON.generate does support this even if it is not documented.
429
427
  *
430
428
  * Returns [_String_] generated JSON.
431
429
  */
@@ -605,9 +603,9 @@ static VALUE mimic_parse_core(int argc, VALUE *argv, VALUE self, bool bang) {
605
603
  * - *source* [_String_|IO] source to parse
606
604
  * - *opts* [_Hash_] options
607
605
  * - *:symbolize* [Boolean] _names flag indicating JSON object keys should be Symbols instead of
608
- * Strings
606
+ * Strings
609
607
  * - *:create_additions* [Boolean] flag indicating a key matching +create_id+ in a JSON object
610
- * should trigger the creation of Ruby Object
608
+ * should trigger the creation of Ruby Object
611
609
  *
612
610
  * Returns [Object]
613
611
  * @see create_id=
@@ -713,6 +711,7 @@ static struct _options mimic_object_to_json_options = {0, // indent
713
711
  0, // cache_str
714
712
  0, // int_range_min
715
713
  0, // int_range_max
714
+ 0, // max_integer_digits
716
715
  oj_json_class, // create_id
717
716
  10, // create_id_len
718
717
  3, // sec_prec
@@ -737,6 +736,8 @@ static struct _options mimic_object_to_json_options = {0, // indent
737
736
  false, // omit_nil
738
737
  false, // omit_null_byte
739
738
  100, // max_depth
739
+ NULL, // only
740
+ NULL, // except
740
741
  },
741
742
  {
742
743
  // str_rx
@@ -768,8 +769,7 @@ static VALUE mimic_object_to_json(int argc, VALUE *argv, VALUE self) {
768
769
  if (NULL == out.buf) {
769
770
  rb_raise(rb_eNoMemError, "Not enough memory.");
770
771
  }
771
- rstr = rb_str_new2(out.buf);
772
- rstr = oj_encode(rstr);
772
+ rstr = rb_utf8_str_new_cstr(out.buf);
773
773
 
774
774
  oj_out_free(&out);
775
775
 
@@ -837,11 +837,15 @@ void oj_mimic_json_methods(VALUE json) {
837
837
  } else {
838
838
  json_error = rb_define_class_under(json, "JSONError", rb_eStandardError);
839
839
  }
840
+
841
+ rb_global_variable(&oj_json_parser_error_class);
840
842
  if (rb_const_defined_at(json, rb_intern("ParserError"))) {
841
843
  oj_json_parser_error_class = rb_const_get(json, rb_intern("ParserError"));
842
844
  } else {
843
845
  oj_json_parser_error_class = rb_define_class_under(json, "ParserError", json_error);
844
846
  }
847
+
848
+ rb_global_variable(&oj_json_generator_error_class);
845
849
  if (rb_const_defined_at(json, rb_intern("GeneratorError"))) {
846
850
  oj_json_generator_error_class = rb_const_get(json, rb_intern("GeneratorError"));
847
851
  } else {
@@ -867,8 +871,8 @@ void oj_mimic_json_methods(VALUE json) {
867
871
  rb_require("oj/state");
868
872
  }
869
873
  // Pull in the JSON::State mimic file.
874
+ rb_global_variable(&state_class);
870
875
  state_class = rb_const_get_at(generator, rb_intern("State"));
871
- rb_gc_register_mark_object(state_class);
872
876
  }
873
877
 
874
878
  /* Document-module: JSON
@@ -905,7 +909,9 @@ oj_define_mimic_json(int argc, VALUE *argv, VALUE self) {
905
909
  }
906
910
  oj_mimic_json_methods(json);
907
911
 
908
- rb_define_method(rb_cObject, "to_json", mimic_object_to_json, -1);
912
+ if (!rb_const_defined(rb_cObject, rb_intern("ActiveSupport"))) {
913
+ rb_define_method(rb_cObject, "to_json", mimic_object_to_json, -1);
914
+ }
909
915
 
910
916
  rb_gv_set("$VERBOSE", verbose);
911
917
 
data/ext/oj/object.c CHANGED
@@ -83,8 +83,9 @@ static int parse_num(const char *str, const char *end, int cnt) {
83
83
 
84
84
  VALUE
85
85
  oj_parse_xml_time(const char *str, int len) {
86
- VALUE args[8];
87
- const char *end = str + len;
86
+ VALUE args[7];
87
+ const char *end = str + len;
88
+ const char *orig = str;
88
89
  int n;
89
90
 
90
91
  // year
@@ -144,7 +145,9 @@ oj_parse_xml_time(const char *str, int len) {
144
145
  char c = *str++;
145
146
 
146
147
  if ('.' == c) {
147
- long long nsec = 0;
148
+ unsigned long long num = 0;
149
+ unsigned long long den = 1;
150
+ const unsigned long long last_den_limit = ULLONG_MAX / 10;
148
151
 
149
152
  for (; str < end; str++) {
150
153
  c = *str;
@@ -152,9 +155,14 @@ oj_parse_xml_time(const char *str, int len) {
152
155
  str++;
153
156
  break;
154
157
  }
155
- nsec = nsec * 10 + (c - '0');
158
+ if (den > last_den_limit) {
159
+ // bail to Time.parse if there are more fractional digits than a ULLONG rational can hold
160
+ return rb_funcall(rb_cTime, oj_parse_id, 1, rb_str_new(orig, len));
161
+ }
162
+ num = num * 10 + (c - '0');
163
+ den *= 10;
156
164
  }
157
- args[5] = rb_float_new((double)n + ((double)nsec + 0.5) / 1000000000.0);
165
+ args[5] = rb_funcall(INT2NUM(n), oj_plus_id, 1, rb_rational_new(ULL2NUM(num), ULL2NUM(den)));
158
166
  } else {
159
167
  args[5] = rb_ll2inum(n);
160
168
  }
@@ -297,7 +305,7 @@ static int hat_num(ParseInfo pi, Val parent, Val kval, NumInfo ni) {
297
305
 
298
306
  static int hat_value(ParseInfo pi, Val parent, const char *key, size_t klen, volatile VALUE value) {
299
307
  if (T_ARRAY == rb_type(value)) {
300
- int len = (int)RARRAY_LEN(value);
308
+ size_t len = RARRAY_LEN(value);
301
309
 
302
310
  if (2 == klen && 'u' == key[1]) {
303
311
  volatile VALUE sc;
@@ -313,19 +321,20 @@ static int hat_value(ParseInfo pi, Val parent, const char *key, size_t klen, vol
313
321
  if (T_ARRAY == rb_type(e1)) {
314
322
  VALUE args[1024];
315
323
  volatile VALUE rstr;
316
- int i, cnt = (int)RARRAY_LEN(e1);
324
+ size_t i;
325
+ size_t cnt = RARRAY_LEN(e1);
317
326
 
318
327
  for (i = 0; i < cnt; i++) {
319
328
  rstr = RARRAY_AREF(e1, i);
320
329
  args[i] = rb_funcall(rstr, oj_to_sym_id, 0);
321
330
  }
322
- sc = rb_funcall2(rb_cStruct, oj_new_id, cnt, args);
331
+ sc = rb_funcall2(rb_cStruct, oj_new_id, (int)cnt, args);
323
332
  } else {
324
333
  // If struct is not defined then we let this fail and raise an exception.
325
334
  sc = oj_name2struct(pi, *RARRAY_CONST_PTR(value), rb_eArgError);
326
335
  }
327
336
  if (sc == rb_cRange) {
328
- parent->val = rb_class_new_instance(len - 1, RARRAY_CONST_PTR(value) + 1, rb_cRange);
337
+ parent->val = rb_class_new_instance((int)(len - 1), RARRAY_CONST_PTR(value) + 1, rb_cRange);
329
338
  } else {
330
339
  // Create a properly initialized struct instance without calling the initialize method.
331
340
  parent->val = rb_obj_alloc(sc);
@@ -340,10 +349,10 @@ static int hat_value(ParseInfo pi, Val parent, const char *key, size_t klen, vol
340
349
  slen = FIX2INT(rb_funcall2(parent->val, oj_length_id, 0, 0));
341
350
  #endif
342
351
  // MRI >= 1.9
343
- if (len - 1 > slen) {
352
+ if (len - 1 > (size_t)slen) {
344
353
  oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "Invalid struct data");
345
354
  } else {
346
- int i;
355
+ size_t i;
347
356
 
348
357
  for (i = 0; i < len - 1; i++) {
349
358
  rb_struct_aset(parent->val, INT2FIX(i), RARRAY_CONST_PTR(value)[i + 1]);
@@ -690,9 +699,8 @@ oj_object_parse(int argc, VALUE *argv, VALUE self) {
690
699
 
691
700
  if (T_STRING == rb_type(*argv)) {
692
701
  return oj_pi_parse(argc, argv, &pi, 0, 0, 1);
693
- } else {
694
- return oj_pi_sparse(argc, argv, &pi, 0);
695
702
  }
703
+ return oj_pi_sparse(argc, argv, &pi, 0);
696
704
  }
697
705
 
698
706
  VALUE