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/mimic_json.c CHANGED
@@ -3,6 +3,7 @@
3
3
 
4
4
  #include "dump.h"
5
5
  #include "encode.h"
6
+ #include "mem.h"
6
7
  #include "oj.h"
7
8
  #include "parse.h"
8
9
 
@@ -198,7 +199,6 @@ static int mimic_limit_arg(VALUE a) {
198
199
  * Returns [_String_] a JSON string.
199
200
  */
200
201
  static VALUE mimic_dump(int argc, VALUE *argv, VALUE self) {
201
- char buf[4096];
202
202
  struct _out out;
203
203
  struct _options copts = oj_default_options;
204
204
  VALUE rstr;
@@ -206,10 +206,9 @@ static VALUE mimic_dump(int argc, VALUE *argv, VALUE self) {
206
206
 
207
207
  copts.str_rx.head = NULL;
208
208
  copts.str_rx.tail = NULL;
209
- out.buf = buf;
210
- out.end = buf + sizeof(buf) - 10;
211
- out.allocated = false;
212
- out.caller = CALLER_DUMP;
209
+
210
+ oj_out_init(&out);
211
+
213
212
  copts.escape_mode = JXEsc;
214
213
  copts.mode = CompatMode;
215
214
 
@@ -257,9 +256,9 @@ static VALUE mimic_dump(int argc, VALUE *argv, VALUE self) {
257
256
  rb_funcall2(io, oj_write_id, 1, args);
258
257
  rstr = io;
259
258
  }
260
- if (out.allocated) {
261
- xfree(out.buf);
262
- }
259
+
260
+ oj_out_free(&out);
261
+
263
262
  return rstr;
264
263
  }
265
264
 
@@ -272,7 +271,7 @@ static int mimic_walk(VALUE key, VALUE obj, VALUE proc) {
272
271
  size_t i;
273
272
 
274
273
  for (i = 0; i < cnt; i++) {
275
- mimic_walk(Qnil, rb_ary_entry(obj, i), proc);
274
+ mimic_walk(Qnil, RARRAY_AREF(obj, i), proc);
276
275
  }
277
276
  break;
278
277
  }
@@ -349,26 +348,25 @@ static VALUE mimic_load(int argc, VALUE *argv, VALUE self) {
349
348
  static VALUE mimic_dump_load(int argc, VALUE *argv, VALUE self) {
350
349
  if (1 > argc) {
351
350
  rb_raise(rb_eArgError, "wrong number of arguments (0 for 1)");
352
- } else if (T_STRING == rb_type(*argv)) {
351
+ }
352
+ if (T_STRING == rb_type(*argv)) {
353
353
  return mimic_load(argc, argv, self);
354
- } else {
355
- return mimic_dump(argc, argv, self);
356
354
  }
357
- return Qnil;
355
+ return mimic_dump(argc, argv, self);
358
356
  }
359
357
 
360
358
  static VALUE mimic_generate_core(int argc, VALUE *argv, Options copts) {
361
- char buf[4096];
362
359
  struct _out out;
363
360
  VALUE rstr;
364
361
 
365
- memset(buf, 0, sizeof(buf));
362
+ if (0 == argc) {
363
+ rb_raise(rb_eArgError, "wrong number of arguments (0))");
364
+ }
365
+ memset(out.stack_buffer, 0, sizeof(out.stack_buffer));
366
+
367
+ oj_out_init(&out);
366
368
 
367
- out.buf = buf;
368
- out.end = buf + sizeof(buf) - 10;
369
- out.allocated = false;
370
- out.omit_nil = copts->dump_opts.omit_nil;
371
- out.caller = CALLER_GENERATE;
369
+ out.omit_nil = copts->dump_opts.omit_nil;
372
370
  // For obj.to_json or generate nan is not allowed but if called from dump
373
371
  // it is.
374
372
  copts->dump_opts.nan_dump = RaiseNan;
@@ -388,6 +386,8 @@ static VALUE mimic_generate_core(int argc, VALUE *argv, Options copts) {
388
386
  VALUE active_hack[1];
389
387
 
390
388
  if (Qundef == state_class) {
389
+ rb_warn("Oj::Rails.mimic_JSON was called implicitly. "
390
+ "Call it explicitly beforehand if you want to remove this warning.");
391
391
  oj_define_mimic_json(0, NULL, Qnil);
392
392
  }
393
393
  active_hack[0] = rb_funcall(state_class, oj_new_id, 0);
@@ -398,9 +398,9 @@ static VALUE mimic_generate_core(int argc, VALUE *argv, Options copts) {
398
398
  }
399
399
  rstr = rb_str_new2(out.buf);
400
400
  rstr = oj_encode(rstr);
401
- if (out.allocated) {
402
- xfree(out.buf);
403
- }
401
+
402
+ oj_out_free(&out);
403
+
404
404
  return rstr;
405
405
  }
406
406
 
@@ -457,7 +457,10 @@ oj_mimic_pretty_generate(int argc, VALUE *argv, VALUE self) {
457
457
  // a Hash. I haven't dug deep enough to find out why but using a State
458
458
  // instance and not a Hash gives the desired behavior.
459
459
  *rargs = *argv;
460
- if (1 == argc) {
460
+ if (0 == argc) {
461
+ rb_raise(rb_eArgError, "wrong number of arguments (0))");
462
+ }
463
+ if (1 == argc || Qnil == argv[1]) {
461
464
  h = rb_hash_new();
462
465
  } else {
463
466
  h = argv[1];
@@ -478,6 +481,8 @@ oj_mimic_pretty_generate(int argc, VALUE *argv, VALUE self) {
478
481
  rb_hash_aset(h, oj_array_nl_sym, rb_str_new2("\n"));
479
482
  }
480
483
  if (Qundef == state_class) {
484
+ rb_warn("Oj::Rails.mimic_JSON was called implicitly. "
485
+ "Call it explicitly beforehand if you want to remove this warning.");
481
486
  oj_define_mimic_json(0, NULL, Qnil);
482
487
  }
483
488
  rargs[1] = rb_funcall(state_class, oj_new_id, 1, h);
@@ -499,6 +504,44 @@ oj_mimic_pretty_generate(int argc, VALUE *argv, VALUE self) {
499
504
  return mimic_generate_core(2, rargs, &copts);
500
505
  }
501
506
 
507
+ static int parse_options_cb(VALUE k, VALUE v, VALUE info) {
508
+ struct _parseInfo *pi = (struct _parseInfo *)info;
509
+
510
+ if (oj_symbolize_names_sym == k) {
511
+ pi->options.sym_key = (Qtrue == v) ? Yes : No;
512
+ } else if (oj_quirks_mode_sym == k) {
513
+ pi->options.quirks_mode = (Qtrue == v) ? Yes : No;
514
+ } else if (oj_create_additions_sym == k) {
515
+ pi->options.create_ok = (Qtrue == v) ? Yes : No;
516
+ } else if (oj_allow_nan_sym == k) {
517
+ pi->options.allow_nan = (Qtrue == v) ? Yes : No;
518
+ } else if (oj_hash_class_sym == k) {
519
+ if (Qnil == v) {
520
+ pi->options.hash_class = Qnil;
521
+ } else {
522
+ rb_check_type(v, T_CLASS);
523
+ pi->options.hash_class = v;
524
+ }
525
+ } else if (oj_object_class_sym == k) {
526
+ if (Qnil == v) {
527
+ pi->options.hash_class = Qnil;
528
+ } else {
529
+ rb_check_type(v, T_CLASS);
530
+ pi->options.hash_class = v;
531
+ }
532
+ } else if (oj_array_class_sym == k) {
533
+ if (Qnil == v) {
534
+ pi->options.array_class = Qnil;
535
+ } else {
536
+ rb_check_type(v, T_CLASS);
537
+ pi->options.array_class = v;
538
+ }
539
+ } else if (oj_decimal_class_sym == k) {
540
+ pi->options.compat_bigdec = (oj_bigdecimal_class == v);
541
+ }
542
+ return ST_CONTINUE;
543
+ }
544
+
502
545
  static VALUE mimic_parse_core(int argc, VALUE *argv, VALUE self, bool bang) {
503
546
  struct _parseInfo pi;
504
547
  VALUE ropts;
@@ -529,46 +572,7 @@ static VALUE mimic_parse_core(int argc, VALUE *argv, VALUE self, bool bang) {
529
572
  if (T_HASH != rb_type(ropts)) {
530
573
  rb_raise(rb_eArgError, "options must be a hash.");
531
574
  }
532
- if (Qnil != (v = rb_hash_lookup(ropts, oj_symbolize_names_sym))) {
533
- pi.options.sym_key = (Qtrue == v) ? Yes : No;
534
- }
535
- if (Qnil != (v = rb_hash_lookup(ropts, oj_quirks_mode_sym))) {
536
- pi.options.quirks_mode = (Qtrue == v) ? Yes : No;
537
- }
538
- if (Qnil != (v = rb_hash_lookup(ropts, oj_create_additions_sym))) {
539
- pi.options.create_ok = (Qtrue == v) ? Yes : No;
540
- }
541
- if (Qnil != (v = rb_hash_lookup(ropts, oj_allow_nan_sym))) {
542
- pi.options.allow_nan = (Qtrue == v) ? Yes : No;
543
- }
544
-
545
- if (oj_hash_has_key(ropts, oj_hash_class_sym)) {
546
- if (Qnil == (v = rb_hash_lookup(ropts, oj_hash_class_sym))) {
547
- pi.options.hash_class = Qnil;
548
- } else {
549
- rb_check_type(v, T_CLASS);
550
- pi.options.hash_class = v;
551
- }
552
- }
553
- if (oj_hash_has_key(ropts, oj_object_class_sym)) {
554
- if (Qnil == (v = rb_hash_lookup(ropts, oj_object_class_sym))) {
555
- pi.options.hash_class = Qnil;
556
- } else {
557
- rb_check_type(v, T_CLASS);
558
- pi.options.hash_class = v;
559
- }
560
- }
561
- if (oj_hash_has_key(ropts, oj_array_class_sym)) {
562
- if (Qnil == (v = rb_hash_lookup(ropts, oj_array_class_sym))) {
563
- pi.options.array_class = Qnil;
564
- } else {
565
- rb_check_type(v, T_CLASS);
566
- pi.options.array_class = v;
567
- }
568
- }
569
- if (oj_hash_has_key(ropts, oj_decimal_class_sym)) {
570
- pi.options.compat_bigdec = (oj_bigdecimal_class == rb_hash_lookup(ropts, oj_decimal_class_sym));
571
- }
575
+ rb_hash_foreach(ropts, parse_options_cb, (VALUE)&pi);
572
576
  v = rb_hash_lookup(ropts, oj_max_nesting_sym);
573
577
  if (Qtrue == v) {
574
578
  pi.max_depth = 100;
@@ -646,23 +650,22 @@ static VALUE mimic_recurse_proc(VALUE self, VALUE obj) {
646
650
  *
647
651
  * - *id* [_nil_|String] new create_id
648
652
  *
649
- * Returns [_String_] the id.
653
+ * Returns [_nil_|_String_] the id.
650
654
  */
651
655
  static VALUE mimic_set_create_id(VALUE self, VALUE id) {
652
- Check_Type(id, T_STRING);
653
-
654
656
  if (NULL != oj_default_options.create_id) {
655
657
  if (oj_json_class != oj_default_options.create_id) {
656
- xfree((char *)oj_default_options.create_id);
658
+ OJ_R_FREE((char *)oj_default_options.create_id);
657
659
  }
658
660
  oj_default_options.create_id = NULL;
659
661
  oj_default_options.create_id_len = 0;
660
662
  }
661
663
  if (Qnil != id) {
662
- size_t len = RSTRING_LEN(id) + 1;
664
+ const char *ptr = StringValueCStr(id);
665
+ size_t len = RSTRING_LEN(id) + 1;
663
666
 
664
- oj_default_options.create_id = ALLOC_N(char, len);
665
- strcpy((char *)oj_default_options.create_id, StringValuePtr(id));
667
+ oj_default_options.create_id = OJ_R_ALLOC_N(char, len);
668
+ strcpy((char *)oj_default_options.create_id, ptr);
666
669
  oj_default_options.create_id_len = len - 1;
667
670
  }
668
671
  return id;
@@ -732,6 +735,7 @@ static struct _options mimic_object_to_json_options = {0, // indent
732
735
  0, // array_size
733
736
  RaiseNan, // nan_dump
734
737
  false, // omit_nil
738
+ false, // omit_null_byte
735
739
  100, // max_depth
736
740
  },
737
741
  {
@@ -742,19 +746,18 @@ static struct _options mimic_object_to_json_options = {0, // indent
742
746
  }};
743
747
 
744
748
  static VALUE mimic_object_to_json(int argc, VALUE *argv, VALUE self) {
745
- char buf[4096];
746
749
  struct _out out;
747
750
  VALUE rstr;
748
751
  struct _options copts = oj_default_options;
749
752
 
750
753
  copts.str_rx.head = NULL;
751
754
  copts.str_rx.tail = NULL;
752
- out.buf = buf;
753
- out.end = buf + sizeof(buf) - 10;
754
- out.allocated = false;
755
- out.omit_nil = copts.dump_opts.omit_nil;
756
- copts.mode = CompatMode;
757
- copts.to_json = No;
755
+
756
+ oj_out_init(&out);
757
+
758
+ out.omit_nil = copts.dump_opts.omit_nil;
759
+ copts.mode = CompatMode;
760
+ copts.to_json = No;
758
761
  if (1 <= argc && Qnil != argv[0]) {
759
762
  oj_parse_mimic_dump_options(argv[0], &copts);
760
763
  }
@@ -767,9 +770,9 @@ static VALUE mimic_object_to_json(int argc, VALUE *argv, VALUE self) {
767
770
  }
768
771
  rstr = rb_str_new2(out.buf);
769
772
  rstr = oj_encode(rstr);
770
- if (out.allocated) {
771
- xfree(out.buf);
772
- }
773
+
774
+ oj_out_free(&out);
775
+
773
776
  return rstr;
774
777
  }
775
778
 
@@ -786,28 +789,48 @@ void oj_mimic_json_methods(VALUE json) {
786
789
  VALUE json_error;
787
790
  VALUE generator;
788
791
  VALUE ext;
792
+ VALUE verbose;
793
+
794
+ // rb_undef_method doesn't work for modules or maybe sometimes
795
+ // doesn't. Anyway setting verbose should hide the warning.
796
+ verbose = rb_gv_get("$VERBOSE");
797
+ rb_gv_set("$VERBOSE", Qfalse);
789
798
 
799
+ rb_undef_method(json, "create_id=");
790
800
  rb_define_module_function(json, "create_id=", mimic_set_create_id, 1);
801
+ rb_undef_method(json, "create_id");
791
802
  rb_define_module_function(json, "create_id", mimic_create_id, 0);
792
803
 
804
+ rb_undef_method(json, "dump");
793
805
  rb_define_module_function(json, "dump", mimic_dump, -1);
806
+ rb_undef_method(json, "load");
794
807
  rb_define_module_function(json, "load", mimic_load, -1);
795
808
  rb_define_module_function(json, "restore", mimic_load, -1);
809
+ rb_undef_method(json, "recurse_proc");
796
810
  rb_define_module_function(json, "recurse_proc", mimic_recurse_proc, 1);
811
+ rb_undef_method(json, "[]");
797
812
  rb_define_module_function(json, "[]", mimic_dump_load, -1);
798
813
 
814
+ rb_undef_method(json, "generate");
799
815
  rb_define_module_function(json, "generate", oj_mimic_generate, -1);
816
+ rb_undef_method(json, "fast_generate");
800
817
  rb_define_module_function(json, "fast_generate", oj_mimic_generate, -1);
818
+ rb_undef_method(json, "pretty_generate");
801
819
  rb_define_module_function(json, "pretty_generate", oj_mimic_pretty_generate, -1);
802
820
  // For older versions of JSON, the deprecated unparse methods.
821
+ rb_undef_method(json, "unparse");
803
822
  rb_define_module_function(json, "unparse", oj_mimic_generate, -1);
804
823
  rb_define_module_function(json, "fast_unparse", oj_mimic_generate, -1);
805
824
  rb_define_module_function(json, "pretty_unparse", oj_mimic_pretty_generate, -1);
806
825
 
826
+ rb_undef_method(json, "parse");
807
827
  rb_define_module_function(json, "parse", oj_mimic_parse, -1);
828
+ rb_undef_method(json, "parse!");
808
829
  rb_define_module_function(json, "parse!", mimic_parse_bang, -1);
809
830
 
831
+ rb_undef_method(json, "state");
810
832
  rb_define_module_function(json, "state", mimic_state, 0);
833
+ rb_gv_set("$VERBOSE", verbose);
811
834
 
812
835
  if (rb_const_defined_at(json, rb_intern("JSONError"))) {
813
836
  json_error = rb_const_get(json, rb_intern("JSONError"));
data/ext/oj/object.c CHANGED
@@ -67,9 +67,9 @@ static VALUE str_to_value(ParseInfo pi, const char *str, size_t len, const char
67
67
 
68
68
  // The much faster approach (4x faster)
69
69
  static int parse_num(const char *str, const char *end, int cnt) {
70
- int n = 0;
70
+ int n = 0;
71
71
  char c;
72
- int i;
72
+ int i;
73
73
 
74
74
  for (i = cnt; 0 < i; i--, str++) {
75
75
  c = *str;
@@ -83,9 +83,9 @@ static int parse_num(const char *str, const char *end, int cnt) {
83
83
 
84
84
  VALUE
85
85
  oj_parse_xml_time(const char *str, int len) {
86
- VALUE args[8];
86
+ VALUE args[8];
87
87
  const char *end = str + len;
88
- int n;
88
+ int n;
89
89
 
90
90
  // year
91
91
  if (0 > (n = parse_num(str, end, 4))) {
@@ -269,19 +269,10 @@ static int hat_num(ParseInfo pi, Val parent, Val kval, NumInfo ni) {
269
269
  // match the expected value.
270
270
  parent->val = rb_funcall2(parent->val, oj_utc_id, 0, 0);
271
271
  } else if (ni->has_exp) {
272
- int64_t t = (int64_t)(ni->i + ni->exp);
273
- struct _timeInfo ti;
274
- VALUE args[8];
275
-
276
- sec_as_time(t, &ti);
277
- args[0] = LONG2NUM((long)(ti.year));
278
- args[1] = LONG2NUM(ti.mon);
279
- args[2] = LONG2NUM(ti.day);
280
- args[3] = LONG2NUM(ti.hour);
281
- args[4] = LONG2NUM(ti.min);
282
- args[5] = rb_float_new((double)ti.sec + ((double)nsec + 0.5) / 1000000000.0);
283
- args[6] = LONG2NUM(ni->exp);
284
- parent->val = rb_funcall2(rb_cTime, oj_new_id, 7, args);
272
+ struct timespec ts;
273
+ ts.tv_sec = ni->i;
274
+ ts.tv_nsec = nsec;
275
+ parent->val = rb_time_timespec_new(&ts, (int)ni->exp);
285
276
  } else {
286
277
  parent->val = rb_time_nano_new(ni->i, (long)nsec);
287
278
  }
@@ -317,7 +308,7 @@ static int hat_value(ParseInfo pi, Val parent, const char *key, size_t klen, vol
317
308
  oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "Invalid struct data");
318
309
  return 1;
319
310
  }
320
- e1 = *RARRAY_PTR(value);
311
+ e1 = *RARRAY_CONST_PTR(value);
321
312
  // check for anonymous Struct
322
313
  if (T_ARRAY == rb_type(e1)) {
323
314
  VALUE args[1024];
@@ -325,46 +316,50 @@ static int hat_value(ParseInfo pi, Val parent, const char *key, size_t klen, vol
325
316
  int i, cnt = (int)RARRAY_LEN(e1);
326
317
 
327
318
  for (i = 0; i < cnt; i++) {
328
- rstr = rb_ary_entry(e1, i);
319
+ rstr = RARRAY_AREF(e1, i);
329
320
  args[i] = rb_funcall(rstr, oj_to_sym_id, 0);
330
321
  }
331
322
  sc = rb_funcall2(rb_cStruct, oj_new_id, cnt, args);
332
323
  } else {
333
324
  // If struct is not defined then we let this fail and raise an exception.
334
- sc = oj_name2struct(pi, *RARRAY_PTR(value), rb_eArgError);
325
+ sc = oj_name2struct(pi, *RARRAY_CONST_PTR(value), rb_eArgError);
335
326
  }
336
- // Create a properly initialized struct instance without calling the initialize method.
337
- parent->val = rb_obj_alloc(sc);
338
- // If the JSON array has more entries than the struct class allows, we record an error.
327
+ if (sc == rb_cRange) {
328
+ parent->val = rb_class_new_instance(len - 1, RARRAY_CONST_PTR(value) + 1, rb_cRange);
329
+ } else {
330
+ // Create a properly initialized struct instance without calling the initialize method.
331
+ parent->val = rb_obj_alloc(sc);
332
+ // If the JSON array has more entries than the struct class allows, we record an error.
339
333
  #ifdef RSTRUCT_LEN
340
334
  #if RSTRUCT_LEN_RETURNS_INTEGER_OBJECT
341
- slen = (int)NUM2LONG(RSTRUCT_LEN(parent->val));
335
+ slen = (int)NUM2LONG(RSTRUCT_LEN(parent->val));
342
336
  #else // RSTRUCT_LEN_RETURNS_INTEGER_OBJECT
343
- slen = (int)RSTRUCT_LEN(parent->val);
337
+ slen = (int)RSTRUCT_LEN(parent->val);
344
338
  #endif // RSTRUCT_LEN_RETURNS_INTEGER_OBJECT
345
339
  #else
346
- slen = FIX2INT(rb_funcall2(parent->val, oj_length_id, 0, 0));
340
+ slen = FIX2INT(rb_funcall2(parent->val, oj_length_id, 0, 0));
347
341
  #endif
348
- // MRI >= 1.9
349
- if (len - 1 > slen) {
350
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "Invalid struct data");
351
- } else {
352
- int i;
342
+ // MRI >= 1.9
343
+ if (len - 1 > slen) {
344
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "Invalid struct data");
345
+ } else {
346
+ int i;
353
347
 
354
- for (i = 0; i < len - 1; i++) {
355
- rb_struct_aset(parent->val, INT2FIX(i), RARRAY_PTR(value)[i + 1]);
348
+ for (i = 0; i < len - 1; i++) {
349
+ rb_struct_aset(parent->val, INT2FIX(i), RARRAY_CONST_PTR(value)[i + 1]);
350
+ }
356
351
  }
357
352
  }
358
353
  return 1;
359
354
  } else if (3 <= klen && '#' == key[1]) {
360
- volatile VALUE *a;
355
+ volatile const VALUE *a;
361
356
 
362
357
  if (2 != len) {
363
358
  oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "invalid hash pair");
364
359
  return 1;
365
360
  }
366
361
  parent->val = rb_hash_new();
367
- a = RARRAY_PTR(value);
362
+ a = RARRAY_CONST_PTR(value);
368
363
  rb_hash_aset(parent->val, *a, a[1]);
369
364
 
370
365
  return 1;
@@ -374,11 +369,17 @@ static int hat_value(ParseInfo pi, Val parent, const char *key, size_t klen, vol
374
369
  }
375
370
 
376
371
  void oj_set_obj_ivar(Val parent, Val kval, VALUE value) {
377
- rb_ivar_set(parent->val, oj_attr_intern(kval->key, kval->klen), value);
372
+ if (kval->klen == 5 && strncmp("~mesg", kval->key, 5) == 0 && rb_obj_is_kind_of(parent->val, rb_eException)) {
373
+ parent->val = rb_funcall(parent->val, rb_intern("exception"), 1, value);
374
+ } else if (kval->klen == 3 && strncmp("~bt", kval->key, 3) == 0 && rb_obj_is_kind_of(parent->val, rb_eException)) {
375
+ rb_funcall(parent->val, rb_intern("set_backtrace"), 1, value);
376
+ } else {
377
+ rb_ivar_set(parent->val, oj_attr_intern(kval->key, kval->klen), value);
378
+ }
378
379
  }
379
380
 
380
381
  static void hash_set_cstr(ParseInfo pi, Val kval, const char *str, size_t len, const char *orig) {
381
- const char * key = kval->key;
382
+ const char *key = kval->key;
382
383
  int klen = kval->klen;
383
384
  Val parent = stack_peek(&pi->stack);
384
385
  volatile VALUE rval = Qnil;
@@ -445,13 +446,11 @@ WHICH_TYPE:
445
446
  rb_class2name(rb_obj_class(parent->val)));
446
447
  return;
447
448
  }
448
- if (Yes == pi->options.trace) {
449
- oj_trace_parse_call("set_string", pi, __FILE__, __LINE__, rval);
450
- }
449
+ TRACE_PARSE_CALL(pi->options.trace, "set_string", pi, rval);
451
450
  }
452
451
 
453
452
  static void hash_set_num(ParseInfo pi, Val kval, NumInfo ni) {
454
- const char * key = kval->key;
453
+ const char *key = kval->key;
455
454
  int klen = kval->klen;
456
455
  Val parent = stack_peek(&pi->stack);
457
456
  volatile VALUE rval = Qnil;
@@ -516,9 +515,7 @@ WHICH_TYPE:
516
515
  rb_class2name(rb_obj_class(parent->val)));
517
516
  return;
518
517
  }
519
- if (Yes == pi->options.trace) {
520
- oj_trace_parse_call("add_number", pi, __FILE__, __LINE__, rval);
521
- }
518
+ TRACE_PARSE_CALL(pi->options.trace, "add_number", pi, rval);
522
519
  }
523
520
 
524
521
  static void hash_set_value(ParseInfo pi, Val kval, VALUE value) {
@@ -544,8 +541,8 @@ WHICH_TYPE:
544
541
  }
545
542
  } else {
546
543
  if (3 <= klen && '^' == *key && '#' == key[1] && T_ARRAY == rb_type(value)) {
547
- long len = RARRAY_LEN(value);
548
- volatile VALUE *a = RARRAY_PTR(value);
544
+ long len = RARRAY_LEN(value);
545
+ volatile const VALUE *a = RARRAY_CONST_PTR(value);
549
546
 
550
547
  if (2 != len) {
551
548
  oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "invalid hash pair");
@@ -602,15 +599,11 @@ WHICH_TYPE:
602
599
  rb_class2name(rb_obj_class(parent->val)));
603
600
  return;
604
601
  }
605
- if (Yes == pi->options.trace) {
606
- oj_trace_parse_call("add_value", pi, __FILE__, __LINE__, value);
607
- }
602
+ TRACE_PARSE_CALL(pi->options.trace, "add_value", pi, value);
608
603
  }
609
604
 
610
605
  static VALUE start_hash(ParseInfo pi) {
611
- if (Yes == pi->options.trace) {
612
- oj_trace_parse_in("start_hash", pi, __FILE__, __LINE__);
613
- }
606
+ TRACE_PARSE_IN(pi->options.trace, "start_hash", pi);
614
607
  return Qnil;
615
608
  }
616
609
 
@@ -626,9 +619,7 @@ static void end_hash(ParseInfo pi) {
626
619
  oj_odd_free(oa);
627
620
  parent->odd_args = NULL;
628
621
  }
629
- if (Yes == pi->options.trace) {
630
- oj_trace_parse_hash_end(pi, __FILE__, __LINE__);
631
- }
622
+ TRACE_PARSE_HASH_END(pi->options.trace, pi);
632
623
  }
633
624
 
634
625
  static void array_append_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
@@ -654,32 +645,24 @@ static void array_append_cstr(ParseInfo pi, const char *str, size_t len, const c
654
645
  }
655
646
  rval = str_to_value(pi, str, len, orig);
656
647
  rb_ary_push(stack_peek(&pi->stack)->val, rval);
657
- if (Yes == pi->options.trace) {
658
- oj_trace_parse_call("append_string", pi, __FILE__, __LINE__, rval);
659
- }
648
+ TRACE_PARSE_CALL(pi->options.trace, "append_string", pi, rval);
660
649
  }
661
650
 
662
651
  static void array_append_num(ParseInfo pi, NumInfo ni) {
663
652
  volatile VALUE rval = oj_num_as_value(ni);
664
653
 
665
654
  rb_ary_push(stack_peek(&pi->stack)->val, rval);
666
- if (Yes == pi->options.trace) {
667
- oj_trace_parse_call("append_number", pi, __FILE__, __LINE__, rval);
668
- }
655
+ TRACE_PARSE_CALL(pi->options.trace, "append_number", pi, rval);
669
656
  }
670
657
 
671
658
  static void add_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
672
659
  pi->stack.head->val = str_to_value(pi, str, len, orig);
673
- if (Yes == pi->options.trace) {
674
- oj_trace_parse_call("add_string", pi, __FILE__, __LINE__, pi->stack.head->val);
675
- }
660
+ TRACE_PARSE_CALL(pi->options.trace, "add_string", pi, pi->stack.head->val);
676
661
  }
677
662
 
678
663
  static void add_num(ParseInfo pi, NumInfo ni) {
679
664
  pi->stack.head->val = oj_num_as_value(ni);
680
- if (Yes == pi->options.trace) {
681
- oj_trace_parse_call("add_num", pi, __FILE__, __LINE__, pi->stack.head->val);
682
- }
665
+ TRACE_PARSE_CALL(pi->options.trace, "add_num", pi, pi->stack.head->val);
683
666
  }
684
667
 
685
668
  void oj_set_object_callbacks(ParseInfo pi) {