oj 3.12.3 → 3.13.3

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 (56) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -3
  3. data/ext/oj/buf.h +9 -0
  4. data/ext/oj/cache.c +341 -0
  5. data/ext/oj/cache.h +21 -0
  6. data/ext/oj/compat.c +7 -22
  7. data/ext/oj/custom.c +15 -17
  8. data/ext/oj/debug.c +132 -0
  9. data/ext/oj/dump.c +12 -15
  10. data/ext/oj/dump_compat.c +3 -3
  11. data/ext/oj/dump_object.c +9 -9
  12. data/ext/oj/dump_strict.c +3 -3
  13. data/ext/oj/err.h +19 -0
  14. data/ext/oj/extconf.rb +5 -0
  15. data/ext/oj/fast.c +7 -18
  16. data/ext/oj/intern.c +281 -0
  17. data/ext/oj/intern.h +26 -0
  18. data/ext/oj/mimic_json.c +2 -2
  19. data/ext/oj/object.c +15 -92
  20. data/ext/oj/odd.c +1 -1
  21. data/ext/oj/oj.c +117 -94
  22. data/ext/oj/oj.h +1 -1
  23. data/ext/oj/parse.c +5 -5
  24. data/ext/oj/parser.c +1483 -0
  25. data/ext/oj/parser.h +90 -0
  26. data/ext/oj/rails.c +5 -5
  27. data/ext/oj/resolve.c +2 -20
  28. data/ext/oj/rxclass.c +1 -1
  29. data/ext/oj/saj.c +1 -1
  30. data/ext/oj/saj2.c +348 -0
  31. data/ext/oj/scp.c +1 -1
  32. data/ext/oj/sparse.c +2 -2
  33. data/ext/oj/stream_writer.c +4 -4
  34. data/ext/oj/strict.c +9 -27
  35. data/ext/oj/string_writer.c +2 -2
  36. data/ext/oj/usual.c +1252 -0
  37. data/ext/oj/validate.c +51 -0
  38. data/ext/oj/wab.c +14 -19
  39. data/lib/oj/error.rb +1 -1
  40. data/lib/oj/state.rb +8 -7
  41. data/lib/oj/version.rb +1 -1
  42. data/pages/Options.md +1 -1
  43. data/pages/Parser.md +309 -0
  44. data/pages/Rails.md +2 -2
  45. data/test/json_gem/json_generator_test.rb +1 -1
  46. data/test/mem.rb +33 -0
  47. data/test/perf_once.rb +58 -0
  48. data/test/perf_parser.rb +189 -0
  49. data/test/test_hash.rb +1 -1
  50. data/test/test_parser.rb +27 -0
  51. data/test/test_parser_saj.rb +245 -0
  52. data/test/test_parser_usual.rb +213 -0
  53. metadata +26 -5
  54. data/ext/oj/hash.c +0 -168
  55. data/ext/oj/hash.h +0 -21
  56. data/ext/oj/hash_test.c +0 -491
data/ext/oj/odd.c CHANGED
@@ -206,7 +206,7 @@ void oj_reg_odd(VALUE clas,
206
206
  *fp = 0;
207
207
  switch (rb_type(*members)) {
208
208
  case T_STRING:
209
- if (NULL == (*np = strdup(rb_string_value_ptr(members)))) {
209
+ if (NULL == (*np = strdup(RSTRING_PTR(*members)))) {
210
210
  rb_raise(rb_eNoMemError, "for attribute name.");
211
211
  }
212
212
  break;
data/ext/oj/oj.c CHANGED
@@ -13,7 +13,7 @@
13
13
 
14
14
  #include "dump.h"
15
15
  #include "encode.h"
16
- #include "hash.h"
16
+ #include "intern.h"
17
17
  #include "odd.h"
18
18
  #include "parse.h"
19
19
  #include "rails.h"
@@ -158,6 +158,8 @@ pthread_mutex_t oj_cache_mutex;
158
158
  VALUE oj_cache_mutex = Qnil;
159
159
  #endif
160
160
 
161
+ extern void oj_parser_init();
162
+
161
163
  const char oj_json_class[] = "json_class";
162
164
 
163
165
  struct _options oj_default_options = {
@@ -188,7 +190,7 @@ struct _options oj_default_options = {
188
190
  false, // sec_prec_set
189
191
  No, // ignore_under
190
192
  Yes, // cache_keys
191
- 3, // cache_str
193
+ 0, // cache_str
192
194
  0, // int_range_min
193
195
  0, // int_range_max
194
196
  oj_json_class, // create_id
@@ -286,7 +288,7 @@ struct _options oj_default_options = {
286
288
  * - *:ignore_under* [_Boolean_] if true then attributes that start with _ are ignored when dumping in
287
289
  *object or custom mode.
288
290
  * - *:cache_keys* [_Boolean_] if true then hash keys are cached
289
- * - *:cache_str* [_Fixnum_] maximum string value length to cache
291
+ * - *:cache_str* [_Fixnum_] maximum string value length to cache (strings less than this are cached)
290
292
  * - *:integer_range* [_Range_] Dump integers outside range as strings.
291
293
  * - *:trace* [_true,_|_false_] Trace all load and dump calls, default is false (trace is off)
292
294
  * - *:safe* [_true,_|_false_] Safe mimic breaks JSON mimic to be safer, default is false (safe is
@@ -507,7 +509,7 @@ static VALUE get_def_opts(VALUE self) {
507
509
  * Sets the default options for load and dump.
508
510
  * - *opts* [_Hash_] options to change
509
511
  * - *:indent* [_Fixnum_|_String_|_nil_] number of spaces to indent each element in a JSON
510
- *document or the String to use for identation.
512
+ *document or the String to use for indentation.
511
513
  * - :circular [_Boolean_|_nil_] support circular references while dumping.
512
514
  * - *:auto_define* [_Boolean_|_nil_] automatically define classes if they do not exist.
513
515
  * - *:symbol_keys* [_Boolean_|_nil_] convert hash keys to symbols.
@@ -569,7 +571,7 @@ static VALUE get_def_opts(VALUE self) {
569
571
  * - *:ignore_under* [_Boolean_] if true then attributes that start with _ are ignored when
570
572
  *dumping in object or custom mode.
571
573
  * - *:cache_keys* [_Boolean_] if true then hash keys are cached
572
- * - *:cache_str* [_Fixnum_] maximum string vsalue length to cache
574
+ * - *:cache_str* [_Fixnum_] maximum string value length to cache (strings less than this are cached)
573
575
  * - *:integer_range* [_Range_] Dump integers outside range as strings.
574
576
  * - *:trace* [_Boolean_] turn trace on or off.
575
577
  * - *:safe* [_Boolean_] turn safe mimic on or off.
@@ -589,7 +591,8 @@ bool oj_hash_has_key(VALUE hash, VALUE key)
589
591
  return true;
590
592
  }
591
593
 
592
- void oj_parse_options(VALUE ropts, Options copts) {
594
+ bool set_yesno_options(VALUE key, VALUE value, Options copts)
595
+ {
593
596
  struct _yesNoOpt ynos[] = {{circular_sym, &copts->circular},
594
597
  {auto_define_sym, &copts->auto_define},
595
598
  {symbol_keys_sym, &copts->sym_key},
@@ -612,15 +615,37 @@ void oj_parse_options(VALUE ropts, Options copts) {
612
615
  {oj_create_additions_sym, &copts->create_ok},
613
616
  {cache_keys_sym, &copts->cache_keys},
614
617
  {Qnil, 0}};
615
- YesNoOpt o;
616
- volatile VALUE v;
617
- size_t len;
618
+ YesNoOpt o;
619
+
620
+ for (o = ynos; 0 != o->attr; o++) {
621
+ if (key == o->sym) {
622
+ if (Qnil == value) {
623
+ *o->attr = NotSet;
624
+ } else if (Qtrue == value) {
625
+ *o->attr = Yes;
626
+ } else if (Qfalse == value) {
627
+ *o->attr = No;
628
+ } else {
629
+ rb_raise(rb_eArgError,
630
+ "%s must be true, false, or nil.",
631
+ rb_id2name(key));
632
+ }
633
+ return true;
634
+ }
635
+ }
636
+ return false;
637
+ }
618
638
 
619
- if (T_HASH != rb_type(ropts)) {
620
- return;
639
+ static int parse_options_cb(VALUE k, VALUE v, VALUE opts)
640
+ {
641
+ Options copts = (Options)opts;
642
+ size_t len;
643
+
644
+ if (set_yesno_options(k, v, copts)) {
645
+ return ST_CONTINUE;
621
646
  }
622
- if (oj_hash_has_key(ropts, oj_indent_sym)) {
623
- v = rb_hash_lookup(ropts, oj_indent_sym);
647
+
648
+ if (oj_indent_sym == k) {
624
649
  switch (rb_type(v)) {
625
650
  case T_NIL:
626
651
  copts->dump_opts.indent_size = 0;
@@ -644,8 +669,7 @@ void oj_parse_options(VALUE ropts, Options copts) {
644
669
  break;
645
670
  default: rb_raise(rb_eTypeError, "indent must be a Fixnum, String, or nil."); break;
646
671
  }
647
- }
648
- if (Qnil != (v = rb_hash_lookup(ropts, float_prec_sym))) {
672
+ } else if (float_prec_sym == k) {
649
673
  int n;
650
674
 
651
675
  #ifdef RUBY_INTEGER_UNIFICATION
@@ -668,8 +692,7 @@ void oj_parse_options(VALUE ropts, Options copts) {
668
692
  sprintf(copts->float_fmt, "%%0.%dg", n);
669
693
  copts->float_prec = n;
670
694
  }
671
- }
672
- if (Qnil != (v = rb_hash_lookup(ropts, cache_str_sym))) {
695
+ } else if (cache_str_sym == k) {
673
696
  int n;
674
697
 
675
698
  #ifdef RUBY_INTEGER_UNIFICATION
@@ -690,8 +713,7 @@ void oj_parse_options(VALUE ropts, Options copts) {
690
713
  }
691
714
  copts->cache_str = (char)n;
692
715
  }
693
- }
694
- if (Qnil != (v = rb_hash_lookup(ropts, sec_prec_sym))) {
716
+ } else if (sec_prec_sym == k) {
695
717
  int n;
696
718
 
697
719
  #ifdef RUBY_INTEGER_UNIFICATION
@@ -714,8 +736,7 @@ void oj_parse_options(VALUE ropts, Options copts) {
714
736
  copts->sec_prec_set = true;
715
737
  }
716
738
  copts->sec_prec = n;
717
- }
718
- if (Qnil != (v = rb_hash_lookup(ropts, mode_sym))) {
739
+ } else if (mode_sym == k) {
719
740
  if (wab_sym == v) {
720
741
  copts->mode = WabMode;
721
742
  } else if (object_sym == v) {
@@ -734,8 +755,7 @@ void oj_parse_options(VALUE ropts, Options copts) {
734
755
  rb_raise(rb_eArgError,
735
756
  ":mode must be :object, :strict, :compat, :null, :custom, :rails, or :wab.");
736
757
  }
737
- }
738
- if (Qnil != (v = rb_hash_lookup(ropts, time_format_sym))) {
758
+ } else if (time_format_sym == k) {
739
759
  if (unix_sym == v) {
740
760
  copts->time_format = UnixTime;
741
761
  } else if (unix_zone_sym == v) {
@@ -747,8 +767,7 @@ void oj_parse_options(VALUE ropts, Options copts) {
747
767
  } else {
748
768
  rb_raise(rb_eArgError, ":time_format must be :unix, :unix_zone, :xmlschema, or :ruby.");
749
769
  }
750
- }
751
- if (Qnil != (v = rb_hash_lookup(ropts, escape_mode_sym))) {
770
+ } else if (escape_mode_sym == k) {
752
771
  if (newline_sym == v) {
753
772
  copts->escape_mode = NLEsc;
754
773
  } else if (json_sym == v) {
@@ -763,8 +782,11 @@ void oj_parse_options(VALUE ropts, Options copts) {
763
782
  rb_raise(rb_eArgError,
764
783
  ":encoding must be :newline, :json, :xss_safe, :unicode_xss, or :ascii.");
765
784
  }
766
- }
767
- if (Qnil != (v = rb_hash_lookup(ropts, bigdecimal_load_sym))) {
785
+ } else if (bigdecimal_load_sym == k) {
786
+ if (Qnil == v) {
787
+ return ST_CONTINUE;
788
+ }
789
+
768
790
  if (bigdecimal_sym == v || Qtrue == v) {
769
791
  copts->bigdec_load = BigDec;
770
792
  } else if (float_sym == v) {
@@ -776,12 +798,13 @@ void oj_parse_options(VALUE ropts, Options copts) {
776
798
  } else {
777
799
  rb_raise(rb_eArgError, ":bigdecimal_load must be :bigdecimal, :float, or :auto.");
778
800
  }
779
- }
780
- if (Qnil != (v = rb_hash_lookup(ropts, compat_bigdecimal_sym))) {
801
+ } else if (compat_bigdecimal_sym == k) {
802
+ if (Qnil == v) {
803
+ return ST_CONTINUE;
804
+ }
805
+
781
806
  copts->compat_bigdec = (Qtrue == v);
782
- }
783
- if (oj_hash_has_key(ropts, oj_decimal_class_sym)) {
784
- v = rb_hash_lookup(ropts, oj_decimal_class_sym);
807
+ } else if (oj_decimal_class_sym == k) {
785
808
  if (rb_cFloat == v) {
786
809
  copts->compat_bigdec = false;
787
810
  } else if (oj_bigdecimal_class == v) {
@@ -789,9 +812,7 @@ void oj_parse_options(VALUE ropts, Options copts) {
789
812
  } else {
790
813
  rb_raise(rb_eArgError, ":decimal_class must be BigDecimal or Float.");
791
814
  }
792
- }
793
- if (oj_hash_has_key(ropts, create_id_sym)) {
794
- v = rb_hash_lookup(ropts, create_id_sym);
815
+ } else if (create_id_sym == k) {
795
816
  if (Qnil == v) {
796
817
  if (oj_json_class != oj_default_options.create_id && NULL != copts->create_id) {
797
818
  xfree((char *)oj_default_options.create_id);
@@ -810,25 +831,8 @@ void oj_parse_options(VALUE ropts, Options copts) {
810
831
  } else {
811
832
  rb_raise(rb_eArgError, ":create_id must be string.");
812
833
  }
813
- }
814
- for (o = ynos; 0 != o->attr; o++) {
815
- if (oj_hash_has_key(ropts, o->sym)) {
816
- v = rb_hash_lookup(ropts, o->sym);
817
- if (Qnil == v) {
818
- *o->attr = NotSet;
819
- } else if (Qtrue == v) {
820
- *o->attr = Yes;
821
- } else if (Qfalse == v) {
822
- *o->attr = No;
823
- } else {
824
- rb_raise(rb_eArgError,
825
- "%s must be true, false, or nil.",
826
- rb_id2name(SYM2ID(o->sym)));
827
- }
828
- }
829
- }
830
- if (oj_hash_has_key(ropts, oj_space_sym)) {
831
- if (Qnil == (v = rb_hash_lookup(ropts, oj_space_sym))) {
834
+ } else if (oj_space_sym == k) {
835
+ if (Qnil == v) {
832
836
  copts->dump_opts.after_size = 0;
833
837
  *copts->dump_opts.after_sep = '\0';
834
838
  } else {
@@ -841,9 +845,8 @@ void oj_parse_options(VALUE ropts, Options copts) {
841
845
  strcpy(copts->dump_opts.after_sep, StringValuePtr(v));
842
846
  copts->dump_opts.after_size = (uint8_t)len;
843
847
  }
844
- }
845
- if (oj_hash_has_key(ropts, oj_space_before_sym)) {
846
- if (Qnil == (v = rb_hash_lookup(ropts, oj_space_before_sym))) {
848
+ } else if (oj_space_before_sym == k) {
849
+ if (Qnil == v) {
847
850
  copts->dump_opts.before_size = 0;
848
851
  *copts->dump_opts.before_sep = '\0';
849
852
  } else {
@@ -856,9 +859,8 @@ void oj_parse_options(VALUE ropts, Options copts) {
856
859
  strcpy(copts->dump_opts.before_sep, StringValuePtr(v));
857
860
  copts->dump_opts.before_size = (uint8_t)len;
858
861
  }
859
- }
860
- if (oj_hash_has_key(ropts, oj_object_nl_sym)) {
861
- if (Qnil == (v = rb_hash_lookup(ropts, oj_object_nl_sym))) {
862
+ } else if (oj_object_nl_sym == k) {
863
+ if (Qnil == v) {
862
864
  copts->dump_opts.hash_size = 0;
863
865
  *copts->dump_opts.hash_nl = '\0';
864
866
  } else {
@@ -871,9 +873,8 @@ void oj_parse_options(VALUE ropts, Options copts) {
871
873
  strcpy(copts->dump_opts.hash_nl, StringValuePtr(v));
872
874
  copts->dump_opts.hash_size = (uint8_t)len;
873
875
  }
874
- }
875
- if (oj_hash_has_key(ropts, oj_array_nl_sym)) {
876
- if (Qnil == (v = rb_hash_lookup(ropts, oj_array_nl_sym))) {
876
+ } else if (oj_array_nl_sym == k) {
877
+ if (Qnil == v) {
877
878
  copts->dump_opts.array_size = 0;
878
879
  *copts->dump_opts.array_nl = '\0';
879
880
  } else {
@@ -886,8 +887,11 @@ void oj_parse_options(VALUE ropts, Options copts) {
886
887
  strcpy(copts->dump_opts.array_nl, StringValuePtr(v));
887
888
  copts->dump_opts.array_size = (uint8_t)len;
888
889
  }
889
- }
890
- if (Qnil != (v = rb_hash_lookup(ropts, nan_sym))) {
890
+ } else if (nan_sym == k) {
891
+ if (Qnil == v) {
892
+ return ST_CONTINUE;
893
+ }
894
+
891
895
  if (null_sym == v) {
892
896
  copts->dump_opts.nan_dump = NullNan;
893
897
  } else if (huge_sym == v) {
@@ -901,11 +905,11 @@ void oj_parse_options(VALUE ropts, Options copts) {
901
905
  } else {
902
906
  rb_raise(rb_eArgError, ":nan must be :null, :huge, :word, :raise, or :auto.");
903
907
  }
904
- }
905
- copts->dump_opts.use = (0 < copts->dump_opts.indent_size || 0 < copts->dump_opts.after_size ||
906
- 0 < copts->dump_opts.before_size || 0 < copts->dump_opts.hash_size ||
907
- 0 < copts->dump_opts.array_size);
908
- if (Qnil != (v = rb_hash_lookup(ropts, omit_nil_sym))) {
908
+ } else if (omit_nil_sym == k) {
909
+ if (Qnil == v) {
910
+ return ST_CONTINUE;
911
+ }
912
+
909
913
  if (Qtrue == v) {
910
914
  copts->dump_opts.omit_nil = true;
911
915
  } else if (Qfalse == v) {
@@ -913,43 +917,38 @@ void oj_parse_options(VALUE ropts, Options copts) {
913
917
  } else {
914
918
  rb_raise(rb_eArgError, ":omit_nil must be true or false.");
915
919
  }
916
- }
917
- // This is here only for backwards compatibility with the original Oj.
918
- v = rb_hash_lookup(ropts, oj_ascii_only_sym);
919
- if (Qtrue == v) {
920
- copts->escape_mode = ASCIIEsc;
921
- } else if (Qfalse == v) {
922
- copts->escape_mode = JSONEsc;
923
- }
924
- if (oj_hash_has_key(ropts, oj_hash_class_sym)) {
925
- if (Qnil == (v = rb_hash_lookup(ropts, oj_hash_class_sym))) {
920
+ } else if(oj_ascii_only_sym == k) {
921
+ // This is here only for backwards compatibility with the original Oj.
922
+ if (Qtrue == v) {
923
+ copts->escape_mode = ASCIIEsc;
924
+ } else if (Qfalse == v) {
925
+ copts->escape_mode = JSONEsc;
926
+ }
927
+ } else if (oj_hash_class_sym == k) {
928
+ if (Qnil == v) {
926
929
  copts->hash_class = Qnil;
927
930
  } else {
928
931
  rb_check_type(v, T_CLASS);
929
932
  copts->hash_class = v;
930
933
  }
931
- }
932
- if (oj_hash_has_key(ropts, oj_object_class_sym)) {
933
- if (Qnil == (v = rb_hash_lookup(ropts, oj_object_class_sym))) {
934
+ } else if (oj_object_class_sym == k) {
935
+ if (Qnil == v) {
934
936
  copts->hash_class = Qnil;
935
937
  } else {
936
938
  rb_check_type(v, T_CLASS);
937
939
  copts->hash_class = v;
938
940
  }
939
- }
940
- if (oj_hash_has_key(ropts, oj_array_class_sym)) {
941
- if (Qnil == (v = rb_hash_lookup(ropts, oj_array_class_sym))) {
941
+ } else if (oj_array_class_sym == k) {
942
+ if (Qnil == v) {
942
943
  copts->array_class = Qnil;
943
944
  } else {
944
945
  rb_check_type(v, T_CLASS);
945
946
  copts->array_class = v;
946
947
  }
947
- }
948
- oj_parse_opt_match_string(&copts->str_rx, ropts);
949
- if (oj_hash_has_key(ropts, ignore_sym)) {
948
+ } else if (ignore_sym == k) {
950
949
  xfree(copts->ignore);
951
950
  copts->ignore = NULL;
952
- if (Qnil != (v = rb_hash_lookup(ropts, ignore_sym))) {
951
+ if (Qnil != v) {
953
952
  int cnt;
954
953
 
955
954
  rb_check_type(v, T_ARRAY);
@@ -964,8 +963,11 @@ void oj_parse_options(VALUE ropts, Options copts) {
964
963
  copts->ignore[i] = Qnil;
965
964
  }
966
965
  }
967
- }
968
- if (Qnil != (v = rb_hash_lookup(ropts, integer_range_sym))) {
966
+ } else if (integer_range_sym == k) {
967
+ if (Qnil == v) {
968
+ return ST_CONTINUE;
969
+ }
970
+
969
971
  if (TYPE(v) == T_STRUCT && rb_obj_class(v) == rb_cRange) {
970
972
  VALUE min = rb_funcall(v, oj_begin_id, 0);
971
973
  VALUE max = rb_funcall(v, oj_end_id, 0);
@@ -980,6 +982,22 @@ void oj_parse_options(VALUE ropts, Options copts) {
980
982
  rb_raise(rb_eArgError, ":integer_range must be a range of Fixnum.");
981
983
  }
982
984
  }
985
+
986
+ return ST_CONTINUE;
987
+ }
988
+
989
+ void oj_parse_options(VALUE ropts, Options copts) {
990
+ if (T_HASH != rb_type(ropts)) {
991
+ return;
992
+ }
993
+
994
+ rb_hash_foreach(ropts, parse_options_cb, (VALUE)copts);
995
+ oj_parse_opt_match_string(&copts->str_rx, ropts);
996
+
997
+ copts->dump_opts.use = (0 < copts->dump_opts.indent_size || 0 < copts->dump_opts.after_size ||
998
+ 0 < copts->dump_opts.before_size || 0 < copts->dump_opts.hash_size ||
999
+ 0 < copts->dump_opts.array_size);
1000
+ return;
983
1001
  }
984
1002
 
985
1003
  static int match_string_cb(VALUE key, VALUE value, VALUE rx) {
@@ -1380,7 +1398,7 @@ static VALUE to_json(int argc, VALUE *argv, VALUE self) {
1380
1398
  * Dumps an Object to the specified file.
1381
1399
  * - *file* [_String_] _path file path to write the JSON document to
1382
1400
  * - *obj* [_Object_] Object to serialize as an JSON document String
1383
- * - *options* [_Hash_] formating options
1401
+ * - *options* [_Hash_] formatting options
1384
1402
  * - *:indent* [_Fixnum_] format expected
1385
1403
  * - *:circular* [_Boolean_] allow circular references, default: false
1386
1404
  */
@@ -1402,7 +1420,7 @@ static VALUE to_file(int argc, VALUE *argv, VALUE self) {
1402
1420
  * Dumps an Object to the specified IO stream.
1403
1421
  * - *io* [_IO_] IO stream to write the JSON document to
1404
1422
  * - *obj* [_Object_] Object to serialize as an JSON document String
1405
- * - *options* [_Hash_] formating options
1423
+ * - *options* [_Hash_] formatting options
1406
1424
  * - *:indent* [_Fixnum_] format expected
1407
1425
  * - *:circular* [_Boolean_] allow circular references, default: false
1408
1426
  */
@@ -1761,6 +1779,9 @@ static VALUE protect_require(VALUE x) {
1761
1779
  void Init_oj() {
1762
1780
  int err = 0;
1763
1781
 
1782
+ #if HAVE_RB_EXT_RACTOR_SAFE
1783
+ rb_ext_ractor_safe(true);
1784
+ #endif
1764
1785
  Oj = rb_define_module("Oj");
1765
1786
 
1766
1787
  oj_cstack_class = rb_define_class_under(Oj, "CStack", rb_cObject);
@@ -2035,4 +2056,6 @@ void Init_oj() {
2035
2056
  rb_gc_register_address(&oj_cache_mutex);
2036
2057
  #endif
2037
2058
  oj_init_doc();
2059
+
2060
+ oj_parser_init();
2038
2061
  }
data/ext/oj/oj.h CHANGED
@@ -143,7 +143,7 @@ typedef struct _options {
143
143
  char safe; // YesNo
144
144
  char sec_prec_set; // boolean (0 or 1)
145
145
  char ignore_under; // YesNo - ignore attrs starting with _ if true in object and custom modes
146
- char cache_keys; // YexNo
146
+ char cache_keys; // YesNo
147
147
  char cache_str; // string short than or equal to this are cache
148
148
  int64_t int_range_min; // dump numbers below as string
149
149
  int64_t int_range_max; // dump numbers above as string
data/ext/oj/parse.c CHANGED
@@ -489,7 +489,7 @@ static void read_num(ParseInfo pi) {
489
489
  if ('.' == *pi->cur) {
490
490
  pi->cur++;
491
491
  // A trailing . is not a valid decimal but if encountered allow it
492
- // except when mimicing the JSON gem or in strict mode.
492
+ // except when mimicking the JSON gem or in strict mode.
493
493
  if (StrictMode == pi->options.mode || CompatMode == pi->options.mode) {
494
494
  int pos = (int)(pi->cur - ni.str);
495
495
 
@@ -964,12 +964,12 @@ static VALUE protect_parse(VALUE pip) {
964
964
  extern int oj_utf8_index;
965
965
 
966
966
  static void oj_pi_set_input_str(ParseInfo pi, volatile VALUE *inputp) {
967
- rb_encoding *enc = rb_to_encoding(rb_obj_encoding(*inputp));
967
+ rb_encoding *enc = rb_enc_get(*inputp);
968
968
 
969
- if (rb_utf8_encoding() != enc) {
970
- *inputp = rb_str_conv_enc(*inputp, enc, rb_utf8_encoding());
969
+ if (oj_utf8_encoding != enc) {
970
+ *inputp = rb_str_conv_enc(*inputp, enc, oj_utf8_encoding);
971
971
  }
972
- pi->json = rb_string_value_ptr((VALUE *)inputp);
972
+ pi->json = RSTRING_PTR(*inputp);
973
973
  pi->end = pi->json + RSTRING_LEN(*inputp);
974
974
  }
975
975