oj 3.13.11 → 3.15.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.
Files changed (158) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +74 -0
  3. data/README.md +4 -2
  4. data/ext/oj/buf.h +11 -6
  5. data/ext/oj/cache.c +25 -24
  6. data/ext/oj/cache8.c +10 -9
  7. data/ext/oj/circarray.c +8 -6
  8. data/ext/oj/circarray.h +2 -2
  9. data/ext/oj/code.c +17 -24
  10. data/ext/oj/code.h +2 -2
  11. data/ext/oj/compat.c +17 -44
  12. data/ext/oj/custom.c +70 -141
  13. data/ext/oj/debug.c +3 -9
  14. data/ext/oj/dump.c +128 -118
  15. data/ext/oj/dump.h +12 -8
  16. data/ext/oj/dump_compat.c +564 -641
  17. data/ext/oj/dump_leaf.c +17 -63
  18. data/ext/oj/dump_object.c +70 -199
  19. data/ext/oj/dump_strict.c +22 -46
  20. data/ext/oj/encoder.c +1 -1
  21. data/ext/oj/err.c +2 -13
  22. data/ext/oj/err.h +9 -12
  23. data/ext/oj/extconf.rb +14 -5
  24. data/ext/oj/fast.c +75 -103
  25. data/ext/oj/intern.c +52 -50
  26. data/ext/oj/intern.h +4 -8
  27. data/ext/oj/mem.c +318 -0
  28. data/ext/oj/mem.h +53 -0
  29. data/ext/oj/mimic_json.c +75 -47
  30. data/ext/oj/object.c +49 -66
  31. data/ext/oj/odd.c +89 -67
  32. data/ext/oj/odd.h +15 -15
  33. data/ext/oj/oj.c +140 -99
  34. data/ext/oj/oj.h +80 -51
  35. data/ext/oj/parse.c +162 -184
  36. data/ext/oj/parse.h +7 -10
  37. data/ext/oj/parser.c +89 -34
  38. data/ext/oj/parser.h +18 -7
  39. data/ext/oj/rails.c +82 -146
  40. data/ext/oj/rails.h +1 -1
  41. data/ext/oj/reader.c +11 -12
  42. data/ext/oj/reader.h +4 -2
  43. data/ext/oj/resolve.c +3 -4
  44. data/ext/oj/rxclass.c +6 -5
  45. data/ext/oj/rxclass.h +1 -1
  46. data/ext/oj/saj.c +20 -31
  47. data/ext/oj/saj2.c +329 -93
  48. data/ext/oj/saj2.h +23 -0
  49. data/ext/oj/scp.c +3 -14
  50. data/ext/oj/sparse.c +26 -70
  51. data/ext/oj/stream_writer.c +12 -22
  52. data/ext/oj/strict.c +20 -52
  53. data/ext/oj/string_writer.c +21 -21
  54. data/ext/oj/trace.h +31 -4
  55. data/ext/oj/usual.c +105 -150
  56. data/ext/oj/usual.h +68 -0
  57. data/ext/oj/util.h +1 -1
  58. data/ext/oj/val_stack.c +1 -1
  59. data/ext/oj/val_stack.h +8 -7
  60. data/ext/oj/validate.c +21 -26
  61. data/ext/oj/wab.c +31 -68
  62. data/lib/oj/active_support_helper.rb +0 -1
  63. data/lib/oj/bag.rb +7 -1
  64. data/lib/oj/easy_hash.rb +4 -5
  65. data/lib/oj/error.rb +0 -1
  66. data/lib/oj/json.rb +4 -2
  67. data/lib/oj/mimic.rb +4 -2
  68. data/lib/oj/saj.rb +20 -6
  69. data/lib/oj/state.rb +9 -6
  70. data/lib/oj/version.rb +1 -2
  71. data/lib/oj.rb +2 -0
  72. data/pages/Compatibility.md +1 -1
  73. data/pages/InstallOptions.md +20 -0
  74. data/pages/Options.md +10 -0
  75. data/test/_test_active.rb +8 -9
  76. data/test/_test_active_mimic.rb +7 -8
  77. data/test/_test_mimic_rails.rb +17 -20
  78. data/test/activerecord/result_test.rb +5 -6
  79. data/test/{activesupport5 → activesupport7}/abstract_unit.rb +16 -12
  80. data/test/{activesupport5 → activesupport7}/decoding_test.rb +2 -10
  81. data/test/{activesupport5 → activesupport7}/encoding_test.rb +20 -34
  82. data/test/{activesupport5 → activesupport7}/encoding_test_cases.rb +6 -0
  83. data/test/{activesupport5 → activesupport7}/time_zone_test_helpers.rb +8 -0
  84. data/test/files.rb +15 -15
  85. data/test/foo.rb +9 -71
  86. data/test/helper.rb +11 -8
  87. data/test/isolated/shared.rb +3 -2
  88. data/test/json_gem/json_addition_test.rb +2 -2
  89. data/test/json_gem/json_common_interface_test.rb +4 -4
  90. data/test/json_gem/json_encoding_test.rb +0 -0
  91. data/test/json_gem/json_ext_parser_test.rb +1 -0
  92. data/test/json_gem/json_fixtures_test.rb +3 -2
  93. data/test/json_gem/json_generator_test.rb +48 -36
  94. data/test/json_gem/json_generic_object_test.rb +11 -11
  95. data/test/json_gem/json_parser_test.rb +54 -47
  96. data/test/json_gem/json_string_matching_test.rb +9 -9
  97. data/test/json_gem/test_helper.rb +7 -3
  98. data/test/mem.rb +13 -12
  99. data/test/perf.rb +21 -26
  100. data/test/perf_compat.rb +31 -33
  101. data/test/perf_dump.rb +50 -0
  102. data/test/perf_fast.rb +80 -82
  103. data/test/perf_file.rb +27 -29
  104. data/test/perf_object.rb +65 -69
  105. data/test/perf_once.rb +12 -11
  106. data/test/perf_parser.rb +42 -48
  107. data/test/perf_saj.rb +46 -54
  108. data/test/perf_scp.rb +57 -69
  109. data/test/perf_simple.rb +41 -39
  110. data/test/perf_strict.rb +68 -70
  111. data/test/perf_wab.rb +67 -69
  112. data/test/prec.rb +3 -3
  113. data/test/sample/change.rb +0 -1
  114. data/test/sample/dir.rb +0 -1
  115. data/test/sample/doc.rb +0 -1
  116. data/test/sample/file.rb +0 -1
  117. data/test/sample/group.rb +0 -1
  118. data/test/sample/hasprops.rb +0 -1
  119. data/test/sample/layer.rb +0 -1
  120. data/test/sample/rect.rb +0 -1
  121. data/test/sample/shape.rb +0 -1
  122. data/test/sample/text.rb +0 -1
  123. data/test/sample.rb +16 -16
  124. data/test/sample_json.rb +8 -8
  125. data/test/test_compat.rb +76 -42
  126. data/test/test_custom.rb +72 -51
  127. data/test/test_debian.rb +7 -10
  128. data/test/test_fast.rb +86 -90
  129. data/test/test_file.rb +41 -30
  130. data/test/test_gc.rb +16 -5
  131. data/test/test_generate.rb +5 -5
  132. data/test/test_hash.rb +4 -4
  133. data/test/test_integer_range.rb +9 -9
  134. data/test/test_null.rb +20 -20
  135. data/test/test_object.rb +85 -96
  136. data/test/test_parser.rb +6 -22
  137. data/test/test_parser_debug.rb +27 -0
  138. data/test/test_parser_saj.rb +115 -23
  139. data/test/test_parser_usual.rb +6 -6
  140. data/test/test_rails.rb +2 -2
  141. data/test/test_saj.rb +10 -8
  142. data/test/test_scp.rb +37 -39
  143. data/test/test_strict.rb +30 -32
  144. data/test/test_various.rb +147 -99
  145. data/test/test_wab.rb +48 -44
  146. data/test/test_writer.rb +47 -47
  147. data/test/tests.rb +13 -4
  148. data/test/tests_mimic.rb +12 -3
  149. data/test/tests_mimic_addition.rb +12 -3
  150. metadata +33 -144
  151. data/test/activesupport4/decoding_test.rb +0 -108
  152. data/test/activesupport4/encoding_test.rb +0 -531
  153. data/test/activesupport4/test_helper.rb +0 -41
  154. data/test/activesupport5/test_helper.rb +0 -72
  155. data/test/bar.rb +0 -16
  156. data/test/baz.rb +0 -16
  157. data/test/bug.rb +0 -16
  158. data/test/zoo.rb +0 -13
data/ext/oj/rails.c CHANGED
@@ -5,6 +5,7 @@
5
5
 
6
6
  #include "code.h"
7
7
  #include "encode.h"
8
+ #include "mem.h"
8
9
  #include "trace.h"
9
10
  #include "util.h"
10
11
 
@@ -15,7 +16,7 @@ typedef struct _encoder {
15
16
  struct _rOptTable ropts;
16
17
  struct _options opts;
17
18
  VALUE arg;
18
- } * Encoder;
19
+ } *Encoder;
19
20
 
20
21
  bool oj_rails_hash_opt = false;
21
22
  bool oj_rails_array_opt = false;
@@ -76,7 +77,7 @@ static ROptTable copy_opts(ROptTable src, ROptTable dest) {
76
77
  if (NULL == src->table) {
77
78
  dest->table = NULL;
78
79
  } else {
79
- dest->table = ALLOC_N(struct _rOpt, dest->alen);
80
+ dest->table = OJ_R_ALLOC_N(struct _rOpt, dest->alen);
80
81
  memcpy(dest->table, src->table, sizeof(struct _rOpt) * dest->alen);
81
82
  }
82
83
  return NULL;
@@ -140,7 +141,7 @@ static void dump_struct(VALUE obj, int depth, Out out, bool as_ok) {
140
141
  int cnt;
141
142
  int i;
142
143
  int len;
143
- const char * name;
144
+ const char *name;
144
145
 
145
146
  #ifdef RSTRUCT_LEN
146
147
  #if RSTRUCT_LEN_RETURNS_INTEGER_OBJECT
@@ -167,17 +168,14 @@ static void dump_struct(VALUE obj, int depth, Out out, bool as_ok) {
167
168
  }
168
169
  fill_indent(out, d3);
169
170
  *out->cur++ = '"';
170
- memcpy(out->cur, name, len);
171
- out->cur += len;
171
+ APPEND_CHARS(out->cur, name, len);
172
172
  *out->cur++ = '"';
173
173
  if (0 < out->opts->dump_opts.before_size) {
174
- strcpy(out->cur, out->opts->dump_opts.before_sep);
175
- out->cur += out->opts->dump_opts.before_size;
174
+ APPEND_CHARS(out->cur, out->opts->dump_opts.before_sep, out->opts->dump_opts.before_size);
176
175
  }
177
176
  *out->cur++ = ':';
178
177
  if (0 < out->opts->dump_opts.after_size) {
179
- strcpy(out->cur, out->opts->dump_opts.after_sep);
180
- out->cur += out->opts->dump_opts.after_size;
178
+ APPEND_CHARS(out->cur, out->opts->dump_opts.after_sep, out->opts->dump_opts.after_size);
181
179
  }
182
180
  #ifdef RSTRUCT_LEN
183
181
  v = RSTRUCT_GET(obj, i);
@@ -201,8 +199,8 @@ static void dump_enumerable(VALUE obj, int depth, Out out, bool as_ok) {
201
199
  }
202
200
 
203
201
  static void dump_bigdecimal(VALUE obj, int depth, Out out, bool as_ok) {
204
- volatile VALUE rstr = rb_funcall(obj, oj_to_s_id, 0);
205
- const char * str = RSTRING_PTR(rstr);
202
+ volatile VALUE rstr = oj_safe_string_convert(obj);
203
+ const char *str = RSTRING_PTR(rstr);
206
204
 
207
205
  if ('I' == *str || 'N' == *str || ('-' == *str && 'I' == str[1])) {
208
206
  oj_dump_nil(Qnil, depth, out, false);
@@ -265,14 +263,7 @@ static void dump_sec_nano(VALUE obj, int64_t sec, long nsec, Out out) {
265
263
  tzmin);
266
264
  } else if (0 == out->opts->sec_prec) {
267
265
  if (0 == tzsecs && rb_funcall2(obj, oj_utcq_id, 0, 0)) {
268
- len = sprintf(buf,
269
- "%04d-%02d-%02dT%02d:%02d:%02dZ",
270
- ti.year,
271
- ti.mon,
272
- ti.day,
273
- ti.hour,
274
- ti.min,
275
- ti.sec);
266
+ len = sprintf(buf, "%04d-%02d-%02dT%02d:%02d:%02dZ", ti.year, ti.mon, ti.day, ti.hour, ti.min, ti.sec);
276
267
  } else {
277
268
  len = sprintf(buf,
278
269
  "%04d-%02d-%02dT%02d:%02d:%02d%c%02d:%02d",
@@ -303,18 +294,7 @@ static void dump_sec_nano(VALUE obj, int64_t sec, long nsec, Out out) {
303
294
  format[32] = '0' + out->opts->sec_prec;
304
295
  len -= 9 - out->opts->sec_prec;
305
296
  }
306
- len = sprintf(buf,
307
- format,
308
- ti.year,
309
- ti.mon,
310
- ti.day,
311
- ti.hour,
312
- ti.min,
313
- ti.sec,
314
- nsec,
315
- tzsign,
316
- tzhour,
317
- tzmin);
297
+ len = sprintf(buf, format, ti.year, ti.mon, ti.day, ti.hour, ti.min, ti.sec, nsec, tzsign, tzhour, tzmin);
318
298
  }
319
299
  oj_dump_cstr(buf, len, 0, 0, out);
320
300
  }
@@ -323,20 +303,15 @@ static void dump_time(VALUE obj, int depth, Out out, bool as_ok) {
323
303
  long long sec;
324
304
  long long nsec;
325
305
 
326
- #ifdef HAVE_RB_TIME_TIMESPEC
327
306
  if (16 <= sizeof(struct timespec)) {
328
307
  struct timespec ts = rb_time_timespec(obj);
329
308
 
330
309
  sec = (long long)ts.tv_sec;
331
310
  nsec = ts.tv_nsec;
332
311
  } else {
333
- sec = rb_num2ll(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
334
- nsec = rb_num2ll(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
312
+ sec = NUM2LL(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
313
+ nsec = NUM2LL(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
335
314
  }
336
- #else
337
- sec = rb_num2ll(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
338
- nsec = rb_num2ll(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
339
- #endif
340
315
  dump_sec_nano(obj, sec, nsec, out);
341
316
  }
342
317
 
@@ -345,15 +320,15 @@ static void dump_timewithzone(VALUE obj, int depth, Out out, bool as_ok) {
345
320
  long long nsec = 0;
346
321
 
347
322
  if (rb_respond_to(obj, oj_tv_nsec_id)) {
348
- nsec = rb_num2ll(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
323
+ nsec = NUM2LL(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
349
324
  } else if (rb_respond_to(obj, oj_tv_usec_id)) {
350
- nsec = rb_num2ll(rb_funcall2(obj, oj_tv_usec_id, 0, 0)) * 1000;
325
+ nsec = NUM2LL(rb_funcall2(obj, oj_tv_usec_id, 0, 0)) * 1000;
351
326
  }
352
327
  dump_sec_nano(obj, sec, nsec, out);
353
328
  }
354
329
 
355
330
  static void dump_to_s(VALUE obj, int depth, Out out, bool as_ok) {
356
- volatile VALUE rstr = rb_funcall(obj, oj_to_s_id, 0);
331
+ volatile VALUE rstr = oj_safe_string_convert(obj);
357
332
 
358
333
  oj_dump_cstr(RSTRING_PTR(rstr), (int)RSTRING_LEN(rstr), 0, 0, out);
359
334
  }
@@ -363,7 +338,7 @@ static ID parameters_id = 0;
363
338
  typedef struct _strLen {
364
339
  const char *str;
365
340
  int len;
366
- } * StrLen;
341
+ } *StrLen;
367
342
 
368
343
  static void dump_actioncontroller_parameters(VALUE obj, int depth, Out out, bool as_ok) {
369
344
  if (0 == parameters_id) {
@@ -381,11 +356,11 @@ static StrLen columns_array(VALUE rcols, int *ccnt) {
381
356
  int cnt = (int)RARRAY_LEN(rcols);
382
357
 
383
358
  *ccnt = cnt;
384
- cols = ALLOC_N(struct _strLen, cnt);
359
+ cols = OJ_R_ALLOC_N(struct _strLen, cnt);
385
360
  for (i = 0, cp = cols; i < cnt; i++, cp++) {
386
361
  v = RARRAY_AREF(rcols, i);
387
362
  if (T_STRING != rb_type(v)) {
388
- v = rb_funcall(v, oj_to_s_id, 0);
363
+ v = oj_safe_string_convert(v);
389
364
  }
390
365
  cp->str = StringValuePtr(v);
391
366
  cp->len = (int)RSTRING_LEN(v);
@@ -405,14 +380,12 @@ static void dump_row(VALUE row, StrLen cols, int ccnt, int depth, Out out) {
405
380
  assure_size(out, size);
406
381
  if (out->opts->dump_opts.use) {
407
382
  if (0 < out->opts->dump_opts.array_size) {
408
- strcpy(out->cur, out->opts->dump_opts.array_nl);
409
- out->cur += out->opts->dump_opts.array_size;
383
+ APPEND_CHARS(out->cur, out->opts->dump_opts.array_nl, out->opts->dump_opts.array_size);
410
384
  }
411
385
  if (0 < out->opts->dump_opts.indent_size) {
412
386
  int i;
413
387
  for (i = d2; 0 < i; i--) {
414
- strcpy(out->cur, out->opts->dump_opts.indent_str);
415
- out->cur += out->opts->dump_opts.indent_size;
388
+ APPEND_CHARS(out->cur, out->opts->dump_opts.indent_str, out->opts->dump_opts.indent_size);
416
389
  }
417
390
  }
418
391
  } else {
@@ -429,15 +402,13 @@ static void dump_row(VALUE row, StrLen cols, int ccnt, int depth, Out out) {
429
402
  assure_size(out, size);
430
403
  if (out->opts->dump_opts.use) {
431
404
  if (0 < out->opts->dump_opts.array_size) {
432
- strcpy(out->cur, out->opts->dump_opts.array_nl);
433
- out->cur += out->opts->dump_opts.array_size;
405
+ APPEND_CHARS(out->cur, out->opts->dump_opts.array_nl, out->opts->dump_opts.array_size);
434
406
  }
435
407
  if (0 < out->opts->dump_opts.indent_size) {
436
408
  int i;
437
409
 
438
410
  for (i = depth; 0 < i; i--) {
439
- strcpy(out->cur, out->opts->dump_opts.indent_str);
440
- out->cur += out->opts->dump_opts.indent_size;
411
+ APPEND_CHARS(out->cur, out->opts->dump_opts.indent_str, out->opts->dump_opts.indent_size);
441
412
  }
442
413
  }
443
414
  } else {
@@ -477,14 +448,12 @@ static void dump_activerecord_result(VALUE obj, int depth, Out out, bool as_ok)
477
448
  assure_size(out, size);
478
449
  if (out->opts->dump_opts.use) {
479
450
  if (0 < out->opts->dump_opts.array_size) {
480
- strcpy(out->cur, out->opts->dump_opts.array_nl);
481
- out->cur += out->opts->dump_opts.array_size;
451
+ APPEND_CHARS(out->cur, out->opts->dump_opts.array_nl, out->opts->dump_opts.array_size);
482
452
  }
483
453
  if (0 < out->opts->dump_opts.indent_size) {
484
454
  int i;
485
455
  for (i = d2; 0 < i; i--) {
486
- strcpy(out->cur, out->opts->dump_opts.indent_str);
487
- out->cur += out->opts->dump_opts.indent_size;
456
+ APPEND_CHARS(out->cur, out->opts->dump_opts.indent_str, out->opts->dump_opts.indent_size);
488
457
  }
489
458
  }
490
459
  } else {
@@ -495,20 +464,18 @@ static void dump_activerecord_result(VALUE obj, int depth, Out out, bool as_ok)
495
464
  *out->cur++ = ',';
496
465
  }
497
466
  }
498
- xfree(cols);
467
+ OJ_R_FREE(cols);
499
468
  size = depth * out->indent + 1;
500
469
  assure_size(out, size);
501
470
  if (out->opts->dump_opts.use) {
502
471
  if (0 < out->opts->dump_opts.array_size) {
503
- strcpy(out->cur, out->opts->dump_opts.array_nl);
504
- out->cur += out->opts->dump_opts.array_size;
472
+ APPEND_CHARS(out->cur, out->opts->dump_opts.array_nl, out->opts->dump_opts.array_size);
505
473
  }
506
474
  if (0 < out->opts->dump_opts.indent_size) {
507
475
  int i;
508
476
 
509
477
  for (i = depth; 0 < i; i--) {
510
- strcpy(out->cur, out->opts->dump_opts.indent_str);
511
- out->cur += out->opts->dump_opts.indent_size;
478
+ APPEND_CHARS(out->cur, out->opts->dump_opts.indent_str, out->opts->dump_opts.indent_size);
512
479
  }
513
480
  }
514
481
  } else {
@@ -520,7 +487,7 @@ static void dump_activerecord_result(VALUE obj, int depth, Out out, bool as_ok)
520
487
  typedef struct _namedFunc {
521
488
  const char *name;
522
489
  DumpFunc func;
523
- } * NamedFunc;
490
+ } *NamedFunc;
524
491
 
525
492
  static void dump_as_string(VALUE obj, int depth, Out out, bool as_ok) {
526
493
  if (oj_code_dump(oj_compat_codes, obj, depth, out)) {
@@ -533,9 +500,7 @@ static void dump_as_string(VALUE obj, int depth, Out out, bool as_ok) {
533
500
  static void dump_as_json(VALUE obj, int depth, Out out, bool as_ok) {
534
501
  volatile VALUE ja;
535
502
 
536
- if (Yes == out->opts->trace) {
537
- oj_trace("as_json", obj, __FILE__, __LINE__, depth + 1, TraceRubyIn);
538
- }
503
+ TRACE(out->opts->trace, "as_json", obj, depth + 1, TraceRubyIn);
539
504
  // Some classes elect to not take an options argument so check the arity
540
505
  // of as_json.
541
506
  if (0 == rb_obj_method_arity(obj, oj_as_json_id)) {
@@ -543,9 +508,7 @@ static void dump_as_json(VALUE obj, int depth, Out out, bool as_ok) {
543
508
  } else {
544
509
  ja = rb_funcall2(obj, oj_as_json_id, out->argc, out->argv);
545
510
  }
546
- if (Yes == out->opts->trace) {
547
- oj_trace("as_json", obj, __FILE__, __LINE__, depth + 1, TraceRubyOut);
548
- }
511
+ TRACE(out->opts->trace, "as_json", obj, depth + 1, TraceRubyOut);
549
512
 
550
513
  out->argc = 0;
551
514
  if (ja == obj || !as_ok) {
@@ -603,11 +566,11 @@ static ROpt create_opt(ROptTable rot, VALUE clas) {
603
566
  rot->len++;
604
567
  if (NULL == rot->table) {
605
568
  rot->alen = 256;
606
- rot->table = ALLOC_N(struct _rOpt, rot->alen);
569
+ rot->table = OJ_R_ALLOC_N(struct _rOpt, rot->alen);
607
570
  memset(rot->table, 0, sizeof(struct _rOpt) * rot->alen);
608
571
  } else if (rot->alen <= rot->len) {
609
572
  rot->alen *= 2;
610
- REALLOC_N(rot->table, struct _rOpt, rot->alen);
573
+ OJ_R_REALLOC_N(rot->table, struct _rOpt, rot->alen);
611
574
  memset(rot->table + olen, 0, sizeof(struct _rOpt) * olen);
612
575
  }
613
576
  if (0 == olen) {
@@ -660,9 +623,9 @@ static void encoder_free(void *ptr) {
660
623
  Encoder e = (Encoder)ptr;
661
624
 
662
625
  if (NULL != e->ropts.table) {
663
- xfree(e->ropts.table);
626
+ OJ_R_FREE(e->ropts.table);
664
627
  }
665
- xfree(ptr);
628
+ OJ_R_FREE(ptr);
666
629
  }
667
630
  }
668
631
 
@@ -683,7 +646,7 @@ static void encoder_mark(void *ptr) {
683
646
  * - *options* [_Hash_] formatting options
684
647
  */
685
648
  static VALUE encoder_new(int argc, VALUE *argv, VALUE self) {
686
- Encoder e = ALLOC(struct _encoder);
649
+ Encoder e = OJ_R_ALLOC(struct _encoder);
687
650
 
688
651
  e->opts = oj_default_options;
689
652
  e->arg = Qnil;
@@ -699,8 +662,8 @@ static VALUE encoder_new(int argc, VALUE *argv, VALUE self) {
699
662
  static VALUE resolve_classpath(const char *name) {
700
663
  char class_name[1024];
701
664
  VALUE clas;
702
- char * end = class_name + sizeof(class_name) - 1;
703
- char * s;
665
+ char *end = class_name + sizeof(class_name) - 1;
666
+ char *s;
704
667
  const char *n = name;
705
668
  ID cid;
706
669
 
@@ -766,8 +729,7 @@ static void optimize(int argc, VALUE *argv, ROptTable rot, bool on) {
766
729
  oj_rails_float_opt = on;
767
730
  } else if (oj_string_writer_class == *argv) {
768
731
  string_writer_optimized = on;
769
- } else if (NULL != (ro = oj_rails_get_opt(rot, *argv)) ||
770
- NULL != (ro = create_opt(rot, *argv))) {
732
+ } else if (NULL != (ro = oj_rails_get_opt(rot, *argv)) || NULL != (ro = create_opt(rot, *argv))) {
771
733
  ro->on = on;
772
734
  }
773
735
  }
@@ -829,7 +791,7 @@ rails_mimic_json(VALUE self) {
829
791
  }
830
792
  oj_mimic_json_methods(json);
831
793
  // Setting the default mode breaks the prmoise in the docs not to.
832
- //oj_default_options.mode = RailsMode;
794
+ // oj_default_options.mode = RailsMode;
833
795
 
834
796
  return Qnil;
835
797
  }
@@ -897,7 +859,7 @@ static VALUE rails_optimized(VALUE self, VALUE clas) {
897
859
  typedef struct _oo {
898
860
  Out out;
899
861
  VALUE obj;
900
- } * OO;
862
+ } *OO;
901
863
 
902
864
  static VALUE protect_dump(VALUE ov) {
903
865
  OO oo = (OO)ov;
@@ -908,7 +870,6 @@ static VALUE protect_dump(VALUE ov) {
908
870
  }
909
871
 
910
872
  static VALUE encode(VALUE obj, ROptTable ropts, Options opts, int argc, VALUE *argv) {
911
- char buf[4096];
912
873
  struct _out out;
913
874
  struct _options copts = *opts;
914
875
  volatile VALUE rstr = Qnil;
@@ -925,19 +886,19 @@ static VALUE encode(VALUE obj, ROptTable ropts, Options opts, int argc, VALUE *a
925
886
  } else {
926
887
  copts.escape_mode = RailsEsc;
927
888
  }
928
- out.buf = buf;
929
- out.end = buf + sizeof(buf) - 10;
930
- out.allocated = false;
931
- out.omit_nil = copts.dump_opts.omit_nil;
932
- out.caller = 0;
933
- out.cur = out.buf;
934
- out.circ_cnt = 0;
935
- out.opts = &copts;
936
- out.hash_cnt = 0;
937
- out.indent = copts.indent;
938
- out.argc = argc;
939
- out.argv = argv;
940
- out.ropts = ropts;
889
+
890
+ oj_out_init(&out);
891
+
892
+ out.omit_nil = copts.dump_opts.omit_nil;
893
+ out.caller = 0;
894
+ out.cur = out.buf;
895
+ out.circ_cnt = 0;
896
+ out.opts = &copts;
897
+ out.hash_cnt = 0;
898
+ out.indent = copts.indent;
899
+ out.argc = argc;
900
+ out.argv = argv;
901
+ out.ropts = ropts;
941
902
  if (Yes == copts.circular) {
942
903
  oj_cache8_new(&out.circ_cache);
943
904
  }
@@ -963,9 +924,9 @@ static VALUE encode(VALUE obj, ROptTable ropts, Options opts, int argc, VALUE *a
963
924
  if (Yes == copts.circular) {
964
925
  oj_cache8_delete(out.circ_cache);
965
926
  }
966
- if (out.allocated) {
967
- xfree(out.buf);
968
- }
927
+
928
+ oj_out_free(&out);
929
+
969
930
  if (0 != line) {
970
931
  rb_jump_tag(line);
971
932
  }
@@ -1082,28 +1043,16 @@ static VALUE rails_set_encoder(VALUE self) {
1082
1043
  verbose = rb_gv_get("$VERBOSE");
1083
1044
  rb_gv_set("$VERBOSE", Qfalse);
1084
1045
  rb_undef_method(encoding, "use_standard_json_time_format=");
1085
- rb_define_module_function(encoding,
1086
- "use_standard_json_time_format=",
1087
- rails_use_standard_json_time_format,
1088
- 1);
1046
+ rb_define_module_function(encoding, "use_standard_json_time_format=", rails_use_standard_json_time_format, 1);
1089
1047
  rb_undef_method(encoding, "use_standard_json_time_format");
1090
- rb_define_module_function(encoding,
1091
- "use_standard_json_time_format",
1092
- rails_use_standard_json_time_format_get,
1093
- 0);
1048
+ rb_define_module_function(encoding, "use_standard_json_time_format", rails_use_standard_json_time_format_get, 0);
1094
1049
 
1095
1050
  pv = rb_iv_get(encoding, "@escape_html_entities_in_json");
1096
1051
  escape_html = Qtrue == pv;
1097
1052
  rb_undef_method(encoding, "escape_html_entities_in_json=");
1098
- rb_define_module_function(encoding,
1099
- "escape_html_entities_in_json=",
1100
- rails_escape_html_entities_in_json,
1101
- 1);
1053
+ rb_define_module_function(encoding, "escape_html_entities_in_json=", rails_escape_html_entities_in_json, 1);
1102
1054
  rb_undef_method(encoding, "escape_html_entities_in_json");
1103
- rb_define_module_function(encoding,
1104
- "escape_html_entities_in_json",
1105
- rails_escape_html_entities_in_json_get,
1106
- 0);
1055
+ rb_define_module_function(encoding, "escape_html_entities_in_json", rails_escape_html_entities_in_json_get, 0);
1107
1056
 
1108
1057
  pv = rb_iv_get(encoding, "@time_precision");
1109
1058
  oj_default_options.sec_prec = NUM2INT(pv);
@@ -1175,12 +1124,15 @@ oj_optimize_rails(VALUE self) {
1175
1124
  *
1176
1125
  * The Oj ActiveSupport compliant encoder.
1177
1126
  */
1178
- void oj_mimic_rails_init() {
1127
+ void oj_mimic_rails_init(void) {
1179
1128
  VALUE rails = rb_define_module_under(Oj, "Rails");
1180
1129
 
1181
1130
  rb_define_module_function(rails, "encode", rails_encode, -1);
1182
1131
 
1183
1132
  encoder_class = rb_define_class_under(rails, "Encoder", rb_cObject);
1133
+ rb_gc_register_address(&encoder_class);
1134
+ rb_undef_alloc_func(encoder_class);
1135
+
1184
1136
  rb_define_module_function(encoder_class, "new", encoder_new, -1);
1185
1137
  rb_define_module_function(rails, "optimize", rails_optimize, -1);
1186
1138
  rb_define_module_function(rails, "deoptimize", rails_deoptimize, -1);
@@ -1202,7 +1154,7 @@ static void dump_to_hash(VALUE obj, int depth, Out out) {
1202
1154
 
1203
1155
  static void dump_float(VALUE obj, int depth, Out out, bool as_ok) {
1204
1156
  char buf[64];
1205
- char * b;
1157
+ char *b;
1206
1158
  double d = rb_num2dbl(obj);
1207
1159
  int cnt = 0;
1208
1160
 
@@ -1222,7 +1174,7 @@ static void dump_float(VALUE obj, int depth, Out out, bool as_ok) {
1222
1174
  } else if (oj_rails_float_opt) {
1223
1175
  cnt = oj_dump_float_printf(buf, sizeof(buf), obj, d, "%0.16g");
1224
1176
  } else {
1225
- volatile VALUE rstr = rb_funcall(obj, oj_to_s_id, 0);
1177
+ volatile VALUE rstr = oj_safe_string_convert(obj);
1226
1178
 
1227
1179
  strcpy(buf, RSTRING_PTR(rstr));
1228
1180
  cnt = (int)RSTRING_LEN(rstr);
@@ -1263,19 +1215,17 @@ static void dump_array(VALUE a, int depth, Out out, bool as_ok) {
1263
1215
  } else {
1264
1216
  size = d2 * out->indent + 2;
1265
1217
  }
1218
+ assure_size(out, size * cnt);
1266
1219
  cnt--;
1267
1220
  for (i = 0; i <= cnt; i++) {
1268
- assure_size(out, size);
1269
1221
  if (out->opts->dump_opts.use) {
1270
1222
  if (0 < out->opts->dump_opts.array_size) {
1271
- strcpy(out->cur, out->opts->dump_opts.array_nl);
1272
- out->cur += out->opts->dump_opts.array_size;
1223
+ APPEND_CHARS(out->cur, out->opts->dump_opts.array_nl, out->opts->dump_opts.array_size);
1273
1224
  }
1274
1225
  if (0 < out->opts->dump_opts.indent_size) {
1275
1226
  int i;
1276
1227
  for (i = d2; 0 < i; i--) {
1277
- strcpy(out->cur, out->opts->dump_opts.indent_str);
1278
- out->cur += out->opts->dump_opts.indent_size;
1228
+ APPEND_CHARS(out->cur, out->opts->dump_opts.indent_str, out->opts->dump_opts.indent_size);
1279
1229
  }
1280
1230
  }
1281
1231
  } else {
@@ -1290,15 +1240,13 @@ static void dump_array(VALUE a, int depth, Out out, bool as_ok) {
1290
1240
  assure_size(out, size);
1291
1241
  if (out->opts->dump_opts.use) {
1292
1242
  if (0 < out->opts->dump_opts.array_size) {
1293
- strcpy(out->cur, out->opts->dump_opts.array_nl);
1294
- out->cur += out->opts->dump_opts.array_size;
1243
+ APPEND_CHARS(out->cur, out->opts->dump_opts.array_nl, out->opts->dump_opts.array_size);
1295
1244
  }
1296
1245
  if (0 < out->opts->dump_opts.indent_size) {
1297
1246
  int i;
1298
1247
 
1299
1248
  for (i = depth; 0 < i; i--) {
1300
- strcpy(out->cur, out->opts->dump_opts.indent_str);
1301
- out->cur += out->opts->dump_opts.indent_size;
1249
+ APPEND_CHARS(out->cur, out->opts->dump_opts.indent_str, out->opts->dump_opts.indent_size);
1302
1250
  }
1303
1251
  }
1304
1252
  } else {
@@ -1319,7 +1267,7 @@ static int hash_cb(VALUE key, VALUE value, VALUE ov) {
1319
1267
  return ST_CONTINUE;
1320
1268
  }
1321
1269
  if (rtype != T_STRING && rtype != T_SYMBOL) {
1322
- key = rb_funcall(key, oj_to_s_id, 0);
1270
+ key = oj_safe_string_convert(key);
1323
1271
  rtype = rb_type(key);
1324
1272
  }
1325
1273
  if (!out->opts->dump_opts.use) {
@@ -1336,14 +1284,12 @@ static int hash_cb(VALUE key, VALUE value, VALUE ov) {
1336
1284
  size = depth * out->opts->dump_opts.indent_size + out->opts->dump_opts.hash_size + 1;
1337
1285
  assure_size(out, size);
1338
1286
  if (0 < out->opts->dump_opts.hash_size) {
1339
- strcpy(out->cur, out->opts->dump_opts.hash_nl);
1340
- out->cur += out->opts->dump_opts.hash_size;
1287
+ APPEND_CHARS(out->cur, out->opts->dump_opts.hash_nl, out->opts->dump_opts.hash_size);
1341
1288
  }
1342
1289
  if (0 < out->opts->dump_opts.indent_size) {
1343
1290
  int i;
1344
1291
  for (i = depth; 0 < i; i--) {
1345
- strcpy(out->cur, out->opts->dump_opts.indent_str);
1346
- out->cur += out->opts->dump_opts.indent_size;
1292
+ APPEND_CHARS(out->cur, out->opts->dump_opts.indent_str, out->opts->dump_opts.indent_size);
1347
1293
  }
1348
1294
  }
1349
1295
  if (rtype == T_STRING) {
@@ -1354,13 +1300,11 @@ static int hash_cb(VALUE key, VALUE value, VALUE ov) {
1354
1300
  size = out->opts->dump_opts.before_size + out->opts->dump_opts.after_size + 2;
1355
1301
  assure_size(out, size);
1356
1302
  if (0 < out->opts->dump_opts.before_size) {
1357
- strcpy(out->cur, out->opts->dump_opts.before_sep);
1358
- out->cur += out->opts->dump_opts.before_size;
1303
+ APPEND_CHARS(out->cur, out->opts->dump_opts.before_sep, out->opts->dump_opts.before_size);
1359
1304
  }
1360
1305
  *out->cur++ = ':';
1361
1306
  if (0 < out->opts->dump_opts.after_size) {
1362
- strcpy(out->cur, out->opts->dump_opts.after_sep);
1363
- out->cur += out->opts->dump_opts.after_size;
1307
+ APPEND_CHARS(out->cur, out->opts->dump_opts.after_sep, out->opts->dump_opts.after_size);
1364
1308
  }
1365
1309
  }
1366
1310
  dump_rails_val(value, depth, out, true);
@@ -1403,15 +1347,13 @@ static void dump_hash(VALUE obj, int depth, Out out, bool as_ok) {
1403
1347
  size = depth * out->opts->dump_opts.indent_size + out->opts->dump_opts.hash_size + 1;
1404
1348
  assure_size(out, size);
1405
1349
  if (0 < out->opts->dump_opts.hash_size) {
1406
- strcpy(out->cur, out->opts->dump_opts.hash_nl);
1407
- out->cur += out->opts->dump_opts.hash_size;
1350
+ APPEND_CHARS(out->cur, out->opts->dump_opts.hash_nl, out->opts->dump_opts.hash_size);
1408
1351
  }
1409
1352
  if (0 < out->opts->dump_opts.indent_size) {
1410
1353
  int i;
1411
1354
 
1412
1355
  for (i = depth; 0 < i; i--) {
1413
- strcpy(out->cur, out->opts->dump_opts.indent_str);
1414
- out->cur += out->opts->dump_opts.indent_size;
1356
+ APPEND_CHARS(out->cur, out->opts->dump_opts.indent_str, out->opts->dump_opts.indent_size);
1415
1357
  }
1416
1358
  }
1417
1359
  }
@@ -1488,9 +1430,7 @@ static DumpFunc rails_funcs[] = {
1488
1430
  static void dump_rails_val(VALUE obj, int depth, Out out, bool as_ok) {
1489
1431
  int type = rb_type(obj);
1490
1432
 
1491
- if (Yes == out->opts->trace) {
1492
- oj_trace("dump", obj, __FILE__, __LINE__, depth, TraceIn);
1493
- }
1433
+ TRACE(out->opts->trace, "dump", obj, depth, TraceIn);
1494
1434
  if (MAX_DEPTH < depth) {
1495
1435
  rb_raise(rb_eNoMemError, "Too deeply nested.\n");
1496
1436
  }
@@ -1499,16 +1439,12 @@ static void dump_rails_val(VALUE obj, int depth, Out out, bool as_ok) {
1499
1439
 
1500
1440
  if (NULL != f) {
1501
1441
  f(obj, depth, out, as_ok);
1502
- if (Yes == out->opts->trace) {
1503
- oj_trace("dump", obj, __FILE__, __LINE__, depth, TraceOut);
1504
- }
1442
+ TRACE(out->opts->trace, "dump", obj, depth, TraceOut);
1505
1443
  return;
1506
1444
  }
1507
1445
  }
1508
1446
  oj_dump_nil(Qnil, depth, out, false);
1509
- if (Yes == out->opts->trace) {
1510
- oj_trace("dump", Qnil, __FILE__, __LINE__, depth, TraceOut);
1511
- }
1447
+ TRACE(out->opts->trace, "dump", Qnil, depth, TraceOut);
1512
1448
  }
1513
1449
 
1514
1450
  void oj_dump_rails_val(VALUE obj, int depth, Out out) {
data/ext/oj/rails.h CHANGED
@@ -6,7 +6,7 @@
6
6
 
7
7
  #include "dump.h"
8
8
 
9
- extern void oj_mimic_rails_init();
9
+ extern void oj_mimic_rails_init(void);
10
10
  extern ROpt oj_rails_get_opt(ROptTable rot, VALUE clas);
11
11
 
12
12
  extern bool oj_rails_hash_opt;