oj 3.11.0 → 3.16.5

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 (173) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1421 -0
  3. data/README.md +20 -5
  4. data/RELEASE_NOTES.md +61 -0
  5. data/ext/oj/buf.h +48 -38
  6. data/ext/oj/cache.c +329 -0
  7. data/ext/oj/cache.h +22 -0
  8. data/ext/oj/cache8.c +60 -62
  9. data/ext/oj/cache8.h +8 -7
  10. data/ext/oj/circarray.c +35 -35
  11. data/ext/oj/circarray.h +11 -9
  12. data/ext/oj/code.c +156 -174
  13. data/ext/oj/code.h +19 -18
  14. data/ext/oj/compat.c +140 -197
  15. data/ext/oj/custom.c +737 -879
  16. data/ext/oj/debug.c +126 -0
  17. data/ext/oj/dump.c +830 -835
  18. data/ext/oj/dump.h +65 -53
  19. data/ext/oj/dump_compat.c +566 -642
  20. data/ext/oj/dump_leaf.c +95 -182
  21. data/ext/oj/dump_object.c +518 -659
  22. data/ext/oj/dump_strict.c +301 -334
  23. data/ext/oj/encode.h +3 -4
  24. data/ext/oj/encoder.c +43 -0
  25. data/ext/oj/err.c +27 -24
  26. data/ext/oj/err.h +38 -13
  27. data/ext/oj/extconf.rb +23 -7
  28. data/ext/oj/fast.c +1043 -1073
  29. data/ext/oj/intern.c +313 -0
  30. data/ext/oj/intern.h +22 -0
  31. data/ext/oj/mem.c +318 -0
  32. data/ext/oj/mem.h +53 -0
  33. data/ext/oj/mimic_json.c +449 -423
  34. data/ext/oj/object.c +530 -576
  35. data/ext/oj/odd.c +155 -138
  36. data/ext/oj/odd.h +24 -22
  37. data/ext/oj/oj.c +1331 -993
  38. data/ext/oj/oj.h +306 -292
  39. data/ext/oj/parse.c +934 -938
  40. data/ext/oj/parse.h +73 -70
  41. data/ext/oj/parser.c +1600 -0
  42. data/ext/oj/parser.h +101 -0
  43. data/ext/oj/rails.c +795 -845
  44. data/ext/oj/rails.h +7 -7
  45. data/ext/oj/reader.c +132 -140
  46. data/ext/oj/reader.h +67 -78
  47. data/ext/oj/resolve.c +40 -59
  48. data/ext/oj/resolve.h +3 -2
  49. data/ext/oj/rxclass.c +67 -67
  50. data/ext/oj/rxclass.h +11 -9
  51. data/ext/oj/saj.c +441 -480
  52. data/ext/oj/saj2.c +584 -0
  53. data/ext/oj/saj2.h +23 -0
  54. data/ext/oj/scp.c +78 -111
  55. data/ext/oj/sparse.c +726 -730
  56. data/ext/oj/stream_writer.c +146 -165
  57. data/ext/oj/strict.c +103 -123
  58. data/ext/oj/string_writer.c +241 -253
  59. data/ext/oj/trace.c +29 -33
  60. data/ext/oj/trace.h +41 -11
  61. data/ext/oj/usual.c +1218 -0
  62. data/ext/oj/usual.h +69 -0
  63. data/ext/oj/util.c +103 -103
  64. data/ext/oj/util.h +3 -2
  65. data/ext/oj/val_stack.c +60 -49
  66. data/ext/oj/val_stack.h +79 -85
  67. data/ext/oj/validate.c +46 -0
  68. data/ext/oj/wab.c +307 -350
  69. data/lib/oj/active_support_helper.rb +1 -3
  70. data/lib/oj/bag.rb +8 -1
  71. data/lib/oj/easy_hash.rb +9 -9
  72. data/lib/oj/error.rb +1 -2
  73. data/lib/oj/json.rb +162 -150
  74. data/lib/oj/mimic.rb +9 -19
  75. data/lib/oj/saj.rb +20 -6
  76. data/lib/oj/schandler.rb +5 -4
  77. data/lib/oj/state.rb +12 -8
  78. data/lib/oj/version.rb +1 -2
  79. data/lib/oj.rb +2 -0
  80. data/pages/Compatibility.md +1 -1
  81. data/pages/InstallOptions.md +20 -0
  82. data/pages/JsonGem.md +15 -0
  83. data/pages/Modes.md +8 -3
  84. data/pages/Options.md +43 -5
  85. data/pages/Parser.md +309 -0
  86. data/pages/Rails.md +14 -2
  87. data/test/_test_active.rb +8 -9
  88. data/test/_test_active_mimic.rb +7 -8
  89. data/test/_test_mimic_rails.rb +17 -20
  90. data/test/activerecord/result_test.rb +12 -8
  91. data/test/activesupport6/encoding_test.rb +63 -28
  92. data/test/{activesupport5 → activesupport7}/abstract_unit.rb +16 -12
  93. data/test/{activesupport5 → activesupport7}/decoding_test.rb +2 -10
  94. data/test/{activesupport5 → activesupport7}/encoding_test.rb +86 -50
  95. data/test/{activesupport5 → activesupport7}/encoding_test_cases.rb +6 -0
  96. data/test/{activesupport5 → activesupport7}/time_zone_test_helpers.rb +8 -0
  97. data/test/files.rb +15 -15
  98. data/test/foo.rb +17 -43
  99. data/test/helper.rb +16 -3
  100. data/test/isolated/shared.rb +3 -2
  101. data/test/json_gem/json_addition_test.rb +2 -2
  102. data/test/json_gem/json_common_interface_test.rb +8 -6
  103. data/test/json_gem/json_encoding_test.rb +0 -0
  104. data/test/json_gem/json_ext_parser_test.rb +1 -0
  105. data/test/json_gem/json_fixtures_test.rb +3 -2
  106. data/test/json_gem/json_generator_test.rb +71 -41
  107. data/test/json_gem/json_generic_object_test.rb +11 -11
  108. data/test/json_gem/json_parser_test.rb +54 -47
  109. data/test/json_gem/json_string_matching_test.rb +9 -9
  110. data/test/json_gem/test_helper.rb +12 -0
  111. data/test/mem.rb +34 -0
  112. data/test/perf.rb +22 -27
  113. data/test/perf_compat.rb +31 -33
  114. data/test/perf_dump.rb +50 -0
  115. data/test/perf_fast.rb +80 -82
  116. data/test/perf_file.rb +27 -29
  117. data/test/perf_object.rb +65 -69
  118. data/test/perf_once.rb +59 -0
  119. data/test/perf_parser.rb +183 -0
  120. data/test/perf_saj.rb +46 -54
  121. data/test/perf_scp.rb +58 -69
  122. data/test/perf_simple.rb +41 -39
  123. data/test/perf_strict.rb +74 -82
  124. data/test/perf_wab.rb +67 -69
  125. data/test/prec.rb +5 -5
  126. data/test/sample/change.rb +0 -1
  127. data/test/sample/dir.rb +0 -1
  128. data/test/sample/doc.rb +0 -1
  129. data/test/sample/file.rb +0 -1
  130. data/test/sample/group.rb +0 -1
  131. data/test/sample/hasprops.rb +0 -1
  132. data/test/sample/layer.rb +0 -1
  133. data/test/sample/rect.rb +0 -1
  134. data/test/sample/shape.rb +0 -1
  135. data/test/sample/text.rb +0 -1
  136. data/test/sample.rb +16 -16
  137. data/test/sample_json.rb +8 -8
  138. data/test/test_compat.rb +97 -45
  139. data/test/test_custom.rb +73 -51
  140. data/test/test_debian.rb +7 -10
  141. data/test/test_fast.rb +135 -79
  142. data/test/test_file.rb +41 -30
  143. data/test/test_gc.rb +16 -5
  144. data/test/test_generate.rb +21 -0
  145. data/test/test_hash.rb +15 -5
  146. data/test/test_integer_range.rb +9 -9
  147. data/test/test_null.rb +20 -20
  148. data/test/test_object.rb +99 -96
  149. data/test/test_parser.rb +11 -0
  150. data/test/test_parser_debug.rb +27 -0
  151. data/test/test_parser_saj.rb +337 -0
  152. data/test/test_parser_usual.rb +251 -0
  153. data/test/test_rails.rb +2 -2
  154. data/test/test_saj.rb +10 -8
  155. data/test/test_scp.rb +38 -40
  156. data/test/test_strict.rb +40 -32
  157. data/test/test_various.rb +165 -84
  158. data/test/test_wab.rb +48 -44
  159. data/test/test_writer.rb +47 -47
  160. data/test/tests.rb +13 -5
  161. data/test/tests_mimic.rb +12 -3
  162. data/test/tests_mimic_addition.rb +12 -3
  163. metadata +75 -127
  164. data/ext/oj/hash.c +0 -135
  165. data/ext/oj/hash.h +0 -18
  166. data/ext/oj/hash_test.c +0 -484
  167. data/test/activesupport4/decoding_test.rb +0 -108
  168. data/test/activesupport4/encoding_test.rb +0 -531
  169. data/test/activesupport4/test_helper.rb +0 -41
  170. data/test/activesupport5/test_helper.rb +0 -72
  171. data/test/bar.rb +0 -35
  172. data/test/baz.rb +0 -16
  173. data/test/zoo.rb +0 -13
data/ext/oj/strict.c CHANGED
@@ -1,207 +1,187 @@
1
1
  // Copyright (c) 2012 Peter Ohler. All rights reserved.
2
+ // Licensed under the MIT License. See LICENSE file in the project root for license details.
2
3
 
3
- #include <stdlib.h>
4
4
  #include <stdio.h>
5
+ #include <stdlib.h>
5
6
  #include <string.h>
6
7
  #include <unistd.h>
7
8
 
8
- #include "oj.h"
9
+ #include "encode.h"
9
10
  #include "err.h"
11
+ #include "intern.h"
12
+ #include "oj.h"
10
13
  #include "parse.h"
11
- #include "encode.h"
12
14
  #include "trace.h"
13
15
 
14
- static void
15
- hash_end(ParseInfo pi) {
16
- if (Yes == pi->options.trace) {
17
- oj_trace_parse_hash_end(pi, __FILE__, __LINE__);
16
+ VALUE oj_cstr_to_value(const char *str, size_t len, size_t cache_str) {
17
+ volatile VALUE rstr = Qnil;
18
+
19
+ if (len < cache_str) {
20
+ rstr = oj_str_intern(str, len);
21
+ } else {
22
+ rstr = rb_str_new(str, len);
23
+ rstr = oj_encode(rstr);
18
24
  }
25
+ return rstr;
19
26
  }
20
27
 
21
- static void
22
- array_end(ParseInfo pi) {
23
- if (Yes == pi->options.trace) {
24
- oj_trace_parse_array_end(pi, __FILE__, __LINE__);
28
+ VALUE oj_calc_hash_key(ParseInfo pi, Val parent) {
29
+ volatile VALUE rkey = parent->key_val;
30
+
31
+ if (Qundef != rkey) {
32
+ return rkey;
33
+ }
34
+ if (Yes != pi->options.cache_keys) {
35
+ if (Yes == pi->options.sym_key) {
36
+ rkey = ID2SYM(rb_intern3(parent->key, parent->klen, oj_utf8_encoding));
37
+ } else {
38
+ rkey = rb_str_new(parent->key, parent->klen);
39
+ rkey = oj_encode(rkey);
40
+ OBJ_FREEZE(rkey); // frozen when used as a Hash key anyway
41
+ }
42
+ return rkey;
25
43
  }
44
+ if (Yes == pi->options.sym_key) {
45
+ rkey = oj_sym_intern(parent->key, parent->klen);
46
+ } else {
47
+ rkey = oj_str_intern(parent->key, parent->klen);
48
+ }
49
+ return rkey;
26
50
  }
27
51
 
28
- static VALUE
29
- noop_hash_key(ParseInfo pi, const char *key, size_t klen) {
52
+ static void hash_end(ParseInfo pi) {
53
+ TRACE_PARSE_HASH_END(pi->options.trace, pi);
54
+ }
55
+
56
+ static void array_end(ParseInfo pi) {
57
+ TRACE_PARSE_ARRAY_END(pi->options.trace, pi);
58
+ }
59
+
60
+ static VALUE noop_hash_key(ParseInfo pi, const char *key, size_t klen) {
30
61
  return Qundef;
31
62
  }
32
63
 
33
- static void
34
- add_value(ParseInfo pi, VALUE val) {
35
- if (Yes == pi->options.trace) {
36
- oj_trace_parse_call("add_value", pi, __FILE__, __LINE__, val);
37
- }
64
+ static void add_value(ParseInfo pi, VALUE val) {
65
+ TRACE_PARSE_CALL(pi->options.trace, "add_value", pi, val);
38
66
  pi->stack.head->val = val;
39
67
  }
40
68
 
41
- static void
42
- add_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
43
- volatile VALUE rstr = rb_str_new(str, len);
69
+ static void add_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
70
+ volatile VALUE rstr = oj_cstr_to_value(str, len, (size_t)pi->options.cache_str);
44
71
 
45
- rstr = oj_encode(rstr);
46
72
  pi->stack.head->val = rstr;
47
- if (Yes == pi->options.trace) {
48
- oj_trace_parse_call("add_string", pi, __FILE__, __LINE__, rstr);
49
- }
73
+ TRACE_PARSE_CALL(pi->options.trace, "add_string", pi, rstr);
50
74
  }
51
75
 
52
- static void
53
- add_num(ParseInfo pi, NumInfo ni) {
76
+ static void add_num(ParseInfo pi, NumInfo ni) {
54
77
  if (ni->infinity || ni->nan) {
55
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number or other value");
78
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number or other value");
56
79
  }
57
80
  pi->stack.head->val = oj_num_as_value(ni);
58
- if (Yes == pi->options.trace) {
59
- oj_trace_parse_call("add_number", pi, __FILE__, __LINE__, pi->stack.head->val);
60
- }
81
+ TRACE_PARSE_CALL(pi->options.trace, "add_number", pi, pi->stack.head->val);
61
82
  }
62
83
 
63
- static VALUE
64
- start_hash(ParseInfo pi) {
84
+ static VALUE start_hash(ParseInfo pi) {
65
85
  if (Qnil != pi->options.hash_class) {
66
- return rb_class_new_instance(0, NULL, pi->options.hash_class);
67
- }
68
- if (Yes == pi->options.trace) {
69
- oj_trace_parse_in("start_hash", pi, __FILE__, __LINE__);
86
+ return rb_class_new_instance(0, NULL, pi->options.hash_class);
70
87
  }
88
+ TRACE_PARSE_IN(pi->options.trace, "start_hash", pi);
71
89
  return rb_hash_new();
72
90
  }
73
91
 
74
- static VALUE
75
- calc_hash_key(ParseInfo pi, Val parent) {
76
- volatile VALUE rkey = parent->key_val;
92
+ static void hash_set_cstr(ParseInfo pi, Val parent, const char *str, size_t len, const char *orig) {
93
+ volatile VALUE rstr = oj_cstr_to_value(str, len, (size_t)pi->options.cache_str);
77
94
 
78
- if (Qundef == rkey) {
79
- rkey = rb_str_new(parent->key, parent->klen);
80
- }
81
- rkey = oj_encode(rkey);
82
- if (Yes == pi->options.sym_key) {
83
- rkey = rb_str_intern(rkey);
84
- }
85
- return rkey;
95
+ rb_hash_aset(stack_peek(&pi->stack)->val, oj_calc_hash_key(pi, parent), rstr);
96
+ TRACE_PARSE_CALL(pi->options.trace, "set_string", pi, rstr);
86
97
  }
87
98
 
88
- static void
89
- hash_set_cstr(ParseInfo pi, Val parent, const char *str, size_t len, const char *orig) {
90
- volatile VALUE rstr = rb_str_new(str, len);
91
-
92
- rstr = oj_encode(rstr);
93
- rb_hash_aset(stack_peek(&pi->stack)->val, calc_hash_key(pi, parent), rstr);
94
- if (Yes == pi->options.trace) {
95
- oj_trace_parse_call("set_string", pi, __FILE__, __LINE__, rstr);
96
- }
97
- }
98
-
99
- static void
100
- hash_set_num(ParseInfo pi, Val parent, NumInfo ni) {
101
- volatile VALUE v;
99
+ static void hash_set_num(ParseInfo pi, Val parent, NumInfo ni) {
100
+ volatile VALUE v;
102
101
 
103
102
  if (ni->infinity || ni->nan) {
104
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number or other value");
103
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number or other value");
105
104
  }
106
105
  v = oj_num_as_value(ni);
107
- rb_hash_aset(stack_peek(&pi->stack)->val, calc_hash_key(pi, parent), v);
108
- if (Yes == pi->options.trace) {
109
- oj_trace_parse_call("set_number", pi, __FILE__, __LINE__, v);
110
- }
106
+ rb_hash_aset(stack_peek(&pi->stack)->val, oj_calc_hash_key(pi, parent), v);
107
+ TRACE_PARSE_CALL(pi->options.trace, "set_number", pi, v);
111
108
  }
112
109
 
113
- static void
114
- hash_set_value(ParseInfo pi, Val parent, VALUE value) {
115
- rb_hash_aset(stack_peek(&pi->stack)->val, calc_hash_key(pi, parent), value);
116
- if (Yes == pi->options.trace) {
117
- oj_trace_parse_call("set_value", pi, __FILE__, __LINE__, value);
118
- }
110
+ static void hash_set_value(ParseInfo pi, Val parent, VALUE value) {
111
+ rb_hash_aset(stack_peek(&pi->stack)->val, oj_calc_hash_key(pi, parent), value);
112
+ TRACE_PARSE_CALL(pi->options.trace, "set_value", pi, value);
119
113
  }
120
114
 
121
- static VALUE
122
- start_array(ParseInfo pi) {
123
- if (Yes == pi->options.trace) {
124
- oj_trace_parse_in("start_array", pi, __FILE__, __LINE__);
125
- }
115
+ static VALUE start_array(ParseInfo pi) {
116
+ TRACE_PARSE_IN(pi->options.trace, "start_array", pi);
126
117
  return rb_ary_new();
127
118
  }
128
119
 
129
- static void
130
- array_append_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
131
- volatile VALUE rstr = rb_str_new(str, len);
120
+ static void array_append_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
121
+ volatile VALUE rstr = oj_cstr_to_value(str, len, (size_t)pi->options.cache_str);
132
122
 
133
- rstr = oj_encode(rstr);
134
123
  rb_ary_push(stack_peek(&pi->stack)->val, rstr);
135
- if (Yes == pi->options.trace) {
136
- oj_trace_parse_call("append_string", pi, __FILE__, __LINE__, rstr);
137
- }
124
+ TRACE_PARSE_CALL(pi->options.trace, "append_string", pi, rstr);
138
125
  }
139
126
 
140
- static void
141
- array_append_num(ParseInfo pi, NumInfo ni) {
142
- volatile VALUE v;
127
+ static void array_append_num(ParseInfo pi, NumInfo ni) {
128
+ volatile VALUE v;
143
129
 
144
130
  if (ni->infinity || ni->nan) {
145
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number or other value");
131
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number or other value");
146
132
  }
147
133
  v = oj_num_as_value(ni);
148
134
  rb_ary_push(stack_peek(&pi->stack)->val, v);
149
- if (Yes == pi->options.trace) {
150
- oj_trace_parse_call("append_number", pi, __FILE__, __LINE__, v);
151
- }
135
+ TRACE_PARSE_CALL(pi->options.trace, "append_number", pi, v);
152
136
  }
153
137
 
154
- static void
155
- array_append_value(ParseInfo pi, VALUE value) {
138
+ static void array_append_value(ParseInfo pi, VALUE value) {
156
139
  rb_ary_push(stack_peek(&pi->stack)->val, value);
157
- if (Yes == pi->options.trace) {
158
- oj_trace_parse_call("append_value", pi, __FILE__, __LINE__, value);
159
- }
160
- }
161
-
162
- void
163
- oj_set_strict_callbacks(ParseInfo pi) {
164
- pi->start_hash = start_hash;
165
- pi->end_hash = hash_end;
166
- pi->hash_key = noop_hash_key;
167
- pi->hash_set_cstr = hash_set_cstr;
168
- pi->hash_set_num = hash_set_num;
169
- pi->hash_set_value = hash_set_value;
170
- pi->start_array = start_array;
171
- pi->end_array = array_end;
172
- pi->array_append_cstr = array_append_cstr;
173
- pi->array_append_num = array_append_num;
140
+ TRACE_PARSE_CALL(pi->options.trace, "append_value", pi, value);
141
+ }
142
+
143
+ void oj_set_strict_callbacks(ParseInfo pi) {
144
+ pi->start_hash = start_hash;
145
+ pi->end_hash = hash_end;
146
+ pi->hash_key = noop_hash_key;
147
+ pi->hash_set_cstr = hash_set_cstr;
148
+ pi->hash_set_num = hash_set_num;
149
+ pi->hash_set_value = hash_set_value;
150
+ pi->start_array = start_array;
151
+ pi->end_array = array_end;
152
+ pi->array_append_cstr = array_append_cstr;
153
+ pi->array_append_num = array_append_num;
174
154
  pi->array_append_value = array_append_value;
175
- pi->add_cstr = add_cstr;
176
- pi->add_num = add_num;
177
- pi->add_value = add_value;
178
- pi->expect_value = 1;
155
+ pi->add_cstr = add_cstr;
156
+ pi->add_num = add_num;
157
+ pi->add_value = add_value;
158
+ pi->expect_value = 1;
179
159
  }
180
160
 
181
161
  VALUE
182
162
  oj_strict_parse(int argc, VALUE *argv, VALUE self) {
183
- struct _parseInfo pi;
163
+ struct _parseInfo pi;
184
164
 
185
165
  parse_info_init(&pi);
186
- pi.options = oj_default_options;
187
- pi.handler = Qnil;
166
+ pi.options = oj_default_options;
167
+ pi.handler = Qnil;
188
168
  pi.err_class = Qnil;
189
169
  oj_set_strict_callbacks(&pi);
190
170
 
191
171
  if (T_STRING == rb_type(*argv)) {
192
- return oj_pi_parse(argc, argv, &pi, 0, 0, true);
172
+ return oj_pi_parse(argc, argv, &pi, 0, 0, true);
193
173
  } else {
194
- return oj_pi_sparse(argc, argv, &pi, 0);
174
+ return oj_pi_sparse(argc, argv, &pi, 0);
195
175
  }
196
176
  }
197
177
 
198
178
  VALUE
199
179
  oj_strict_parse_cstr(int argc, VALUE *argv, char *json, size_t len) {
200
- struct _parseInfo pi;
180
+ struct _parseInfo pi;
201
181
 
202
182
  parse_info_init(&pi);
203
- pi.options = oj_default_options;
204
- pi.handler = Qnil;
183
+ pi.options = oj_default_options;
184
+ pi.handler = Qnil;
205
185
  pi.err_class = Qnil;
206
186
  oj_set_strict_callbacks(&pi);
207
187