oj 3.13.17 → 3.16.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 (156) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +77 -0
  3. data/README.md +4 -2
  4. data/ext/oj/buf.h +7 -6
  5. data/ext/oj/cache.c +29 -26
  6. data/ext/oj/cache.h +3 -2
  7. data/ext/oj/cache8.c +10 -9
  8. data/ext/oj/circarray.c +7 -5
  9. data/ext/oj/circarray.h +2 -2
  10. data/ext/oj/code.c +5 -12
  11. data/ext/oj/code.h +2 -2
  12. data/ext/oj/compat.c +20 -60
  13. data/ext/oj/custom.c +44 -96
  14. data/ext/oj/debug.c +3 -9
  15. data/ext/oj/dump.c +69 -39
  16. data/ext/oj/dump.h +1 -4
  17. data/ext/oj/dump_compat.c +557 -592
  18. data/ext/oj/dump_leaf.c +3 -5
  19. data/ext/oj/dump_object.c +42 -48
  20. data/ext/oj/dump_strict.c +10 -22
  21. data/ext/oj/encoder.c +1 -1
  22. data/ext/oj/err.c +2 -13
  23. data/ext/oj/err.h +9 -12
  24. data/ext/oj/extconf.rb +16 -6
  25. data/ext/oj/fast.c +76 -106
  26. data/ext/oj/intern.c +63 -51
  27. data/ext/oj/intern.h +3 -7
  28. data/ext/oj/mem.c +318 -0
  29. data/ext/oj/mem.h +53 -0
  30. data/ext/oj/mimic_json.c +43 -30
  31. data/ext/oj/object.c +61 -70
  32. data/ext/oj/odd.c +8 -6
  33. data/ext/oj/odd.h +4 -4
  34. data/ext/oj/oj.c +243 -205
  35. data/ext/oj/oj.h +82 -78
  36. data/ext/oj/parse.c +123 -188
  37. data/ext/oj/parse.h +23 -24
  38. data/ext/oj/parser.c +103 -63
  39. data/ext/oj/parser.h +19 -9
  40. data/ext/oj/rails.c +68 -92
  41. data/ext/oj/reader.c +10 -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 +10 -9
  47. data/ext/oj/saj2.c +74 -92
  48. data/ext/oj/saj2.h +23 -0
  49. data/ext/oj/scp.c +3 -14
  50. data/ext/oj/sparse.c +22 -70
  51. data/ext/oj/stream_writer.c +43 -35
  52. data/ext/oj/strict.c +20 -52
  53. data/ext/oj/string_writer.c +60 -34
  54. data/ext/oj/trace.h +31 -4
  55. data/ext/oj/usual.c +125 -150
  56. data/ext/oj/usual.h +69 -0
  57. data/ext/oj/util.h +1 -1
  58. data/ext/oj/val_stack.c +14 -3
  59. data/ext/oj/val_stack.h +8 -7
  60. data/ext/oj/wab.c +25 -57
  61. data/lib/oj/active_support_helper.rb +1 -3
  62. data/lib/oj/bag.rb +7 -1
  63. data/lib/oj/easy_hash.rb +4 -5
  64. data/lib/oj/error.rb +0 -1
  65. data/lib/oj/json.rb +162 -150
  66. data/lib/oj/mimic.rb +6 -2
  67. data/lib/oj/state.rb +9 -6
  68. data/lib/oj/version.rb +1 -2
  69. data/lib/oj.rb +2 -0
  70. data/pages/Compatibility.md +1 -1
  71. data/pages/InstallOptions.md +20 -0
  72. data/pages/Options.md +10 -0
  73. data/test/_test_active.rb +8 -9
  74. data/test/_test_active_mimic.rb +7 -8
  75. data/test/_test_mimic_rails.rb +17 -20
  76. data/test/activerecord/result_test.rb +5 -6
  77. data/test/files.rb +15 -15
  78. data/test/foo.rb +9 -72
  79. data/test/helper.rb +11 -8
  80. data/test/isolated/shared.rb +3 -2
  81. data/test/json_gem/json_addition_test.rb +2 -2
  82. data/test/json_gem/json_common_interface_test.rb +8 -6
  83. data/test/json_gem/json_encoding_test.rb +0 -0
  84. data/test/json_gem/json_ext_parser_test.rb +1 -0
  85. data/test/json_gem/json_fixtures_test.rb +3 -2
  86. data/test/json_gem/json_generator_test.rb +53 -37
  87. data/test/json_gem/json_generic_object_test.rb +11 -11
  88. data/test/json_gem/json_parser_test.rb +47 -47
  89. data/test/json_gem/json_string_matching_test.rb +9 -9
  90. data/test/json_gem/test_helper.rb +7 -3
  91. data/test/mem.rb +13 -12
  92. data/test/perf.rb +21 -26
  93. data/test/perf_compat.rb +31 -33
  94. data/test/perf_dump.rb +28 -28
  95. data/test/perf_fast.rb +80 -82
  96. data/test/perf_file.rb +27 -29
  97. data/test/perf_object.rb +65 -69
  98. data/test/perf_once.rb +12 -11
  99. data/test/perf_parser.rb +42 -48
  100. data/test/perf_saj.rb +46 -54
  101. data/test/perf_scp.rb +57 -69
  102. data/test/perf_simple.rb +41 -39
  103. data/test/perf_strict.rb +68 -70
  104. data/test/perf_wab.rb +67 -69
  105. data/test/prec.rb +5 -5
  106. data/test/sample/change.rb +0 -1
  107. data/test/sample/dir.rb +0 -1
  108. data/test/sample/doc.rb +0 -1
  109. data/test/sample/file.rb +0 -1
  110. data/test/sample/group.rb +0 -1
  111. data/test/sample/hasprops.rb +0 -1
  112. data/test/sample/layer.rb +0 -1
  113. data/test/sample/rect.rb +0 -1
  114. data/test/sample/shape.rb +0 -1
  115. data/test/sample/text.rb +0 -1
  116. data/test/sample.rb +16 -16
  117. data/test/sample_json.rb +8 -8
  118. data/test/test_compat.rb +80 -53
  119. data/test/test_custom.rb +73 -51
  120. data/test/test_debian.rb +7 -10
  121. data/test/test_fast.rb +86 -90
  122. data/test/test_file.rb +28 -35
  123. data/test/test_gc.rb +16 -5
  124. data/test/test_generate.rb +5 -5
  125. data/test/test_hash.rb +4 -4
  126. data/test/test_integer_range.rb +9 -9
  127. data/test/test_null.rb +20 -20
  128. data/test/test_object.rb +94 -96
  129. data/test/test_parser.rb +6 -22
  130. data/test/test_parser_debug.rb +27 -0
  131. data/test/test_parser_saj.rb +61 -22
  132. data/test/test_parser_usual.rb +16 -6
  133. data/test/test_rails.rb +2 -2
  134. data/test/test_saj.rb +10 -8
  135. data/test/test_scp.rb +37 -39
  136. data/test/test_strict.rb +40 -32
  137. data/test/test_various.rb +148 -100
  138. data/test/test_wab.rb +48 -44
  139. data/test/test_writer.rb +47 -47
  140. data/test/tests.rb +13 -4
  141. data/test/tests_mimic.rb +12 -3
  142. data/test/tests_mimic_addition.rb +12 -3
  143. metadata +36 -27
  144. data/test/activesupport4/decoding_test.rb +0 -108
  145. data/test/activesupport4/encoding_test.rb +0 -531
  146. data/test/activesupport4/test_helper.rb +0 -41
  147. data/test/activesupport5/abstract_unit.rb +0 -45
  148. data/test/activesupport5/decoding_test.rb +0 -133
  149. data/test/activesupport5/encoding_test.rb +0 -500
  150. data/test/activesupport5/encoding_test_cases.rb +0 -98
  151. data/test/activesupport5/test_helper.rb +0 -72
  152. data/test/activesupport5/time_zone_test_helpers.rb +0 -39
  153. data/test/bar.rb +0 -11
  154. data/test/baz.rb +0 -16
  155. data/test/bug.rb +0 -16
  156. data/test/zoo.rb +0 -13
data/ext/oj/dump.c CHANGED
@@ -15,6 +15,7 @@
15
15
  #endif
16
16
 
17
17
  #include "cache8.h"
18
+ #include "mem.h"
18
19
  #include "odd.h"
19
20
  #include "oj.h"
20
21
  #include "trace.h"
@@ -305,8 +306,8 @@ static const char *dump_unicode(const char *str, const char *end, Out out, const
305
306
  uint32_t c1;
306
307
 
307
308
  code -= 0x00010000;
308
- c1 = ((code >> 10) & 0x000003FF) + 0x0000D800;
309
- code = (code & 0x000003FF) + 0x0000DC00;
309
+ c1 = ((code >> 10) & 0x000003FF) + 0x0000D800;
310
+ code = (code & 0x000003FF) + 0x0000DC00;
310
311
  APPEND_CHARS(out->cur, "\\u", 2);
311
312
  for (i = 3; 0 <= i; i--) {
312
313
  *out->cur++ = hex_chars[(uint8_t)(c1 >> (i * 4)) & 0x0F];
@@ -463,7 +464,7 @@ void oj_dump_time(VALUE obj, Out out, int withZone) {
463
464
  }
464
465
 
465
466
  void oj_dump_ruby_time(VALUE obj, Out out) {
466
- volatile VALUE rstr = rb_funcall(obj, oj_to_s_id, 0);
467
+ volatile VALUE rstr = oj_safe_string_convert(obj);
467
468
 
468
469
  oj_dump_cstr(RSTRING_PTR(rstr), (int)RSTRING_LEN(rstr), 0, 0, out);
469
470
  }
@@ -609,7 +610,7 @@ void oj_write_obj_to_file(VALUE obj, const char *path, Options copts) {
609
610
 
610
611
  oj_out_init(&out);
611
612
 
612
- out.omit_nil = copts->dump_opts.omit_nil;
613
+ out.omit_nil = copts->dump_opts.omit_nil;
613
614
  oj_dump_obj_to_json(obj, copts, &out);
614
615
  size = out.cur - out.buf;
615
616
  if (0 == (f = fopen(path, "w"))) {
@@ -657,7 +658,7 @@ void oj_write_obj_to_stream(VALUE obj, VALUE stream, Options copts) {
657
658
 
658
659
  oj_out_init(&out);
659
660
 
660
- out.omit_nil = copts->dump_opts.omit_nil;
661
+ out.omit_nil = copts->dump_opts.omit_nil;
661
662
  oj_dump_obj_to_json(obj, copts, &out);
662
663
  size = out.cur - out.buf;
663
664
  if (oj_stringio_class == clas) {
@@ -697,7 +698,7 @@ void oj_dump_str(VALUE obj, int depth, Out out, bool as_ok) {
697
698
 
698
699
  if (oj_utf8_encoding_index != idx) {
699
700
  rb_encoding *enc = rb_enc_from_index(idx);
700
- obj = rb_str_conv_enc(obj, enc, oj_utf8_encoding);
701
+ obj = rb_str_conv_enc(obj, enc, oj_utf8_encoding);
701
702
  }
702
703
  oj_dump_cstr(RSTRING_PTR(obj), (int)RSTRING_LEN(obj), 0, 0, out);
703
704
  }
@@ -726,8 +727,11 @@ static void debug_raise(const char *orig, size_t cnt, int line) {
726
727
 
727
728
  void oj_dump_raw_json(VALUE obj, int depth, Out out) {
728
729
  if (oj_string_writer_class == rb_obj_class(obj)) {
729
- StrWriter sw = (StrWriter)DATA_PTR(obj);
730
- size_t len = sw->out.cur - sw->out.buf;
730
+ StrWriter sw;
731
+ size_t len;
732
+
733
+ sw = oj_str_writer_unwrap(obj);
734
+ len = sw->out.cur - sw->out.buf;
731
735
 
732
736
  if (0 < len) {
733
737
  len--;
@@ -736,13 +740,9 @@ void oj_dump_raw_json(VALUE obj, int depth, Out out) {
736
740
  } else {
737
741
  volatile VALUE jv;
738
742
 
739
- if (Yes == out->opts->trace) {
740
- oj_trace("raw_json", obj, __FILE__, __LINE__, depth + 1, TraceRubyIn);
741
- }
743
+ TRACE(out->opts->trace, "raw_json", obj, depth + 1, TraceRubyIn);
742
744
  jv = rb_funcall(obj, oj_raw_json_id, 2, RB_INT2NUM(depth), RB_INT2NUM(out->indent));
743
- if (Yes == out->opts->trace) {
744
- oj_trace("raw_json", obj, __FILE__, __LINE__, depth + 1, TraceRubyOut);
745
- }
745
+ TRACE(out->opts->trace, "raw_json", obj, depth + 1, TraceRubyOut);
746
746
  oj_dump_raw(RSTRING_PTR(jv), (size_t)RSTRING_LEN(jv), out);
747
747
  }
748
748
  }
@@ -764,8 +764,8 @@ void oj_dump_cstr(const char *str, size_t cnt, bool is_sym, bool escape1, Out ou
764
764
  break;
765
765
  case SlashEsc:
766
766
  has_hi = true;
767
- cmap = slash_friendly_chars;
768
- size = slash_friendly_size((uint8_t *)str, cnt);
767
+ cmap = slash_friendly_chars;
768
+ size = slash_friendly_size((uint8_t *)str, cnt);
769
769
  break;
770
770
  case XSSEsc:
771
771
  cmap = xss_friendly_chars;
@@ -860,6 +860,9 @@ void oj_dump_cstr(const char *str, size_t cnt, bool is_sym, bool escape1, Out ou
860
860
  break;
861
861
  case '6': // control characters
862
862
  if (*(uint8_t *)str < 0x80) {
863
+ if (0 == (uint8_t)*str && out->opts->dump_opts.omit_null_byte) {
864
+ break;
865
+ }
863
866
  APPEND_CHARS(out->cur, "\\u00", 4);
864
867
  dump_hex((uint8_t)*str, out);
865
868
  } else {
@@ -932,7 +935,7 @@ void oj_dump_class(VALUE obj, int depth, Out out, bool as_ok) {
932
935
  }
933
936
 
934
937
  void oj_dump_obj_to_s(VALUE obj, Out out) {
935
- volatile VALUE rstr = rb_funcall(obj, oj_to_s_id, 0);
938
+ volatile VALUE rstr = oj_safe_string_convert(obj);
936
939
 
937
940
  oj_dump_cstr(RSTRING_PTR(rstr), (int)RSTRING_LEN(rstr), 0, 0, out);
938
941
  }
@@ -944,15 +947,15 @@ void oj_dump_raw(const char *str, size_t cnt, Out out) {
944
947
  }
945
948
 
946
949
  void oj_out_init(Out out) {
947
- out->buf = out->stack_buffer;
948
- out->cur = out->buf;
949
- out->end = out->buf + sizeof(out->stack_buffer) - BUFFER_EXTRA;
950
+ out->buf = out->stack_buffer;
951
+ out->cur = out->buf;
952
+ out->end = out->buf + sizeof(out->stack_buffer) - BUFFER_EXTRA;
950
953
  out->allocated = false;
951
954
  }
952
955
 
953
956
  void oj_out_free(Out out) {
954
957
  if (out->allocated) {
955
- xfree(out->buf); // TBD
958
+ OJ_R_FREE(out->buf); // TBD
956
959
  }
957
960
  }
958
961
 
@@ -966,9 +969,9 @@ void oj_grow_out(Out out, size_t len) {
966
969
  size += len;
967
970
  }
968
971
  if (out->allocated) {
969
- REALLOC_N(buf, char, (size + BUFFER_EXTRA));
972
+ OJ_R_REALLOC_N(buf, char, (size + BUFFER_EXTRA));
970
973
  } else {
971
- buf = ALLOC_N(char, (size + BUFFER_EXTRA));
974
+ buf = OJ_R_ALLOC_N(char, (size + BUFFER_EXTRA));
972
975
  out->allocated = true;
973
976
  memcpy(buf, out->buf, out->end - out->buf + BUFFER_EXTRA);
974
977
  }
@@ -983,26 +986,60 @@ void oj_grow_out(Out out, size_t len) {
983
986
  void oj_dump_nil(VALUE obj, int depth, Out out, bool as_ok) {
984
987
  assure_size(out, 4);
985
988
  APPEND_CHARS(out->cur, "null", 4);
986
- *out->cur = '\0';
989
+ *out->cur = '\0';
987
990
  }
988
991
 
989
992
  void oj_dump_true(VALUE obj, int depth, Out out, bool as_ok) {
990
993
  assure_size(out, 4);
991
994
  APPEND_CHARS(out->cur, "true", 4);
992
- *out->cur = '\0';
995
+ *out->cur = '\0';
993
996
  }
994
997
 
995
998
  void oj_dump_false(VALUE obj, int depth, Out out, bool as_ok) {
996
999
  assure_size(out, 5);
997
1000
  APPEND_CHARS(out->cur, "false", 5);
998
- *out->cur = '\0';
1001
+ *out->cur = '\0';
1002
+ }
1003
+
1004
+ static const char digits_table[] = "\
1005
+ 00010203040506070809\
1006
+ 10111213141516171819\
1007
+ 20212223242526272829\
1008
+ 30313233343536373839\
1009
+ 40414243444546474849\
1010
+ 50515253545556575859\
1011
+ 60616263646566676869\
1012
+ 70717273747576777879\
1013
+ 80818283848586878889\
1014
+ 90919293949596979899";
1015
+
1016
+ char *oj_longlong_to_string(long long num, bool negative, char *buf) {
1017
+ while (100 <= num) {
1018
+ unsigned idx = num % 100 * 2;
1019
+ *buf-- = digits_table[idx + 1];
1020
+ *buf-- = digits_table[idx];
1021
+ num /= 100;
1022
+ }
1023
+ if (num < 10) {
1024
+ *buf-- = num + '0';
1025
+ } else {
1026
+ *buf-- = digits_table[num * 2 + 1];
1027
+ *buf-- = digits_table[num * 2];
1028
+ }
1029
+
1030
+ if (negative) {
1031
+ *buf = '-';
1032
+ } else {
1033
+ buf++;
1034
+ }
1035
+ return buf;
999
1036
  }
1000
1037
 
1001
1038
  void oj_dump_fixnum(VALUE obj, int depth, Out out, bool as_ok) {
1002
1039
  char buf[32];
1003
- char * b = buf + sizeof(buf) - 1;
1040
+ char *b = buf + sizeof(buf) - 1;
1004
1041
  long long num = NUM2LL(obj);
1005
- int neg = 0;
1042
+ bool neg = false;
1006
1043
  size_t cnt = 0;
1007
1044
  bool dump_as_string = false;
1008
1045
 
@@ -1011,7 +1048,7 @@ void oj_dump_fixnum(VALUE obj, int depth, Out out, bool as_ok) {
1011
1048
  dump_as_string = true;
1012
1049
  }
1013
1050
  if (0 > num) {
1014
- neg = 1;
1051
+ neg = true;
1015
1052
  num = -num;
1016
1053
  }
1017
1054
  *b-- = '\0';
@@ -1020,14 +1057,7 @@ void oj_dump_fixnum(VALUE obj, int depth, Out out, bool as_ok) {
1020
1057
  *b-- = '"';
1021
1058
  }
1022
1059
  if (0 < num) {
1023
- for (; 0 < num; num /= 10, b--) {
1024
- *b = (num % 10) + '0';
1025
- }
1026
- if (neg) {
1027
- *b = '-';
1028
- } else {
1029
- b++;
1030
- }
1060
+ b = oj_longlong_to_string(num, neg, b);
1031
1061
  } else {
1032
1062
  *b = '0';
1033
1063
  }
@@ -1173,7 +1203,7 @@ void oj_dump_float(VALUE obj, int depth, Out out, bool as_ok) {
1173
1203
  } else if (d == (double)(long long int)d) {
1174
1204
  cnt = snprintf(buf, sizeof(buf), "%.1f", d);
1175
1205
  } else if (0 == out->opts->float_prec) {
1176
- volatile VALUE rstr = rb_funcall(obj, oj_to_s_id, 0);
1206
+ volatile VALUE rstr = oj_safe_string_convert(obj);
1177
1207
 
1178
1208
  cnt = (int)RSTRING_LEN(rstr);
1179
1209
  if ((int)sizeof(buf) <= cnt) {
@@ -1195,7 +1225,7 @@ int oj_dump_float_printf(char *buf, size_t blen, VALUE obj, double d, const char
1195
1225
  // Round off issues at 16 significant digits so check for obvious ones of
1196
1226
  // 0001 and 9999.
1197
1227
  if (17 <= cnt && (0 == strcmp("0001", buf + cnt - 4) || 0 == strcmp("9999", buf + cnt - 4))) {
1198
- volatile VALUE rstr = rb_funcall(obj, oj_to_s_id, 0);
1228
+ volatile VALUE rstr = oj_safe_string_convert(obj);
1199
1229
 
1200
1230
  strcpy(buf, RSTRING_PTR(rstr));
1201
1231
  cnt = (int)RSTRING_LEN(rstr);
data/ext/oj/dump.h CHANGED
@@ -93,10 +93,7 @@ inline static void dump_ulong(unsigned long num, Out out) {
93
93
 
94
94
  *b-- = '\0';
95
95
  if (0 < num) {
96
- for (; 0 < num; num /= 10, b--) {
97
- *b = (num % 10) + '0';
98
- }
99
- b++;
96
+ b = oj_longlong_to_string((long long)num, false, b);
100
97
  } else {
101
98
  *b = '0';
102
99
  }