oj 3.0.2 → 3.0.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d4567e9da6a54d9e4867e415e0618c17e5108f90
4
- data.tar.gz: 66813867faafbab6d5f2eb758abf5b757e73ef58
3
+ metadata.gz: 0c5c4e44c052cf9e204ada5c41bc6b868b04ec56
4
+ data.tar.gz: d2a0352206bb10de6743c8be87d22120f122c7ca
5
5
  SHA512:
6
- metadata.gz: 16d1a220652f96d07f6a4fbaa589185d332b0d067eebdca3426f875e050d5d8307dd96c29e16093b2356f8ce45d7ca9e831c09a0454e5af2a54718bc25b8b8cb
7
- data.tar.gz: 4cfd12ba09c4a035776f126e7d7ed719ab62bf515ae1716487a57b92ce919397b0074baade3aec6d66166e0c399ac760c11bf99fcd9b630d795db94f3c345fef
6
+ metadata.gz: f4e47a2c590b33dff4fd7057c9874d1ab95f9c0057cc7f22a30617604865d8999b2dab758c47d89ee6445de033eeb07ac3b32077db52080f08a62bf57af3b9e2
7
+ data.tar.gz: 56ea00a656fc87fbc072a240ddcb58223627f4a28874d8b9fe37d1044757bd6e2cab993cadfc711be04adfae11cd2557c084a66e80c853132b6ff40adbef8913
@@ -37,4 +37,6 @@ extern bool oj_code_has(Code codes, VALUE clas, bool encode);
37
37
 
38
38
  extern void oj_code_attrs(VALUE obj, Attr attrs, int depth, Out out);
39
39
 
40
+ extern struct _Code oj_compat_codes[];
41
+
40
42
  #endif /* __OJ_CODE_H__ */
@@ -538,7 +538,7 @@ oj_dump_obj_to_json_using_params(VALUE obj, Options copts, Out out, int argc, VA
538
538
  case NullMode: oj_dump_null_val(obj, 0, out); break;
539
539
  case ObjectMode: oj_dump_obj_val(obj, 0, out); break;
540
540
  case CompatMode: oj_dump_compat_val(obj, 0, out, Yes == copts->to_json); break;
541
- case RailsMode: oj_dump_rails_val(obj, 0, out, true); break;
541
+ case RailsMode: oj_dump_rails_val(obj, 0, out); break;
542
542
  case CustomMode: oj_dump_custom_val(obj, 0, out, true); break;
543
543
  default: oj_dump_custom_val(obj, 0, out, true); break;
544
544
  }
@@ -41,7 +41,7 @@ extern void oj_dump_strict_val(VALUE obj, int depth, Out out);
41
41
  extern void oj_dump_null_val(VALUE obj, int depth, Out out);
42
42
  extern void oj_dump_obj_val(VALUE obj, int depth, Out out);
43
43
  extern void oj_dump_compat_val(VALUE obj, int depth, Out out, bool as_ok);
44
- extern void oj_dump_rails_val(VALUE obj, int depth, Out out, bool as_ok);
44
+ extern void oj_dump_rails_val(VALUE obj, int depth, Out out);
45
45
  extern void oj_dump_custom_val(VALUE obj, int depth, Out out, bool as_ok);
46
46
 
47
47
  extern VALUE oj_add_to_json(int argc, VALUE *argv, VALUE self);
@@ -462,7 +462,7 @@ time_alt(VALUE obj, int depth, Out out) {
462
462
  oj_code_attrs(obj, attrs, depth, out);
463
463
  }
464
464
 
465
- static struct _Code codes[] = {
465
+ struct _Code oj_compat_codes[] = {
466
466
  { "BigDecimal", Qnil, bigdecimal_alt, NULL, false },
467
467
  { "Complex", Qnil, complex_alt, NULL, false },
468
468
  { "Date", Qnil, date_alt, false },
@@ -481,7 +481,7 @@ oj_add_to_json(int argc, VALUE *argv, VALUE self) {
481
481
  Code a;
482
482
 
483
483
  if (0 == argc) {
484
- for (a = codes; NULL != a->name; a++) {
484
+ for (a = oj_compat_codes; NULL != a->name; a++) {
485
485
  if (Qnil == a->clas || Qundef == a->clas) {
486
486
  a->clas = rb_const_get_at(rb_cObject, rb_intern(a->name));
487
487
  }
@@ -514,7 +514,7 @@ oj_add_to_json(int argc, VALUE *argv, VALUE self) {
514
514
  oj_use_array_alt = true;
515
515
  continue;
516
516
  }
517
- for (a = codes; NULL != a->name; a++) {
517
+ for (a = oj_compat_codes; NULL != a->name; a++) {
518
518
  if (Qnil == a->clas || Qundef == a->clas) {
519
519
  a->clas = rb_const_get_at(rb_cObject, rb_intern(a->name));
520
520
  }
@@ -531,7 +531,7 @@ oj_add_to_json(int argc, VALUE *argv, VALUE self) {
531
531
  VALUE
532
532
  oj_remove_to_json(int argc, VALUE *argv, VALUE self) {
533
533
  if (0 == argc) {
534
- oj_code_set_active(codes, Qnil, false);
534
+ oj_code_set_active(oj_compat_codes, Qnil, false);
535
535
  use_struct_alt = false;
536
536
  use_exception_alt = false;
537
537
  use_bignum_alt = false;
@@ -559,7 +559,7 @@ oj_remove_to_json(int argc, VALUE *argv, VALUE self) {
559
559
  oj_use_array_alt = false;
560
560
  continue;
561
561
  }
562
- oj_code_set_active(codes, *argv, false);
562
+ oj_code_set_active(oj_compat_codes, *argv, false);
563
563
  }
564
564
  }
565
565
  return Qnil;
@@ -723,7 +723,7 @@ dump_hash(VALUE obj, int depth, Out out, bool as_ok) {
723
723
  // called.
724
724
  static void
725
725
  dump_obj(VALUE obj, int depth, Out out, bool as_ok) {
726
- if (oj_code_dump(codes, obj, depth, out)) {
726
+ if (oj_code_dump(oj_compat_codes, obj, depth, out)) {
727
727
  return;
728
728
  }
729
729
  if (use_exception_alt && rb_obj_is_kind_of(obj, rb_eException)) {
@@ -754,7 +754,7 @@ static void
754
754
  dump_struct(VALUE obj, int depth, Out out, bool as_ok) {
755
755
  VALUE clas = rb_obj_class(obj);
756
756
 
757
- if (oj_code_dump(codes, obj, depth, out)) {
757
+ if (oj_code_dump(oj_compat_codes, obj, depth, out)) {
758
758
  return;
759
759
  }
760
760
  if (rb_cRange == clas) {
@@ -866,7 +866,6 @@ dump_bignum(VALUE obj, int depth, Out out, bool as_ok) {
866
866
  *out->cur = '\0';
867
867
  }
868
868
 
869
-
870
869
  static DumpFunc compat_funcs[] = {
871
870
  NULL, // RUBY_T_NONE = 0x00,
872
871
  dump_obj, // RUBY_T_OBJECT = 0x01,
@@ -624,7 +624,7 @@ dump_obj_attrs(VALUE obj, VALUE clas, slot_t id, int depth, Out out) {
624
624
  oj_dump_cstr(buf, strlen(attr) + 1, 0, 0, out);
625
625
  }
626
626
  *out->cur++ = ':';
627
- oj_dump_obj_val(value, d2, out, 0, 0, true);
627
+ oj_dump_obj_val(value, d2, out, true);
628
628
  assure_size(out, 2);
629
629
  }
630
630
  #endif
@@ -16,7 +16,7 @@
16
16
  #include "hash.h"
17
17
  #include "odd.h"
18
18
  #include "dump.h"
19
- #include "mimic_rails.h"
19
+ #include "rails.h"
20
20
  #include "encode.h"
21
21
 
22
22
  #if !HAS_ENCODING_SUPPORT || defined(RUBINIUS_RUBY)
@@ -1,11 +1,14 @@
1
- /* mimic_rails.c
1
+ /* rails.c
2
2
  * Copyright (c) 2017, Peter Ohler
3
3
  * All rights reserved.
4
4
  */
5
5
 
6
- #include "dump.h"
7
- #include "mimic_rails.h"
6
+ #include "rails.h"
8
7
  #include "encode.h"
8
+ #include "code.h"
9
+ #include "encode.h"
10
+
11
+ #define OJ_INFINITY (1.0/0.0)
9
12
 
10
13
  // TBD keep static array of strings and functions to help with rails optimization
11
14
  typedef struct _Encoder {
@@ -14,6 +17,11 @@ typedef struct _Encoder {
14
17
  VALUE arg;
15
18
  } *Encoder;
16
19
 
20
+ bool oj_rails_hash_opt = false;
21
+ bool oj_rails_array_opt = false;
22
+
23
+ static void dump_rails_val(VALUE obj, int depth, Out out, bool as_ok);
24
+
17
25
  extern VALUE Oj;
18
26
 
19
27
  static struct _ROptTable ropts = { 0, 0, NULL };
@@ -98,7 +106,7 @@ dump_attr_cb(ID key, VALUE value, Out out) {
98
106
  oj_dump_cstr(buf, strlen(buf), 0, 0, out);
99
107
  }
100
108
  *out->cur++ = ':';
101
- oj_dump_rails_val(value, depth, out, true);
109
+ dump_rails_val(value, depth, out, true);
102
110
  out->depth = depth;
103
111
  *out->cur++ = ',';
104
112
 
@@ -172,7 +180,7 @@ dump_struct(VALUE obj, int depth, Out out, bool as_ok) {
172
180
  #else
173
181
  v = rb_struct_aref(obj, INT2FIX(i));
174
182
  #endif
175
- oj_dump_rails_val(v, d3, out, true);
183
+ dump_rails_val(v, d3, out, true);
176
184
  }
177
185
  fill_indent(out, depth);
178
186
  *out->cur++ = '}';
@@ -187,7 +195,7 @@ dump_enumerable(VALUE obj, int depth, Out out, bool as_ok) {
187
195
  if (0 == to_a_id) {
188
196
  to_a_id = rb_intern("to_a");
189
197
  }
190
- oj_dump_rails_val(rb_funcall(obj, to_a_id, 0), depth, out, false);
198
+ dump_rails_val(rb_funcall(obj, to_a_id, 0), depth, out, false);
191
199
  }
192
200
 
193
201
  static void
@@ -556,7 +564,7 @@ static VALUE
556
564
  protect_dump(VALUE ov) {
557
565
  OO oo = (OO)ov;
558
566
 
559
- oj_dump_rails_val(oo->obj, 0, oo->out, true);
567
+ dump_rails_val(oo->obj, 0, oo->out, true);
560
568
 
561
569
  return Qnil;
562
570
  }
@@ -596,7 +604,7 @@ encode(VALUE obj, ROptTable ropts, Options opts, int argc, VALUE *argv) {
596
604
  if (Yes == copts.circular) {
597
605
  oj_cache8_new(&out.circ_cache);
598
606
  }
599
- //oj_dump_rails_val(*argv, 0, &out, true);
607
+ //dump_rails_val(*argv, 0, &out, true);
600
608
  rb_protect(protect_dump, (VALUE)&oo, &line);
601
609
 
602
610
  if (0 == line) {
@@ -719,6 +727,7 @@ rails_set_encoder(VALUE self) {
719
727
  VALUE json;
720
728
  VALUE encoding;
721
729
  VALUE pv;
730
+ VALUE verbose;
722
731
 
723
732
  if (rb_const_defined_at(rb_cObject, rb_intern("ActiveSupport"))) {
724
733
  active = rb_const_get_at(rb_cObject, rb_intern("ActiveSupport"));
@@ -730,7 +739,11 @@ rails_set_encoder(VALUE self) {
730
739
  json = rb_const_get_at(active, rb_intern("JSON"));
731
740
  encoding = rb_const_get_at(json, rb_intern("Encoding"));
732
741
 
733
- rb_undef_method(active, "use_standard_json_time_format=");
742
+ // rb_undef_method doesn't work for modules or maybe sometimes
743
+ // doesn't. Anyway setting verbose should hide the warning.
744
+ verbose = rb_gv_get("$VERBOSE");
745
+ rb_gv_set("$VERBOSE", Qfalse);
746
+ rb_undef_method(encoding, "use_standard_json_time_format=");
734
747
  rb_define_module_function(encoding, "use_standard_json_time_format=", rails_use_standard_json_time_format, 1);
735
748
 
736
749
  rb_undef_method(encoding, "escape_html_entities_in_json=");
@@ -740,6 +753,7 @@ rails_set_encoder(VALUE self) {
740
753
  oj_default_options.sec_prec = NUM2INT(pv);
741
754
  rb_undef_method(encoding, "time_precision=");
742
755
  rb_define_module_function(encoding, "time_precision=", rails_time_precision, 1);
756
+ rb_gv_set("$VERBOSE", verbose);
743
757
 
744
758
  return Qnil;
745
759
  }
@@ -754,6 +768,7 @@ static VALUE
754
768
  rails_set_decoder(VALUE self) {
755
769
  VALUE json;
756
770
  VALUE json_error;
771
+ VALUE verbose;
757
772
 
758
773
  if (rb_const_defined_at(rb_cObject, rb_intern("JSON"))) {
759
774
  json = rb_const_get_at(rb_cObject, rb_intern("JSON"));
@@ -770,8 +785,13 @@ rails_set_decoder(VALUE self) {
770
785
  } else {
771
786
  oj_json_parser_error_class = rb_define_class_under(json, "ParserError", json_error);
772
787
  }
788
+ // rb_undef_method doesn't work for modules or maybe sometimes
789
+ // doesn't. Anyway setting verbose should hide the warning.
790
+ verbose = rb_gv_get("$VERBOSE");
791
+ rb_gv_set("$VERBOSE", Qfalse);
773
792
  rb_undef_method(json, "parse");
774
793
  rb_define_module_function(json, "parse", oj_mimic_parse, -1);
794
+ rb_gv_set("$VERBOSE", verbose);
775
795
 
776
796
  return Qnil;
777
797
  }
@@ -804,3 +824,337 @@ oj_mimic_rails_init() {
804
824
  rb_define_method(encoder_class, "deoptimize", encoder_deoptimize, -1);
805
825
  rb_define_method(encoder_class, "optimized?", encoder_optimized, 1);
806
826
  }
827
+
828
+ static void
829
+ dump_as_json(VALUE obj, int depth, Out out, bool as_ok) {
830
+ volatile VALUE ja;
831
+
832
+ if (0 < out->argc) {
833
+ ja = rb_funcall2(obj, oj_as_json_id, out->argc, out->argv);
834
+ } else {
835
+ ja = rb_funcall(obj, oj_as_json_id, 0);
836
+ }
837
+ if (ja == obj || !as_ok) {
838
+ // Once as_json is call it should never be called again on the same
839
+ // object with as_ok.
840
+ dump_rails_val(ja, depth, out, false);
841
+ } else {
842
+ int type = rb_type(ja);
843
+
844
+ if (T_HASH == type || T_ARRAY == type) {
845
+ dump_rails_val(ja, depth, out, false);
846
+ } else {
847
+ dump_rails_val(ja, depth, out, true);
848
+ }
849
+ }
850
+ }
851
+
852
+ static void
853
+ dump_to_hash(VALUE obj, int depth, Out out) {
854
+ dump_rails_val(rb_funcall(obj, oj_to_hash_id, 0), depth, out, false);
855
+ }
856
+
857
+ static void
858
+ dump_float(VALUE obj, int depth, Out out, bool as_ok) {
859
+ char buf[64];
860
+ char *b;
861
+ double d = rb_num2dbl(obj);
862
+ int cnt = 0;
863
+
864
+ if (0.0 == d) {
865
+ b = buf;
866
+ *b++ = '0';
867
+ *b++ = '.';
868
+ *b++ = '0';
869
+ *b++ = '\0';
870
+ cnt = 3;
871
+ } else {
872
+ if (isnan(d) || OJ_INFINITY == d || -OJ_INFINITY == d) {
873
+ strcpy(buf, "null");
874
+ cnt = 4;
875
+ } else if (d == (double)(long long int)d) {
876
+ cnt = snprintf(buf, sizeof(buf), "%.1f", d);
877
+ } else {
878
+ cnt = snprintf(buf, sizeof(buf), "%0.16g", d);
879
+ }
880
+ }
881
+ assure_size(out, cnt);
882
+ for (b = buf; '\0' != *b; b++) {
883
+ *out->cur++ = *b;
884
+ }
885
+ *out->cur = '\0';
886
+ }
887
+
888
+ static void
889
+ dump_array(VALUE a, int depth, Out out, bool as_ok) {
890
+ size_t size;
891
+ int i, cnt;
892
+ int d2 = depth + 1;
893
+
894
+ if (Yes == out->opts->circular) {
895
+ if (0 > oj_check_circular(a, out)) {
896
+ oj_dump_nil(Qnil, 0, out, false);
897
+ return;
898
+ }
899
+ }
900
+ if (as_ok && !oj_rails_array_opt && rb_respond_to(a, oj_as_json_id)) {
901
+ dump_as_json(a, depth, out, false);
902
+ return;
903
+ }
904
+ cnt = (int)RARRAY_LEN(a);
905
+ *out->cur++ = '[';
906
+ size = 2;
907
+ assure_size(out, size);
908
+ if (0 == cnt) {
909
+ *out->cur++ = ']';
910
+ } else {
911
+ if (out->opts->dump_opts.use) {
912
+ size = d2 * out->opts->dump_opts.indent_size + out->opts->dump_opts.array_size + 1;
913
+ } else {
914
+ size = d2 * out->indent + 2;
915
+ }
916
+ cnt--;
917
+ for (i = 0; i <= cnt; i++) {
918
+ assure_size(out, size);
919
+ if (out->opts->dump_opts.use) {
920
+ if (0 < out->opts->dump_opts.array_size) {
921
+ strcpy(out->cur, out->opts->dump_opts.array_nl);
922
+ out->cur += out->opts->dump_opts.array_size;
923
+ }
924
+ if (0 < out->opts->dump_opts.indent_size) {
925
+ int i;
926
+ for (i = d2; 0 < i; i--) {
927
+ strcpy(out->cur, out->opts->dump_opts.indent_str);
928
+ out->cur += out->opts->dump_opts.indent_size;
929
+ }
930
+ }
931
+ } else {
932
+ fill_indent(out, d2);
933
+ }
934
+ dump_rails_val(rb_ary_entry(a, i), d2, out, as_ok);
935
+ if (i < cnt) {
936
+ *out->cur++ = ',';
937
+ }
938
+ }
939
+ size = depth * out->indent + 1;
940
+ assure_size(out, size);
941
+ if (out->opts->dump_opts.use) {
942
+ if (0 < out->opts->dump_opts.array_size) {
943
+ strcpy(out->cur, out->opts->dump_opts.array_nl);
944
+ out->cur += out->opts->dump_opts.array_size;
945
+ }
946
+ if (0 < out->opts->dump_opts.indent_size) {
947
+ int i;
948
+
949
+ for (i = depth; 0 < i; i--) {
950
+ strcpy(out->cur, out->opts->dump_opts.indent_str);
951
+ out->cur += out->opts->dump_opts.indent_size;
952
+ }
953
+ }
954
+ } else {
955
+ fill_indent(out, depth);
956
+ }
957
+ *out->cur++ = ']';
958
+ }
959
+ *out->cur = '\0';
960
+ }
961
+
962
+ static int
963
+ hash_cb(VALUE key, VALUE value, Out out) {
964
+ int depth = out->depth;
965
+ long size;
966
+ int rtype = rb_type(key);
967
+
968
+ if (rtype != T_STRING && rtype != T_SYMBOL) {
969
+ key = rb_funcall(key, oj_to_s_id, 0);
970
+ rtype = rb_type(key);
971
+ }
972
+ if (!out->opts->dump_opts.use) {
973
+ size = depth * out->indent + 1;
974
+ assure_size(out, size);
975
+ fill_indent(out, depth);
976
+ if (rtype == T_STRING) {
977
+ oj_dump_str(key, 0, out, false);
978
+ } else {
979
+ oj_dump_sym(key, 0, out, false);
980
+ }
981
+ *out->cur++ = ':';
982
+ } else {
983
+ size = depth * out->opts->dump_opts.indent_size + out->opts->dump_opts.hash_size + 1;
984
+ assure_size(out, size);
985
+ if (0 < out->opts->dump_opts.hash_size) {
986
+ strcpy(out->cur, out->opts->dump_opts.hash_nl);
987
+ out->cur += out->opts->dump_opts.hash_size;
988
+ }
989
+ if (0 < out->opts->dump_opts.indent_size) {
990
+ int i;
991
+ for (i = depth; 0 < i; i--) {
992
+ strcpy(out->cur, out->opts->dump_opts.indent_str);
993
+ out->cur += out->opts->dump_opts.indent_size;
994
+ }
995
+ }
996
+ if (rtype == T_STRING) {
997
+ oj_dump_str(key, 0, out, false);
998
+ } else {
999
+ oj_dump_sym(key, 0, out, false);
1000
+ }
1001
+ size = out->opts->dump_opts.before_size + out->opts->dump_opts.after_size + 2;
1002
+ assure_size(out, size);
1003
+ if (0 < out->opts->dump_opts.before_size) {
1004
+ strcpy(out->cur, out->opts->dump_opts.before_sep);
1005
+ out->cur += out->opts->dump_opts.before_size;
1006
+ }
1007
+ *out->cur++ = ':';
1008
+ if (0 < out->opts->dump_opts.after_size) {
1009
+ strcpy(out->cur, out->opts->dump_opts.after_sep);
1010
+ out->cur += out->opts->dump_opts.after_size;
1011
+ }
1012
+ }
1013
+ dump_rails_val(value, depth, out, false);
1014
+ out->depth = depth;
1015
+ *out->cur++ = ',';
1016
+
1017
+ return ST_CONTINUE;
1018
+ }
1019
+
1020
+ static void
1021
+ dump_hash(VALUE obj, int depth, Out out, bool as_ok) {
1022
+ int cnt;
1023
+ size_t size;
1024
+
1025
+ if (Yes == out->opts->circular) {
1026
+ if (0 > oj_check_circular(obj, out)) {
1027
+ oj_dump_nil(Qnil, 0, out, false);
1028
+ return;
1029
+ }
1030
+ }
1031
+ if (as_ok && !oj_rails_hash_opt && rb_respond_to(obj, oj_as_json_id)) {
1032
+ dump_as_json(obj, depth, out, false);
1033
+ return;
1034
+ }
1035
+ cnt = (int)RHASH_SIZE(obj);
1036
+ size = depth * out->indent + 2;
1037
+ assure_size(out, 2);
1038
+ *out->cur++ = '{';
1039
+ if (0 == cnt) {
1040
+ *out->cur++ = '}';
1041
+ } else {
1042
+ out->depth = depth + 1;
1043
+ rb_hash_foreach(obj, hash_cb, (VALUE)out);
1044
+ if (',' == *(out->cur - 1)) {
1045
+ out->cur--; // backup to overwrite last comma
1046
+ }
1047
+ if (!out->opts->dump_opts.use) {
1048
+ assure_size(out, size);
1049
+ fill_indent(out, depth);
1050
+ } else {
1051
+ size = depth * out->opts->dump_opts.indent_size + out->opts->dump_opts.hash_size + 1;
1052
+ assure_size(out, size);
1053
+ if (0 < out->opts->dump_opts.hash_size) {
1054
+ strcpy(out->cur, out->opts->dump_opts.hash_nl);
1055
+ out->cur += out->opts->dump_opts.hash_size;
1056
+ }
1057
+ if (0 < out->opts->dump_opts.indent_size) {
1058
+ int i;
1059
+
1060
+ for (i = depth; 0 < i; i--) {
1061
+ strcpy(out->cur, out->opts->dump_opts.indent_str);
1062
+ out->cur += out->opts->dump_opts.indent_size;
1063
+ }
1064
+ }
1065
+ }
1066
+ *out->cur++ = '}';
1067
+ }
1068
+ *out->cur = '\0';
1069
+ }
1070
+
1071
+ static void
1072
+ dump_obj(VALUE obj, int depth, Out out, bool as_ok) {
1073
+ if (oj_code_dump(oj_compat_codes, obj, depth, out)) {
1074
+ return;
1075
+ }
1076
+ if (as_ok) {
1077
+ ROpt ro;
1078
+
1079
+ if (NULL != (ro = oj_rails_get_opt(out->ropts, rb_obj_class(obj))) && ro->on) {
1080
+ ro->dump(obj, depth, out, as_ok);
1081
+ } else if (rb_respond_to(obj, oj_as_json_id)) {
1082
+ dump_as_json(obj, depth, out, true);
1083
+ } else if (rb_respond_to(obj, oj_to_hash_id)) {
1084
+ dump_to_hash(obj, depth, out);
1085
+ } else {
1086
+ oj_dump_obj_to_s(obj, out);
1087
+ }
1088
+ } else if (rb_respond_to(obj, oj_to_hash_id)) {
1089
+ // Always attempt to_hash.
1090
+ dump_to_hash(obj, depth, out);
1091
+ } else {
1092
+ oj_dump_obj_to_s(obj, out);
1093
+ }
1094
+ }
1095
+
1096
+ static void
1097
+ dump_as_string(VALUE obj, int depth, Out out, bool as_ok) {
1098
+ if (oj_code_dump(oj_compat_codes, obj, depth, out)) {
1099
+ return;
1100
+ }
1101
+ oj_dump_obj_to_s(obj, out);
1102
+ }
1103
+
1104
+ static DumpFunc rails_funcs[] = {
1105
+ NULL, // RUBY_T_NONE = 0x00,
1106
+ dump_obj, // RUBY_T_OBJECT = 0x01,
1107
+ oj_dump_class, // RUBY_T_CLASS = 0x02,
1108
+ oj_dump_class, // RUBY_T_MODULE = 0x03,
1109
+ dump_float, // RUBY_T_FLOAT = 0x04,
1110
+ oj_dump_str, // RUBY_T_STRING = 0x05,
1111
+ dump_as_string, // RUBY_T_REGEXP = 0x06,
1112
+ dump_array, // RUBY_T_ARRAY = 0x07,
1113
+ dump_hash, // RUBY_T_HASH = 0x08,
1114
+ dump_obj, // RUBY_T_STRUCT = 0x09,
1115
+ oj_dump_bignum, // RUBY_T_BIGNUM = 0x0a,
1116
+ NULL, // RUBY_T_FILE = 0x0b,
1117
+ dump_obj, // RUBY_T_DATA = 0x0c,
1118
+ NULL, // RUBY_T_MATCH = 0x0d,
1119
+ // Rails raises a stack error on Complex and Rational. It also corrupts
1120
+ // something whic causes a segfault on the next call. Oj will not mimic
1121
+ // that behavior.
1122
+ dump_as_string, // RUBY_T_COMPLEX = 0x0e,
1123
+ dump_as_string, // RUBY_T_RATIONAL = 0x0f,
1124
+ NULL, // 0x10
1125
+ oj_dump_nil, // RUBY_T_NIL = 0x11,
1126
+ oj_dump_true, // RUBY_T_TRUE = 0x12,
1127
+ oj_dump_false, // RUBY_T_FALSE = 0x13,
1128
+ oj_dump_sym, // RUBY_T_SYMBOL = 0x14,
1129
+ oj_dump_fixnum, // RUBY_T_FIXNUM = 0x15,
1130
+ };
1131
+
1132
+ static void
1133
+ dump_rails_val(VALUE obj, int depth, Out out, bool as_ok) {
1134
+ int type = rb_type(obj);
1135
+
1136
+ if (MAX_DEPTH < depth) {
1137
+ rb_raise(rb_eNoMemError, "Too deeply nested.\n");
1138
+ }
1139
+ if (0 < type && type <= RUBY_T_FIXNUM) {
1140
+ DumpFunc f = rails_funcs[type];
1141
+
1142
+ if (NULL != f) {
1143
+ f(obj, depth, out, as_ok);
1144
+ return;
1145
+ }
1146
+ }
1147
+ oj_dump_nil(Qnil, depth, out, false);
1148
+ }
1149
+
1150
+ void
1151
+ oj_dump_rails_val(VALUE obj, int depth, Out out) {
1152
+ out->opts->str_rx.head = NULL;
1153
+ out->opts->str_rx.tail = NULL;
1154
+ if (escape_html) {
1155
+ out->opts->escape_mode = JXEsc;
1156
+ } else {
1157
+ out->opts->escape_mode = RailsEsc;
1158
+ }
1159
+ dump_rails_val(obj, depth, out, true);
1160
+ }
@@ -1,10 +1,10 @@
1
- /* mimic_rails.h
1
+ /* rails.h
2
2
  * Copyright (c) 2017, Peter Ohler
3
3
  * All rights reserved.
4
4
  */
5
5
 
6
- #ifndef __OJ_MIMIC_RAILS_H__
7
- #define __OJ_MIMIC_RAILS_H__
6
+ #ifndef __OJ_RAILS_H__
7
+ #define __OJ_RAILS_H__
8
8
 
9
9
  #include "dump.h"
10
10
 
@@ -14,4 +14,4 @@ extern ROpt oj_rails_get_opt(ROptTable rot, VALUE clas);
14
14
  extern bool oj_rails_hash_opt;
15
15
  extern bool oj_rails_array_opt;
16
16
 
17
- #endif /* __OJ_MIMIC_RAILS_H__ */
17
+ #endif /* __OJ_RAILS_H__ */
@@ -1,5 +1,5 @@
1
1
 
2
2
  module Oj
3
3
  # Current version of the module.
4
- VERSION = '3.0.2'
4
+ VERSION = '3.0.3'
5
5
  end
@@ -40,12 +40,15 @@ specific to Oj such as the :circular option which it used to detect circular
40
40
  references while encoding.
41
41
 
42
42
  By default Oj acts like the ActiveSupport encoder and honors any changes in
43
- the as_json() methods. There are also optimized encoders for some
43
+ the as_json() methods. There are some optimized Oj encoders for some
44
44
  classes. When the optimized encoder it toggled the as_json() methods will not
45
45
  be called for that class but instead the optimized version will be called. The
46
46
  optimized version is the same as the ActiveSupport default encoding for a
47
47
  given class. The optimized versions are toggled with the optimize() and
48
- deoptimize() methods.
48
+ deoptimize() methods. There is a default optimized version for every class
49
+ that takes the visible attributes and encodes them but that may not be the
50
+ same as what Rails uses. Trial an error is the best approach for classes not
51
+ listed here.
49
52
 
50
53
  The classes that can be put in optimized mode are:
51
54
 
@@ -76,8 +76,11 @@ class TestJSONDecoding < ActiveSupport::TestCase
76
76
  prev = ActiveSupport.parse_json_times
77
77
  ActiveSupport.parse_json_times = true
78
78
  silence_warnings do
79
- assert_equal expected, ActiveSupport::JSON.decode(json), "JSON decoding \
80
- failed for #{json}"
79
+ if expected.nil?
80
+ assert_nil ActiveSupport::JSON.decode(json), "JSON decoding failed for #{json}"
81
+ else
82
+ assert_equal expected, ActiveSupport::JSON.decode(json), "JSON decoding failed for #{json}"
83
+ end
81
84
  end
82
85
  ActiveSupport.parse_json_times = prev
83
86
  end
@@ -421,7 +421,7 @@ class TestJSONEncoding < ActiveSupport::TestCase
421
421
  end
422
422
 
423
423
  def test_nil_true_and_false_represented_as_themselves
424
- assert_equal nil, nil.as_json
424
+ assert_nil(nil.as_json)
425
425
  assert_equal true, true.as_json
426
426
  assert_equal false, false.as_json
427
427
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: oj
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.2
4
+ version: 3.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter Ohler
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-04-27 00:00:00.000000000 Z
11
+ date: 2017-04-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake-compiler
@@ -85,7 +85,6 @@ files:
85
85
  - ext/oj/dump_compat.c
86
86
  - ext/oj/dump_leaf.c
87
87
  - ext/oj/dump_object.c
88
- - ext/oj/dump_rails.c
89
88
  - ext/oj/dump_strict.c
90
89
  - ext/oj/encode.h
91
90
  - ext/oj/err.c
@@ -96,8 +95,6 @@ files:
96
95
  - ext/oj/hash.h
97
96
  - ext/oj/hash_test.c
98
97
  - ext/oj/mimic_json.c
99
- - ext/oj/mimic_rails.c
100
- - ext/oj/mimic_rails.h
101
98
  - ext/oj/object.c
102
99
  - ext/oj/odd.c
103
100
  - ext/oj/odd.h
@@ -105,6 +102,8 @@ files:
105
102
  - ext/oj/oj.h
106
103
  - ext/oj/parse.c
107
104
  - ext/oj/parse.h
105
+ - ext/oj/rails.c
106
+ - ext/oj/rails.h
108
107
  - ext/oj/reader.c
109
108
  - ext/oj/reader.h
110
109
  - ext/oj/resolve.c
@@ -1,329 +0,0 @@
1
- /* dump_object.c
2
- * Copyright (c) 2012, 2017, Peter Ohler
3
- * All rights reserved.
4
- */
5
-
6
- #include "dump.h"
7
- #include "encode.h"
8
- #include "mimic_rails.h"
9
-
10
- #define OJ_INFINITY (1.0/0.0)
11
-
12
- bool oj_rails_hash_opt = false;
13
- bool oj_rails_array_opt = false;
14
-
15
- static void
16
- dump_as_json(VALUE obj, int depth, Out out, bool as_ok) {
17
- volatile VALUE ja;
18
-
19
- if (0 < out->argc) {
20
- ja = rb_funcall2(obj, oj_as_json_id, out->argc, out->argv);
21
- } else {
22
- ja = rb_funcall(obj, oj_as_json_id, 0);
23
- }
24
- if (ja == obj || !as_ok) {
25
- // Once as_json is call it should never be called again on the same
26
- // object with as_ok.
27
- oj_dump_rails_val(ja, depth, out, false);
28
- } else {
29
- int type = rb_type(ja);
30
-
31
- if (T_HASH == type || T_ARRAY == type) {
32
- oj_dump_rails_val(ja, depth, out, false);
33
- } else {
34
- oj_dump_rails_val(ja, depth, out, true);
35
- }
36
- }
37
- }
38
-
39
- static void
40
- dump_to_hash(VALUE obj, int depth, Out out) {
41
- oj_dump_rails_val(rb_funcall(obj, oj_to_hash_id, 0), depth, out, false);
42
- }
43
-
44
- static void
45
- dump_float(VALUE obj, int depth, Out out, bool as_ok) {
46
- char buf[64];
47
- char *b;
48
- double d = rb_num2dbl(obj);
49
- int cnt = 0;
50
-
51
- if (0.0 == d) {
52
- b = buf;
53
- *b++ = '0';
54
- *b++ = '.';
55
- *b++ = '0';
56
- *b++ = '\0';
57
- cnt = 3;
58
- } else {
59
- if (isnan(d) || OJ_INFINITY == d || -OJ_INFINITY == d) {
60
- strcpy(buf, "null");
61
- cnt = 4;
62
- } else if (d == (double)(long long int)d) {
63
- cnt = snprintf(buf, sizeof(buf), "%.1f", d);
64
- } else {
65
- cnt = snprintf(buf, sizeof(buf), "%0.16g", d);
66
- }
67
- }
68
- assure_size(out, cnt);
69
- for (b = buf; '\0' != *b; b++) {
70
- *out->cur++ = *b;
71
- }
72
- *out->cur = '\0';
73
- }
74
-
75
- static void
76
- dump_array(VALUE a, int depth, Out out, bool as_ok) {
77
- size_t size;
78
- int i, cnt;
79
- int d2 = depth + 1;
80
-
81
- if (Yes == out->opts->circular) {
82
- if (0 > oj_check_circular(a, out)) {
83
- oj_dump_nil(Qnil, 0, out, false);
84
- return;
85
- }
86
- }
87
- if (as_ok && !oj_rails_array_opt && rb_respond_to(a, oj_as_json_id)) {
88
- dump_as_json(a, depth, out, false);
89
- return;
90
- }
91
- cnt = (int)RARRAY_LEN(a);
92
- *out->cur++ = '[';
93
- size = 2;
94
- assure_size(out, size);
95
- if (0 == cnt) {
96
- *out->cur++ = ']';
97
- } else {
98
- if (out->opts->dump_opts.use) {
99
- size = d2 * out->opts->dump_opts.indent_size + out->opts->dump_opts.array_size + 1;
100
- } else {
101
- size = d2 * out->indent + 2;
102
- }
103
- cnt--;
104
- for (i = 0; i <= cnt; i++) {
105
- assure_size(out, size);
106
- if (out->opts->dump_opts.use) {
107
- if (0 < out->opts->dump_opts.array_size) {
108
- strcpy(out->cur, out->opts->dump_opts.array_nl);
109
- out->cur += out->opts->dump_opts.array_size;
110
- }
111
- if (0 < out->opts->dump_opts.indent_size) {
112
- int i;
113
- for (i = d2; 0 < i; i--) {
114
- strcpy(out->cur, out->opts->dump_opts.indent_str);
115
- out->cur += out->opts->dump_opts.indent_size;
116
- }
117
- }
118
- } else {
119
- fill_indent(out, d2);
120
- }
121
- oj_dump_rails_val(rb_ary_entry(a, i), d2, out, as_ok);
122
- if (i < cnt) {
123
- *out->cur++ = ',';
124
- }
125
- }
126
- size = depth * out->indent + 1;
127
- assure_size(out, size);
128
- if (out->opts->dump_opts.use) {
129
- if (0 < out->opts->dump_opts.array_size) {
130
- strcpy(out->cur, out->opts->dump_opts.array_nl);
131
- out->cur += out->opts->dump_opts.array_size;
132
- }
133
- if (0 < out->opts->dump_opts.indent_size) {
134
- int i;
135
-
136
- for (i = depth; 0 < i; i--) {
137
- strcpy(out->cur, out->opts->dump_opts.indent_str);
138
- out->cur += out->opts->dump_opts.indent_size;
139
- }
140
- }
141
- } else {
142
- fill_indent(out, depth);
143
- }
144
- *out->cur++ = ']';
145
- }
146
- *out->cur = '\0';
147
- }
148
-
149
- static int
150
- hash_cb(VALUE key, VALUE value, Out out) {
151
- int depth = out->depth;
152
- long size;
153
- int rtype = rb_type(key);
154
-
155
- if (rtype != T_STRING && rtype != T_SYMBOL) {
156
- key = rb_funcall(key, oj_to_s_id, 0);
157
- rtype = rb_type(key);
158
- }
159
- if (!out->opts->dump_opts.use) {
160
- size = depth * out->indent + 1;
161
- assure_size(out, size);
162
- fill_indent(out, depth);
163
- if (rtype == T_STRING) {
164
- oj_dump_str(key, 0, out, false);
165
- } else {
166
- oj_dump_sym(key, 0, out, false);
167
- }
168
- *out->cur++ = ':';
169
- } else {
170
- size = depth * out->opts->dump_opts.indent_size + out->opts->dump_opts.hash_size + 1;
171
- assure_size(out, size);
172
- if (0 < out->opts->dump_opts.hash_size) {
173
- strcpy(out->cur, out->opts->dump_opts.hash_nl);
174
- out->cur += out->opts->dump_opts.hash_size;
175
- }
176
- if (0 < out->opts->dump_opts.indent_size) {
177
- int i;
178
- for (i = depth; 0 < i; i--) {
179
- strcpy(out->cur, out->opts->dump_opts.indent_str);
180
- out->cur += out->opts->dump_opts.indent_size;
181
- }
182
- }
183
- if (rtype == T_STRING) {
184
- oj_dump_str(key, 0, out, false);
185
- } else {
186
- oj_dump_sym(key, 0, out, false);
187
- }
188
- size = out->opts->dump_opts.before_size + out->opts->dump_opts.after_size + 2;
189
- assure_size(out, size);
190
- if (0 < out->opts->dump_opts.before_size) {
191
- strcpy(out->cur, out->opts->dump_opts.before_sep);
192
- out->cur += out->opts->dump_opts.before_size;
193
- }
194
- *out->cur++ = ':';
195
- if (0 < out->opts->dump_opts.after_size) {
196
- strcpy(out->cur, out->opts->dump_opts.after_sep);
197
- out->cur += out->opts->dump_opts.after_size;
198
- }
199
- }
200
- oj_dump_rails_val(value, depth, out, false);
201
- out->depth = depth;
202
- *out->cur++ = ',';
203
-
204
- return ST_CONTINUE;
205
- }
206
-
207
- static void
208
- dump_hash(VALUE obj, int depth, Out out, bool as_ok) {
209
- int cnt;
210
- size_t size;
211
-
212
- if (Yes == out->opts->circular) {
213
- if (0 > oj_check_circular(obj, out)) {
214
- oj_dump_nil(Qnil, 0, out, false);
215
- return;
216
- }
217
- }
218
- if (as_ok && !oj_rails_hash_opt && rb_respond_to(obj, oj_as_json_id)) {
219
- dump_as_json(obj, depth, out, false);
220
- return;
221
- }
222
- cnt = (int)RHASH_SIZE(obj);
223
- size = depth * out->indent + 2;
224
- assure_size(out, 2);
225
- *out->cur++ = '{';
226
- if (0 == cnt) {
227
- *out->cur++ = '}';
228
- } else {
229
- out->depth = depth + 1;
230
- rb_hash_foreach(obj, hash_cb, (VALUE)out);
231
- if (',' == *(out->cur - 1)) {
232
- out->cur--; // backup to overwrite last comma
233
- }
234
- if (!out->opts->dump_opts.use) {
235
- assure_size(out, size);
236
- fill_indent(out, depth);
237
- } else {
238
- size = depth * out->opts->dump_opts.indent_size + out->opts->dump_opts.hash_size + 1;
239
- assure_size(out, size);
240
- if (0 < out->opts->dump_opts.hash_size) {
241
- strcpy(out->cur, out->opts->dump_opts.hash_nl);
242
- out->cur += out->opts->dump_opts.hash_size;
243
- }
244
- if (0 < out->opts->dump_opts.indent_size) {
245
- int i;
246
-
247
- for (i = depth; 0 < i; i--) {
248
- strcpy(out->cur, out->opts->dump_opts.indent_str);
249
- out->cur += out->opts->dump_opts.indent_size;
250
- }
251
- }
252
- }
253
- *out->cur++ = '}';
254
- }
255
- *out->cur = '\0';
256
- }
257
-
258
- static void
259
- dump_obj(VALUE obj, int depth, Out out, bool as_ok) {
260
- if (as_ok) {
261
- ROpt ro;
262
-
263
- if (NULL != (ro = oj_rails_get_opt(out->ropts, rb_obj_class(obj))) && ro->on) {
264
- ro->dump(obj, depth, out, as_ok);
265
- } else if (rb_respond_to(obj, oj_as_json_id)) {
266
- dump_as_json(obj, depth, out, true);
267
- } else if (rb_respond_to(obj, oj_to_hash_id)) {
268
- dump_to_hash(obj, depth, out);
269
- } else {
270
- oj_dump_obj_to_s(obj, out);
271
- }
272
- } else if (rb_respond_to(obj, oj_to_hash_id)) {
273
- // Always attempt to_hash.
274
- dump_to_hash(obj, depth, out);
275
- } else {
276
- oj_dump_obj_to_s(obj, out);
277
- }
278
- }
279
-
280
- static void
281
- dump_as_string(VALUE obj, int depth, Out out, bool as_ok) {
282
- oj_dump_obj_to_s(obj, out);
283
- }
284
-
285
- static DumpFunc rails_funcs[] = {
286
- NULL, // RUBY_T_NONE = 0x00,
287
- dump_obj, // RUBY_T_OBJECT = 0x01,
288
- oj_dump_class, // RUBY_T_CLASS = 0x02,
289
- oj_dump_class, // RUBY_T_MODULE = 0x03,
290
- dump_float, // RUBY_T_FLOAT = 0x04,
291
- oj_dump_str, // RUBY_T_STRING = 0x05,
292
- dump_as_string, // RUBY_T_REGEXP = 0x06,
293
- dump_array, // RUBY_T_ARRAY = 0x07,
294
- dump_hash, // RUBY_T_HASH = 0x08,
295
- dump_obj, // RUBY_T_STRUCT = 0x09,
296
- oj_dump_bignum, // RUBY_T_BIGNUM = 0x0a,
297
- NULL, // RUBY_T_FILE = 0x0b,
298
- dump_obj, // RUBY_T_DATA = 0x0c,
299
- NULL, // RUBY_T_MATCH = 0x0d,
300
- // Rails raises a stack error on Complex and Rational. It also corrupts
301
- // something whic causes a segfault on the next call. Oj will not mimic
302
- // that behavior.
303
- dump_as_string, // RUBY_T_COMPLEX = 0x0e,
304
- dump_as_string, // RUBY_T_RATIONAL = 0x0f,
305
- NULL, // 0x10
306
- oj_dump_nil, // RUBY_T_NIL = 0x11,
307
- oj_dump_true, // RUBY_T_TRUE = 0x12,
308
- oj_dump_false, // RUBY_T_FALSE = 0x13,
309
- oj_dump_sym, // RUBY_T_SYMBOL = 0x14,
310
- oj_dump_fixnum, // RUBY_T_FIXNUM = 0x15,
311
- };
312
-
313
- void
314
- oj_dump_rails_val(VALUE obj, int depth, Out out, bool as_ok) {
315
- int type = rb_type(obj);
316
-
317
- if (MAX_DEPTH < depth) {
318
- rb_raise(rb_eNoMemError, "Too deeply nested.\n");
319
- }
320
- if (0 < type && type <= RUBY_T_FIXNUM) {
321
- DumpFunc f = rails_funcs[type];
322
-
323
- if (NULL != f) {
324
- f(obj, depth, out, as_ok);
325
- return;
326
- }
327
- }
328
- oj_dump_nil(Qnil, depth, out, false);
329
- }