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/oj.c CHANGED
@@ -14,6 +14,7 @@
14
14
  #include "dump.h"
15
15
  #include "encode.h"
16
16
  #include "intern.h"
17
+ #include "mem.h"
17
18
  #include "odd.h"
18
19
  #include "parse.h"
19
20
  #include "rails.h"
@@ -21,7 +22,7 @@
21
22
  typedef struct _yesNoOpt {
22
23
  VALUE sym;
23
24
  char *attr;
24
- } * YesNoOpt;
25
+ } *YesNoOpt;
25
26
 
26
27
  void Init_oj();
27
28
 
@@ -32,6 +33,7 @@ ID oj_array_append_id;
32
33
  ID oj_array_end_id;
33
34
  ID oj_array_start_id;
34
35
  ID oj_as_json_id;
36
+ ID oj_at_id;
35
37
  ID oj_begin_id;
36
38
  ID oj_bigdecimal_id;
37
39
  ID oj_end_id;
@@ -45,7 +47,6 @@ ID oj_hash_key_id;
45
47
  ID oj_hash_set_id;
46
48
  ID oj_hash_start_id;
47
49
  ID oj_iconv_id;
48
- ID oj_instance_variables_id;
49
50
  ID oj_json_create_id;
50
51
  ID oj_length_id;
51
52
  ID oj_new_id;
@@ -90,7 +91,9 @@ VALUE oj_array_class_sym;
90
91
  VALUE oj_create_additions_sym;
91
92
  VALUE oj_decimal_class_sym;
92
93
  VALUE oj_hash_class_sym;
94
+ VALUE oj_in_sym;
93
95
  VALUE oj_indent_sym;
96
+ VALUE oj_nanosecond_sym;
94
97
  VALUE oj_object_class_sym;
95
98
  VALUE oj_quirks_mode_sym;
96
99
  VALUE oj_safe_sym;
@@ -132,11 +135,13 @@ static VALUE newline_sym;
132
135
  static VALUE nilnil_sym;
133
136
  static VALUE null_sym;
134
137
  static VALUE object_sym;
138
+ static VALUE omit_null_byte_sym;
135
139
  static VALUE omit_nil_sym;
136
140
  static VALUE rails_sym;
137
141
  static VALUE raise_sym;
138
142
  static VALUE ruby_sym;
139
143
  static VALUE sec_prec_sym;
144
+ static VALUE slash_sym;
140
145
  static VALUE strict_sym;
141
146
  static VALUE symbol_keys_sym;
142
147
  static VALUE time_format_sym;
@@ -152,7 +157,8 @@ static VALUE word_sym;
152
157
  static VALUE xmlschema_sym;
153
158
  static VALUE xss_safe_sym;
154
159
 
155
- rb_encoding *oj_utf8_encoding = 0;
160
+ rb_encoding *oj_utf8_encoding = 0;
161
+ int oj_utf8_encoding_index = 0;
156
162
 
157
163
  #ifdef HAVE_PTHREAD_MUTEX_INIT
158
164
  pthread_mutex_t oj_cache_mutex;
@@ -217,6 +223,7 @@ struct _options oj_default_options = {
217
223
  0, // array_size
218
224
  AutoNan, // nan_dump
219
225
  false, // omit_nil
226
+ false, // omit_null_byte
220
227
  MAX_DEPTH, // max_depth
221
228
  },
222
229
  {
@@ -239,7 +246,7 @@ struct _options oj_default_options = {
239
246
  *references
240
247
  * - *:auto_define* [_Boolean_|_nil_] automatically define classes if they do not exist
241
248
  * - *:symbol_keys* [_Boolean_|_nil_] use symbols instead of strings for hash keys
242
- * - *:escape_mode* [_:newline_|_:json_|_:xss_safe_|_:ascii_|_unicode_xss_|_nil_] determines the
249
+ * - *:escape_mode* [_:newline_|_:json_|_:slash_|_:xss_safe_|_:ascii_|_:unicode_xss_|_nil_] determines the
243
250
  *characters to escape
244
251
  * - *:class_cache* [_Boolean_|_nil_] cache classes for faster parsing (if dynamically modifying
245
252
  *classes or reloading classes then don't use this)
@@ -247,7 +254,7 @@ struct _options oj_default_options = {
247
254
  *to use for JSON
248
255
  * - *:time_format* [_:unix_|_:unix_zone_|_:xmlschema_|_:ruby_] time format when dumping
249
256
  * - *:bigdecimal_as_decimal* [_Boolean_|_nil_] dump BigDecimal as a decimal number or as a String
250
- * - *:bigdecimal_load* [_:bigdecimal_|_:float_|_:auto_|_:fast_] load decimals as BigDecimal instead
257
+ * - *:bigdecimal_load* [_:bigdecimal_|_:float_|_:auto_|_:fast_|_:ruby_] load decimals as BigDecimal instead
251
258
  *of as a Float. :auto pick the most precise for the number of digits. :float should be the same as
252
259
  *ruby. :fast may require rounding but is must faster.
253
260
  * - *:compat_bigdecimal* [_true_|_false_] load decimals as BigDecimal instead of as a Float when in
@@ -286,6 +293,7 @@ struct _options oj_default_options = {
286
293
  *used
287
294
  * - *:array_class* [_Class_|_nil_] Class to use instead of Array on load
288
295
  * - *:omit_nil* [_true_|_false_] if true Hash and Object attributes with nil values are omitted
296
+ * - *:omit_null_byte* [_true_|_false_] if true null bytes in strings will be omitted when dumping
289
297
  * - *:ignore* [_nil_|_Array_] either nil or an Array of classes to ignore when dumping
290
298
  * - *:ignore_under* [_Boolean_] if true then attributes that start with _ are ignored when dumping in
291
299
  *object or custom mode.
@@ -379,6 +387,7 @@ static VALUE get_def_opts(VALUE self) {
379
387
  opts,
380
388
  cache_keys_sym,
381
389
  (Yes == oj_default_options.cache_keys) ? Qtrue : ((No == oj_default_options.cache_keys) ? Qfalse : Qnil));
390
+
382
391
  switch (oj_default_options.mode) {
383
392
  case StrictMode: rb_hash_aset(opts, mode_sym, strict_sym); break;
384
393
  case CompatMode: rb_hash_aset(opts, mode_sym, compat_sym); break;
@@ -404,6 +413,7 @@ static VALUE get_def_opts(VALUE self) {
404
413
  switch (oj_default_options.escape_mode) {
405
414
  case NLEsc: rb_hash_aset(opts, escape_mode_sym, newline_sym); break;
406
415
  case JSONEsc: rb_hash_aset(opts, escape_mode_sym, json_sym); break;
416
+ case SlashEsc: rb_hash_aset(opts, escape_mode_sym, slash_sym); break;
407
417
  case XSSEsc: rb_hash_aset(opts, escape_mode_sym, xss_safe_sym); break;
408
418
  case ASCIIEsc: rb_hash_aset(opts, escape_mode_sym, ascii_sym); break;
409
419
  case JXEsc: rb_hash_aset(opts, escape_mode_sym, unicode_xss_sym); break;
@@ -453,13 +463,14 @@ static VALUE get_def_opts(VALUE self) {
453
463
  default: rb_hash_aset(opts, nan_sym, auto_sym); break;
454
464
  }
455
465
  rb_hash_aset(opts, omit_nil_sym, oj_default_options.dump_opts.omit_nil ? Qtrue : Qfalse);
466
+ rb_hash_aset(opts, omit_null_byte_sym, oj_default_options.dump_opts.omit_null_byte ? Qtrue : Qfalse);
456
467
  rb_hash_aset(opts, oj_hash_class_sym, oj_default_options.hash_class);
457
468
  rb_hash_aset(opts, oj_array_class_sym, oj_default_options.array_class);
458
469
 
459
470
  if (NULL == oj_default_options.ignore) {
460
471
  rb_hash_aset(opts, ignore_sym, Qnil);
461
472
  } else {
462
- VALUE * vp;
473
+ VALUE *vp;
463
474
  volatile VALUE a = rb_ary_new();
464
475
 
465
476
  for (vp = oj_default_options.ignore; Qnil != *vp; vp++) {
@@ -634,15 +645,9 @@ static int parse_options_cb(VALUE k, VALUE v, VALUE opts) {
634
645
  } else if (float_prec_sym == k) {
635
646
  int n;
636
647
 
637
- #ifdef RUBY_INTEGER_UNIFICATION
638
648
  if (rb_cInteger != rb_obj_class(v)) {
639
649
  rb_raise(rb_eArgError, ":float_precision must be a Integer.");
640
650
  }
641
- #else
642
- if (T_FIXNUM != rb_type(v)) {
643
- rb_raise(rb_eArgError, ":float_precision must be a Fixnum.");
644
- }
645
- #endif
646
651
  n = FIX2INT(v);
647
652
  if (0 >= n) {
648
653
  *copts->float_fmt = '\0';
@@ -657,15 +662,9 @@ static int parse_options_cb(VALUE k, VALUE v, VALUE opts) {
657
662
  } else if (cache_str_sym == k || cache_string_sym == k) {
658
663
  int n;
659
664
 
660
- #ifdef RUBY_INTEGER_UNIFICATION
661
665
  if (rb_cInteger != rb_obj_class(v)) {
662
666
  rb_raise(rb_eArgError, ":cache_str must be a Integer.");
663
667
  }
664
- #else
665
- if (T_FIXNUM != rb_type(v)) {
666
- rb_raise(rb_eArgError, ":cache_str must be a Fixnum.");
667
- }
668
- #endif
669
668
  n = FIX2INT(v);
670
669
  if (0 >= n) {
671
670
  copts->cache_str = 0;
@@ -678,15 +677,9 @@ static int parse_options_cb(VALUE k, VALUE v, VALUE opts) {
678
677
  } else if (sec_prec_sym == k) {
679
678
  int n;
680
679
 
681
- #ifdef RUBY_INTEGER_UNIFICATION
682
680
  if (rb_cInteger != rb_obj_class(v)) {
683
681
  rb_raise(rb_eArgError, ":second_precision must be a Integer.");
684
682
  }
685
- #else
686
- if (T_FIXNUM != rb_type(v)) {
687
- rb_raise(rb_eArgError, ":second_precision must be a Fixnum.");
688
- }
689
- #endif
690
683
  n = NUM2INT(v);
691
684
  if (0 > n) {
692
685
  n = 0;
@@ -733,6 +726,8 @@ static int parse_options_cb(VALUE k, VALUE v, VALUE opts) {
733
726
  copts->escape_mode = NLEsc;
734
727
  } else if (json_sym == v) {
735
728
  copts->escape_mode = JSONEsc;
729
+ } else if (slash_sym == v) {
730
+ copts->escape_mode = SlashEsc;
736
731
  } else if (xss_safe_sym == v) {
737
732
  copts->escape_mode = XSSEsc;
738
733
  } else if (ascii_sym == v) {
@@ -775,7 +770,7 @@ static int parse_options_cb(VALUE k, VALUE v, VALUE opts) {
775
770
  } else if (create_id_sym == k) {
776
771
  if (Qnil == v) {
777
772
  if (oj_json_class != oj_default_options.create_id && NULL != copts->create_id) {
778
- xfree((char *)oj_default_options.create_id);
773
+ OJ_R_FREE((char *)oj_default_options.create_id);
779
774
  }
780
775
  copts->create_id = NULL;
781
776
  copts->create_id_len = 0;
@@ -784,7 +779,7 @@ static int parse_options_cb(VALUE k, VALUE v, VALUE opts) {
784
779
 
785
780
  len = RSTRING_LEN(v);
786
781
  if (len != copts->create_id_len || 0 != strcmp(copts->create_id, str)) {
787
- copts->create_id = ALLOC_N(char, len + 1);
782
+ copts->create_id = OJ_R_ALLOC_N(char, len + 1);
788
783
  strcpy((char *)copts->create_id, str);
789
784
  copts->create_id_len = len;
790
785
  }
@@ -875,6 +870,17 @@ static int parse_options_cb(VALUE k, VALUE v, VALUE opts) {
875
870
  } else {
876
871
  rb_raise(rb_eArgError, ":omit_nil must be true or false.");
877
872
  }
873
+ } else if (omit_null_byte_sym == k) {
874
+ if (Qnil == v) {
875
+ return ST_CONTINUE;
876
+ }
877
+ if (Qtrue == v) {
878
+ copts->dump_opts.omit_null_byte = true;
879
+ } else if (Qfalse == v) {
880
+ copts->dump_opts.omit_null_byte = false;
881
+ } else {
882
+ rb_raise(rb_eArgError, ":omit_null_byte must be true or false.");
883
+ }
878
884
  } else if (oj_ascii_only_sym == k) {
879
885
  // This is here only for backwards compatibility with the original Oj.
880
886
  if (Qtrue == v) {
@@ -904,7 +910,7 @@ static int parse_options_cb(VALUE k, VALUE v, VALUE opts) {
904
910
  copts->array_class = v;
905
911
  }
906
912
  } else if (ignore_sym == k) {
907
- xfree(copts->ignore);
913
+ OJ_R_FREE(copts->ignore);
908
914
  copts->ignore = NULL;
909
915
  if (Qnil != v) {
910
916
  int cnt;
@@ -914,7 +920,7 @@ static int parse_options_cb(VALUE k, VALUE v, VALUE opts) {
914
920
  if (0 < cnt) {
915
921
  int i;
916
922
 
917
- copts->ignore = ALLOC_N(VALUE, cnt + 1);
923
+ copts->ignore = OJ_R_ALLOC_N(VALUE, cnt + 1);
918
924
  for (i = 0; i < cnt; i++) {
919
925
  copts->ignore[i] = RARRAY_AREF(v, i);
920
926
  }
@@ -925,7 +931,7 @@ static int parse_options_cb(VALUE k, VALUE v, VALUE opts) {
925
931
  if (Qnil == v) {
926
932
  return ST_CONTINUE;
927
933
  }
928
- if (TYPE(v) == T_STRUCT && rb_obj_class(v) == rb_cRange) {
934
+ if (rb_obj_class(v) == rb_cRange) {
929
935
  VALUE min = rb_funcall(v, oj_begin_id, 0);
930
936
  VALUE max = rb_funcall(v, oj_end_id, 0);
931
937
 
@@ -942,7 +948,7 @@ static int parse_options_cb(VALUE k, VALUE v, VALUE opts) {
942
948
  if (Qnil == v) {
943
949
  return ST_CONTINUE;
944
950
  }
945
- copts->sym_key = (Qtrue == v) ? Yes : No;
951
+ copts->sym_key = (Qtrue == v) ? Yes : No;
946
952
  }
947
953
  return ST_CONTINUE;
948
954
  }
@@ -1107,7 +1113,7 @@ static VALUE load(int argc, VALUE *argv, VALUE self) {
1107
1113
  * Returns [_Object_|_Hash_|_Array_|_String_|_Fixnum_|_Float_|_Boolean_|_nil_]
1108
1114
  */
1109
1115
  static VALUE load_file(int argc, VALUE *argv, VALUE self) {
1110
- char * path;
1116
+ char *path;
1111
1117
  int fd;
1112
1118
  Mode mode = oj_default_options.mode;
1113
1119
  struct _parseInfo pi;
@@ -1115,7 +1121,7 @@ static VALUE load_file(int argc, VALUE *argv, VALUE self) {
1115
1121
  if (1 > argc) {
1116
1122
  rb_raise(rb_eArgError, "Wrong number of arguments to load().");
1117
1123
  }
1118
- Check_Type(*argv, T_STRING);
1124
+ path = StringValuePtr(*argv);
1119
1125
  parse_info_init(&pi);
1120
1126
  pi.options = oj_default_options;
1121
1127
  pi.handler = Qnil;
@@ -1146,8 +1152,17 @@ static VALUE load_file(int argc, VALUE *argv, VALUE self) {
1146
1152
  }
1147
1153
  }
1148
1154
  }
1149
- path = StringValuePtr(*argv);
1150
- if (0 == (fd = open(path, O_RDONLY))) {
1155
+ #ifdef _WIN32
1156
+ {
1157
+ WCHAR *wide_path;
1158
+ wide_path = rb_w32_mbstr_to_wstr(CP_UTF8, path, -1, NULL);
1159
+ fd = rb_w32_wopen(wide_path, O_RDONLY);
1160
+ OJ_FREE(wide_path);
1161
+ }
1162
+ #else
1163
+ fd = open(path, O_RDONLY);
1164
+ #endif
1165
+ if (0 == fd) {
1151
1166
  rb_raise(rb_eIOError, "%s", strerror(errno));
1152
1167
  }
1153
1168
  switch (mode) {
@@ -1220,10 +1235,10 @@ static VALUE safe_load(VALUE self, VALUE doc) {
1220
1235
  */
1221
1236
 
1222
1237
  struct dump_arg {
1223
- struct _out * out;
1238
+ struct _out *out;
1224
1239
  struct _options *copts;
1225
1240
  int argc;
1226
- VALUE * argv;
1241
+ VALUE *argv;
1227
1242
  };
1228
1243
 
1229
1244
  static VALUE dump_body(VALUE a) {
@@ -1243,9 +1258,8 @@ static VALUE dump_body(VALUE a) {
1243
1258
  static VALUE dump_ensure(VALUE a) {
1244
1259
  volatile struct dump_arg *arg = (void *)a;
1245
1260
 
1246
- if (arg->out->allocated) {
1247
- xfree(arg->out->buf);
1248
- }
1261
+ oj_out_free(arg->out);
1262
+
1249
1263
  return Qnil;
1250
1264
  }
1251
1265
 
@@ -1257,7 +1271,6 @@ static VALUE dump_ensure(VALUE a) {
1257
1271
  * - *options* [_Hash_] same as default_options
1258
1272
  */
1259
1273
  static VALUE dump(int argc, VALUE *argv, VALUE self) {
1260
- char buf[4096];
1261
1274
  struct dump_arg arg;
1262
1275
  struct _out out;
1263
1276
  struct _options copts = oj_default_options;
@@ -1279,11 +1292,11 @@ static VALUE dump(int argc, VALUE *argv, VALUE self) {
1279
1292
  arg.argc = argc;
1280
1293
  arg.argv = argv;
1281
1294
 
1282
- arg.out->buf = buf;
1283
- arg.out->end = buf + sizeof(buf) - 10;
1284
- arg.out->allocated = false;
1285
- arg.out->omit_nil = copts.dump_opts.omit_nil;
1286
- arg.out->caller = CALLER_DUMP;
1295
+ oj_out_init(arg.out);
1296
+
1297
+ arg.out->omit_nil = copts.dump_opts.omit_nil;
1298
+ arg.out->omit_null_byte = copts.dump_opts.omit_null_byte;
1299
+ arg.out->caller = CALLER_DUMP;
1287
1300
 
1288
1301
  return rb_ensure(dump_body, (VALUE)&arg, dump_ensure, (VALUE)&arg);
1289
1302
  }
@@ -1313,7 +1326,6 @@ static VALUE dump(int argc, VALUE *argv, VALUE self) {
1313
1326
  * Returns [_String_] the encoded JSON.
1314
1327
  */
1315
1328
  static VALUE to_json(int argc, VALUE *argv, VALUE self) {
1316
- char buf[4096];
1317
1329
  struct _out out;
1318
1330
  struct _options copts = oj_default_options;
1319
1331
  VALUE rstr;
@@ -1328,10 +1340,11 @@ static VALUE to_json(int argc, VALUE *argv, VALUE self) {
1328
1340
  }
1329
1341
  copts.mode = CompatMode;
1330
1342
  copts.to_json = Yes;
1331
- out.buf = buf;
1332
- out.end = buf + sizeof(buf) - 10;
1333
- out.allocated = false;
1334
- out.omit_nil = copts.dump_opts.omit_nil;
1343
+
1344
+ oj_out_init(&out);
1345
+
1346
+ out.omit_nil = copts.dump_opts.omit_nil;
1347
+ out.omit_null_byte = copts.dump_opts.omit_null_byte;
1335
1348
  // For obj.to_json or generate nan is not allowed but if called from dump
1336
1349
  // it is.
1337
1350
  oj_dump_obj_to_json_using_params(*argv, &copts, &out, argc - 1, argv + 1);
@@ -1341,9 +1354,9 @@ static VALUE to_json(int argc, VALUE *argv, VALUE self) {
1341
1354
  }
1342
1355
  rstr = rb_str_new2(out.buf);
1343
1356
  rstr = oj_encode(rstr);
1344
- if (out.allocated) {
1345
- xfree(out.buf);
1346
- }
1357
+
1358
+ oj_out_free(&out);
1359
+
1347
1360
  return rstr;
1348
1361
  }
1349
1362
 
@@ -1363,7 +1376,6 @@ static VALUE to_file(int argc, VALUE *argv, VALUE self) {
1363
1376
  if (3 == argc) {
1364
1377
  oj_parse_options(argv[2], &copts);
1365
1378
  }
1366
- Check_Type(*argv, T_STRING);
1367
1379
  oj_write_obj_to_file(argv[1], StringValuePtr(*argv), &copts);
1368
1380
 
1369
1381
  return Qnil;
@@ -1703,6 +1715,18 @@ static VALUE protect_require(VALUE x) {
1703
1715
  return Qnil;
1704
1716
  }
1705
1717
 
1718
+ extern void print_all_odds(const char *label);
1719
+
1720
+ static VALUE debug_odd(VALUE self, VALUE label) {
1721
+ print_all_odds(RSTRING_PTR(label));
1722
+ return Qnil;
1723
+ }
1724
+
1725
+ static VALUE mem_report(VALUE self) {
1726
+ oj_mem_report();
1727
+ return Qnil;
1728
+ }
1729
+
1706
1730
  /* Document-module: Oj
1707
1731
  *
1708
1732
  * Optimized JSON (Oj), as the name implies was written to provide speed
@@ -1731,15 +1755,19 @@ static VALUE protect_require(VALUE x) {
1731
1755
  *
1732
1756
  * - *:wab* specifically for WAB data exchange.
1733
1757
  */
1734
- void Init_oj() {
1758
+ void Init_oj(void) {
1735
1759
  int err = 0;
1736
1760
 
1737
1761
  #if HAVE_RB_EXT_RACTOR_SAFE
1738
1762
  rb_ext_ractor_safe(true);
1739
1763
  #endif
1740
1764
  Oj = rb_define_module("Oj");
1765
+ rb_gc_register_address(&Oj);
1741
1766
 
1742
1767
  oj_cstack_class = rb_define_class_under(Oj, "CStack", rb_cObject);
1768
+ rb_gc_register_address(&oj_cstack_class);
1769
+
1770
+ rb_undef_alloc_func(oj_cstack_class);
1743
1771
 
1744
1772
  oj_string_writer_init();
1745
1773
  oj_stream_writer_init();
@@ -1748,9 +1776,11 @@ void Init_oj() {
1748
1776
  // On Rubinius the require fails but can be done from a ruby file.
1749
1777
  rb_protect(protect_require, Qnil, &err);
1750
1778
  rb_require("stringio");
1751
- oj_utf8_encoding = rb_enc_find("UTF-8");
1779
+ oj_utf8_encoding_index = rb_enc_find_index("UTF-8");
1780
+ oj_utf8_encoding = rb_enc_from_index(oj_utf8_encoding_index);
1752
1781
 
1753
1782
  // rb_define_module_function(Oj, "hash_test", hash_test, 0);
1783
+ rb_define_module_function(Oj, "debug_odd", debug_odd, 1);
1754
1784
 
1755
1785
  rb_define_module_function(Oj, "default_options", get_def_opts, 0);
1756
1786
  rb_define_module_function(Oj, "default_options=", set_def_opts, 1);
@@ -1784,49 +1814,51 @@ void Init_oj() {
1784
1814
 
1785
1815
  rb_define_module_function(Oj, "optimize_rails", oj_optimize_rails, 0);
1786
1816
 
1787
- oj_add_value_id = rb_intern("add_value");
1788
- oj_array_append_id = rb_intern("array_append");
1789
- oj_array_end_id = rb_intern("array_end");
1790
- oj_array_start_id = rb_intern("array_start");
1791
- oj_as_json_id = rb_intern("as_json");
1792
- oj_begin_id = rb_intern("begin");
1793
- oj_bigdecimal_id = rb_intern("BigDecimal");
1794
- oj_end_id = rb_intern("end");
1795
- oj_error_id = rb_intern("error");
1796
- oj_exclude_end_id = rb_intern("exclude_end?");
1797
- oj_file_id = rb_intern("file?");
1798
- oj_fileno_id = rb_intern("fileno");
1799
- oj_ftype_id = rb_intern("ftype");
1800
- oj_hash_end_id = rb_intern("hash_end");
1801
- oj_hash_key_id = rb_intern("hash_key");
1802
- oj_hash_set_id = rb_intern("hash_set");
1803
- oj_hash_start_id = rb_intern("hash_start");
1804
- oj_iconv_id = rb_intern("iconv");
1805
- oj_instance_variables_id = rb_intern("instance_variables");
1806
- oj_json_create_id = rb_intern("json_create");
1807
- oj_length_id = rb_intern("length");
1808
- oj_new_id = rb_intern("new");
1809
- oj_parse_id = rb_intern("parse");
1810
- oj_pos_id = rb_intern("pos");
1811
- oj_raw_json_id = rb_intern("raw_json");
1812
- oj_read_id = rb_intern("read");
1813
- oj_readpartial_id = rb_intern("readpartial");
1814
- oj_replace_id = rb_intern("replace");
1815
- oj_stat_id = rb_intern("stat");
1816
- oj_string_id = rb_intern("string");
1817
- oj_to_h_id = rb_intern("to_h");
1818
- oj_to_hash_id = rb_intern("to_hash");
1819
- oj_to_json_id = rb_intern("to_json");
1820
- oj_to_s_id = rb_intern("to_s");
1821
- oj_to_sym_id = rb_intern("to_sym");
1822
- oj_to_time_id = rb_intern("to_time");
1823
- oj_tv_nsec_id = rb_intern("tv_nsec");
1824
- oj_tv_sec_id = rb_intern("tv_sec");
1825
- oj_tv_usec_id = rb_intern("tv_usec");
1826
- oj_utc_id = rb_intern("utc");
1827
- oj_utc_offset_id = rb_intern("utc_offset");
1828
- oj_utcq_id = rb_intern("utc?");
1829
- oj_write_id = rb_intern("write");
1817
+ rb_define_module_function(Oj, "mem_report", mem_report, 0);
1818
+
1819
+ oj_add_value_id = rb_intern("add_value");
1820
+ oj_array_append_id = rb_intern("array_append");
1821
+ oj_array_end_id = rb_intern("array_end");
1822
+ oj_array_start_id = rb_intern("array_start");
1823
+ oj_as_json_id = rb_intern("as_json");
1824
+ oj_at_id = rb_intern("at");
1825
+ oj_begin_id = rb_intern("begin");
1826
+ oj_bigdecimal_id = rb_intern("BigDecimal");
1827
+ oj_end_id = rb_intern("end");
1828
+ oj_error_id = rb_intern("error");
1829
+ oj_exclude_end_id = rb_intern("exclude_end?");
1830
+ oj_file_id = rb_intern("file?");
1831
+ oj_fileno_id = rb_intern("fileno");
1832
+ oj_ftype_id = rb_intern("ftype");
1833
+ oj_hash_end_id = rb_intern("hash_end");
1834
+ oj_hash_key_id = rb_intern("hash_key");
1835
+ oj_hash_set_id = rb_intern("hash_set");
1836
+ oj_hash_start_id = rb_intern("hash_start");
1837
+ oj_iconv_id = rb_intern("iconv");
1838
+ oj_json_create_id = rb_intern("json_create");
1839
+ oj_length_id = rb_intern("length");
1840
+ oj_new_id = rb_intern("new");
1841
+ oj_parse_id = rb_intern("parse");
1842
+ oj_pos_id = rb_intern("pos");
1843
+ oj_raw_json_id = rb_intern("raw_json");
1844
+ oj_read_id = rb_intern("read");
1845
+ oj_readpartial_id = rb_intern("readpartial");
1846
+ oj_replace_id = rb_intern("replace");
1847
+ oj_stat_id = rb_intern("stat");
1848
+ oj_string_id = rb_intern("string");
1849
+ oj_to_h_id = rb_intern("to_h");
1850
+ oj_to_hash_id = rb_intern("to_hash");
1851
+ oj_to_json_id = rb_intern("to_json");
1852
+ oj_to_s_id = rb_intern("to_s");
1853
+ oj_to_sym_id = rb_intern("to_sym");
1854
+ oj_to_time_id = rb_intern("to_time");
1855
+ oj_tv_nsec_id = rb_intern("tv_nsec");
1856
+ oj_tv_sec_id = rb_intern("tv_sec");
1857
+ oj_tv_usec_id = rb_intern("tv_usec");
1858
+ oj_utc_id = rb_intern("utc");
1859
+ oj_utc_offset_id = rb_intern("utc_offset");
1860
+ oj_utcq_id = rb_intern("utc?");
1861
+ oj_write_id = rb_intern("write");
1830
1862
 
1831
1863
  rb_require("oj/bag");
1832
1864
  rb_require("oj/error");
@@ -1937,10 +1969,14 @@ void Init_oj() {
1937
1969
  rb_gc_register_address(&oj_decimal_class_sym);
1938
1970
  oj_hash_class_sym = ID2SYM(rb_intern("hash_class"));
1939
1971
  rb_gc_register_address(&oj_hash_class_sym);
1972
+ oj_in_sym = ID2SYM(rb_intern("in"));
1973
+ rb_gc_register_address(&oj_in_sym);
1940
1974
  oj_indent_sym = ID2SYM(rb_intern("indent"));
1941
1975
  rb_gc_register_address(&oj_indent_sym);
1942
1976
  oj_max_nesting_sym = ID2SYM(rb_intern("max_nesting"));
1943
1977
  rb_gc_register_address(&oj_max_nesting_sym);
1978
+ oj_nanosecond_sym = ID2SYM(rb_intern("nanosecond"));
1979
+ rb_gc_register_address(&oj_nanosecond_sym);
1944
1980
  oj_object_class_sym = ID2SYM(rb_intern("object_class"));
1945
1981
  rb_gc_register_address(&oj_object_class_sym);
1946
1982
  oj_object_nl_sym = ID2SYM(rb_intern("object_nl"));
@@ -1949,6 +1985,8 @@ void Init_oj() {
1949
1985
  rb_gc_register_address(&oj_quirks_mode_sym);
1950
1986
  oj_safe_sym = ID2SYM(rb_intern("safe"));
1951
1987
  rb_gc_register_address(&oj_safe_sym);
1988
+ omit_null_byte_sym = ID2SYM(rb_intern("omit_null_byte"));
1989
+ rb_gc_register_address(&omit_null_byte_sym);
1952
1990
  oj_space_before_sym = ID2SYM(rb_intern("space_before"));
1953
1991
  rb_gc_register_address(&oj_space_before_sym);
1954
1992
  oj_space_sym = ID2SYM(rb_intern("space"));
@@ -1965,6 +2003,8 @@ void Init_oj() {
1965
2003
  rb_gc_register_address(&ruby_sym);
1966
2004
  sec_prec_sym = ID2SYM(rb_intern("second_precision"));
1967
2005
  rb_gc_register_address(&sec_prec_sym);
2006
+ slash_sym = ID2SYM(rb_intern("slash"));
2007
+ rb_gc_register_address(&slash_sym);
1968
2008
  strict_sym = ID2SYM(rb_intern("strict"));
1969
2009
  rb_gc_register_address(&strict_sym);
1970
2010
  symbol_keys_sym = ID2SYM(rb_intern("symbol_keys"));
@@ -2017,4 +2057,5 @@ void Init_oj() {
2017
2057
  oj_init_doc();
2018
2058
 
2019
2059
  oj_parser_init();
2060
+ oj_scanner_init();
2020
2061
  }