oj 3.13.9 → 3.16.1

Sign up to get free protection for your applications and to get access to all the features.
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) {