oj 3.13.9 → 3.16.1

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 (161) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +101 -0
  3. data/README.md +13 -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 +19 -33
  10. data/ext/oj/code.h +2 -2
  11. data/ext/oj/compat.c +20 -60
  12. data/ext/oj/custom.c +76 -155
  13. data/ext/oj/debug.c +3 -9
  14. data/ext/oj/dump.c +203 -213
  15. data/ext/oj/dump.h +26 -12
  16. data/ext/oj/dump_compat.c +565 -642
  17. data/ext/oj/dump_leaf.c +17 -63
  18. data/ext/oj/dump_object.c +59 -181
  19. data/ext/oj/dump_strict.c +24 -48
  20. data/ext/oj/encoder.c +43 -0
  21. data/ext/oj/err.c +2 -13
  22. data/ext/oj/err.h +9 -12
  23. data/ext/oj/extconf.rb +18 -7
  24. data/ext/oj/fast.c +83 -108
  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 +104 -81
  30. data/ext/oj/object.c +50 -67
  31. data/ext/oj/odd.c +89 -67
  32. data/ext/oj/odd.h +15 -15
  33. data/ext/oj/oj.c +171 -106
  34. data/ext/oj/oj.h +96 -74
  35. data/ext/oj/parse.c +169 -189
  36. data/ext/oj/parse.h +23 -24
  37. data/ext/oj/parser.c +89 -34
  38. data/ext/oj/parser.h +20 -9
  39. data/ext/oj/rails.c +86 -151
  40. data/ext/oj/rails.h +1 -1
  41. data/ext/oj/reader.c +12 -15
  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 +21 -32
  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 -22
  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 +32 -69
  62. data/lib/oj/active_support_helper.rb +1 -3
  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 +162 -150
  67. data/lib/oj/mimic.rb +6 -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/JsonGem.md +15 -0
  75. data/pages/Modes.md +6 -3
  76. data/pages/Options.md +10 -0
  77. data/pages/Rails.md +12 -0
  78. data/test/_test_active.rb +8 -9
  79. data/test/_test_active_mimic.rb +7 -8
  80. data/test/_test_mimic_rails.rb +17 -20
  81. data/test/activerecord/result_test.rb +5 -6
  82. data/test/{activesupport5 → activesupport7}/abstract_unit.rb +16 -12
  83. data/test/{activesupport5 → activesupport7}/decoding_test.rb +2 -10
  84. data/test/{activesupport5 → activesupport7}/encoding_test.rb +20 -34
  85. data/test/{activesupport5 → activesupport7}/encoding_test_cases.rb +6 -0
  86. data/test/{activesupport5 → activesupport7}/time_zone_test_helpers.rb +8 -0
  87. data/test/files.rb +15 -15
  88. data/test/foo.rb +15 -15
  89. data/test/helper.rb +11 -8
  90. data/test/isolated/shared.rb +3 -2
  91. data/test/json_gem/json_addition_test.rb +2 -2
  92. data/test/json_gem/json_common_interface_test.rb +8 -6
  93. data/test/json_gem/json_encoding_test.rb +0 -0
  94. data/test/json_gem/json_ext_parser_test.rb +1 -0
  95. data/test/json_gem/json_fixtures_test.rb +3 -2
  96. data/test/json_gem/json_generator_test.rb +49 -37
  97. data/test/json_gem/json_generic_object_test.rb +11 -11
  98. data/test/json_gem/json_parser_test.rb +54 -47
  99. data/test/json_gem/json_string_matching_test.rb +9 -9
  100. data/test/json_gem/test_helper.rb +7 -3
  101. data/test/mem.rb +13 -12
  102. data/test/perf.rb +21 -26
  103. data/test/perf_compat.rb +31 -33
  104. data/test/perf_dump.rb +50 -0
  105. data/test/perf_fast.rb +80 -82
  106. data/test/perf_file.rb +27 -29
  107. data/test/perf_object.rb +65 -69
  108. data/test/perf_once.rb +12 -11
  109. data/test/perf_parser.rb +42 -48
  110. data/test/perf_saj.rb +46 -54
  111. data/test/perf_scp.rb +57 -69
  112. data/test/perf_simple.rb +41 -39
  113. data/test/perf_strict.rb +68 -70
  114. data/test/perf_wab.rb +67 -69
  115. data/test/prec.rb +3 -3
  116. data/test/sample/change.rb +0 -1
  117. data/test/sample/dir.rb +0 -1
  118. data/test/sample/doc.rb +0 -1
  119. data/test/sample/file.rb +0 -1
  120. data/test/sample/group.rb +0 -1
  121. data/test/sample/hasprops.rb +0 -1
  122. data/test/sample/layer.rb +0 -1
  123. data/test/sample/rect.rb +0 -1
  124. data/test/sample/shape.rb +0 -1
  125. data/test/sample/text.rb +0 -1
  126. data/test/sample.rb +16 -16
  127. data/test/sample_json.rb +8 -8
  128. data/test/test_compat.rb +95 -43
  129. data/test/test_custom.rb +72 -51
  130. data/test/test_debian.rb +7 -10
  131. data/test/test_fast.rb +102 -87
  132. data/test/test_file.rb +41 -30
  133. data/test/test_gc.rb +16 -5
  134. data/test/test_generate.rb +5 -5
  135. data/test/test_hash.rb +4 -4
  136. data/test/test_integer_range.rb +9 -9
  137. data/test/test_null.rb +20 -20
  138. data/test/test_object.rb +85 -96
  139. data/test/test_parser.rb +6 -22
  140. data/test/test_parser_debug.rb +27 -0
  141. data/test/test_parser_saj.rb +115 -23
  142. data/test/test_parser_usual.rb +6 -6
  143. data/test/test_rails.rb +2 -2
  144. data/test/test_saj.rb +10 -8
  145. data/test/test_scp.rb +37 -39
  146. data/test/test_strict.rb +40 -32
  147. data/test/test_various.rb +163 -84
  148. data/test/test_wab.rb +48 -44
  149. data/test/test_writer.rb +47 -47
  150. data/test/tests.rb +13 -5
  151. data/test/tests_mimic.rb +12 -3
  152. data/test/tests_mimic_addition.rb +12 -3
  153. metadata +34 -144
  154. data/test/activesupport4/decoding_test.rb +0 -108
  155. data/test/activesupport4/encoding_test.rb +0 -531
  156. data/test/activesupport4/test_helper.rb +0 -41
  157. data/test/activesupport5/test_helper.rb +0 -72
  158. data/test/bar.rb +0 -16
  159. data/test/baz.rb +0 -16
  160. data/test/bug.rb +0 -16
  161. data/test/zoo.rb +0 -13
data/ext/oj/custom.c CHANGED
@@ -9,6 +9,7 @@
9
9
  #include "encode.h"
10
10
  #include "err.h"
11
11
  #include "intern.h"
12
+ #include "mem.h"
12
13
  #include "odd.h"
13
14
  #include "oj.h"
14
15
  #include "parse.h"
@@ -24,21 +25,21 @@ static void dump_obj_str(VALUE obj, int depth, Out out) {
24
25
  {"s", 1, Qnil},
25
26
  {NULL, 0, Qnil},
26
27
  };
27
- attrs->value = rb_funcall(obj, oj_to_s_id, 0);
28
+ attrs->value = oj_safe_string_convert(obj);
28
29
 
29
30
  oj_code_attrs(obj, attrs, depth, out, Yes == out->opts->create_ok);
30
31
  }
31
32
 
32
33
  static void dump_obj_as_str(VALUE obj, int depth, Out out) {
33
- volatile VALUE rstr = rb_funcall(obj, oj_to_s_id, 0);
34
- const char * str = RSTRING_PTR(rstr);
34
+ volatile VALUE rstr = oj_safe_string_convert(obj);
35
+ const char *str = RSTRING_PTR(rstr);
35
36
 
36
37
  oj_dump_cstr(str, RSTRING_LEN(rstr), 0, 0, out);
37
38
  }
38
39
 
39
40
  static void bigdecimal_dump(VALUE obj, int depth, Out out) {
40
- volatile VALUE rstr = rb_funcall(obj, oj_to_s_id, 0);
41
- const char * str = RSTRING_PTR(rstr);
41
+ volatile VALUE rstr = oj_safe_string_convert(obj);
42
+ const char *str = RSTRING_PTR(rstr);
42
43
  int len = (int)RSTRING_LEN(rstr);
43
44
 
44
45
  if (0 == strcasecmp("Infinity", str)) {
@@ -82,8 +83,7 @@ static VALUE complex_load(VALUE clas, VALUE args) {
82
83
  real_id = rb_intern("real");
83
84
  imag_id = rb_intern("imag");
84
85
  }
85
- return rb_complex_new(rb_hash_aref(args, rb_id2str(real_id)),
86
- rb_hash_aref(args, rb_id2str(imag_id)));
86
+ return rb_complex_new(rb_hash_aref(args, rb_id2str(real_id)), rb_hash_aref(args, rb_id2str(imag_id)));
87
87
  }
88
88
 
89
89
  static void time_dump(VALUE obj, int depth, Out out) {
@@ -246,8 +246,7 @@ static VALUE rational_load(VALUE clas, VALUE args) {
246
246
  numerator_id = rb_intern("numerator");
247
247
  denominator_id = rb_intern("denominator");
248
248
  }
249
- return rb_rational_new(rb_hash_aref(args, rb_id2str(numerator_id)),
250
- rb_hash_aref(args, rb_id2str(denominator_id)));
249
+ return rb_rational_new(rb_hash_aref(args, rb_id2str(numerator_id)), rb_hash_aref(args, rb_id2str(denominator_id)));
251
250
  }
252
251
 
253
252
  static VALUE regexp_load(VALUE clas, VALUE args) {
@@ -282,7 +281,7 @@ static int hash_cb(VALUE key, VALUE value, VALUE ov) {
282
281
  Out out = (Out)ov;
283
282
  int depth = out->depth;
284
283
 
285
- if (oj_dump_ignore(out->opts, value)) {
284
+ if (dump_ignore(out->opts, value)) {
286
285
  return ST_CONTINUE;
287
286
  }
288
287
  if (out->omit_nil && Qnil == value) {
@@ -292,38 +291,33 @@ static int hash_cb(VALUE key, VALUE value, VALUE ov) {
292
291
  assure_size(out, depth * out->indent + 1);
293
292
  fill_indent(out, depth);
294
293
  } else {
295
- assure_size(out,
296
- depth * out->opts->dump_opts.indent_size + out->opts->dump_opts.hash_size + 1);
294
+ assure_size(out, depth * out->opts->dump_opts.indent_size + out->opts->dump_opts.hash_size + 1);
297
295
  if (0 < out->opts->dump_opts.hash_size) {
298
- strcpy(out->cur, out->opts->dump_opts.hash_nl);
299
- out->cur += out->opts->dump_opts.hash_size;
296
+ APPEND_CHARS(out->cur, out->opts->dump_opts.hash_nl, out->opts->dump_opts.hash_size);
300
297
  }
301
298
  if (0 < out->opts->dump_opts.indent_size) {
302
299
  int i;
303
300
 
304
301
  for (i = depth; 0 < i; i--) {
305
- strcpy(out->cur, out->opts->dump_opts.indent_str);
306
- out->cur += out->opts->dump_opts.indent_size;
302
+ APPEND_CHARS(out->cur, out->opts->dump_opts.indent_str, out->opts->dump_opts.indent_size);
307
303
  }
308
304
  }
309
305
  }
310
306
  switch (rb_type(key)) {
311
307
  case T_STRING: oj_dump_str(key, 0, out, false); break;
312
308
  case T_SYMBOL: oj_dump_sym(key, 0, out, false); break;
313
- default: oj_dump_str(rb_funcall(key, oj_to_s_id, 0), 0, out, false); break;
309
+ default: oj_dump_str(oj_safe_string_convert(key), 0, out, false); break;
314
310
  }
315
311
  if (!out->opts->dump_opts.use) {
316
312
  *out->cur++ = ':';
317
313
  } else {
318
314
  assure_size(out, out->opts->dump_opts.before_size + out->opts->dump_opts.after_size + 2);
319
315
  if (0 < out->opts->dump_opts.before_size) {
320
- strcpy(out->cur, out->opts->dump_opts.before_sep);
321
- out->cur += out->opts->dump_opts.before_size;
316
+ APPEND_CHARS(out->cur, out->opts->dump_opts.before_sep, out->opts->dump_opts.before_size);
322
317
  }
323
318
  *out->cur++ = ':';
324
319
  if (0 < out->opts->dump_opts.after_size) {
325
- strcpy(out->cur, out->opts->dump_opts.after_sep);
326
- out->cur += out->opts->dump_opts.after_size;
320
+ APPEND_CHARS(out->cur, out->opts->dump_opts.after_sep, out->opts->dump_opts.after_size);
327
321
  }
328
322
  }
329
323
  oj_dump_custom_val(value, depth, out, true);
@@ -344,8 +338,7 @@ static void dump_hash(VALUE obj, int depth, Out out, bool as_ok) {
344
338
  cnt = (int)RHASH_SIZE(obj);
345
339
  assure_size(out, 2);
346
340
  if (0 == cnt) {
347
- *out->cur++ = '{';
348
- *out->cur++ = '}';
341
+ APPEND_CHARS(out->cur, "{}", 2);
349
342
  } else {
350
343
  *out->cur++ = '{';
351
344
  out->depth = depth + 1;
@@ -357,19 +350,15 @@ static void dump_hash(VALUE obj, int depth, Out out, bool as_ok) {
357
350
  assure_size(out, depth * out->indent + 2);
358
351
  fill_indent(out, depth);
359
352
  } else {
360
- assure_size(
361
- out,
362
- depth * out->opts->dump_opts.indent_size + out->opts->dump_opts.hash_size + 1);
353
+ assure_size(out, depth * out->opts->dump_opts.indent_size + out->opts->dump_opts.hash_size + 1);
363
354
  if (0 < out->opts->dump_opts.hash_size) {
364
- strcpy(out->cur, out->opts->dump_opts.hash_nl);
365
- out->cur += out->opts->dump_opts.hash_size;
355
+ APPEND_CHARS(out->cur, out->opts->dump_opts.hash_nl, out->opts->dump_opts.hash_size);
366
356
  }
367
357
  if (0 < out->opts->dump_opts.indent_size) {
368
358
  int i;
369
359
 
370
360
  for (i = depth; 0 < i; i--) {
371
- strcpy(out->cur, out->opts->dump_opts.indent_str);
372
- out->cur += out->opts->dump_opts.indent_size;
361
+ APPEND_CHARS(out->cur, out->opts->dump_opts.indent_str, out->opts->dump_opts.indent_size);
373
362
  }
374
363
  }
375
364
  }
@@ -379,10 +368,10 @@ static void dump_hash(VALUE obj, int depth, Out out, bool as_ok) {
379
368
  }
380
369
 
381
370
  static void dump_odd(VALUE obj, Odd odd, VALUE clas, int depth, Out out) {
382
- ID * idp;
383
- AttrGetFunc * fp;
371
+ ID *idp;
372
+ AttrGetFunc *fp;
384
373
  volatile VALUE v;
385
- const char * name;
374
+ const char *name;
386
375
  size_t size;
387
376
  int d2 = depth + 1;
388
377
 
@@ -391,29 +380,24 @@ static void dump_odd(VALUE obj, Odd odd, VALUE clas, int depth, Out out) {
391
380
  if (NULL != out->opts->create_id && Yes == out->opts->create_ok) {
392
381
  const char *classname = rb_class2name(clas);
393
382
  int clen = (int)strlen(classname);
394
- size_t sep_len = out->opts->dump_opts.before_size + out->opts->dump_opts.after_size + 2;
383
+ size_t sep_len = out->opts->dump_opts.before_size + out->opts->dump_opts.after_size + 2;
395
384
 
396
385
  size = d2 * out->indent + 10 + clen + out->opts->create_id_len + sep_len;
397
386
  assure_size(out, size);
398
387
  fill_indent(out, d2);
399
388
  *out->cur++ = '"';
400
- memcpy(out->cur, out->opts->create_id, out->opts->create_id_len);
401
- out->cur += out->opts->create_id_len;
389
+ APPEND_CHARS(out->cur, out->opts->create_id, out->opts->create_id_len);
402
390
  *out->cur++ = '"';
403
391
  if (0 < out->opts->dump_opts.before_size) {
404
- strcpy(out->cur, out->opts->dump_opts.before_sep);
405
- out->cur += out->opts->dump_opts.before_size;
392
+ APPEND_CHARS(out->cur, out->opts->dump_opts.before_sep, out->opts->dump_opts.before_size);
406
393
  }
407
394
  *out->cur++ = ':';
408
395
  if (0 < out->opts->dump_opts.after_size) {
409
- strcpy(out->cur, out->opts->dump_opts.after_sep);
410
- out->cur += out->opts->dump_opts.after_size;
396
+ APPEND_CHARS(out->cur, out->opts->dump_opts.after_sep, out->opts->dump_opts.after_size);
411
397
  }
412
398
  *out->cur++ = '"';
413
- memcpy(out->cur, classname, clen);
414
- out->cur += clen;
415
- *out->cur++ = '"';
416
- *out->cur++ = ',';
399
+ APPEND_CHARS(out->cur, classname, clen);
400
+ APPEND_CHARS(out->cur, "\",", 2);
417
401
  }
418
402
  if (odd->raw) {
419
403
  v = rb_funcall(obj, *odd->attrs, 0);
@@ -429,12 +413,9 @@ static void dump_odd(VALUE obj, Odd odd, VALUE clas, int depth, Out out) {
429
413
  assure_size(out, size);
430
414
  fill_indent(out, d2);
431
415
  *out->cur++ = '"';
432
- memcpy(out->cur, name, nlen);
433
- out->cur += nlen;
434
- *out->cur++ = '"';
435
- *out->cur++ = ':';
436
- memcpy(out->cur, s, len);
437
- out->cur += len;
416
+ APPEND_CHARS(out->cur, name, nlen);
417
+ APPEND_CHARS(out->cur, "\":", 2);
418
+ APPEND_CHARS(out->cur, s, len);
438
419
  *out->cur = '\0';
439
420
  }
440
421
  } else {
@@ -457,7 +438,7 @@ static void dump_odd(VALUE obj, Odd odd, VALUE clas, int depth, Out out) {
457
438
  ID i;
458
439
 
459
440
  if (sizeof(nbuf) <= nlen) {
460
- if (NULL == (n2 = strdup(name))) {
441
+ if (NULL == (n2 = OJ_STRDUP(name))) {
461
442
  rb_raise(rb_eNoMemError, "for attribute name.");
462
443
  }
463
444
  } else {
@@ -474,7 +455,7 @@ static void dump_odd(VALUE obj, Odd odd, VALUE clas, int depth, Out out) {
474
455
  i = rb_intern(n);
475
456
  v = rb_funcall(v, i, 0);
476
457
  if (nbuf != n2) {
477
- free(n2);
458
+ OJ_FREE(n2);
478
459
  }
479
460
  }
480
461
  fill_indent(out, d2);
@@ -496,33 +477,26 @@ static VALUE dump_common(VALUE obj, int depth, Out out) {
496
477
  oj_dump_raw_json(obj, depth, out);
497
478
  } else if (Yes == out->opts->to_json && rb_respond_to(obj, oj_to_json_id)) {
498
479
  volatile VALUE rs;
499
- const char * s;
480
+ const char *s;
500
481
  int len;
501
482
 
502
- if (Yes == out->opts->trace) {
503
- oj_trace("to_json", obj, __FILE__, __LINE__, depth + 1, TraceRubyIn);
504
- }
483
+ TRACE(out->opts->trace, "to_json", obj, depth + 1, TraceRubyIn);
505
484
  if (0 == rb_obj_method_arity(obj, oj_to_json_id)) {
506
485
  rs = rb_funcall(obj, oj_to_json_id, 0);
507
486
  } else {
508
487
  rs = rb_funcall2(obj, oj_to_json_id, out->argc, out->argv);
509
488
  }
510
- if (Yes == out->opts->trace) {
511
- oj_trace("to_json", obj, __FILE__, __LINE__, depth + 1, TraceRubyOut);
512
- }
489
+ TRACE(out->opts->trace, "to_json", obj, depth + 1, TraceRubyOut);
513
490
  s = RSTRING_PTR(rs);
514
491
  len = (int)RSTRING_LEN(rs);
515
492
 
516
493
  assure_size(out, len + 1);
517
- memcpy(out->cur, s, len);
518
- out->cur += len;
494
+ APPEND_CHARS(out->cur, s, len);
519
495
  *out->cur = '\0';
520
496
  } else if (Yes == out->opts->as_json && rb_respond_to(obj, oj_as_json_id)) {
521
497
  volatile VALUE aj;
522
498
 
523
- if (Yes == out->opts->trace) {
524
- oj_trace("as_json", obj, __FILE__, __LINE__, depth + 1, TraceRubyIn);
525
- }
499
+ TRACE(out->opts->trace, "as_json", obj, depth + 1, TraceRubyIn);
526
500
  // Some classes elect to not take an options argument so check the arity
527
501
  // of as_json.
528
502
  if (0 == rb_obj_method_arity(obj, oj_as_json_id)) {
@@ -530,18 +504,12 @@ static VALUE dump_common(VALUE obj, int depth, Out out) {
530
504
  } else {
531
505
  aj = rb_funcall2(obj, oj_as_json_id, out->argc, out->argv);
532
506
  }
533
- if (Yes == out->opts->trace) {
534
- oj_trace("as_json", obj, __FILE__, __LINE__, depth + 1, TraceRubyOut);
535
- }
507
+ TRACE(out->opts->trace, "as_json", obj, depth + 1, TraceRubyOut);
536
508
  // Catch the obvious brain damaged recursive dumping.
537
509
  if (aj == obj) {
538
- volatile VALUE rstr = rb_funcall(obj, oj_to_s_id, 0);
510
+ volatile VALUE rstr = oj_safe_string_convert(obj);
539
511
 
540
- oj_dump_cstr(RSTRING_PTR(rstr),
541
- (int)RSTRING_LEN(rstr),
542
- false,
543
- false,
544
- out);
512
+ oj_dump_cstr(RSTRING_PTR(rstr), (int)RSTRING_LEN(rstr), false, false, out);
545
513
  } else {
546
514
  oj_dump_custom_val(aj, depth, out, true);
547
515
  }
@@ -577,7 +545,7 @@ static int dump_attr_cb(ID key, VALUE value, VALUE ov) {
577
545
  size_t size;
578
546
  const char *attr;
579
547
 
580
- if (oj_dump_ignore(out->opts, value)) {
548
+ if (dump_ignore(out->opts, value)) {
581
549
  return ST_CONTINUE;
582
550
  }
583
551
  if (out->omit_nil && Qnil == value) {
@@ -625,7 +593,7 @@ static void dump_obj_attrs(VALUE obj, VALUE clas, slot_t id, int depth, Out out)
625
593
  assure_size(out, 2);
626
594
  *out->cur++ = '{';
627
595
  if (Qundef != clas && NULL != out->opts->create_id && Yes == out->opts->create_ok) {
628
- size_t sep_len = out->opts->dump_opts.before_size + out->opts->dump_opts.after_size + 2;
596
+ size_t sep_len = out->opts->dump_opts.before_size + out->opts->dump_opts.after_size + 2;
629
597
  const char *classname = rb_obj_classname(obj);
630
598
  size_t len = strlen(classname);
631
599
 
@@ -633,21 +601,17 @@ static void dump_obj_attrs(VALUE obj, VALUE clas, slot_t id, int depth, Out out)
633
601
  assure_size(out, size);
634
602
  fill_indent(out, d2);
635
603
  *out->cur++ = '"';
636
- memcpy(out->cur, out->opts->create_id, out->opts->create_id_len);
637
- out->cur += out->opts->create_id_len;
604
+ APPEND_CHARS(out->cur, out->opts->create_id, out->opts->create_id_len);
638
605
  *out->cur++ = '"';
639
606
  if (0 < out->opts->dump_opts.before_size) {
640
- strcpy(out->cur, out->opts->dump_opts.before_sep);
641
- out->cur += out->opts->dump_opts.before_size;
607
+ APPEND_CHARS(out->cur, out->opts->dump_opts.before_sep, out->opts->dump_opts.before_size);
642
608
  }
643
609
  *out->cur++ = ':';
644
610
  if (0 < out->opts->dump_opts.after_size) {
645
- strcpy(out->cur, out->opts->dump_opts.after_sep);
646
- out->cur += out->opts->dump_opts.after_size;
611
+ APPEND_CHARS(out->cur, out->opts->dump_opts.after_sep, out->opts->dump_opts.after_size);
647
612
  }
648
613
  *out->cur++ = '"';
649
- memcpy(out->cur, classname, len);
650
- out->cur += len;
614
+ APPEND_CHARS(out->cur, classname, len);
651
615
  *out->cur++ = '"';
652
616
  class_written = true;
653
617
  }
@@ -731,25 +695,23 @@ static void dump_array(VALUE a, int depth, Out out, bool as_ok) {
731
695
  } else {
732
696
  size = d2 * out->indent + 2;
733
697
  }
698
+ assure_size(out, size * cnt);
734
699
  cnt--;
735
700
  for (i = 0; i <= cnt; i++) {
736
- assure_size(out, size);
737
701
  if (out->opts->dump_opts.use) {
738
702
  if (0 < out->opts->dump_opts.array_size) {
739
- strcpy(out->cur, out->opts->dump_opts.array_nl);
740
- out->cur += out->opts->dump_opts.array_size;
703
+ APPEND_CHARS(out->cur, out->opts->dump_opts.array_nl, out->opts->dump_opts.array_size);
741
704
  }
742
705
  if (0 < out->opts->dump_opts.indent_size) {
743
706
  int i;
744
707
  for (i = d2; 0 < i; i--) {
745
- strcpy(out->cur, out->opts->dump_opts.indent_str);
746
- out->cur += out->opts->dump_opts.indent_size;
708
+ APPEND_CHARS(out->cur, out->opts->dump_opts.indent_str, out->opts->dump_opts.indent_size);
747
709
  }
748
710
  }
749
711
  } else {
750
712
  fill_indent(out, d2);
751
713
  }
752
- oj_dump_custom_val(rb_ary_entry(a, i), d2, out, true);
714
+ oj_dump_custom_val(RARRAY_AREF(a, i), d2, out, true);
753
715
  if (i < cnt) {
754
716
  *out->cur++ = ',';
755
717
  }
@@ -758,15 +720,13 @@ static void dump_array(VALUE a, int depth, Out out, bool as_ok) {
758
720
  assure_size(out, size);
759
721
  if (out->opts->dump_opts.use) {
760
722
  if (0 < out->opts->dump_opts.array_size) {
761
- strcpy(out->cur, out->opts->dump_opts.array_nl);
762
- out->cur += out->opts->dump_opts.array_size;
723
+ APPEND_CHARS(out->cur, out->opts->dump_opts.array_nl, out->opts->dump_opts.array_size);
763
724
  }
764
725
  if (0 < out->opts->dump_opts.indent_size) {
765
726
  int i;
766
727
 
767
728
  for (i = depth; 0 < i; i--) {
768
- strcpy(out->cur, out->opts->dump_opts.indent_str);
769
- out->cur += out->opts->dump_opts.indent_size;
729
+ APPEND_CHARS(out->cur, out->opts->dump_opts.indent_str, out->opts->dump_opts.indent_size);
770
730
  }
771
731
  }
772
732
  } else {
@@ -800,8 +760,7 @@ static void dump_struct(VALUE obj, int depth, Out out, bool as_ok) {
800
760
  *out->cur++ = '"';
801
761
  oj_dump_custom_val(rb_funcall(obj, oj_begin_id, 0), d3, out, false);
802
762
  assure_size(out, 3);
803
- *out->cur++ = '.';
804
- *out->cur++ = '.';
763
+ APPEND_CHARS(out->cur, "..", 2);
805
764
  if (Qtrue == rb_funcall(obj, oj_exclude_end_id, 0)) {
806
765
  *out->cur++ = '.';
807
766
  }
@@ -833,7 +792,7 @@ static void dump_struct(VALUE obj, int depth, Out out, bool as_ok) {
833
792
  v = rb_struct_aref(obj, INT2FIX(i));
834
793
  #endif
835
794
  if (ma != Qnil) {
836
- volatile VALUE s = rb_sym2str(rb_ary_entry(ma, i));
795
+ volatile VALUE s = rb_sym2str(RARRAY_AREF(ma, i));
837
796
 
838
797
  name = RSTRING_PTR(s);
839
798
  len = (int)RSTRING_LEN(s);
@@ -844,10 +803,8 @@ static void dump_struct(VALUE obj, int depth, Out out, bool as_ok) {
844
803
  assure_size(out, size + len + 3);
845
804
  fill_indent(out, d3);
846
805
  *out->cur++ = '"';
847
- memcpy(out->cur, name, len);
848
- out->cur += len;
849
- *out->cur++ = '"';
850
- *out->cur++ = ':';
806
+ APPEND_CHARS(out->cur, name, len);
807
+ APPEND_CHARS(out->cur, "\":", 2);
851
808
  oj_dump_custom_val(v, d3, out, true);
852
809
  *out->cur++ = ',';
853
810
  }
@@ -912,9 +869,7 @@ static DumpFunc custom_funcs[] = {
912
869
  void oj_dump_custom_val(VALUE obj, int depth, Out out, bool as_ok) {
913
870
  int type = rb_type(obj);
914
871
 
915
- if (Yes == out->opts->trace) {
916
- oj_trace("dump", obj, __FILE__, __LINE__, depth, TraceIn);
917
- }
872
+ TRACE(out->opts->trace, "dump", obj, depth, TraceIn);
918
873
  if (MAX_DEPTH < depth) {
919
874
  rb_raise(rb_eNoMemError, "Too deeply nested.\n");
920
875
  }
@@ -923,27 +878,22 @@ void oj_dump_custom_val(VALUE obj, int depth, Out out, bool as_ok) {
923
878
 
924
879
  if (NULL != f) {
925
880
  f(obj, depth, out, true);
926
- if (Yes == out->opts->trace) {
927
- oj_trace("dump", obj, __FILE__, __LINE__, depth, TraceOut);
928
- }
881
+ TRACE(out->opts->trace, "dump", obj, depth, TraceOut);
929
882
  return;
930
883
  }
931
884
  }
932
885
  oj_dump_nil(Qnil, depth, out, false);
933
- if (Yes == out->opts->trace) {
934
- oj_trace("dump", Qnil, __FILE__, __LINE__, depth, TraceOut);
935
- }
886
+ TRACE(out->opts->trace, "dump", Qnil, depth, TraceOut);
936
887
  }
937
888
 
938
889
  ///// load functions /////
939
890
 
940
891
  static void hash_set_cstr(ParseInfo pi, Val kval, const char *str, size_t len, const char *orig) {
941
- const char * key = kval->key;
942
- int klen = kval->klen;
943
- Val parent = stack_peek(&pi->stack);
944
- volatile VALUE rkey = kval->key_val;
892
+ const char *key = kval->key;
893
+ int klen = kval->klen;
894
+ Val parent = stack_peek(&pi->stack);
945
895
 
946
- if (Qundef == rkey && Yes == pi->options.create_ok && NULL != pi->options.create_id &&
896
+ if (Qundef == kval->key_val && Yes == pi->options.create_ok && NULL != pi->options.create_id &&
947
897
  *pi->options.create_id == *key && (int)pi->options.create_id_len == klen &&
948
898
  0 == strncmp(pi->options.create_id, key, klen)) {
949
899
  parent->clas = oj_name2class(pi, str, len, false, rb_eArgError);
@@ -955,16 +905,9 @@ static void hash_set_cstr(ParseInfo pi, Val kval, const char *str, size_t len, c
955
905
  }
956
906
  }
957
907
  } else {
958
- volatile VALUE rstr = oj_cstr_to_value(str, len, (size_t)pi->options.cache_str);
959
- //volatile VALUE rstr = rb_utf8_str_new(str, len);
908
+ volatile VALUE rstr = oj_cstr_to_value(str, len, (size_t)pi->options.cache_str);
909
+ volatile VALUE rkey = oj_calc_hash_key(pi, kval);
960
910
 
961
- if (Qundef == rkey) {
962
- if (Yes == pi->options.sym_key) {
963
- rkey = ID2SYM(rb_intern3(key, klen, oj_utf8_encoding));
964
- } else {
965
- rkey = rb_utf8_str_new(key, klen);
966
- }
967
- }
968
911
  if (Yes == pi->options.create_ok && NULL != pi->options.str_rx.head) {
969
912
  VALUE clas = oj_rxclass_match(&pi->options.str_rx, str, (int)len);
970
913
 
@@ -986,9 +929,7 @@ static void hash_set_cstr(ParseInfo pi, Val kval, const char *str, size_t len, c
986
929
  break;
987
930
  default: break;
988
931
  }
989
- if (Yes == pi->options.trace) {
990
- oj_trace_parse_call("set_string", pi, __FILE__, __LINE__, rstr);
991
- }
932
+ TRACE_PARSE_CALL(pi->options.trace, "set_string", pi, rstr);
992
933
  }
993
934
  }
994
935
 
@@ -1005,9 +946,7 @@ static void end_hash(struct _parseInfo *pi) {
1005
946
  }
1006
947
  parent->clas = Qundef;
1007
948
  }
1008
- if (Yes == pi->options.trace) {
1009
- oj_trace_parse_hash_end(pi, __FILE__, __LINE__);
1010
- }
949
+ TRACE_PARSE_HASH_END(pi->options.trace, pi);
1011
950
  }
1012
951
 
1013
952
  static void hash_set_num(struct _parseInfo *pi, Val kval, NumInfo ni) {
@@ -1035,20 +974,10 @@ static void hash_set_num(struct _parseInfo *pi, Val kval, NumInfo ni) {
1035
974
  // match the expected value.
1036
975
  parent->val = rb_funcall2(parent->val, oj_utc_id, 0, 0);
1037
976
  } else if (ni->has_exp) {
1038
- int64_t t = (int64_t)(ni->i + ni->exp);
1039
- struct _timeInfo ti;
1040
- VALUE args[8];
1041
-
1042
- sec_as_time(t, &ti);
1043
-
1044
- args[0] = LONG2NUM(ti.year);
1045
- args[1] = LONG2NUM(ti.mon);
1046
- args[2] = LONG2NUM(ti.day);
1047
- args[3] = LONG2NUM(ti.hour);
1048
- args[4] = LONG2NUM(ti.min);
1049
- args[5] = rb_float_new((double)ti.sec + ((double)nsec + 0.5) / 1000000000.0);
1050
- args[6] = LONG2NUM(ni->exp);
1051
- parent->val = rb_funcall2(rb_cTime, oj_new_id, 7, args);
977
+ struct timespec ts;
978
+ ts.tv_sec = ni->i;
979
+ ts.tv_nsec = nsec;
980
+ parent->val = rb_time_timespec_new(&ts, (int)ni->exp);
1052
981
  } else {
1053
982
  parent->val = rb_time_nano_new(ni->i, (long)nsec);
1054
983
  }
@@ -1059,9 +988,7 @@ static void hash_set_num(struct _parseInfo *pi, Val kval, NumInfo ni) {
1059
988
  break;
1060
989
  default: break;
1061
990
  }
1062
- if (Yes == pi->options.trace) {
1063
- oj_trace_parse_call("set_string", pi, __FILE__, __LINE__, rval);
1064
- }
991
+ TRACE_PARSE_CALL(pi->options.trace, "set_string", pi, rval);
1065
992
  }
1066
993
 
1067
994
  static void hash_set_value(ParseInfo pi, Val kval, VALUE value) {
@@ -1072,9 +999,7 @@ static void hash_set_value(ParseInfo pi, Val kval, VALUE value) {
1072
999
  case T_HASH: rb_hash_aset(parent->val, oj_calc_hash_key(pi, kval), value); break;
1073
1000
  default: break;
1074
1001
  }
1075
- if (Yes == pi->options.trace) {
1076
- oj_trace_parse_call("set_value", pi, __FILE__, __LINE__, value);
1077
- }
1002
+ TRACE_PARSE_CALL(pi->options.trace, "set_value", pi, value);
1078
1003
  }
1079
1004
 
1080
1005
  static void array_append_num(ParseInfo pi, NumInfo ni) {
@@ -1082,9 +1007,7 @@ static void array_append_num(ParseInfo pi, NumInfo ni) {
1082
1007
  volatile VALUE rval = oj_num_as_value(ni);
1083
1008
 
1084
1009
  rb_ary_push(parent->val, rval);
1085
- if (Yes == pi->options.trace) {
1086
- oj_trace_parse_call("append_number", pi, __FILE__, __LINE__, rval);
1087
- }
1010
+ TRACE_PARSE_CALL(pi->options.trace, "append_number", pi, rval);
1088
1011
  }
1089
1012
 
1090
1013
  static void array_append_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
@@ -1099,9 +1022,7 @@ static void array_append_cstr(ParseInfo pi, const char *str, size_t len, const c
1099
1022
  }
1100
1023
  }
1101
1024
  rb_ary_push(stack_peek(&pi->stack)->val, rstr);
1102
- if (Yes == pi->options.trace) {
1103
- oj_trace_parse_call("append_string", pi, __FILE__, __LINE__, rstr);
1104
- }
1025
+ TRACE_PARSE_CALL(pi->options.trace, "append_string", pi, rstr);
1105
1026
  }
1106
1027
 
1107
1028
  void oj_set_custom_callbacks(ParseInfo pi) {
data/ext/oj/debug.c CHANGED
@@ -30,9 +30,7 @@ static void add_int(struct _ojParser *p) {
30
30
  switch (p->stack[p->depth]) {
31
31
  case TOP_FUN: printf("*** add_int %lld at top\n", (long long)p->num.fixnum); break;
32
32
  case ARRAY_FUN: printf("*** add_int %lld to array\n", (long long)p->num.fixnum); break;
33
- case OBJECT_FUN:
34
- printf("*** add_int %lld with '%s'\n", (long long)p->num.fixnum, buf_str(&p->key));
35
- break;
33
+ case OBJECT_FUN: printf("*** add_int %lld with '%s'\n", (long long)p->num.fixnum, buf_str(&p->key)); break;
36
34
  }
37
35
  }
38
36
 
@@ -48,9 +46,7 @@ static void add_big(struct _ojParser *p) {
48
46
  switch (p->stack[p->depth]) {
49
47
  case TOP_FUN: printf("*** add_big %s at top\n", buf_str(&p->buf)); break;
50
48
  case ARRAY_FUN: printf("*** add_big %s to array\n", buf_str(&p->buf)); break;
51
- case OBJECT_FUN:
52
- printf("*** add_big %s with '%s'\n", buf_str(&p->buf), buf_str(&p->key));
53
- break;
49
+ case OBJECT_FUN: printf("*** add_big %s with '%s'\n", buf_str(&p->buf), buf_str(&p->key)); break;
54
50
  }
55
51
  }
56
52
 
@@ -58,9 +54,7 @@ static void add_str(struct _ojParser *p) {
58
54
  switch (p->stack[p->depth]) {
59
55
  case TOP_FUN: printf("*** add_str '%s' at top\n", buf_str(&p->buf)); break;
60
56
  case ARRAY_FUN: printf("*** add_str '%s' to array\n", buf_str(&p->buf)); break;
61
- case OBJECT_FUN:
62
- printf("*** add_str '%s' with '%s'\n", buf_str(&p->buf), buf_str(&p->key));
63
- break;
57
+ case OBJECT_FUN: printf("*** add_str '%s' with '%s'\n", buf_str(&p->buf), buf_str(&p->key)); break;
64
58
  }
65
59
  }
66
60