oj 3.16.3 → 3.17.4

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 (134) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +99 -0
  3. data/README.md +0 -16
  4. data/ext/oj/compat.c +3 -3
  5. data/ext/oj/custom.c +17 -11
  6. data/ext/oj/dump.c +619 -88
  7. data/ext/oj/dump.h +9 -2
  8. data/ext/oj/dump_compat.c +16 -9
  9. data/ext/oj/dump_leaf.c +1 -1
  10. data/ext/oj/dump_object.c +52 -27
  11. data/ext/oj/dump_strict.c +20 -14
  12. data/ext/oj/extconf.rb +11 -9
  13. data/ext/oj/fast.c +90 -65
  14. data/ext/oj/intern.c +1 -1
  15. data/ext/oj/mimic_json.c +14 -8
  16. data/ext/oj/object.c +18 -12
  17. data/ext/oj/oj.c +426 -11
  18. data/ext/oj/oj.h +60 -52
  19. data/ext/oj/parse.c +252 -48
  20. data/ext/oj/parse.h +0 -1
  21. data/ext/oj/parser.c +179 -47
  22. data/ext/oj/parser.h +4 -2
  23. data/ext/oj/rails.c +57 -36
  24. data/ext/oj/reader.c +17 -5
  25. data/ext/oj/rxclass.c +17 -1
  26. data/ext/oj/rxclass.h +2 -1
  27. data/ext/oj/safe.c +230 -0
  28. data/ext/oj/safe.h +79 -0
  29. data/ext/oj/saj.c +55 -20
  30. data/ext/oj/scp.c +3 -6
  31. data/ext/oj/simd.h +219 -0
  32. data/ext/oj/sparse.c +15 -3
  33. data/ext/oj/stream_writer.c +19 -14
  34. data/ext/oj/strict.c +2 -4
  35. data/ext/oj/string_writer.c +26 -14
  36. data/ext/oj/usual.c +37 -35
  37. data/ext/oj/wab.c +5 -4
  38. data/lib/oj/mimic.rb +1 -5
  39. data/lib/oj/schandler.rb +5 -4
  40. data/lib/oj/version.rb +1 -1
  41. data/pages/Encoding.md +1 -1
  42. metadata +22 -100
  43. data/test/_test_active.rb +0 -75
  44. data/test/_test_active_mimic.rb +0 -95
  45. data/test/_test_mimic_rails.rb +0 -123
  46. data/test/activerecord/result_test.rb +0 -31
  47. data/test/activesupport6/abstract_unit.rb +0 -44
  48. data/test/activesupport6/decoding_test.rb +0 -133
  49. data/test/activesupport6/encoding_test.rb +0 -507
  50. data/test/activesupport6/encoding_test_cases.rb +0 -98
  51. data/test/activesupport6/test_common.rb +0 -17
  52. data/test/activesupport6/test_helper.rb +0 -163
  53. data/test/activesupport6/time_zone_test_helpers.rb +0 -39
  54. data/test/activesupport7/abstract_unit.rb +0 -49
  55. data/test/activesupport7/decoding_test.rb +0 -125
  56. data/test/activesupport7/encoding_test.rb +0 -486
  57. data/test/activesupport7/encoding_test_cases.rb +0 -104
  58. data/test/activesupport7/time_zone_test_helpers.rb +0 -47
  59. data/test/files.rb +0 -29
  60. data/test/foo.rb +0 -14
  61. data/test/helper.rb +0 -39
  62. data/test/isolated/shared.rb +0 -309
  63. data/test/isolated/test_mimic_after.rb +0 -13
  64. data/test/isolated/test_mimic_alone.rb +0 -12
  65. data/test/isolated/test_mimic_as_json.rb +0 -45
  66. data/test/isolated/test_mimic_before.rb +0 -13
  67. data/test/isolated/test_mimic_define.rb +0 -28
  68. data/test/isolated/test_mimic_rails_after.rb +0 -22
  69. data/test/isolated/test_mimic_rails_before.rb +0 -21
  70. data/test/isolated/test_mimic_redefine.rb +0 -15
  71. data/test/json_gem/json_addition_test.rb +0 -216
  72. data/test/json_gem/json_common_interface_test.rb +0 -155
  73. data/test/json_gem/json_encoding_test.rb +0 -107
  74. data/test/json_gem/json_ext_parser_test.rb +0 -21
  75. data/test/json_gem/json_fixtures_test.rb +0 -36
  76. data/test/json_gem/json_generator_test.rb +0 -413
  77. data/test/json_gem/json_generic_object_test.rb +0 -90
  78. data/test/json_gem/json_parser_test.rb +0 -477
  79. data/test/json_gem/json_string_matching_test.rb +0 -42
  80. data/test/json_gem/test_helper.rb +0 -30
  81. data/test/mem.rb +0 -34
  82. data/test/perf.rb +0 -102
  83. data/test/perf_compat.rb +0 -128
  84. data/test/perf_dump.rb +0 -50
  85. data/test/perf_fast.rb +0 -162
  86. data/test/perf_file.rb +0 -62
  87. data/test/perf_object.rb +0 -134
  88. data/test/perf_once.rb +0 -59
  89. data/test/perf_parser.rb +0 -183
  90. data/test/perf_saj.rb +0 -101
  91. data/test/perf_scp.rb +0 -140
  92. data/test/perf_simple.rb +0 -289
  93. data/test/perf_strict.rb +0 -137
  94. data/test/perf_wab.rb +0 -129
  95. data/test/prec.rb +0 -23
  96. data/test/sample/change.rb +0 -13
  97. data/test/sample/dir.rb +0 -18
  98. data/test/sample/doc.rb +0 -35
  99. data/test/sample/file.rb +0 -47
  100. data/test/sample/group.rb +0 -15
  101. data/test/sample/hasprops.rb +0 -15
  102. data/test/sample/layer.rb +0 -11
  103. data/test/sample/line.rb +0 -20
  104. data/test/sample/oval.rb +0 -10
  105. data/test/sample/rect.rb +0 -9
  106. data/test/sample/shape.rb +0 -34
  107. data/test/sample/text.rb +0 -19
  108. data/test/sample.rb +0 -54
  109. data/test/sample_json.rb +0 -37
  110. data/test/test_compat.rb +0 -567
  111. data/test/test_custom.rb +0 -555
  112. data/test/test_debian.rb +0 -50
  113. data/test/test_fast.rb +0 -526
  114. data/test/test_file.rb +0 -250
  115. data/test/test_gc.rb +0 -60
  116. data/test/test_generate.rb +0 -21
  117. data/test/test_hash.rb +0 -39
  118. data/test/test_integer_range.rb +0 -72
  119. data/test/test_null.rb +0 -376
  120. data/test/test_object.rb +0 -1030
  121. data/test/test_parser.rb +0 -11
  122. data/test/test_parser_debug.rb +0 -27
  123. data/test/test_parser_saj.rb +0 -337
  124. data/test/test_parser_usual.rb +0 -227
  125. data/test/test_rails.rb +0 -35
  126. data/test/test_saj.rb +0 -188
  127. data/test/test_scp.rb +0 -431
  128. data/test/test_strict.rb +0 -441
  129. data/test/test_various.rb +0 -801
  130. data/test/test_wab.rb +0 -311
  131. data/test/test_writer.rb +0 -380
  132. data/test/tests.rb +0 -33
  133. data/test/tests_mimic.rb +0 -23
  134. data/test/tests_mimic_addition.rb +0 -16
data/ext/oj/dump.h CHANGED
@@ -7,12 +7,17 @@
7
7
  #include <ruby.h>
8
8
 
9
9
  #include "oj.h"
10
+ #include "simd.h"
10
11
 
11
12
  #define MAX_DEPTH 1000
12
13
 
13
14
  // Extra padding at end of buffer.
14
15
  #define BUFFER_EXTRA 64
15
16
 
17
+ #ifdef HAVE_SIMD_NEON
18
+ extern void initialize_neon(void);
19
+ #endif /* HAVE_SIMD_NEON */
20
+
16
21
  extern void oj_dump_nil(VALUE obj, int depth, Out out, bool as_ok);
17
22
  extern void oj_dump_true(VALUE obj, int depth, Out out, bool as_ok);
18
23
  extern void oj_dump_false(VALUE obj, int depth, Out out, bool as_ok);
@@ -30,7 +35,7 @@ extern void oj_dump_xml_time(VALUE obj, Out out);
30
35
  extern void oj_dump_time(VALUE obj, Out out, int withZone);
31
36
  extern void oj_dump_obj_to_s(VALUE obj, Out out);
32
37
 
33
- extern const char *oj_nan_str(VALUE obj, int opt, int mode, bool plus, int *lenp);
38
+ extern const char *oj_nan_str(VALUE obj, int opt, int mode, bool plus, size_t *lenp);
34
39
 
35
40
  // initialize an out buffer with the provided stack allocated memory
36
41
  extern void oj_out_init(Out out);
@@ -53,10 +58,12 @@ extern void oj_dump_raw_json(VALUE obj, int depth, Out out);
53
58
  extern VALUE oj_add_to_json(int argc, VALUE *argv, VALUE self);
54
59
  extern VALUE oj_remove_to_json(int argc, VALUE *argv, VALUE self);
55
60
 
56
- extern int oj_dump_float_printf(char *buf, size_t blen, VALUE obj, double d, const char *format);
61
+ extern size_t oj_dump_float_printf(char *buf, size_t blen, VALUE obj, double d, const char *format);
57
62
 
58
63
  extern time_t oj_sec_from_time_hard_way(VALUE obj);
59
64
 
65
+ extern bool oj_key_skip(VALUE key, const char *only, const char *except);
66
+
60
67
  inline static void assure_size(Out out, size_t len) {
61
68
  if (out->end - out->cur <= (long)len) {
62
69
  oj_grow_out(out, len);
data/ext/oj/dump_compat.c CHANGED
@@ -103,7 +103,7 @@ static void dump_values_array(VALUE *values, int depth, Out out) {
103
103
  static void dump_to_json(VALUE obj, Out out) {
104
104
  volatile VALUE rs;
105
105
  const char *s;
106
- int len;
106
+ size_t len;
107
107
 
108
108
  TRACE(out->opts->trace, "to_json", obj, 0, TraceRubyIn);
109
109
  if (0 == rb_obj_method_arity(obj, oj_to_json_id)) {
@@ -115,7 +115,7 @@ static void dump_to_json(VALUE obj, Out out) {
115
115
 
116
116
  StringValue(rs);
117
117
  s = RSTRING_PTR(rs);
118
- len = (int)RSTRING_LEN(rs);
118
+ len = RSTRING_LEN(rs);
119
119
 
120
120
  assure_size(out, len + 1);
121
121
  APPEND_CHARS(out->cur, s, len);
@@ -124,7 +124,8 @@ static void dump_to_json(VALUE obj, Out out) {
124
124
 
125
125
  static void dump_array(VALUE a, int depth, Out out, bool as_ok) {
126
126
  size_t size;
127
- int i, cnt;
127
+ size_t i;
128
+ size_t cnt;
128
129
  int d2 = depth + 1;
129
130
  long id = oj_check_circular(a, out);
130
131
 
@@ -136,7 +137,7 @@ static void dump_array(VALUE a, int depth, Out out, bool as_ok) {
136
137
  dump_to_json(a, out);
137
138
  return;
138
139
  }
139
- cnt = (int)RARRAY_LEN(a);
140
+ cnt = RARRAY_LEN(a);
140
141
  *out->cur++ = '[';
141
142
  assure_size(out, 2);
142
143
  if (0 == cnt) {
@@ -147,10 +148,10 @@ static void dump_array(VALUE a, int depth, Out out, bool as_ok) {
147
148
  } else {
148
149
  size = d2 * out->indent + 2;
149
150
  }
150
- assure_size(out, size * cnt);
151
151
  cnt--;
152
152
  for (i = 0; i <= cnt; i++) {
153
153
  if (out->opts->dump_opts.use) {
154
+ assure_size(out, size);
154
155
  if (0 < out->opts->dump_opts.array_size) {
155
156
  APPEND_CHARS(out->cur, out->opts->dump_opts.array_nl, out->opts->dump_opts.array_size);
156
157
  }
@@ -161,6 +162,7 @@ static void dump_array(VALUE a, int depth, Out out, bool as_ok) {
161
162
  }
162
163
  }
163
164
  } else {
165
+ assure_size(out, size);
164
166
  fill_indent(out, d2);
165
167
  }
166
168
  oj_dump_compat_val(RARRAY_AREF(a, i), d2, out, true);
@@ -552,7 +554,7 @@ static void dump_float(VALUE obj, int depth, Out out, bool as_ok) {
552
554
  char buf[64];
553
555
  char *b;
554
556
  double d = rb_num2dbl(obj);
555
- int cnt = 0;
557
+ size_t cnt = 0;
556
558
 
557
559
  if (0.0 == d) {
558
560
  b = buf;
@@ -590,7 +592,7 @@ static void dump_float(VALUE obj, int depth, Out out, bool as_ok) {
590
592
  volatile VALUE rstr = oj_safe_string_convert(obj);
591
593
 
592
594
  strcpy(buf, RSTRING_PTR(rstr));
593
- cnt = (int)RSTRING_LEN(rstr);
595
+ cnt = RSTRING_LEN(rstr);
594
596
  }
595
597
  assure_size(out, cnt);
596
598
  APPEND_CHARS(out->cur, buf, cnt);
@@ -604,6 +606,11 @@ static int hash_cb(VALUE key, VALUE value, VALUE ov) {
604
606
  if (out->omit_nil && Qnil == value) {
605
607
  return ST_CONTINUE;
606
608
  }
609
+ if (NULL != out->opts->dump_opts.only || NULL != out->opts->dump_opts.except) {
610
+ if (oj_key_skip(key, out->opts->dump_opts.only, out->opts->dump_opts.except)) {
611
+ return ST_CONTINUE;
612
+ }
613
+ }
607
614
  if (!out->opts->dump_opts.use) {
608
615
  assure_size(out, depth * out->indent + 1);
609
616
  fill_indent(out, depth);
@@ -800,7 +807,7 @@ static void dump_bignum(VALUE obj, int depth, Out out, bool as_ok) {
800
807
  // rb_big2str can not so unless overridden by using add_to_json(Integer)
801
808
  // this must use to_s to pass the json gem unit tests.
802
809
  volatile VALUE rs;
803
- int cnt;
810
+ size_t cnt;
804
811
  bool dump_as_string = false;
805
812
 
806
813
  if (use_bignum_alt) {
@@ -809,7 +816,7 @@ static void dump_bignum(VALUE obj, int depth, Out out, bool as_ok) {
809
816
  rs = oj_safe_string_convert(obj);
810
817
  }
811
818
  rb_check_type(rs, T_STRING);
812
- cnt = (int)RSTRING_LEN(rs);
819
+ cnt = RSTRING_LEN(rs);
813
820
 
814
821
  if (out->opts->int_range_min != 0 || out->opts->int_range_max != 0) {
815
822
  dump_as_string = true; // Bignum cannot be inside of Fixnum range
data/ext/oj/dump_leaf.c CHANGED
@@ -17,7 +17,7 @@ inline static void dump_chars(const char *s, size_t size, Out out) {
17
17
  static void dump_leaf_str(Leaf leaf, Out out) {
18
18
  switch (leaf->value_type) {
19
19
  case STR_VAL: oj_dump_cstr(leaf->str, strlen(leaf->str), 0, 0, out); break;
20
- case RUBY_VAL: oj_dump_cstr(StringValueCStr(leaf->value), (int)RSTRING_LEN(leaf->value), 0, 0, out); break;
20
+ case RUBY_VAL: oj_dump_cstr(StringValueCStr(leaf->value), RSTRING_LEN(leaf->value), 0, 0, out); break;
21
21
  case COL_VAL:
22
22
  default: rb_raise(rb_eTypeError, "Unexpected value type %02x.\n", leaf->value_type); break;
23
23
  }
data/ext/oj/dump_object.c CHANGED
@@ -10,6 +10,24 @@ static const char hex_chars[17] = "0123456789abcdef";
10
10
 
11
11
  static void dump_obj_attrs(VALUE obj, VALUE clas, slot_t id, int depth, Out out);
12
12
 
13
+ // An odd class is dumped as {"^O":class,...} and is rebuilt with a create
14
+ // function when loaded so there is no place to put a "^i" circular id on it.
15
+ // Registering it in the circular cache would consume an id that is never
16
+ // written and any later occurrence would then be dumped as a "^r" that refers
17
+ // to nothing. Instead dump odd classes in full each time they are encountered
18
+ // just like Time, Rational, and Complex are.
19
+ static void dump_circular_obj(VALUE obj, VALUE clas, int depth, Out out) {
20
+ if (NULL != oj_get_odd(clas)) {
21
+ dump_obj_attrs(obj, clas, 0, depth, out);
22
+ } else {
23
+ long id = oj_check_circular(obj, out);
24
+
25
+ if (0 <= id) {
26
+ dump_obj_attrs(obj, clas, id, depth, out);
27
+ }
28
+ }
29
+ }
30
+
13
31
  static void dump_time(VALUE obj, Out out) {
14
32
  switch (out->opts->time_format) {
15
33
  case RubyTime:
@@ -33,7 +51,7 @@ static void dump_data(VALUE obj, int depth, Out out, bool as_ok) {
33
51
  if (oj_bigdecimal_class == clas) {
34
52
  volatile VALUE rstr = oj_safe_string_convert(obj);
35
53
  const char *str = RSTRING_PTR(rstr);
36
- int len = (int)RSTRING_LEN(rstr);
54
+ size_t len = RSTRING_LEN(rstr);
37
55
 
38
56
  if (No != out->opts->bigdec_as_num) {
39
57
  oj_dump_raw(str, len, out);
@@ -47,11 +65,7 @@ static void dump_data(VALUE obj, int depth, Out out, bool as_ok) {
47
65
  oj_dump_cstr(str, len, 0, 0, out);
48
66
  }
49
67
  } else {
50
- long id = oj_check_circular(obj, out);
51
-
52
- if (0 <= id) {
53
- dump_obj_attrs(obj, clas, id, depth, out);
54
- }
68
+ dump_circular_obj(obj, clas, depth, out);
55
69
  }
56
70
  }
57
71
  }
@@ -62,7 +76,7 @@ static void dump_obj(VALUE obj, int depth, Out out, bool as_ok) {
62
76
  if (oj_bigdecimal_class == clas) {
63
77
  volatile VALUE rstr = oj_safe_string_convert(obj);
64
78
  const char *str = RSTRING_PTR(rstr);
65
- int len = (int)RSTRING_LEN(rstr);
79
+ size_t len = RSTRING_LEN(rstr);
66
80
 
67
81
  if (0 == strcasecmp("Infinity", str)) {
68
82
  str = oj_nan_str(obj, out->opts->dump_opts.nan_dump, out->opts->mode, true, &len);
@@ -74,11 +88,7 @@ static void dump_obj(VALUE obj, int depth, Out out, bool as_ok) {
74
88
  oj_dump_raw(str, len, out);
75
89
  }
76
90
  } else {
77
- long id = oj_check_circular(obj, out);
78
-
79
- if (0 <= id) {
80
- dump_obj_attrs(obj, clas, id, depth, out);
81
- }
91
+ dump_circular_obj(obj, clas, depth, out);
82
92
  }
83
93
  }
84
94
 
@@ -95,7 +105,8 @@ static void dump_class(VALUE obj, int depth, Out out, bool as_ok) {
95
105
 
96
106
  static void dump_array_class(VALUE a, VALUE clas, int depth, Out out) {
97
107
  size_t size;
98
- int i, cnt;
108
+ size_t i;
109
+ size_t cnt;
99
110
  int d2 = depth + 1;
100
111
  long id = oj_check_circular(a, out);
101
112
 
@@ -106,7 +117,7 @@ static void dump_array_class(VALUE a, VALUE clas, int depth, Out out) {
106
117
  dump_obj_attrs(a, clas, 0, depth, out);
107
118
  return;
108
119
  }
109
- cnt = (int)RARRAY_LEN(a);
120
+ cnt = RARRAY_LEN(a);
110
121
  *out->cur++ = '[';
111
122
  if (0 < id) {
112
123
  assure_size(out, d2 * out->indent + 16);
@@ -181,7 +192,7 @@ static void dump_str_class(VALUE obj, VALUE clas, int depth, Out out) {
181
192
  dump_obj_attrs(obj, clas, 0, depth, out);
182
193
  } else {
183
194
  const char *s = RSTRING_PTR(obj);
184
- size_t len = (int)RSTRING_LEN(obj);
195
+ size_t len = RSTRING_LEN(obj);
185
196
  char s1 = s[1];
186
197
 
187
198
  oj_dump_cstr(s, len, 0, (':' == *s || ('^' == *s && ('r' == s1 || 'i' == s1))), out);
@@ -195,7 +206,7 @@ static void dump_str(VALUE obj, int depth, Out out, bool as_ok) {
195
206
  static void dump_sym(VALUE obj, int depth, Out out, bool as_ok) {
196
207
  volatile VALUE s = rb_sym2str(obj);
197
208
 
198
- oj_dump_cstr(RSTRING_PTR(s), (int)RSTRING_LEN(s), 1, 0, out);
209
+ oj_dump_cstr(RSTRING_PTR(s), RSTRING_LEN(s), 1, 0, out);
199
210
  }
200
211
 
201
212
  static int hash_cb(VALUE key, VALUE value, VALUE ov) {
@@ -209,6 +220,11 @@ static int hash_cb(VALUE key, VALUE value, VALUE ov) {
209
220
  if (out->omit_nil && Qnil == value) {
210
221
  return ST_CONTINUE;
211
222
  }
223
+ if (NULL != out->opts->dump_opts.only || NULL != out->opts->dump_opts.except) {
224
+ if (oj_key_skip(key, out->opts->dump_opts.only, out->opts->dump_opts.except)) {
225
+ return ST_CONTINUE;
226
+ }
227
+ }
212
228
  assure_size(out, size);
213
229
  fill_indent(out, depth);
214
230
  switch (rb_type(key)) {
@@ -389,7 +405,7 @@ static void dump_odd(VALUE obj, Odd odd, VALUE clas, int depth, Out out) {
389
405
  rb_raise(rb_eEncodingError, "Invalid type for raw JSON.");
390
406
  } else {
391
407
  const char *s = RSTRING_PTR(v);
392
- int len = (int)RSTRING_LEN(v);
408
+ size_t len = RSTRING_LEN(v);
393
409
  const char *name = rb_id2name(*odd->attrs);
394
410
  size_t nlen = strlen(name);
395
411
 
@@ -489,7 +505,7 @@ static void dump_obj_attrs(VALUE obj, VALUE clas, slot_t id, int depth, Out out)
489
505
  *out->cur++ = ',';
490
506
  fill_indent(out, d2);
491
507
  APPEND_CHARS(out->cur, "\"self\":", 7);
492
- oj_dump_cstr(RSTRING_PTR(obj), (int)RSTRING_LEN(obj), 0, 0, out);
508
+ oj_dump_cstr(RSTRING_PTR(obj), RSTRING_LEN(obj), 0, 0, out);
493
509
  break;
494
510
  case T_ARRAY:
495
511
  assure_size(out, d2 * out->indent + 14);
@@ -564,11 +580,12 @@ static void dump_regexp(VALUE obj, int depth, Out out, bool as_ok) {
564
580
  static void dump_struct(VALUE obj, int depth, Out out, bool as_ok) {
565
581
  VALUE clas = rb_obj_class(obj);
566
582
  const char *class_name = rb_class2name(clas);
567
- int i;
568
- int d2 = depth + 1;
569
- int d3 = d2 + 1;
570
- size_t len = strlen(class_name);
571
- size_t size = d2 * out->indent + d3 * out->indent + 10 + len;
583
+ size_t i;
584
+ int d2 = depth + 1;
585
+ int d3 = d2 + 1;
586
+ size_t len = strlen(class_name);
587
+ size_t size = d2 * out->indent + d3 * out->indent + 10 + len;
588
+ char circular = out->opts->circular;
572
589
 
573
590
  assure_size(out, size);
574
591
  *out->cur++ = '{';
@@ -577,14 +594,14 @@ static void dump_struct(VALUE obj, int depth, Out out, bool as_ok) {
577
594
  if ('#' == *class_name) {
578
595
  VALUE ma = rb_struct_s_members(clas);
579
596
  const char *name;
580
- int cnt = (int)RARRAY_LEN(ma);
597
+ size_t cnt = RARRAY_LEN(ma);
581
598
 
582
599
  *out->cur++ = '[';
583
600
  for (i = 0; i < cnt; i++) {
584
601
  volatile VALUE s = rb_sym2str(RARRAY_AREF(ma, i));
585
602
 
586
603
  name = RSTRING_PTR(s);
587
- len = (int)RSTRING_LEN(s);
604
+ len = RSTRING_LEN(s);
588
605
  size = len + 3;
589
606
  assure_size(out, size);
590
607
  if (0 < i) {
@@ -607,14 +624,18 @@ static void dump_struct(VALUE obj, int depth, Out out, bool as_ok) {
607
624
  {
608
625
  VALUE v;
609
626
  int cnt;
627
+
610
628
  #if RSTRUCT_LEN_RETURNS_INTEGER_OBJECT
611
629
  cnt = (int)NUM2LONG(RSTRUCT_LEN(obj));
612
630
  #else // RSTRUCT_LEN_RETURNS_INTEGER_OBJECT
613
631
  cnt = (int)RSTRUCT_LEN(obj);
614
632
  #endif // RSTRUCT_LEN_RETURNS_INTEGER_OBJECT
615
633
 
616
- for (i = 0; i < cnt; i++) {
617
- v = RSTRUCT_GET(obj, i);
634
+ if (0 == strcmp(class_name, "Range")) {
635
+ out->opts->circular = 'n';
636
+ }
637
+ for (i = 0; i < (size_t)cnt; i++) {
638
+ v = RSTRUCT_GET(obj, (int)i);
618
639
  if (dump_ignore(out->opts, v)) {
619
640
  v = Qnil;
620
641
  }
@@ -630,6 +651,9 @@ static void dump_struct(VALUE obj, int depth, Out out, bool as_ok) {
630
651
  // class in interpreted Ruby so length() may not be defined.
631
652
  int slen = FIX2INT(rb_funcall2(obj, oj_length_id, 0, 0));
632
653
 
654
+ if (0 == strcmp(class_name, "Range")) {
655
+ out->opts->circular = 'n';
656
+ }
633
657
  for (i = 0; i < slen; i++) {
634
658
  assure_size(out, size);
635
659
  fill_indent(out, d3);
@@ -641,6 +665,7 @@ static void dump_struct(VALUE obj, int depth, Out out, bool as_ok) {
641
665
  }
642
666
  }
643
667
  #endif
668
+ out->opts->circular = circular;
644
669
  out->cur--;
645
670
  APPEND_CHARS(out->cur, "]}", 2);
646
671
  *out->cur = '\0';
data/ext/oj/dump_strict.c CHANGED
@@ -30,7 +30,7 @@ static void dump_float(VALUE obj, int depth, Out out, bool as_ok) {
30
30
  char buf[64];
31
31
  char* b;
32
32
  double d = rb_num2dbl(obj);
33
- int cnt = 0;
33
+ size_t cnt = 0;
34
34
 
35
35
  if (0.0 == d) {
36
36
  b = buf;
@@ -92,7 +92,7 @@ static void dump_float(VALUE obj, int depth, Out out, bool as_ok) {
92
92
  } else if (0 == out->opts->float_prec) {
93
93
  volatile VALUE rstr = oj_safe_string_convert(obj);
94
94
 
95
- cnt = (int)RSTRING_LEN(rstr);
95
+ cnt = RSTRING_LEN(rstr);
96
96
  if ((int)sizeof(buf) <= cnt) {
97
97
  cnt = sizeof(buf) - 1;
98
98
  }
@@ -109,7 +109,8 @@ static void dump_float(VALUE obj, int depth, Out out, bool as_ok) {
109
109
 
110
110
  static void dump_array(VALUE a, int depth, Out out, bool as_ok) {
111
111
  size_t size;
112
- int i, cnt;
112
+ size_t i;
113
+ size_t cnt;
113
114
  int d2 = depth + 1;
114
115
 
115
116
  if (Yes == out->opts->circular) {
@@ -118,7 +119,7 @@ static void dump_array(VALUE a, int depth, Out out, bool as_ok) {
118
119
  return;
119
120
  }
120
121
  }
121
- cnt = (int)RARRAY_LEN(a);
122
+ cnt = RARRAY_LEN(a);
122
123
  *out->cur++ = '[';
123
124
  size = 2;
124
125
  assure_size(out, size);
@@ -192,14 +193,19 @@ static int hash_cb(VALUE key, VALUE value, VALUE ov) {
192
193
  if (out->omit_nil && Qnil == value) {
193
194
  return ST_CONTINUE;
194
195
  }
196
+ if (NULL != out->opts->dump_opts.only || NULL != out->opts->dump_opts.except) {
197
+ if (oj_key_skip(key, out->opts->dump_opts.only, out->opts->dump_opts.except)) {
198
+ return ST_CONTINUE;
199
+ }
200
+ }
195
201
  if (!out->opts->dump_opts.use) {
196
202
  size = depth * out->indent + 1;
197
203
  assure_size(out, size);
198
204
  fill_indent(out, depth);
199
- if (rtype == T_STRING) {
200
- oj_dump_str(key, 0, out, false);
201
- } else {
202
- oj_dump_sym(key, 0, out, false);
205
+ switch (rtype) {
206
+ case T_STRING: oj_dump_str(key, 0, out, false); break;
207
+ case T_SYMBOL: oj_dump_sym(key, 0, out, false); break;
208
+ default: oj_dump_str(oj_safe_string_convert(key), 0, out, false); break;
203
209
  }
204
210
  *out->cur++ = ':';
205
211
  } else {
@@ -214,10 +220,10 @@ static int hash_cb(VALUE key, VALUE value, VALUE ov) {
214
220
  APPEND_CHARS(out->cur, out->opts->dump_opts.indent_str, out->opts->dump_opts.indent_size);
215
221
  }
216
222
  }
217
- if (rtype == T_STRING) {
218
- oj_dump_str(key, 0, out, false);
219
- } else {
220
- oj_dump_sym(key, 0, out, false);
223
+ switch (rtype) {
224
+ case T_STRING: oj_dump_str(key, 0, out, false); break;
225
+ case T_SYMBOL: oj_dump_sym(key, 0, out, false); break;
226
+ default: oj_dump_str(oj_safe_string_convert(key), 0, out, false); break;
221
227
  }
222
228
  size = out->opts->dump_opts.before_size + out->opts->dump_opts.after_size + 2;
223
229
  assure_size(out, size);
@@ -290,7 +296,7 @@ static void dump_data_strict(VALUE obj, int depth, Out out, bool as_ok) {
290
296
  if (oj_bigdecimal_class == clas) {
291
297
  volatile VALUE rstr = oj_safe_string_convert(obj);
292
298
 
293
- oj_dump_raw(RSTRING_PTR(rstr), (int)RSTRING_LEN(rstr), out);
299
+ oj_dump_raw(RSTRING_PTR(rstr), RSTRING_LEN(rstr), out);
294
300
  } else {
295
301
  raise_strict(obj);
296
302
  }
@@ -302,7 +308,7 @@ static void dump_data_null(VALUE obj, int depth, Out out, bool as_ok) {
302
308
  if (oj_bigdecimal_class == clas) {
303
309
  volatile VALUE rstr = oj_safe_string_convert(obj);
304
310
 
305
- oj_dump_raw(RSTRING_PTR(rstr), (int)RSTRING_LEN(rstr), out);
311
+ oj_dump_raw(RSTRING_PTR(rstr), RSTRING_LEN(rstr), out);
306
312
  } else {
307
313
  oj_dump_nil(Qnil, depth, out, false);
308
314
  }
data/ext/oj/extconf.rb CHANGED
@@ -29,20 +29,22 @@ dflags = {
29
29
  have_func('rb_gc_mark_movable')
30
30
  have_func('stpcpy')
31
31
  have_func('pthread_mutex_init')
32
+ have_func('getrlimit', 'sys/resource.h')
32
33
  have_func('rb_enc_interned_str')
33
34
  have_func('rb_ext_ractor_safe', 'ruby.h')
34
- # rb_hash_bulk_insert is deep down in a header not included in normal build and that seems to fool have_func.
35
- have_func('rb_hash_bulk_insert', 'ruby.h') unless '2' == version[0] && '6' == version[1]
36
35
 
37
36
  dflags['OJ_DEBUG'] = true unless ENV['OJ_DEBUG'].nil?
38
37
 
39
- if with_config('--with-sse42')
40
- if try_cflags('-msse4.2')
41
- $CPPFLAGS += ' -msse4.2'
42
- dflags['OJ_USE_SSE4_2'] = 1
43
- else
44
- warn 'SSE 4.2 is not supported on this platform.'
45
- end
38
+ # SIMD optimizations use runtime CPU detection and function-level target attributes
39
+ # We do NOT add global -msse4.2/-msse2 flags here because:
40
+ # 1. It would cause illegal instruction errors on CPUs without SSE4.2
41
+ # 2. The code uses __attribute__((target("sse4.2"))) for SSE4.2 functions
42
+ # 3. Runtime detection in oj_get_simd_implementation() selects the right path
43
+ #
44
+ # We only add -msse2 if available, since SSE2 is baseline for all x86_64 CPUs
45
+ # and needed for compiling the SSE2 fallback code on 32-bit x86
46
+ if try_cflags('-msse2')
47
+ $CPPFLAGS += ' -msse2'
46
48
  end
47
49
 
48
50
  if enable_config('trace-log', false)