oj 3.9.1 → 3.16.11

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 (171) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1452 -0
  3. data/README.md +21 -6
  4. data/RELEASE_NOTES.md +61 -0
  5. data/ext/oj/buf.h +50 -68
  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 +9 -36
  10. data/ext/oj/circarray.c +38 -42
  11. data/ext/oj/circarray.h +12 -13
  12. data/ext/oj/code.c +158 -179
  13. data/ext/oj/code.h +20 -22
  14. data/ext/oj/compat.c +145 -205
  15. data/ext/oj/custom.c +740 -880
  16. data/ext/oj/debug.c +126 -0
  17. data/ext/oj/dump.c +1145 -844
  18. data/ext/oj/dump.h +71 -57
  19. data/ext/oj/dump_compat.c +575 -655
  20. data/ext/oj/dump_leaf.c +96 -186
  21. data/ext/oj/dump_object.c +533 -660
  22. data/ext/oj/dump_strict.c +306 -340
  23. data/ext/oj/encode.h +4 -33
  24. data/ext/oj/encoder.c +43 -0
  25. data/ext/oj/err.c +28 -28
  26. data/ext/oj/err.h +39 -42
  27. data/ext/oj/extconf.rb +28 -7
  28. data/ext/oj/fast.c +1052 -1113
  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 +471 -430
  34. data/ext/oj/object.c +532 -580
  35. data/ext/oj/odd.c +156 -142
  36. data/ext/oj/odd.h +25 -26
  37. data/ext/oj/oj.c +1346 -961
  38. data/ext/oj/oj.h +307 -290
  39. data/ext/oj/parse.c +954 -858
  40. data/ext/oj/parse.h +74 -72
  41. data/ext/oj/parser.c +1600 -0
  42. data/ext/oj/parser.h +103 -0
  43. data/ext/oj/rails.c +819 -836
  44. data/ext/oj/rails.h +8 -11
  45. data/ext/oj/reader.c +136 -147
  46. data/ext/oj/reader.h +69 -83
  47. data/ext/oj/resolve.c +41 -63
  48. data/ext/oj/resolve.h +4 -6
  49. data/ext/oj/rxclass.c +69 -72
  50. data/ext/oj/rxclass.h +12 -13
  51. data/ext/oj/saj.c +440 -485
  52. data/ext/oj/saj2.c +584 -0
  53. data/ext/oj/saj2.h +23 -0
  54. data/ext/oj/scp.c +79 -118
  55. data/ext/oj/simd.h +10 -0
  56. data/ext/oj/sparse.c +739 -709
  57. data/ext/oj/stream_writer.c +141 -175
  58. data/ext/oj/strict.c +103 -128
  59. data/ext/oj/string_writer.c +244 -261
  60. data/ext/oj/trace.c +34 -41
  61. data/ext/oj/trace.h +42 -15
  62. data/ext/oj/usual.c +1218 -0
  63. data/ext/oj/usual.h +69 -0
  64. data/ext/oj/util.c +107 -107
  65. data/ext/oj/util.h +4 -3
  66. data/ext/oj/val_stack.c +61 -78
  67. data/ext/oj/val_stack.h +80 -114
  68. data/ext/oj/validate.c +46 -0
  69. data/ext/oj/wab.c +316 -361
  70. data/lib/oj/active_support_helper.rb +1 -3
  71. data/lib/oj/bag.rb +8 -1
  72. data/lib/oj/easy_hash.rb +9 -9
  73. data/lib/oj/error.rb +1 -2
  74. data/lib/oj/json.rb +162 -150
  75. data/lib/oj/mimic.rb +54 -20
  76. data/lib/oj/saj.rb +20 -6
  77. data/lib/oj/schandler.rb +5 -4
  78. data/lib/oj/state.rb +12 -8
  79. data/lib/oj/version.rb +1 -2
  80. data/lib/oj.rb +2 -8
  81. data/pages/Compatibility.md +1 -1
  82. data/pages/Encoding.md +1 -1
  83. data/pages/InstallOptions.md +20 -0
  84. data/pages/JsonGem.md +15 -0
  85. data/pages/Modes.md +9 -3
  86. data/pages/Options.md +62 -12
  87. data/pages/Parser.md +309 -0
  88. data/pages/Rails.md +73 -22
  89. metadata +68 -192
  90. data/ext/oj/hash.c +0 -163
  91. data/ext/oj/hash.h +0 -46
  92. data/ext/oj/hash_test.c +0 -512
  93. data/test/_test_active.rb +0 -76
  94. data/test/_test_active_mimic.rb +0 -96
  95. data/test/_test_mimic_rails.rb +0 -126
  96. data/test/activerecord/result_test.rb +0 -27
  97. data/test/activesupport4/decoding_test.rb +0 -108
  98. data/test/activesupport4/encoding_test.rb +0 -531
  99. data/test/activesupport4/test_helper.rb +0 -41
  100. data/test/activesupport5/decoding_test.rb +0 -125
  101. data/test/activesupport5/encoding_test.rb +0 -485
  102. data/test/activesupport5/encoding_test_cases.rb +0 -90
  103. data/test/activesupport5/test_helper.rb +0 -50
  104. data/test/activesupport5/time_zone_test_helpers.rb +0 -24
  105. data/test/bar.rb +0 -25
  106. data/test/files.rb +0 -29
  107. data/test/foo.rb +0 -21
  108. data/test/helper.rb +0 -26
  109. data/test/isolated/shared.rb +0 -308
  110. data/test/isolated/test_mimic_after.rb +0 -13
  111. data/test/isolated/test_mimic_alone.rb +0 -12
  112. data/test/isolated/test_mimic_as_json.rb +0 -45
  113. data/test/isolated/test_mimic_before.rb +0 -13
  114. data/test/isolated/test_mimic_define.rb +0 -28
  115. data/test/isolated/test_mimic_rails_after.rb +0 -22
  116. data/test/isolated/test_mimic_rails_before.rb +0 -21
  117. data/test/isolated/test_mimic_redefine.rb +0 -15
  118. data/test/json_gem/json_addition_test.rb +0 -216
  119. data/test/json_gem/json_common_interface_test.rb +0 -148
  120. data/test/json_gem/json_encoding_test.rb +0 -107
  121. data/test/json_gem/json_ext_parser_test.rb +0 -20
  122. data/test/json_gem/json_fixtures_test.rb +0 -35
  123. data/test/json_gem/json_generator_test.rb +0 -383
  124. data/test/json_gem/json_generic_object_test.rb +0 -90
  125. data/test/json_gem/json_parser_test.rb +0 -470
  126. data/test/json_gem/json_string_matching_test.rb +0 -42
  127. data/test/json_gem/test_helper.rb +0 -18
  128. data/test/perf.rb +0 -107
  129. data/test/perf_compat.rb +0 -130
  130. data/test/perf_fast.rb +0 -164
  131. data/test/perf_file.rb +0 -64
  132. data/test/perf_object.rb +0 -138
  133. data/test/perf_saj.rb +0 -109
  134. data/test/perf_scp.rb +0 -151
  135. data/test/perf_simple.rb +0 -287
  136. data/test/perf_strict.rb +0 -145
  137. data/test/perf_wab.rb +0 -131
  138. data/test/sample/change.rb +0 -14
  139. data/test/sample/dir.rb +0 -19
  140. data/test/sample/doc.rb +0 -36
  141. data/test/sample/file.rb +0 -48
  142. data/test/sample/group.rb +0 -16
  143. data/test/sample/hasprops.rb +0 -16
  144. data/test/sample/layer.rb +0 -12
  145. data/test/sample/line.rb +0 -20
  146. data/test/sample/oval.rb +0 -10
  147. data/test/sample/rect.rb +0 -10
  148. data/test/sample/shape.rb +0 -35
  149. data/test/sample/text.rb +0 -20
  150. data/test/sample.rb +0 -54
  151. data/test/sample_json.rb +0 -37
  152. data/test/test_compat.rb +0 -509
  153. data/test/test_custom.rb +0 -503
  154. data/test/test_debian.rb +0 -53
  155. data/test/test_fast.rb +0 -470
  156. data/test/test_file.rb +0 -239
  157. data/test/test_gc.rb +0 -49
  158. data/test/test_hash.rb +0 -29
  159. data/test/test_integer_range.rb +0 -73
  160. data/test/test_null.rb +0 -376
  161. data/test/test_object.rb +0 -1018
  162. data/test/test_saj.rb +0 -186
  163. data/test/test_scp.rb +0 -433
  164. data/test/test_strict.rb +0 -410
  165. data/test/test_various.rb +0 -741
  166. data/test/test_wab.rb +0 -307
  167. data/test/test_writer.rb +0 -380
  168. data/test/tests.rb +0 -24
  169. data/test/tests_mimic.rb +0 -14
  170. data/test/tests_mimic_addition.rb +0 -7
  171. data/test/zoo.rb +0 -13
data/ext/oj/saj2.c ADDED
@@ -0,0 +1,584 @@
1
+ // Copyright (c) 2021, Peter Ohler, All rights reserved.
2
+
3
+ #include "saj2.h"
4
+
5
+ #include "cache.h"
6
+ #include "mem.h"
7
+ #include "oj.h"
8
+ #include "parser.h"
9
+
10
+ static VALUE get_key(ojParser p) {
11
+ Saj d = (Saj)p->ctx;
12
+ const char *key = buf_str(&p->key);
13
+ size_t len = buf_len(&p->key);
14
+ volatile VALUE rkey;
15
+
16
+ if (d->cache_keys) {
17
+ rkey = cache_intern(d->str_cache, key, len);
18
+ } else {
19
+ rkey = rb_utf8_str_new(key, len);
20
+ }
21
+ return rkey;
22
+ }
23
+
24
+ static void push_key(Saj d, VALUE key) {
25
+ if (d->klen <= (size_t)(d->tail - d->keys)) {
26
+ size_t off = d->tail - d->keys;
27
+
28
+ d->klen += d->klen / 2;
29
+ OJ_R_REALLOC_N(d->keys, VALUE, d->klen);
30
+ d->tail = d->keys + off;
31
+ }
32
+ *d->tail = key;
33
+ d->tail++;
34
+ }
35
+
36
+ static void noop(ojParser p) {
37
+ }
38
+
39
+ static void open_object(ojParser p) {
40
+ rb_funcall(((Saj)p->ctx)->handler, oj_hash_start_id, 1, Qnil);
41
+ }
42
+
43
+ static void open_object_loc(ojParser p) {
44
+ rb_funcall(((Saj)p->ctx)->handler, oj_hash_start_id, 3, Qnil, LONG2FIX(p->line), LONG2FIX(p->cur - p->col));
45
+ }
46
+
47
+ static void open_object_key(ojParser p) {
48
+ Saj d = (Saj)p->ctx;
49
+ volatile VALUE key = get_key(p);
50
+
51
+ push_key(d, key);
52
+ rb_funcall(d->handler, oj_hash_start_id, 1, key);
53
+ }
54
+
55
+ static void open_object_loc_key(ojParser p) {
56
+ Saj d = (Saj)p->ctx;
57
+ volatile VALUE key = get_key(p);
58
+
59
+ push_key(d, key);
60
+ rb_funcall(d->handler, oj_hash_start_id, 3, key, LONG2FIX(p->line), LONG2FIX(p->cur - p->col));
61
+ }
62
+
63
+ static void open_array(ojParser p) {
64
+ rb_funcall(((Saj)p->ctx)->handler, oj_array_start_id, 1, Qnil);
65
+ }
66
+
67
+ static void open_array_loc(ojParser p) {
68
+ rb_funcall(((Saj)p->ctx)->handler, oj_array_start_id, 3, Qnil, LONG2FIX(p->line), LONG2FIX(p->cur - p->col));
69
+ }
70
+
71
+ static void open_array_key(ojParser p) {
72
+ Saj d = (Saj)p->ctx;
73
+ volatile VALUE key = get_key(p);
74
+
75
+ push_key(d, key);
76
+ rb_funcall(d->handler, oj_array_start_id, 1, key);
77
+ }
78
+
79
+ static void open_array_loc_key(ojParser p) {
80
+ Saj d = (Saj)p->ctx;
81
+ volatile VALUE key = get_key(p);
82
+
83
+ push_key(d, key);
84
+ rb_funcall(d->handler, oj_array_start_id, 3, key, LONG2FIX(p->line), LONG2FIX(p->cur - p->col));
85
+ }
86
+
87
+ static void close_object(ojParser p) {
88
+ Saj d = (Saj)p->ctx;
89
+ VALUE key = Qnil;
90
+
91
+ if (OBJECT_FUN == p->stack[p->depth]) {
92
+ d->tail--;
93
+ if (d->tail < d->keys) {
94
+ rb_raise(rb_eIndexError, "accessing key stack");
95
+ }
96
+ key = *d->tail;
97
+ }
98
+ rb_funcall(d->handler, oj_hash_end_id, 1, key);
99
+ }
100
+
101
+ static void close_object_loc(ojParser p) {
102
+ Saj d = (Saj)p->ctx;
103
+ VALUE key = Qnil;
104
+
105
+ if (OBJECT_FUN == p->stack[p->depth]) {
106
+ d->tail--;
107
+ if (d->tail < d->keys) {
108
+ rb_raise(rb_eIndexError, "accessing key stack");
109
+ }
110
+ key = *d->tail;
111
+ }
112
+ rb_funcall(d->handler, oj_hash_end_id, 3, key, LONG2FIX(p->line), LONG2FIX(p->cur - p->col));
113
+ }
114
+
115
+ static void close_array(ojParser p) {
116
+ Saj d = (Saj)p->ctx;
117
+ VALUE key = Qnil;
118
+
119
+ if (OBJECT_FUN == p->stack[p->depth]) {
120
+ d->tail--;
121
+ if (d->tail < d->keys) {
122
+ rb_raise(rb_eIndexError, "accessing key stack");
123
+ }
124
+ key = *d->tail;
125
+ }
126
+ rb_funcall(d->handler, oj_array_end_id, 1, key);
127
+ }
128
+
129
+ static void close_array_loc(ojParser p) {
130
+ Saj d = (Saj)p->ctx;
131
+ VALUE key = Qnil;
132
+
133
+ if (OBJECT_FUN == p->stack[p->depth]) {
134
+ d->tail--;
135
+ if (d->tail < d->keys) {
136
+ rb_raise(rb_eIndexError, "accessing key stack");
137
+ }
138
+ key = *d->tail;
139
+ }
140
+ rb_funcall(d->handler, oj_array_end_id, 3, key, LONG2FIX(p->line), LONG2FIX(p->cur - p->col));
141
+ }
142
+
143
+ static void add_null(ojParser p) {
144
+ rb_funcall(((Saj)p->ctx)->handler, oj_add_value_id, 2, Qnil, Qnil);
145
+ }
146
+
147
+ static void add_null_loc(ojParser p) {
148
+ rb_funcall(((Saj)p->ctx)->handler, oj_add_value_id, 4, Qnil, Qnil, LONG2FIX(p->line), LONG2FIX(p->cur - p->col));
149
+ }
150
+
151
+ static void add_null_key(ojParser p) {
152
+ rb_funcall(((Saj)p->ctx)->handler, oj_add_value_id, 2, Qnil, get_key(p));
153
+ }
154
+
155
+ static void add_null_key_loc(ojParser p) {
156
+ rb_funcall(((Saj)p->ctx)->handler,
157
+ oj_add_value_id,
158
+ 4,
159
+ Qnil,
160
+ get_key(p),
161
+ LONG2FIX(p->line),
162
+ LONG2FIX(p->cur - p->col));
163
+ }
164
+
165
+ static void add_true(ojParser p) {
166
+ rb_funcall(((Saj)p->ctx)->handler, oj_add_value_id, 2, Qtrue, Qnil);
167
+ }
168
+
169
+ static void add_true_loc(ojParser p) {
170
+ rb_funcall(((Saj)p->ctx)->handler, oj_add_value_id, 4, Qtrue, Qnil, LONG2FIX(p->line), LONG2FIX(p->cur - p->col));
171
+ }
172
+
173
+ static void add_true_key(ojParser p) {
174
+ rb_funcall(((Saj)p->ctx)->handler, oj_add_value_id, 2, Qtrue, get_key(p));
175
+ }
176
+
177
+ static void add_true_key_loc(ojParser p) {
178
+ rb_funcall(((Saj)p->ctx)->handler,
179
+ oj_add_value_id,
180
+ 4,
181
+ Qtrue,
182
+ get_key(p),
183
+ LONG2FIX(p->line),
184
+ LONG2FIX(p->cur - p->col));
185
+ }
186
+
187
+ static void add_false(ojParser p) {
188
+ rb_funcall(((Saj)p->ctx)->handler, oj_add_value_id, 2, Qfalse, Qnil);
189
+ }
190
+
191
+ static void add_false_loc(ojParser p) {
192
+ rb_funcall(((Saj)p->ctx)->handler, oj_add_value_id, 4, Qfalse, Qnil, LONG2FIX(p->line), LONG2FIX(p->cur - p->col));
193
+ }
194
+
195
+ static void add_false_key(ojParser p) {
196
+ rb_funcall(((Saj)p->ctx)->handler, oj_add_value_id, 2, Qfalse, get_key(p));
197
+ }
198
+
199
+ static void add_false_key_loc(ojParser p) {
200
+ rb_funcall(((Saj)p->ctx)->handler,
201
+ oj_add_value_id,
202
+ 4,
203
+ Qfalse,
204
+ get_key(p),
205
+ LONG2FIX(p->line),
206
+ LONG2FIX(p->cur - p->col));
207
+ }
208
+
209
+ static void add_int(ojParser p) {
210
+ rb_funcall(((Saj)p->ctx)->handler, oj_add_value_id, 2, LONG2NUM(p->num.fixnum), Qnil);
211
+ }
212
+
213
+ static void add_int_loc(ojParser p) {
214
+ rb_funcall(((Saj)p->ctx)->handler,
215
+ oj_add_value_id,
216
+ 4,
217
+ LONG2NUM(p->num.fixnum),
218
+ Qnil,
219
+ LONG2FIX(p->line),
220
+ LONG2FIX(p->cur - p->col));
221
+ }
222
+
223
+ static void add_int_key(ojParser p) {
224
+ rb_funcall(((Saj)p->ctx)->handler, oj_add_value_id, 2, LONG2NUM(p->num.fixnum), get_key(p));
225
+ }
226
+
227
+ static void add_int_key_loc(ojParser p) {
228
+ rb_funcall(((Saj)p->ctx)->handler,
229
+ oj_add_value_id,
230
+ 4,
231
+ LONG2NUM(p->num.fixnum),
232
+ get_key(p),
233
+ LONG2FIX(p->line),
234
+ LONG2FIX(p->cur - p->col));
235
+ }
236
+
237
+ static void add_float(ojParser p) {
238
+ rb_funcall(((Saj)p->ctx)->handler, oj_add_value_id, 2, rb_float_new(p->num.dub), Qnil);
239
+ }
240
+
241
+ static void add_float_loc(ojParser p) {
242
+ rb_funcall(((Saj)p->ctx)->handler,
243
+ oj_add_value_id,
244
+ 4,
245
+ rb_float_new(p->num.dub),
246
+ Qnil,
247
+ LONG2FIX(p->line),
248
+ LONG2FIX(p->cur - p->col));
249
+ }
250
+
251
+ static void add_float_key(ojParser p) {
252
+ rb_funcall(((Saj)p->ctx)->handler, oj_add_value_id, 2, rb_float_new(p->num.dub), get_key(p));
253
+ }
254
+
255
+ static void add_float_key_loc(ojParser p) {
256
+ rb_funcall(((Saj)p->ctx)->handler,
257
+ oj_add_value_id,
258
+ 4,
259
+ rb_float_new(p->num.dub),
260
+ get_key(p),
261
+ LONG2FIX(p->line),
262
+ LONG2FIX(p->cur - p->col));
263
+ }
264
+
265
+ static void add_big(ojParser p) {
266
+ rb_funcall(((Saj)p->ctx)->handler,
267
+ oj_add_value_id,
268
+ 2,
269
+ rb_funcall(rb_cObject, oj_bigdecimal_id, 1, rb_str_new(buf_str(&p->buf), buf_len(&p->buf))),
270
+ Qnil);
271
+ }
272
+
273
+ static void add_big_loc(ojParser p) {
274
+ rb_funcall(((Saj)p->ctx)->handler,
275
+ oj_add_value_id,
276
+ 4,
277
+ rb_funcall(rb_cObject, oj_bigdecimal_id, 1, rb_str_new(buf_str(&p->buf), buf_len(&p->buf))),
278
+ Qnil,
279
+ LONG2FIX(p->line),
280
+ LONG2FIX(p->cur - p->col));
281
+ }
282
+
283
+ static void add_big_key(ojParser p) {
284
+ rb_funcall(((Saj)p->ctx)->handler,
285
+ oj_add_value_id,
286
+ 2,
287
+ rb_funcall(rb_cObject, oj_bigdecimal_id, 1, rb_str_new(buf_str(&p->buf), buf_len(&p->buf))),
288
+ get_key(p));
289
+ }
290
+
291
+ static void add_big_key_loc(ojParser p) {
292
+ rb_funcall(((Saj)p->ctx)->handler,
293
+ oj_add_value_id,
294
+ 4,
295
+ rb_funcall(rb_cObject, oj_bigdecimal_id, 1, rb_str_new(buf_str(&p->buf), buf_len(&p->buf))),
296
+ get_key(p),
297
+ LONG2FIX(p->line),
298
+ LONG2FIX(p->cur - p->col));
299
+ }
300
+
301
+ static void add_str(ojParser p) {
302
+ Saj d = (Saj)p->ctx;
303
+ volatile VALUE rstr;
304
+ const char *str = buf_str(&p->buf);
305
+ size_t len = buf_len(&p->buf);
306
+
307
+ if (d->cache_str < len) {
308
+ rstr = cache_intern(d->str_cache, str, len);
309
+ } else {
310
+ rstr = rb_utf8_str_new(str, len);
311
+ }
312
+ rb_funcall(d->handler, oj_add_value_id, 2, rstr, Qnil);
313
+ }
314
+
315
+ static void add_str_loc(ojParser p) {
316
+ Saj d = (Saj)p->ctx;
317
+ volatile VALUE rstr;
318
+ const char *str = buf_str(&p->buf);
319
+ size_t len = buf_len(&p->buf);
320
+
321
+ if (d->cache_str < len) {
322
+ rstr = cache_intern(d->str_cache, str, len);
323
+ } else {
324
+ rstr = rb_utf8_str_new(str, len);
325
+ }
326
+ rb_funcall(d->handler, oj_add_value_id, 4, rstr, Qnil, LONG2FIX(p->line), LONG2FIX(p->cur - p->col));
327
+ }
328
+
329
+ static void add_str_key(ojParser p) {
330
+ Saj d = (Saj)p->ctx;
331
+ volatile VALUE rstr;
332
+ const char *str = buf_str(&p->buf);
333
+ size_t len = buf_len(&p->buf);
334
+
335
+ if (d->cache_str < len) {
336
+ rstr = cache_intern(d->str_cache, str, len);
337
+ } else {
338
+ rstr = rb_utf8_str_new(str, len);
339
+ }
340
+ rb_funcall(d->handler, oj_add_value_id, 2, rstr, get_key(p));
341
+ }
342
+
343
+ static void add_str_key_loc(ojParser p) {
344
+ Saj d = (Saj)p->ctx;
345
+ volatile VALUE rstr;
346
+ const char *str = buf_str(&p->buf);
347
+ size_t len = buf_len(&p->buf);
348
+
349
+ if (d->cache_str < len) {
350
+ rstr = cache_intern(d->str_cache, str, len);
351
+ } else {
352
+ rstr = rb_utf8_str_new(str, len);
353
+ }
354
+ rb_funcall(d->handler, oj_add_value_id, 4, rstr, get_key(p), LONG2FIX(p->line), LONG2FIX(p->cur - p->col));
355
+ }
356
+
357
+ static void reset(ojParser p) {
358
+ Funcs end = p->funcs + 3;
359
+ Funcs f;
360
+
361
+ for (f = p->funcs; f < end; f++) {
362
+ f->add_null = noop;
363
+ f->add_true = noop;
364
+ f->add_false = noop;
365
+ f->add_int = noop;
366
+ f->add_float = noop;
367
+ f->add_big = noop;
368
+ f->add_str = noop;
369
+ f->open_array = noop;
370
+ f->close_array = noop;
371
+ f->open_object = noop;
372
+ f->close_object = noop;
373
+ }
374
+ }
375
+
376
+ static VALUE option(ojParser p, const char *key, VALUE value) {
377
+ Saj d = (Saj)p->ctx;
378
+
379
+ if (0 == strcmp(key, "handler")) {
380
+ return d->handler;
381
+ }
382
+ if (0 == strcmp(key, "handler=")) {
383
+ d->tail = d->keys;
384
+ d->handler = value;
385
+ reset(p);
386
+ if (rb_respond_to(value, oj_hash_start_id)) {
387
+ if (1 == rb_obj_method_arity(value, oj_hash_start_id)) {
388
+ p->funcs[TOP_FUN].open_object = open_object;
389
+ p->funcs[ARRAY_FUN].open_object = open_object;
390
+ p->funcs[OBJECT_FUN].open_object = open_object_key;
391
+ } else {
392
+ p->funcs[TOP_FUN].open_object = open_object_loc;
393
+ p->funcs[ARRAY_FUN].open_object = open_object_loc;
394
+ p->funcs[OBJECT_FUN].open_object = open_object_loc_key;
395
+ }
396
+ }
397
+ if (rb_respond_to(value, oj_array_start_id)) {
398
+ if (1 == rb_obj_method_arity(value, oj_array_start_id)) {
399
+ p->funcs[TOP_FUN].open_array = open_array;
400
+ p->funcs[ARRAY_FUN].open_array = open_array;
401
+ p->funcs[OBJECT_FUN].open_array = open_array_key;
402
+ } else {
403
+ p->funcs[TOP_FUN].open_array = open_array_loc;
404
+ p->funcs[ARRAY_FUN].open_array = open_array_loc;
405
+ p->funcs[OBJECT_FUN].open_array = open_array_loc_key;
406
+ }
407
+ }
408
+ if (rb_respond_to(value, oj_hash_end_id)) {
409
+ if (1 == rb_obj_method_arity(value, oj_hash_end_id)) {
410
+ p->funcs[TOP_FUN].close_object = close_object;
411
+ p->funcs[ARRAY_FUN].close_object = close_object;
412
+ p->funcs[OBJECT_FUN].close_object = close_object;
413
+ } else {
414
+ p->funcs[TOP_FUN].close_object = close_object_loc;
415
+ p->funcs[ARRAY_FUN].close_object = close_object_loc;
416
+ p->funcs[OBJECT_FUN].close_object = close_object_loc;
417
+ }
418
+ }
419
+ if (rb_respond_to(value, oj_array_end_id)) {
420
+ if (1 == rb_obj_method_arity(value, oj_array_end_id)) {
421
+ p->funcs[TOP_FUN].close_array = close_array;
422
+ p->funcs[ARRAY_FUN].close_array = close_array;
423
+ p->funcs[OBJECT_FUN].close_array = close_array;
424
+ } else {
425
+ p->funcs[TOP_FUN].close_array = close_array_loc;
426
+ p->funcs[ARRAY_FUN].close_array = close_array_loc;
427
+ p->funcs[OBJECT_FUN].close_array = close_array_loc;
428
+ }
429
+ }
430
+ if (rb_respond_to(value, oj_add_value_id)) {
431
+ if (2 == rb_obj_method_arity(value, oj_add_value_id)) {
432
+ p->funcs[TOP_FUN].add_null = add_null;
433
+ p->funcs[ARRAY_FUN].add_null = add_null;
434
+ p->funcs[OBJECT_FUN].add_null = add_null_key;
435
+
436
+ p->funcs[TOP_FUN].add_true = add_true;
437
+ p->funcs[ARRAY_FUN].add_true = add_true;
438
+ p->funcs[OBJECT_FUN].add_true = add_true_key;
439
+
440
+ p->funcs[TOP_FUN].add_false = add_false;
441
+ p->funcs[ARRAY_FUN].add_false = add_false;
442
+ p->funcs[OBJECT_FUN].add_false = add_false_key;
443
+
444
+ p->funcs[TOP_FUN].add_int = add_int;
445
+ p->funcs[ARRAY_FUN].add_int = add_int;
446
+ p->funcs[OBJECT_FUN].add_int = add_int_key;
447
+
448
+ p->funcs[TOP_FUN].add_float = add_float;
449
+ p->funcs[ARRAY_FUN].add_float = add_float;
450
+ p->funcs[OBJECT_FUN].add_float = add_float_key;
451
+
452
+ p->funcs[TOP_FUN].add_big = add_big;
453
+ p->funcs[ARRAY_FUN].add_big = add_big;
454
+ p->funcs[OBJECT_FUN].add_big = add_big_key;
455
+
456
+ p->funcs[TOP_FUN].add_str = add_str;
457
+ p->funcs[ARRAY_FUN].add_str = add_str;
458
+ p->funcs[OBJECT_FUN].add_str = add_str_key;
459
+ } else {
460
+ p->funcs[TOP_FUN].add_null = add_null_loc;
461
+ p->funcs[ARRAY_FUN].add_null = add_null_loc;
462
+ p->funcs[OBJECT_FUN].add_null = add_null_key_loc;
463
+
464
+ p->funcs[TOP_FUN].add_true = add_true_loc;
465
+ p->funcs[ARRAY_FUN].add_true = add_true_loc;
466
+ p->funcs[OBJECT_FUN].add_true = add_true_key_loc;
467
+
468
+ p->funcs[TOP_FUN].add_false = add_false_loc;
469
+ p->funcs[ARRAY_FUN].add_false = add_false_loc;
470
+ p->funcs[OBJECT_FUN].add_false = add_false_key_loc;
471
+
472
+ p->funcs[TOP_FUN].add_int = add_int_loc;
473
+ p->funcs[ARRAY_FUN].add_int = add_int_loc;
474
+ p->funcs[OBJECT_FUN].add_int = add_int_key_loc;
475
+
476
+ p->funcs[TOP_FUN].add_float = add_float_loc;
477
+ p->funcs[ARRAY_FUN].add_float = add_float_loc;
478
+ p->funcs[OBJECT_FUN].add_float = add_float_key_loc;
479
+
480
+ p->funcs[TOP_FUN].add_big = add_big_loc;
481
+ p->funcs[ARRAY_FUN].add_big = add_big_loc;
482
+ p->funcs[OBJECT_FUN].add_big = add_big_key_loc;
483
+
484
+ p->funcs[TOP_FUN].add_str = add_str_loc;
485
+ p->funcs[ARRAY_FUN].add_str = add_str_loc;
486
+ p->funcs[OBJECT_FUN].add_str = add_str_key_loc;
487
+ }
488
+ }
489
+ return Qnil;
490
+ }
491
+ if (0 == strcmp(key, "cache_keys")) {
492
+ return d->cache_keys ? Qtrue : Qfalse;
493
+ }
494
+ if (0 == strcmp(key, "cache_keys=")) {
495
+ d->cache_keys = (Qtrue == value);
496
+
497
+ return d->cache_keys ? Qtrue : Qfalse;
498
+ }
499
+ if (0 == strcmp(key, "cache_strings")) {
500
+ return INT2NUM((int)d->cache_str);
501
+ }
502
+ if (0 == strcmp(key, "cache_strings=")) {
503
+ int limit = NUM2INT(value);
504
+
505
+ if (CACHE_MAX_KEY < limit) {
506
+ limit = CACHE_MAX_KEY;
507
+ } else if (limit < 0) {
508
+ limit = 0;
509
+ }
510
+ d->cache_str = limit;
511
+
512
+ return INT2NUM((int)d->cache_str);
513
+ }
514
+ rb_raise(rb_eArgError, "%s is not an option for the SAJ (Simple API for JSON) saj", key);
515
+
516
+ return Qnil; // Never reached due to the raise but required by the compiler.
517
+ }
518
+
519
+ static VALUE result(ojParser p) {
520
+ return Qnil;
521
+ }
522
+
523
+ static void start(ojParser p) {
524
+ Saj d = (Saj)p->ctx;
525
+
526
+ d->tail = d->keys;
527
+ }
528
+
529
+ static void dfree(ojParser p) {
530
+ Saj d = (Saj)p->ctx;
531
+
532
+ if (NULL != d->keys) {
533
+ OJ_R_FREE(d->keys);
534
+ }
535
+ cache_free(d->str_cache);
536
+ OJ_R_FREE(p->ctx);
537
+ }
538
+
539
+ static void mark(ojParser p) {
540
+ if (NULL == p || NULL == p->ctx) {
541
+ return;
542
+ }
543
+ Saj d = (Saj)p->ctx;
544
+ VALUE *kp;
545
+
546
+ cache_mark(d->str_cache);
547
+ if (Qnil != d->handler) {
548
+ rb_gc_mark(d->handler);
549
+ }
550
+ if (!d->cache_keys) {
551
+ for (kp = d->keys; kp < d->tail; kp++) {
552
+ rb_gc_mark(*kp);
553
+ }
554
+ }
555
+ }
556
+
557
+ static VALUE form_str(const char *str, size_t len) {
558
+ return rb_str_freeze(rb_utf8_str_new(str, len));
559
+ }
560
+
561
+ void oj_init_saj(ojParser p, Saj d) {
562
+ d->klen = 256;
563
+ d->keys = OJ_R_ALLOC_N(VALUE, d->klen);
564
+ d->tail = d->keys;
565
+ d->handler = Qnil;
566
+ d->str_cache = cache_create(0, form_str, true, false);
567
+ d->cache_str = 16;
568
+ d->cache_keys = true;
569
+ d->thread_safe = false;
570
+
571
+ p->ctx = (void *)d;
572
+ reset(p);
573
+ p->option = option;
574
+ p->result = result;
575
+ p->free = dfree;
576
+ p->mark = mark;
577
+ p->start = start;
578
+ }
579
+
580
+ void oj_set_parser_saj(ojParser p) {
581
+ Saj d = OJ_R_ALLOC(struct _saj);
582
+
583
+ oj_init_saj(p, d);
584
+ }
data/ext/oj/saj2.h ADDED
@@ -0,0 +1,23 @@
1
+ // Copyright (c) 2021, Peter Ohler, All rights reserved.
2
+
3
+ #include <ruby.h>
4
+ #include <stdbool.h>
5
+
6
+ struct _cache;
7
+ struct _ojParser;
8
+
9
+ typedef struct _saj {
10
+ VALUE handler;
11
+ VALUE *keys;
12
+ VALUE *tail;
13
+ size_t klen;
14
+ struct _cache *str_cache;
15
+ uint8_t cache_str;
16
+ bool cache_keys;
17
+ bool thread_safe;
18
+ } *Saj;
19
+
20
+ // Initialize the parser with the SAJ delegate. If the SAJ delegate is wrapped
21
+ // then this function is called first and then the parser functions can be
22
+ // replaced.
23
+ extern void oj_init_saj(struct _ojParser *p, Saj d);