oj 3.13.7 → 3.13.23

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 (83) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +75 -0
  3. data/README.md +11 -0
  4. data/ext/oj/buf.h +4 -0
  5. data/ext/oj/circarray.c +1 -1
  6. data/ext/oj/code.c +15 -22
  7. data/ext/oj/compat.c +10 -10
  8. data/ext/oj/custom.c +66 -112
  9. data/ext/oj/dump.c +147 -184
  10. data/ext/oj/dump.h +25 -8
  11. data/ext/oj/dump_compat.c +47 -89
  12. data/ext/oj/dump_leaf.c +14 -58
  13. data/ext/oj/dump_object.c +72 -188
  14. data/ext/oj/dump_strict.c +19 -31
  15. data/ext/oj/encoder.c +43 -0
  16. data/ext/oj/extconf.rb +5 -4
  17. data/ext/oj/fast.c +36 -24
  18. data/ext/oj/intern.c +22 -12
  19. data/ext/oj/intern.h +1 -1
  20. data/ext/oj/mimic_json.c +74 -73
  21. data/ext/oj/object.c +54 -72
  22. data/ext/oj/odd.c +83 -63
  23. data/ext/oj/odd.h +13 -13
  24. data/ext/oj/oj.c +166 -175
  25. data/ext/oj/oj.h +25 -3
  26. data/ext/oj/parse.c +123 -79
  27. data/ext/oj/parse.h +2 -0
  28. data/ext/oj/parser.c +77 -21
  29. data/ext/oj/parser.h +12 -0
  30. data/ext/oj/rails.c +46 -70
  31. data/ext/oj/rails.h +1 -1
  32. data/ext/oj/reader.c +2 -0
  33. data/ext/oj/saj.c +11 -23
  34. data/ext/oj/saj2.c +333 -85
  35. data/ext/oj/saj2.h +23 -0
  36. data/ext/oj/sparse.c +4 -0
  37. data/ext/oj/stream_writer.c +3 -1
  38. data/ext/oj/strict.c +13 -13
  39. data/ext/oj/string_writer.c +12 -5
  40. data/ext/oj/usual.c +86 -131
  41. data/ext/oj/usual.h +68 -0
  42. data/ext/oj/val_stack.c +1 -1
  43. data/ext/oj/validate.c +21 -26
  44. data/ext/oj/wab.c +22 -27
  45. data/lib/oj/saj.rb +20 -6
  46. data/lib/oj/state.rb +1 -1
  47. data/lib/oj/version.rb +1 -1
  48. data/pages/Compatibility.md +1 -1
  49. data/pages/JsonGem.md +15 -0
  50. data/pages/Modes.md +6 -3
  51. data/pages/Options.md +6 -0
  52. data/pages/Rails.md +12 -0
  53. data/test/activesupport7/abstract_unit.rb +49 -0
  54. data/test/activesupport7/decoding_test.rb +125 -0
  55. data/test/activesupport7/encoding_test.rb +486 -0
  56. data/test/activesupport7/encoding_test_cases.rb +104 -0
  57. data/test/activesupport7/time_zone_test_helpers.rb +47 -0
  58. data/test/bar.rb +3 -8
  59. data/test/bug.rb +16 -0
  60. data/test/foo.rb +71 -7
  61. data/test/helper.rb +8 -2
  62. data/test/json_gem/json_generator_test.rb +5 -4
  63. data/test/json_gem/json_parser_test.rb +8 -1
  64. data/test/json_gem/test_helper.rb +7 -3
  65. data/test/perf_dump.rb +50 -0
  66. data/test/test_compat.rb +25 -0
  67. data/test/test_custom.rb +13 -2
  68. data/test/test_fast.rb +37 -7
  69. data/test/test_file.rb +23 -7
  70. data/test/test_gc.rb +11 -0
  71. data/test/test_object.rb +8 -10
  72. data/test/test_parser.rb +3 -19
  73. data/test/test_parser_debug.rb +27 -0
  74. data/test/test_parser_saj.rb +92 -2
  75. data/test/test_saj.rb +1 -1
  76. data/test/test_scp.rb +2 -4
  77. data/test/test_strict.rb +2 -0
  78. data/test/test_various.rb +32 -2
  79. data/test/test_wab.rb +2 -0
  80. data/test/tests.rb +9 -1
  81. data/test/tests_mimic.rb +9 -0
  82. data/test/tests_mimic_addition.rb +9 -0
  83. metadata +15 -115
data/ext/oj/dump.h CHANGED
@@ -32,6 +32,11 @@ extern void oj_dump_obj_to_s(VALUE obj, Out out);
32
32
 
33
33
  extern const char *oj_nan_str(VALUE obj, int opt, int mode, bool plus, int *lenp);
34
34
 
35
+ // initialize an out buffer with the provided stack allocated memory
36
+ extern void oj_out_init(Out out);
37
+ // clean up the out buffer if it uses heap allocated memory
38
+ extern void oj_out_free(Out out);
39
+
35
40
  extern void oj_grow_out(Out out, size_t len);
36
41
  extern long oj_check_circular(VALUE obj, Out out);
37
42
 
@@ -50,7 +55,6 @@ extern VALUE oj_remove_to_json(int argc, VALUE *argv, VALUE self);
50
55
 
51
56
  extern int oj_dump_float_printf(char *buf, size_t blen, VALUE obj, double d, const char *format);
52
57
 
53
- extern bool oj_dump_ignore(Options opts, VALUE obj);
54
58
  extern time_t oj_sec_from_time_hard_way(VALUE obj);
55
59
 
56
60
  inline static void assure_size(Out out, size_t len) {
@@ -63,15 +67,29 @@ inline static void fill_indent(Out out, int cnt) {
63
67
  if (0 < out->indent) {
64
68
  cnt *= out->indent;
65
69
  *out->cur++ = '\n';
66
- for (; 0 < cnt; cnt--) {
67
- *out->cur++ = ' ';
70
+ memset(out->cur, ' ', cnt);
71
+ out->cur += cnt;
72
+ }
73
+ }
74
+
75
+ inline static bool dump_ignore(Options opts, VALUE obj) {
76
+ if (NULL != opts->ignore && (ObjectMode == opts->mode || CustomMode == opts->mode)) {
77
+ VALUE *vp = opts->ignore;
78
+ VALUE clas = rb_obj_class(obj);
79
+
80
+ for (; Qnil != *vp; vp++) {
81
+ if (clas == *vp) {
82
+ return true;
83
+ }
68
84
  }
69
85
  }
86
+ return false;
70
87
  }
71
88
 
72
89
  inline static void dump_ulong(unsigned long num, Out out) {
73
- char buf[32];
74
- char *b = buf + sizeof(buf) - 1;
90
+ char buf[32];
91
+ char *b = buf + sizeof(buf) - 1;
92
+ size_t cnt = 0;
75
93
 
76
94
  *b-- = '\0';
77
95
  if (0 < num) {
@@ -82,9 +100,8 @@ inline static void dump_ulong(unsigned long num, Out out) {
82
100
  } else {
83
101
  *b = '0';
84
102
  }
85
- for (; '\0' != *b; b++) {
86
- *out->cur++ = *b;
87
- }
103
+ cnt = sizeof(buf) - (b - buf) - 1;
104
+ APPEND_CHARS(out->cur, b, cnt);
88
105
  *out->cur = '\0';
89
106
  }
90
107
 
data/ext/oj/dump_compat.c CHANGED
@@ -32,21 +32,17 @@ dump_obj_classname(const char *classname, int depth, Out out) {
32
32
  *out->cur++ = '{';
33
33
  fill_indent(out, d2);
34
34
  *out->cur++ = '"';
35
- memcpy(out->cur, out->opts->create_id, out->opts->create_id_len);
36
- out->cur += out->opts->create_id_len;
35
+ APPEND_CHARS(out->cur, out->opts->create_id, out->opts->create_id_len);
37
36
  *out->cur++ = '"';
38
37
  if (0 < out->opts->dump_opts.before_size) {
39
- strcpy(out->cur, out->opts->dump_opts.before_sep);
40
- out->cur += out->opts->dump_opts.before_size;
38
+ APPEND_CHARS(out->cur, out->opts->dump_opts.before_sep, out->opts->dump_opts.before_size);
41
39
  }
42
40
  *out->cur++ = ':';
43
41
  if (0 < out->opts->dump_opts.after_size) {
44
- strcpy(out->cur, out->opts->dump_opts.after_sep);
45
- out->cur += out->opts->dump_opts.after_size;
42
+ APPEND_CHARS(out->cur, out->opts->dump_opts.after_sep, out->opts->dump_opts.after_size);
46
43
  }
47
44
  *out->cur++ = '"';
48
- memcpy(out->cur, classname, len);
49
- out->cur += len;
45
+ APPEND_CHARS(out->cur, classname, len);
50
46
  *out->cur++ = '"';
51
47
  }
52
48
 
@@ -71,15 +67,13 @@ dump_values_array(VALUE *values, int depth, Out out) {
71
67
  assure_size(out, size);
72
68
  if (out->opts->dump_opts.use) {
73
69
  if (0 < out->opts->dump_opts.array_size) {
74
- strcpy(out->cur, out->opts->dump_opts.array_nl);
75
- out->cur += out->opts->dump_opts.array_size;
70
+ APPEND_CHARS(out->cur, out->opts->dump_opts.array_nl, out->opts->dump_opts.array_size);
76
71
  }
77
72
  if (0 < out->opts->dump_opts.indent_size) {
78
73
  int i;
79
74
 
80
75
  for (i = d2; 0 < i; i--) {
81
- strcpy(out->cur, out->opts->dump_opts.indent_str);
82
- out->cur += out->opts->dump_opts.indent_size;
76
+ APPEND_CHARS(out->cur, out->opts->dump_opts.indent_str, out->opts->dump_opts.indent_size);
83
77
  }
84
78
  }
85
79
  } else {
@@ -93,15 +87,13 @@ dump_values_array(VALUE *values, int depth, Out out) {
93
87
  assure_size(out, size);
94
88
  if (out->opts->dump_opts.use) {
95
89
  if (0 < out->opts->dump_opts.array_size) {
96
- strcpy(out->cur, out->opts->dump_opts.array_nl);
97
- out->cur += out->opts->dump_opts.array_size;
90
+ APPEND_CHARS(out->cur, out->opts->dump_opts.array_nl, out->opts->dump_opts.array_size);
98
91
  }
99
92
  if (0 < out->opts->dump_opts.indent_size) {
100
93
  int i;
101
94
 
102
95
  for (i = depth; 0 < i; i--) {
103
- strcpy(out->cur, out->opts->dump_opts.indent_str);
104
- out->cur += out->opts->dump_opts.indent_size;
96
+ APPEND_CHARS(out->cur, out->opts->dump_opts.indent_str, out->opts->dump_opts.indent_size);
105
97
  }
106
98
  }
107
99
  } else {
@@ -117,7 +109,7 @@ dump_to_json(VALUE obj, Out out) {
117
109
  const char *s;
118
110
  int len;
119
111
 
120
- if (Yes == out->opts->trace) {
112
+ if (RB_UNLIKELY(Yes == out->opts->trace)) {
121
113
  oj_trace("to_json", obj, __FILE__, __LINE__, 0, TraceRubyIn);
122
114
  }
123
115
  if (0 == rb_obj_method_arity(obj, oj_to_json_id)) {
@@ -125,7 +117,7 @@ dump_to_json(VALUE obj, Out out) {
125
117
  } else {
126
118
  rs = rb_funcall2(obj, oj_to_json_id, out->argc, out->argv);
127
119
  }
128
- if (Yes == out->opts->trace) {
120
+ if (RB_UNLIKELY(Yes == out->opts->trace)) {
129
121
  oj_trace("to_json", obj, __FILE__, __LINE__, 0, TraceRubyOut);
130
122
  }
131
123
 
@@ -133,8 +125,7 @@ dump_to_json(VALUE obj, Out out) {
133
125
  len = (int)RSTRING_LEN(rs);
134
126
 
135
127
  assure_size(out, len + 1);
136
- memcpy(out->cur, s, len);
137
- out->cur += len;
128
+ APPEND_CHARS(out->cur, s, len);
138
129
  *out->cur = '\0';
139
130
  }
140
131
 
@@ -164,25 +155,23 @@ dump_array(VALUE a, int depth, Out out, bool as_ok) {
164
155
  } else {
165
156
  size = d2 * out->indent + 2;
166
157
  }
158
+ assure_size(out, size * cnt);
167
159
  cnt--;
168
160
  for (i = 0; i <= cnt; i++) {
169
- assure_size(out, size);
170
161
  if (out->opts->dump_opts.use) {
171
162
  if (0 < out->opts->dump_opts.array_size) {
172
- strcpy(out->cur, out->opts->dump_opts.array_nl);
173
- out->cur += out->opts->dump_opts.array_size;
163
+ APPEND_CHARS(out->cur, out->opts->dump_opts.array_nl, out->opts->dump_opts.array_size);
174
164
  }
175
165
  if (0 < out->opts->dump_opts.indent_size) {
176
166
  int i;
177
167
  for (i = d2; 0 < i; i--) {
178
- strcpy(out->cur, out->opts->dump_opts.indent_str);
179
- out->cur += out->opts->dump_opts.indent_size;
168
+ APPEND_CHARS(out->cur, out->opts->dump_opts.indent_str, out->opts->dump_opts.indent_size);
180
169
  }
181
170
  }
182
171
  } else {
183
172
  fill_indent(out, d2);
184
173
  }
185
- oj_dump_compat_val(rb_ary_entry(a, i), d2, out, true);
174
+ oj_dump_compat_val(RARRAY_AREF(a, i), d2, out, true);
186
175
  if (i < cnt) {
187
176
  *out->cur++ = ',';
188
177
  }
@@ -191,15 +180,13 @@ dump_array(VALUE a, int depth, Out out, bool as_ok) {
191
180
  size = out->opts->dump_opts.array_size + out->opts->dump_opts.indent_size * depth + 1;
192
181
  assure_size(out, size);
193
182
  if (0 < out->opts->dump_opts.array_size) {
194
- strcpy(out->cur, out->opts->dump_opts.array_nl);
195
- out->cur += out->opts->dump_opts.array_size;
183
+ APPEND_CHARS(out->cur, out->opts->dump_opts.array_nl, out->opts->dump_opts.array_size);
196
184
  }
197
185
  if (0 < out->opts->dump_opts.indent_size) {
198
186
  int i;
199
187
 
200
188
  for (i = depth; 0 < i; i--) {
201
- strcpy(out->cur, out->opts->dump_opts.indent_str);
202
- out->cur += out->opts->dump_opts.indent_size;
189
+ APPEND_CHARS(out->cur, out->opts->dump_opts.indent_str, out->opts->dump_opts.indent_size);
203
190
  }
204
191
  }
205
192
  } else {
@@ -336,33 +323,25 @@ exception_alt(VALUE obj, int depth, Out out) {
336
323
  assure_size(out, size + sep_len + 6);
337
324
  *out->cur++ = ',';
338
325
  fill_indent(out, d3);
339
- *out->cur++ = '"';
340
- *out->cur++ = 'm';
341
- *out->cur++ = '"';
326
+ APPEND_CHARS(out->cur, "\"m\"", 3);
342
327
  if (0 < out->opts->dump_opts.before_size) {
343
- strcpy(out->cur, out->opts->dump_opts.before_sep);
344
- out->cur += out->opts->dump_opts.before_size;
328
+ APPEND_CHARS(out->cur, out->opts->dump_opts.before_sep, out->opts->dump_opts.before_size);
345
329
  }
346
330
  *out->cur++ = ':';
347
331
  if (0 < out->opts->dump_opts.after_size) {
348
- strcpy(out->cur, out->opts->dump_opts.after_sep);
349
- out->cur += out->opts->dump_opts.after_size;
332
+ APPEND_CHARS(out->cur, out->opts->dump_opts.after_sep, out->opts->dump_opts.after_size);
350
333
  }
351
334
  oj_dump_str(rb_funcall(obj, message_id, 0), 0, out, false);
352
335
  assure_size(out, size + sep_len + 6);
353
336
  *out->cur++ = ',';
354
337
  fill_indent(out, d3);
355
- *out->cur++ = '"';
356
- *out->cur++ = 'b';
357
- *out->cur++ = '"';
338
+ APPEND_CHARS(out->cur, "\"b\"", 3);
358
339
  if (0 < out->opts->dump_opts.before_size) {
359
- strcpy(out->cur, out->opts->dump_opts.before_sep);
360
- out->cur += out->opts->dump_opts.before_size;
340
+ APPEND_CHARS(out->cur, out->opts->dump_opts.before_sep, out->opts->dump_opts.before_size);
361
341
  }
362
342
  *out->cur++ = ':';
363
343
  if (0 < out->opts->dump_opts.after_size) {
364
- strcpy(out->cur, out->opts->dump_opts.after_sep);
365
- out->cur += out->opts->dump_opts.after_size;
344
+ APPEND_CHARS(out->cur, out->opts->dump_opts.after_sep, out->opts->dump_opts.after_size);
366
345
  }
367
346
  dump_array(rb_funcall(obj, backtrace_id, 0), depth, out, false);
368
347
  fill_indent(out, depth);
@@ -398,17 +377,13 @@ range_alt(VALUE obj, int depth, Out out) {
398
377
  assure_size(out, size + sep_len + 6);
399
378
  *out->cur++ = ',';
400
379
  fill_indent(out, d3);
401
- *out->cur++ = '"';
402
- *out->cur++ = 'a';
403
- *out->cur++ = '"';
380
+ APPEND_CHARS(out->cur, "\"a\"", 3);
404
381
  if (0 < out->opts->dump_opts.before_size) {
405
- strcpy(out->cur, out->opts->dump_opts.before_sep);
406
- out->cur += out->opts->dump_opts.before_size;
382
+ APPEND_CHARS(out->cur, out->opts->dump_opts.before_sep, out->opts->dump_opts.before_size);
407
383
  }
408
384
  *out->cur++ = ':';
409
385
  if (0 < out->opts->dump_opts.after_size) {
410
- strcpy(out->cur, out->opts->dump_opts.after_sep);
411
- out->cur += out->opts->dump_opts.after_size;
386
+ APPEND_CHARS(out->cur, out->opts->dump_opts.after_sep, out->opts->dump_opts.after_size);
412
387
  }
413
388
  args[0] = rb_funcall(obj, oj_begin_id, 0);
414
389
  args[1] = rb_funcall(obj, oj_end_id, 0);
@@ -469,20 +444,15 @@ time_alt(VALUE obj, int depth, Out out) {
469
444
  time_t sec;
470
445
  long long nsec;
471
446
 
472
- #ifdef HAVE_RB_TIME_TIMESPEC
473
447
  if (16 <= sizeof(struct timespec)) {
474
448
  struct timespec ts = rb_time_timespec(obj);
475
449
 
476
450
  sec = (long long)ts.tv_sec;
477
451
  nsec = ts.tv_nsec;
478
452
  } else {
479
- sec = rb_num2ll(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
480
- nsec = rb_num2ll(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
453
+ sec = NUM2LL(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
454
+ nsec = NUM2LL(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
481
455
  }
482
- #else
483
- sec = rb_num2ll(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
484
- nsec = rb_num2ll(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
485
- #endif
486
456
 
487
457
  attrs[0].num = sec;
488
458
  attrs[1].num = nsec;
@@ -613,18 +583,21 @@ dump_float(VALUE obj, int depth, Out out, bool as_ok) {
613
583
  } else if (OJ_INFINITY == d) {
614
584
  if (WordNan == out->opts->dump_opts.nan_dump) {
615
585
  strcpy(buf, "Infinity");
586
+ cnt = 8;
616
587
  } else {
617
588
  raise_json_err("Infinity not allowed in JSON.", "GeneratorError");
618
589
  }
619
590
  } else if (-OJ_INFINITY == d) {
620
591
  if (WordNan == out->opts->dump_opts.nan_dump) {
621
592
  strcpy(buf, "-Infinity");
593
+ cnt = 9;
622
594
  } else {
623
595
  raise_json_err("-Infinity not allowed in JSON.", "GeneratorError");
624
596
  }
625
597
  } else if (isnan(d)) {
626
598
  if (WordNan == out->opts->dump_opts.nan_dump) {
627
599
  strcpy(buf, "NaN");
600
+ cnt = 3;
628
601
  } else {
629
602
  raise_json_err("NaN not allowed in JSON.", "GeneratorError");
630
603
  }
@@ -639,9 +612,7 @@ dump_float(VALUE obj, int depth, Out out, bool as_ok) {
639
612
  cnt = (int)RSTRING_LEN(rstr);
640
613
  }
641
614
  assure_size(out, cnt);
642
- for (b = buf; '\0' != *b; b++) {
643
- *out->cur++ = *b;
644
- }
615
+ APPEND_CHARS(out->cur, buf, cnt);
645
616
  *out->cur = '\0';
646
617
  }
647
618
 
@@ -659,14 +630,12 @@ hash_cb(VALUE key, VALUE value, VALUE ov) {
659
630
  } else {
660
631
  assure_size(out, depth * out->opts->dump_opts.indent_size + out->opts->dump_opts.hash_size + 1);
661
632
  if (0 < out->opts->dump_opts.hash_size) {
662
- strcpy(out->cur, out->opts->dump_opts.hash_nl);
663
- out->cur += out->opts->dump_opts.hash_size;
633
+ APPEND_CHARS(out->cur, out->opts->dump_opts.hash_nl, out->opts->dump_opts.hash_size);
664
634
  }
665
635
  if (0 < out->opts->dump_opts.indent_size) {
666
636
  int i;
667
637
  for (i = depth; 0 < i; i--) {
668
- strcpy(out->cur, out->opts->dump_opts.indent_str);
669
- out->cur += out->opts->dump_opts.indent_size;
638
+ APPEND_CHARS(out->cur, out->opts->dump_opts.indent_str, out->opts->dump_opts.indent_size);
670
639
  }
671
640
  }
672
641
  }
@@ -687,13 +656,11 @@ hash_cb(VALUE key, VALUE value, VALUE ov) {
687
656
  } else {
688
657
  assure_size(out, out->opts->dump_opts.before_size + out->opts->dump_opts.after_size + 2);
689
658
  if (0 < out->opts->dump_opts.before_size) {
690
- strcpy(out->cur, out->opts->dump_opts.before_sep);
691
- out->cur += out->opts->dump_opts.before_size;
659
+ APPEND_CHARS(out->cur, out->opts->dump_opts.before_sep, out->opts->dump_opts.before_size);
692
660
  }
693
661
  *out->cur++ = ':';
694
662
  if (0 < out->opts->dump_opts.after_size) {
695
- strcpy(out->cur, out->opts->dump_opts.after_sep);
696
- out->cur += out->opts->dump_opts.after_size;
663
+ APPEND_CHARS(out->cur, out->opts->dump_opts.after_sep, out->opts->dump_opts.after_size);
697
664
  }
698
665
  }
699
666
  oj_dump_compat_val(value, depth, out, true);
@@ -719,8 +686,7 @@ dump_hash(VALUE obj, int depth, Out out, bool as_ok) {
719
686
  cnt = (int)RHASH_SIZE(obj);
720
687
  assure_size(out, 2);
721
688
  if (0 == cnt) {
722
- *out->cur++ = '{';
723
- *out->cur++ = '}';
689
+ APPEND_CHARS(out->cur, "{}", 2);
724
690
  } else {
725
691
  *out->cur++ = '{';
726
692
  out->depth = depth + 1;
@@ -734,15 +700,13 @@ dump_hash(VALUE obj, int depth, Out out, bool as_ok) {
734
700
  } else {
735
701
  assure_size(out, depth * out->opts->dump_opts.indent_size + out->opts->dump_opts.hash_size + 1);
736
702
  if (0 < out->opts->dump_opts.hash_size) {
737
- strcpy(out->cur, out->opts->dump_opts.hash_nl);
738
- out->cur += out->opts->dump_opts.hash_size;
703
+ APPEND_CHARS(out->cur, out->opts->dump_opts.hash_nl, out->opts->dump_opts.hash_size);
739
704
  }
740
705
  if (0 < out->opts->dump_opts.indent_size) {
741
706
  int i;
742
707
 
743
708
  for (i = depth; 0 < i; i--) {
744
- strcpy(out->cur, out->opts->dump_opts.indent_str);
745
- out->cur += out->opts->dump_opts.indent_size;
709
+ APPEND_CHARS(out->cur, out->opts->dump_opts.indent_str, out->opts->dump_opts.indent_size);
746
710
  }
747
711
  }
748
712
  }
@@ -786,8 +750,7 @@ dump_struct(VALUE obj, int depth, Out out, bool as_ok) {
786
750
  *out->cur++ = '"';
787
751
  oj_dump_compat_val(rb_funcall(obj, oj_begin_id, 0), 0, out, false);
788
752
  assure_size(out, 3);
789
- *out->cur++ = '.';
790
- *out->cur++ = '.';
753
+ APPEND_CHARS(out->cur, "..", 2);
791
754
  if (Qtrue == rb_funcall(obj, oj_exclude_end_id, 0)) {
792
755
  *out->cur++ = '.';
793
756
  }
@@ -833,17 +796,13 @@ dump_struct(VALUE obj, int depth, Out out, bool as_ok) {
833
796
  assure_size(out, size + sep_len + 6);
834
797
  *out->cur++ = ',';
835
798
  fill_indent(out, d3);
836
- *out->cur++ = '"';
837
- *out->cur++ = 'v';
838
- *out->cur++ = '"';
799
+ APPEND_CHARS(out->cur, "\"v\"", 3);
839
800
  if (0 < out->opts->dump_opts.before_size) {
840
- strcpy(out->cur, out->opts->dump_opts.before_sep);
841
- out->cur += out->opts->dump_opts.before_size;
801
+ APPEND_CHARS(out->cur, out->opts->dump_opts.before_sep, out->opts->dump_opts.before_size);
842
802
  }
843
803
  *out->cur++ = ':';
844
804
  if (0 < out->opts->dump_opts.after_size) {
845
- strcpy(out->cur, out->opts->dump_opts.after_sep);
846
- out->cur += out->opts->dump_opts.after_size;
805
+ APPEND_CHARS(out->cur, out->opts->dump_opts.after_sep, out->opts->dump_opts.after_size);
847
806
  }
848
807
  for (i = 0; i < cnt; i++) {
849
808
  #ifdef RSTRUCT_LEN
@@ -886,8 +845,7 @@ dump_bignum(VALUE obj, int depth, Out out, bool as_ok) {
886
845
  } else {
887
846
  assure_size(out, cnt);
888
847
  }
889
- memcpy(out->cur, RSTRING_PTR(rs), cnt);
890
- out->cur += cnt;
848
+ APPEND_CHARS(out->cur, RSTRING_PTR(rs), cnt);
891
849
  if (dump_as_string) {
892
850
  *out->cur++ = '"';
893
851
  }
@@ -935,7 +893,7 @@ void
935
893
  oj_dump_compat_val(VALUE obj, int depth, Out out, bool as_ok) {
936
894
  int type = rb_type(obj);
937
895
 
938
- if (Yes == out->opts->trace) {
896
+ if (RB_UNLIKELY(Yes == out->opts->trace)) {
939
897
  oj_trace("dump", obj, __FILE__, __LINE__, depth, TraceIn);
940
898
  }
941
899
  if (out->opts->dump_opts.max_depth <= depth) {
@@ -960,14 +918,14 @@ oj_dump_compat_val(VALUE obj, int depth, Out out, bool as_ok) {
960
918
 
961
919
  if (NULL != f) {
962
920
  f(obj, depth, out, as_ok);
963
- if (Yes == out->opts->trace) {
921
+ if (RB_UNLIKELY(Yes == out->opts->trace)) {
964
922
  oj_trace("dump", obj, __FILE__, __LINE__, depth, TraceOut);
965
923
  }
966
924
  return;
967
925
  }
968
926
  }
969
927
  oj_dump_nil(Qnil, depth, out, false);
970
- if (Yes == out->opts->trace) {
928
+ if (RB_UNLIKELY(Yes == out->opts->trace)) {
971
929
  oj_trace("dump", Qnil, __FILE__, __LINE__, depth, TraceOut);
972
930
  }
973
931
  }
data/ext/oj/dump_leaf.c CHANGED
@@ -8,36 +8,9 @@
8
8
 
9
9
  static void dump_leaf(Leaf leaf, int depth, Out out);
10
10
 
11
- static void grow(Out out, size_t len) {
12
- size_t size = out->end - out->buf;
13
- long pos = out->cur - out->buf;
14
- char * buf;
15
-
16
- size *= 2;
17
- if (size <= len * 2 + pos) {
18
- size += len;
19
- }
20
- if (out->allocated) {
21
- buf = REALLOC_N(out->buf, char, (size + BUFFER_EXTRA));
22
- } else {
23
- buf = ALLOC_N(char, (size + BUFFER_EXTRA));
24
- out->allocated = true;
25
- memcpy(buf, out->buf, out->end - out->buf + BUFFER_EXTRA);
26
- }
27
- if (0 == buf) {
28
- rb_raise(rb_eNoMemError, "Failed to create string. [%d:%s]\n", ENOSPC, strerror(ENOSPC));
29
- }
30
- out->buf = buf;
31
- out->end = buf + size;
32
- out->cur = out->buf + pos;
33
- }
34
-
35
11
  inline static void dump_chars(const char *s, size_t size, Out out) {
36
- if (out->end - out->cur <= (long)size) {
37
- grow(out, size);
38
- }
39
- memcpy(out->cur, s, size);
40
- out->cur += size;
12
+ assure_size(out, size);
13
+ APPEND_CHARS(out->cur, s, size);
41
14
  *out->cur = '\0';
42
15
  }
43
16
 
@@ -81,9 +54,7 @@ static void dump_leaf_array(Leaf leaf, int depth, Out out) {
81
54
  int d2 = depth + 1;
82
55
 
83
56
  size = 2;
84
- if (out->end - out->cur <= (long)size) {
85
- grow(out, size);
86
- }
57
+ assure_size(out, size);
87
58
  *out->cur++ = '[';
88
59
  if (0 == leaf->elements) {
89
60
  *out->cur++ = ']';
@@ -93,9 +64,7 @@ static void dump_leaf_array(Leaf leaf, int depth, Out out) {
93
64
 
94
65
  size = d2 * out->indent + 2;
95
66
  do {
96
- if (out->end - out->cur <= (long)size) {
97
- grow(out, size);
98
- }
67
+ assure_size(out, size);
99
68
  fill_indent(out, d2);
100
69
  dump_leaf(e, d2, out);
101
70
  if (e->next != first) {
@@ -104,9 +73,7 @@ static void dump_leaf_array(Leaf leaf, int depth, Out out) {
104
73
  e = e->next;
105
74
  } while (e != first);
106
75
  size = depth * out->indent + 1;
107
- if (out->end - out->cur <= (long)size) {
108
- grow(out, size);
109
- }
76
+ assure_size(out, size);
110
77
  fill_indent(out, depth);
111
78
  *out->cur++ = ']';
112
79
  }
@@ -118,9 +85,7 @@ static void dump_leaf_hash(Leaf leaf, int depth, Out out) {
118
85
  int d2 = depth + 1;
119
86
 
120
87
  size = 2;
121
- if (out->end - out->cur <= (long)size) {
122
- grow(out, size);
123
- }
88
+ assure_size(out, size);
124
89
  *out->cur++ = '{';
125
90
  if (0 == leaf->elements) {
126
91
  *out->cur++ = '}';
@@ -130,9 +95,7 @@ static void dump_leaf_hash(Leaf leaf, int depth, Out out) {
130
95
 
131
96
  size = d2 * out->indent + 2;
132
97
  do {
133
- if (out->end - out->cur <= (long)size) {
134
- grow(out, size);
135
- }
98
+ assure_size(out, size);
136
99
  fill_indent(out, d2);
137
100
  oj_dump_cstr(e->key, strlen(e->key), 0, 0, out);
138
101
  *out->cur++ = ':';
@@ -143,9 +106,7 @@ static void dump_leaf_hash(Leaf leaf, int depth, Out out) {
143
106
  e = e->next;
144
107
  } while (e != first);
145
108
  size = depth * out->indent + 1;
146
- if (out->end - out->cur <= (long)size) {
147
- grow(out, size);
148
- }
109
+ assure_size(out, size);
149
110
  fill_indent(out, depth);
150
111
  *out->cur++ = '}';
151
112
  }
@@ -168,10 +129,7 @@ static void dump_leaf(Leaf leaf, int depth, Out out) {
168
129
 
169
130
  void oj_dump_leaf_to_json(Leaf leaf, Options copts, Out out) {
170
131
  if (0 == out->buf) {
171
- out->buf = ALLOC_N(char, 4096);
172
- out->end = out->buf + 4095 -
173
- BUFFER_EXTRA; // 1 less than end plus extra for possible errors
174
- out->allocated = true;
132
+ oj_out_init(out);
175
133
  }
176
134
  out->cur = out->buf;
177
135
  out->circ_cnt = 0;
@@ -182,14 +140,12 @@ void oj_dump_leaf_to_json(Leaf leaf, Options copts, Out out) {
182
140
  }
183
141
 
184
142
  void oj_write_leaf_to_file(Leaf leaf, const char *path, Options copts) {
185
- char buf[4096];
186
143
  struct _out out;
187
144
  size_t size;
188
145
  FILE * f;
189
146
 
190
- out.buf = buf;
191
- out.end = buf + sizeof(buf) - BUFFER_EXTRA;
192
- out.allocated = false;
147
+ oj_out_init(&out);
148
+
193
149
  out.omit_nil = copts->dump_opts.omit_nil;
194
150
  oj_dump_leaf_to_json(leaf, copts, &out);
195
151
  size = out.cur - out.buf;
@@ -201,8 +157,8 @@ void oj_write_leaf_to_file(Leaf leaf, const char *path, Options copts) {
201
157
 
202
158
  rb_raise(rb_eIOError, "Write failed. [%d:%s]\n", err, strerror(err));
203
159
  }
204
- if (out.allocated) {
205
- xfree(out.buf);
206
- }
160
+
161
+ oj_out_free(&out);
162
+
207
163
  fclose(f);
208
164
  }