oj 2.18.5 → 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 (166) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +1452 -0
  3. data/README.md +53 -221
  4. data/RELEASE_NOTES.md +61 -0
  5. data/ext/oj/buf.h +54 -72
  6. data/ext/oj/cache.c +329 -0
  7. data/ext/oj/cache.h +22 -0
  8. data/ext/oj/cache8.c +61 -63
  9. data/ext/oj/cache8.h +12 -39
  10. data/ext/oj/circarray.c +38 -67
  11. data/ext/oj/circarray.h +16 -42
  12. data/ext/oj/code.c +214 -0
  13. data/ext/oj/code.h +40 -0
  14. data/ext/oj/compat.c +194 -110
  15. data/ext/oj/custom.c +1074 -0
  16. data/ext/oj/debug.c +126 -0
  17. data/ext/oj/dump.c +1276 -2494
  18. data/ext/oj/dump.h +110 -0
  19. data/ext/oj/dump_compat.c +897 -0
  20. data/ext/oj/dump_leaf.c +162 -0
  21. data/ext/oj/dump_object.c +710 -0
  22. data/ext/oj/dump_strict.c +399 -0
  23. data/ext/oj/encode.h +7 -42
  24. data/ext/oj/encoder.c +43 -0
  25. data/ext/oj/err.c +28 -53
  26. data/ext/oj/err.h +49 -46
  27. data/ext/oj/extconf.rb +33 -32
  28. data/ext/oj/fast.c +1082 -1098
  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 +919 -0
  34. data/ext/oj/object.c +545 -625
  35. data/ext/oj/odd.c +158 -168
  36. data/ext/oj/odd.h +32 -58
  37. data/ext/oj/oj.c +1727 -2080
  38. data/ext/oj/oj.h +334 -259
  39. data/ext/oj/parse.c +974 -753
  40. data/ext/oj/parse.h +97 -90
  41. data/ext/oj/parser.c +1600 -0
  42. data/ext/oj/parser.h +103 -0
  43. data/ext/oj/rails.c +1478 -0
  44. data/ext/oj/rails.h +18 -0
  45. data/ext/oj/reader.c +136 -163
  46. data/ext/oj/reader.h +76 -112
  47. data/ext/oj/resolve.c +45 -94
  48. data/ext/oj/resolve.h +7 -34
  49. data/ext/oj/rxclass.c +144 -0
  50. data/ext/oj/rxclass.h +26 -0
  51. data/ext/oj/saj.c +445 -511
  52. data/ext/oj/saj2.c +584 -0
  53. data/ext/oj/saj2.h +23 -0
  54. data/ext/oj/scp.c +82 -143
  55. data/ext/oj/simd.h +10 -0
  56. data/ext/oj/sparse.c +749 -644
  57. data/ext/oj/stream_writer.c +329 -0
  58. data/ext/oj/strict.c +114 -112
  59. data/ext/oj/string_writer.c +517 -0
  60. data/ext/oj/trace.c +72 -0
  61. data/ext/oj/trace.h +55 -0
  62. data/ext/oj/usual.c +1218 -0
  63. data/ext/oj/usual.h +69 -0
  64. data/ext/oj/util.c +136 -0
  65. data/ext/oj/util.h +20 -0
  66. data/ext/oj/val_stack.c +75 -72
  67. data/ext/oj/val_stack.h +94 -127
  68. data/ext/oj/validate.c +46 -0
  69. data/ext/oj/wab.c +586 -0
  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 +21 -13
  73. data/lib/oj/error.rb +10 -12
  74. data/lib/oj/json.rb +188 -0
  75. data/lib/oj/mimic.rb +165 -26
  76. data/lib/oj/saj.rb +20 -6
  77. data/lib/oj/schandler.rb +5 -4
  78. data/lib/oj/state.rb +135 -0
  79. data/lib/oj/version.rb +2 -3
  80. data/lib/oj.rb +3 -31
  81. data/pages/Advanced.md +22 -0
  82. data/pages/Compatibility.md +25 -0
  83. data/pages/Custom.md +23 -0
  84. data/pages/Encoding.md +65 -0
  85. data/pages/InstallOptions.md +20 -0
  86. data/pages/JsonGem.md +94 -0
  87. data/pages/Modes.md +161 -0
  88. data/pages/Options.md +337 -0
  89. data/pages/Parser.md +309 -0
  90. data/pages/Rails.md +167 -0
  91. data/pages/Security.md +20 -0
  92. data/pages/WAB.md +13 -0
  93. metadata +126 -163
  94. data/ext/oj/hash.c +0 -163
  95. data/ext/oj/hash.h +0 -46
  96. data/ext/oj/hash_test.c +0 -512
  97. data/test/_test_active.rb +0 -76
  98. data/test/_test_active_mimic.rb +0 -96
  99. data/test/_test_mimic_rails.rb +0 -126
  100. data/test/activesupport_datetime_test.rb +0 -23
  101. data/test/bug.rb +0 -51
  102. data/test/bug2.rb +0 -10
  103. data/test/bug3.rb +0 -46
  104. data/test/bug_fast.rb +0 -32
  105. data/test/bug_load.rb +0 -24
  106. data/test/crash.rb +0 -111
  107. data/test/curl/curl_oj.rb +0 -46
  108. data/test/curl/get_oj.rb +0 -24
  109. data/test/curl/just_curl.rb +0 -31
  110. data/test/curl/just_oj.rb +0 -51
  111. data/test/example.rb +0 -11
  112. data/test/files.rb +0 -29
  113. data/test/foo.rb +0 -24
  114. data/test/helper.rb +0 -27
  115. data/test/io.rb +0 -48
  116. data/test/isolated/shared.rb +0 -310
  117. data/test/isolated/test_mimic_after.rb +0 -13
  118. data/test/isolated/test_mimic_alone.rb +0 -12
  119. data/test/isolated/test_mimic_as_json.rb +0 -45
  120. data/test/isolated/test_mimic_before.rb +0 -13
  121. data/test/isolated/test_mimic_define.rb +0 -28
  122. data/test/isolated/test_mimic_rails_after.rb +0 -22
  123. data/test/isolated/test_mimic_rails_before.rb +0 -21
  124. data/test/isolated/test_mimic_rails_datetime.rb +0 -27
  125. data/test/isolated/test_mimic_redefine.rb +0 -15
  126. data/test/mod.rb +0 -16
  127. data/test/perf.rb +0 -107
  128. data/test/perf_compat.rb +0 -128
  129. data/test/perf_fast.rb +0 -164
  130. data/test/perf_file.rb +0 -64
  131. data/test/perf_object.rb +0 -138
  132. data/test/perf_saj.rb +0 -109
  133. data/test/perf_scp.rb +0 -151
  134. data/test/perf_simple.rb +0 -287
  135. data/test/perf_strict.rb +0 -128
  136. data/test/rails.rb +0 -50
  137. data/test/russian.rb +0 -18
  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 -55
  151. data/test/sample_json.rb +0 -37
  152. data/test/struct.rb +0 -29
  153. data/test/test_compat.rb +0 -398
  154. data/test/test_debian.rb +0 -53
  155. data/test/test_fast.rb +0 -458
  156. data/test/test_file.rb +0 -245
  157. data/test/test_gc.rb +0 -49
  158. data/test/test_hash.rb +0 -29
  159. data/test/test_object.rb +0 -745
  160. data/test/test_saj.rb +0 -186
  161. data/test/test_scp.rb +0 -396
  162. data/test/test_serializer.rb +0 -59
  163. data/test/test_strict.rb +0 -254
  164. data/test/test_various.rb +0 -1383
  165. data/test/test_writer.rb +0 -308
  166. data/test/write_timebars.rb +0 -31
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);