oj 3.13.7 → 3.13.23

Sign up to get free protection for your applications and to get access to all the features.
Files changed (83) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +75 -0
  3. data/README.md +11 -0
  4. data/ext/oj/buf.h +4 -0
  5. data/ext/oj/circarray.c +1 -1
  6. data/ext/oj/code.c +15 -22
  7. data/ext/oj/compat.c +10 -10
  8. data/ext/oj/custom.c +66 -112
  9. data/ext/oj/dump.c +147 -184
  10. data/ext/oj/dump.h +25 -8
  11. data/ext/oj/dump_compat.c +47 -89
  12. data/ext/oj/dump_leaf.c +14 -58
  13. data/ext/oj/dump_object.c +72 -188
  14. data/ext/oj/dump_strict.c +19 -31
  15. data/ext/oj/encoder.c +43 -0
  16. data/ext/oj/extconf.rb +5 -4
  17. data/ext/oj/fast.c +36 -24
  18. data/ext/oj/intern.c +22 -12
  19. data/ext/oj/intern.h +1 -1
  20. data/ext/oj/mimic_json.c +74 -73
  21. data/ext/oj/object.c +54 -72
  22. data/ext/oj/odd.c +83 -63
  23. data/ext/oj/odd.h +13 -13
  24. data/ext/oj/oj.c +166 -175
  25. data/ext/oj/oj.h +25 -3
  26. data/ext/oj/parse.c +123 -79
  27. data/ext/oj/parse.h +2 -0
  28. data/ext/oj/parser.c +77 -21
  29. data/ext/oj/parser.h +12 -0
  30. data/ext/oj/rails.c +46 -70
  31. data/ext/oj/rails.h +1 -1
  32. data/ext/oj/reader.c +2 -0
  33. data/ext/oj/saj.c +11 -23
  34. data/ext/oj/saj2.c +333 -85
  35. data/ext/oj/saj2.h +23 -0
  36. data/ext/oj/sparse.c +4 -0
  37. data/ext/oj/stream_writer.c +3 -1
  38. data/ext/oj/strict.c +13 -13
  39. data/ext/oj/string_writer.c +12 -5
  40. data/ext/oj/usual.c +86 -131
  41. data/ext/oj/usual.h +68 -0
  42. data/ext/oj/val_stack.c +1 -1
  43. data/ext/oj/validate.c +21 -26
  44. data/ext/oj/wab.c +22 -27
  45. data/lib/oj/saj.rb +20 -6
  46. data/lib/oj/state.rb +1 -1
  47. data/lib/oj/version.rb +1 -1
  48. data/pages/Compatibility.md +1 -1
  49. data/pages/JsonGem.md +15 -0
  50. data/pages/Modes.md +6 -3
  51. data/pages/Options.md +6 -0
  52. data/pages/Rails.md +12 -0
  53. data/test/activesupport7/abstract_unit.rb +49 -0
  54. data/test/activesupport7/decoding_test.rb +125 -0
  55. data/test/activesupport7/encoding_test.rb +486 -0
  56. data/test/activesupport7/encoding_test_cases.rb +104 -0
  57. data/test/activesupport7/time_zone_test_helpers.rb +47 -0
  58. data/test/bar.rb +3 -8
  59. data/test/bug.rb +16 -0
  60. data/test/foo.rb +71 -7
  61. data/test/helper.rb +8 -2
  62. data/test/json_gem/json_generator_test.rb +5 -4
  63. data/test/json_gem/json_parser_test.rb +8 -1
  64. data/test/json_gem/test_helper.rb +7 -3
  65. data/test/perf_dump.rb +50 -0
  66. data/test/test_compat.rb +25 -0
  67. data/test/test_custom.rb +13 -2
  68. data/test/test_fast.rb +37 -7
  69. data/test/test_file.rb +23 -7
  70. data/test/test_gc.rb +11 -0
  71. data/test/test_object.rb +8 -10
  72. data/test/test_parser.rb +3 -19
  73. data/test/test_parser_debug.rb +27 -0
  74. data/test/test_parser_saj.rb +92 -2
  75. data/test/test_saj.rb +1 -1
  76. data/test/test_scp.rb +2 -4
  77. data/test/test_strict.rb +2 -0
  78. data/test/test_various.rb +32 -2
  79. data/test/test_wab.rb +2 -0
  80. data/test/tests.rb +9 -1
  81. data/test/tests_mimic.rb +9 -0
  82. data/test/tests_mimic_addition.rb +9 -0
  83. metadata +15 -115
data/ext/oj/saj2.c CHANGED
@@ -3,21 +3,11 @@
3
3
  #include "cache.h"
4
4
  #include "oj.h"
5
5
  #include "parser.h"
6
-
7
- typedef struct _delegate {
8
- VALUE handler;
9
- VALUE * keys;
10
- VALUE * tail;
11
- size_t klen;
12
- struct _cache *str_cache;
13
- uint8_t cache_str;
14
- bool cache_keys;
15
- bool thread_safe;
16
- } * Delegate;
6
+ #include "saj2.h"
17
7
 
18
8
  static VALUE get_key(ojParser p) {
19
- Delegate d = (Delegate)p->ctx;
20
- const char * key = buf_str(&p->key);
9
+ Saj d = (Saj)p->ctx;
10
+ const char *key = buf_str(&p->key);
21
11
  size_t len = buf_len(&p->key);
22
12
  volatile VALUE rkey;
23
13
 
@@ -29,7 +19,7 @@ static VALUE get_key(ojParser p) {
29
19
  return rkey;
30
20
  }
31
21
 
32
- static void push_key(Delegate d, VALUE key) {
22
+ static void push_key(Saj d, VALUE key) {
33
23
  if (d->klen <= (size_t)(d->tail - d->keys)) {
34
24
  size_t off = d->tail - d->keys;
35
25
 
@@ -45,31 +35,55 @@ static void noop(ojParser p) {
45
35
  }
46
36
 
47
37
  static void open_object(ojParser p) {
48
- rb_funcall(((Delegate)p->ctx)->handler, oj_hash_start_id, 1, Qnil);
38
+ rb_funcall(((Saj)p->ctx)->handler, oj_hash_start_id, 1, Qnil);
39
+ }
40
+
41
+ static void open_object_loc(ojParser p) {
42
+ rb_funcall(((Saj)p->ctx)->handler, oj_hash_start_id, 3, Qnil, LONG2FIX(p->line), LONG2FIX(p->cur - p->col));
49
43
  }
50
44
 
51
45
  static void open_object_key(ojParser p) {
52
- Delegate d = (Delegate)p->ctx;
46
+ Saj d = (Saj)p->ctx;
53
47
  volatile VALUE key = get_key(p);
54
48
 
55
49
  push_key(d, key);
56
50
  rb_funcall(d->handler, oj_hash_start_id, 1, key);
57
51
  }
58
52
 
53
+ static void open_object_loc_key(ojParser p) {
54
+ Saj d = (Saj)p->ctx;
55
+ volatile VALUE key = get_key(p);
56
+
57
+ push_key(d, key);
58
+ rb_funcall(d->handler, oj_hash_start_id, 3, key, LONG2FIX(p->line), LONG2FIX(p->cur - p->col));
59
+ }
60
+
59
61
  static void open_array(ojParser p) {
60
- rb_funcall(((Delegate)p->ctx)->handler, oj_array_start_id, 1, Qnil);
62
+ rb_funcall(((Saj)p->ctx)->handler, oj_array_start_id, 1, Qnil);
63
+ }
64
+
65
+ static void open_array_loc(ojParser p) {
66
+ rb_funcall(((Saj)p->ctx)->handler, oj_array_start_id, 3, Qnil, LONG2FIX(p->line), LONG2FIX(p->cur - p->col));
61
67
  }
62
68
 
63
69
  static void open_array_key(ojParser p) {
64
- Delegate d = (Delegate)p->ctx;
70
+ Saj d = (Saj)p->ctx;
65
71
  volatile VALUE key = get_key(p);
66
72
 
67
73
  push_key(d, key);
68
74
  rb_funcall(d->handler, oj_array_start_id, 1, key);
69
75
  }
70
76
 
77
+ static void open_array_loc_key(ojParser p) {
78
+ Saj d = (Saj)p->ctx;
79
+ volatile VALUE key = get_key(p);
80
+
81
+ push_key(d, key);
82
+ rb_funcall(d->handler, oj_array_start_id, 3, key, LONG2FIX(p->line), LONG2FIX(p->cur - p->col));
83
+ }
84
+
71
85
  static void close_object(ojParser p) {
72
- Delegate d = (Delegate)p->ctx;
86
+ Saj d = (Saj)p->ctx;
73
87
  VALUE key = Qnil;
74
88
 
75
89
  if (OBJECT_FUN == p->stack[p->depth]) {
@@ -82,8 +96,22 @@ static void close_object(ojParser p) {
82
96
  rb_funcall(d->handler, oj_hash_end_id, 1, key);
83
97
  }
84
98
 
99
+ static void close_object_loc(ojParser p) {
100
+ Saj d = (Saj)p->ctx;
101
+ VALUE key = Qnil;
102
+
103
+ if (OBJECT_FUN == p->stack[p->depth]) {
104
+ d->tail--;
105
+ if (d->tail < d->keys) {
106
+ rb_raise(rb_eIndexError, "accessing key stack");
107
+ }
108
+ key = *d->tail;
109
+ }
110
+ rb_funcall(d->handler, oj_hash_end_id, 3, key, LONG2FIX(p->line), LONG2FIX(p->cur - p->col));
111
+ }
112
+
85
113
  static void close_array(ojParser p) {
86
- Delegate d = (Delegate)p->ctx;
114
+ Saj d = (Saj)p->ctx;
87
115
  VALUE key = Qnil;
88
116
 
89
117
  if (OBJECT_FUN == p->stack[p->depth]) {
@@ -96,66 +124,200 @@ static void close_array(ojParser p) {
96
124
  rb_funcall(d->handler, oj_array_end_id, 1, key);
97
125
  }
98
126
 
127
+ static void close_array_loc(ojParser p) {
128
+ Saj d = (Saj)p->ctx;
129
+ VALUE key = Qnil;
130
+
131
+ if (OBJECT_FUN == p->stack[p->depth]) {
132
+ d->tail--;
133
+ if (d->tail < d->keys) {
134
+ rb_raise(rb_eIndexError, "accessing key stack");
135
+ }
136
+ key = *d->tail;
137
+ }
138
+ rb_funcall(d->handler, oj_array_end_id, 3, key, LONG2FIX(p->line), LONG2FIX(p->cur - p->col));
139
+ }
140
+
99
141
  static void add_null(ojParser p) {
100
- rb_funcall(((Delegate)p->ctx)->handler, oj_add_value_id, 2, Qnil, Qnil);
142
+ rb_funcall(((Saj)p->ctx)->handler, oj_add_value_id, 2, Qnil, Qnil);
143
+ }
144
+
145
+ static void add_null_loc(ojParser p) {
146
+ rb_funcall(((Saj)p->ctx)->handler,
147
+ oj_add_value_id,
148
+ 4,
149
+ Qnil,
150
+ Qnil,
151
+ LONG2FIX(p->line),
152
+ LONG2FIX(p->cur - p->col));
101
153
  }
102
154
 
103
155
  static void add_null_key(ojParser p) {
104
- rb_funcall(((Delegate)p->ctx)->handler, oj_add_value_id, 2, Qnil, get_key(p));
156
+ rb_funcall(((Saj)p->ctx)->handler, oj_add_value_id, 2, Qnil, get_key(p));
157
+ }
158
+
159
+ static void add_null_key_loc(ojParser p) {
160
+ rb_funcall(((Saj)p->ctx)->handler,
161
+ oj_add_value_id,
162
+ 4,
163
+ Qnil,
164
+ get_key(p),
165
+ LONG2FIX(p->line),
166
+ LONG2FIX(p->cur - p->col));
105
167
  }
106
168
 
107
169
  static void add_true(ojParser p) {
108
- rb_funcall(((Delegate)p->ctx)->handler, oj_add_value_id, 2, Qtrue, Qnil);
170
+ rb_funcall(((Saj)p->ctx)->handler, oj_add_value_id, 2, Qtrue, Qnil);
171
+ }
172
+
173
+ static void add_true_loc(ojParser p) {
174
+ rb_funcall(((Saj)p->ctx)->handler,
175
+ oj_add_value_id,
176
+ 4,
177
+ Qtrue,
178
+ Qnil,
179
+ LONG2FIX(p->line),
180
+ LONG2FIX(p->cur - p->col));
109
181
  }
110
182
 
111
183
  static void add_true_key(ojParser p) {
112
- rb_funcall(((Delegate)p->ctx)->handler, oj_add_value_id, 2, Qtrue, get_key(p));
184
+ rb_funcall(((Saj)p->ctx)->handler, oj_add_value_id, 2, Qtrue, get_key(p));
185
+ }
186
+
187
+ static void add_true_key_loc(ojParser p) {
188
+ rb_funcall(((Saj)p->ctx)->handler,
189
+ oj_add_value_id,
190
+ 4,
191
+ Qtrue,
192
+ get_key(p),
193
+ LONG2FIX(p->line),
194
+ LONG2FIX(p->cur - p->col));
113
195
  }
114
196
 
115
197
  static void add_false(ojParser p) {
116
- rb_funcall(((Delegate)p->ctx)->handler, oj_add_value_id, 2, Qfalse, Qnil);
198
+ rb_funcall(((Saj)p->ctx)->handler, oj_add_value_id, 2, Qfalse, Qnil);
199
+ }
200
+
201
+ static void add_false_loc(ojParser p) {
202
+ rb_funcall(((Saj)p->ctx)->handler,
203
+ oj_add_value_id,
204
+ 4,
205
+ Qfalse,
206
+ Qnil,
207
+ LONG2FIX(p->line),
208
+ LONG2FIX(p->cur - p->col));
117
209
  }
118
210
 
119
211
  static void add_false_key(ojParser p) {
120
- rb_funcall(((Delegate)p->ctx)->handler, oj_add_value_id, 2, Qfalse, get_key(p));
212
+ rb_funcall(((Saj)p->ctx)->handler, oj_add_value_id, 2, Qfalse, get_key(p));
213
+ }
214
+
215
+ static void add_false_key_loc(ojParser p) {
216
+ rb_funcall(((Saj)p->ctx)->handler,
217
+ oj_add_value_id,
218
+ 4,
219
+ Qfalse,
220
+ get_key(p),
221
+ LONG2FIX(p->line),
222
+ LONG2FIX(p->cur - p->col));
121
223
  }
122
224
 
123
225
  static void add_int(ojParser p) {
124
- rb_funcall(((Delegate)p->ctx)->handler, oj_add_value_id, 2, LONG2NUM(p->num.fixnum), Qnil);
226
+ rb_funcall(((Saj)p->ctx)->handler, oj_add_value_id, 2, LONG2NUM(p->num.fixnum), Qnil);
227
+ }
228
+
229
+ static void add_int_loc(ojParser p) {
230
+ rb_funcall(((Saj)p->ctx)->handler,
231
+ oj_add_value_id,
232
+ 4,
233
+ LONG2NUM(p->num.fixnum),
234
+ Qnil,
235
+ LONG2FIX(p->line),
236
+ LONG2FIX(p->cur - p->col));
125
237
  }
126
238
 
127
239
  static void add_int_key(ojParser p) {
128
- rb_funcall(((Delegate)p->ctx)->handler, oj_add_value_id, 2, LONG2NUM(p->num.fixnum), get_key(p));
240
+ rb_funcall(((Saj)p->ctx)->handler, oj_add_value_id, 2, LONG2NUM(p->num.fixnum), get_key(p));
241
+ }
242
+
243
+ static void add_int_key_loc(ojParser p) {
244
+ rb_funcall(((Saj)p->ctx)->handler,
245
+ oj_add_value_id,
246
+ 4,
247
+ LONG2NUM(p->num.fixnum),
248
+ get_key(p),
249
+ LONG2FIX(p->line),
250
+ LONG2FIX(p->cur - p->col));
129
251
  }
130
252
 
131
253
  static void add_float(ojParser p) {
132
- rb_funcall(((Delegate)p->ctx)->handler, oj_add_value_id, 2, rb_float_new(p->num.dub), Qnil);
254
+ rb_funcall(((Saj)p->ctx)->handler, oj_add_value_id, 2, rb_float_new(p->num.dub), Qnil);
255
+ }
256
+
257
+ static void add_float_loc(ojParser p) {
258
+ rb_funcall(((Saj)p->ctx)->handler,
259
+ oj_add_value_id,
260
+ 4,
261
+ rb_float_new(p->num.dub),
262
+ Qnil,
263
+ LONG2FIX(p->line),
264
+ LONG2FIX(p->cur - p->col));
133
265
  }
134
266
 
135
267
  static void add_float_key(ojParser p) {
136
- rb_funcall(((Delegate)p->ctx)->handler, oj_add_value_id, 2, rb_float_new(p->num.dub), get_key(p));
268
+ rb_funcall(((Saj)p->ctx)->handler, oj_add_value_id, 2, rb_float_new(p->num.dub), get_key(p));
269
+ }
270
+
271
+ static void add_float_key_loc(ojParser p) {
272
+ rb_funcall(((Saj)p->ctx)->handler,
273
+ oj_add_value_id,
274
+ 4,
275
+ rb_float_new(p->num.dub),
276
+ get_key(p),
277
+ LONG2FIX(p->line),
278
+ LONG2FIX(p->cur - p->col));
137
279
  }
138
280
 
139
281
  static void add_big(ojParser p) {
140
- rb_funcall((VALUE)p->ctx,
282
+ rb_funcall(((Saj)p->ctx)->handler,
141
283
  oj_add_value_id,
142
284
  2,
143
285
  rb_funcall(rb_cObject, oj_bigdecimal_id, 1, rb_str_new(buf_str(&p->buf), buf_len(&p->buf))),
144
286
  Qnil);
145
287
  }
146
288
 
289
+ static void add_big_loc(ojParser p) {
290
+ rb_funcall(((Saj)p->ctx)->handler,
291
+ oj_add_value_id,
292
+ 4,
293
+ rb_funcall(rb_cObject, oj_bigdecimal_id, 1, rb_str_new(buf_str(&p->buf), buf_len(&p->buf))),
294
+ Qnil,
295
+ LONG2FIX(p->line),
296
+ LONG2FIX(p->cur - p->col));
297
+ }
298
+
147
299
  static void add_big_key(ojParser p) {
148
- rb_funcall((VALUE)p->ctx,
300
+ rb_funcall(((Saj)p->ctx)->handler,
149
301
  oj_add_value_id,
150
302
  2,
151
303
  rb_funcall(rb_cObject, oj_bigdecimal_id, 1, rb_str_new(buf_str(&p->buf), buf_len(&p->buf))),
152
304
  get_key(p));
153
305
  }
154
306
 
307
+ static void add_big_key_loc(ojParser p) {
308
+ rb_funcall(((Saj)p->ctx)->handler,
309
+ oj_add_value_id,
310
+ 4,
311
+ rb_funcall(rb_cObject, oj_bigdecimal_id, 1, rb_str_new(buf_str(&p->buf), buf_len(&p->buf))),
312
+ get_key(p),
313
+ LONG2FIX(p->line),
314
+ LONG2FIX(p->cur - p->col));
315
+ }
316
+
155
317
  static void add_str(ojParser p) {
156
- Delegate d = (Delegate)p->ctx;
318
+ Saj d = (Saj)p->ctx;
157
319
  volatile VALUE rstr;
158
- const char * str = buf_str(&p->buf);
320
+ const char *str = buf_str(&p->buf);
159
321
  size_t len = buf_len(&p->buf);
160
322
 
161
323
  if (d->cache_str < len) {
@@ -166,10 +328,24 @@ static void add_str(ojParser p) {
166
328
  rb_funcall(d->handler, oj_add_value_id, 2, rstr, Qnil);
167
329
  }
168
330
 
331
+ static void add_str_loc(ojParser p) {
332
+ Saj d = (Saj)p->ctx;
333
+ volatile VALUE rstr;
334
+ const char *str = buf_str(&p->buf);
335
+ size_t len = buf_len(&p->buf);
336
+
337
+ if (d->cache_str < len) {
338
+ rstr = cache_intern(d->str_cache, str, len);
339
+ } else {
340
+ rstr = rb_utf8_str_new(str, len);
341
+ }
342
+ rb_funcall(d->handler, oj_add_value_id, 4, rstr, Qnil, LONG2FIX(p->line), LONG2FIX(p->cur - p->col));
343
+ }
344
+
169
345
  static void add_str_key(ojParser p) {
170
- Delegate d = (Delegate)p->ctx;
346
+ Saj d = (Saj)p->ctx;
171
347
  volatile VALUE rstr;
172
- const char * str = buf_str(&p->buf);
348
+ const char *str = buf_str(&p->buf);
173
349
  size_t len = buf_len(&p->buf);
174
350
 
175
351
  if (d->cache_str < len) {
@@ -180,6 +356,20 @@ static void add_str_key(ojParser p) {
180
356
  rb_funcall(d->handler, oj_add_value_id, 2, rstr, get_key(p));
181
357
  }
182
358
 
359
+ static void add_str_key_loc(ojParser p) {
360
+ Saj d = (Saj)p->ctx;
361
+ volatile VALUE rstr;
362
+ const char *str = buf_str(&p->buf);
363
+ size_t len = buf_len(&p->buf);
364
+
365
+ if (d->cache_str < len) {
366
+ rstr = cache_intern(d->str_cache, str, len);
367
+ } else {
368
+ rstr = rb_utf8_str_new(str, len);
369
+ }
370
+ rb_funcall(d->handler, oj_add_value_id, 4, rstr, get_key(p), LONG2FIX(p->line), LONG2FIX(p->cur - p->col));
371
+ }
372
+
183
373
  static void reset(ojParser p) {
184
374
  Funcs end = p->funcs + 3;
185
375
  Funcs f;
@@ -200,7 +390,7 @@ static void reset(ojParser p) {
200
390
  }
201
391
 
202
392
  static VALUE option(ojParser p, const char *key, VALUE value) {
203
- Delegate d = (Delegate)p->ctx;
393
+ Saj d = (Saj)p->ctx;
204
394
 
205
395
  if (0 == strcmp(key, "handler")) {
206
396
  return d->handler;
@@ -210,53 +400,107 @@ static VALUE option(ojParser p, const char *key, VALUE value) {
210
400
  d->handler = value;
211
401
  reset(p);
212
402
  if (rb_respond_to(value, oj_hash_start_id)) {
213
- p->funcs[TOP_FUN].open_object = open_object;
214
- p->funcs[ARRAY_FUN].open_object = open_object;
215
- p->funcs[OBJECT_FUN].open_object = open_object_key;
403
+ if (1 == rb_obj_method_arity(value, oj_hash_start_id)) {
404
+ p->funcs[TOP_FUN].open_object = open_object;
405
+ p->funcs[ARRAY_FUN].open_object = open_object;
406
+ p->funcs[OBJECT_FUN].open_object = open_object_key;
407
+ } else {
408
+ p->funcs[TOP_FUN].open_object = open_object_loc;
409
+ p->funcs[ARRAY_FUN].open_object = open_object_loc;
410
+ p->funcs[OBJECT_FUN].open_object = open_object_loc_key;
411
+ }
216
412
  }
217
413
  if (rb_respond_to(value, oj_array_start_id)) {
218
- p->funcs[TOP_FUN].open_array = open_array;
219
- p->funcs[ARRAY_FUN].open_array = open_array;
220
- p->funcs[OBJECT_FUN].open_array = open_array_key;
414
+ if (1 == rb_obj_method_arity(value, oj_array_start_id)) {
415
+ p->funcs[TOP_FUN].open_array = open_array;
416
+ p->funcs[ARRAY_FUN].open_array = open_array;
417
+ p->funcs[OBJECT_FUN].open_array = open_array_key;
418
+ } else {
419
+ p->funcs[TOP_FUN].open_array = open_array_loc;
420
+ p->funcs[ARRAY_FUN].open_array = open_array_loc;
421
+ p->funcs[OBJECT_FUN].open_array = open_array_loc_key;
422
+ }
221
423
  }
222
424
  if (rb_respond_to(value, oj_hash_end_id)) {
223
- p->funcs[TOP_FUN].close_object = close_object;
224
- p->funcs[ARRAY_FUN].close_object = close_object;
225
- p->funcs[OBJECT_FUN].close_object = close_object;
425
+ if (1 == rb_obj_method_arity(value, oj_hash_end_id)) {
426
+ p->funcs[TOP_FUN].close_object = close_object;
427
+ p->funcs[ARRAY_FUN].close_object = close_object;
428
+ p->funcs[OBJECT_FUN].close_object = close_object;
429
+ } else {
430
+ p->funcs[TOP_FUN].close_object = close_object_loc;
431
+ p->funcs[ARRAY_FUN].close_object = close_object_loc;
432
+ p->funcs[OBJECT_FUN].close_object = close_object_loc;
433
+ }
226
434
  }
227
435
  if (rb_respond_to(value, oj_array_end_id)) {
228
- p->funcs[TOP_FUN].close_array = close_array;
229
- p->funcs[ARRAY_FUN].close_array = close_array;
230
- p->funcs[OBJECT_FUN].close_array = close_array;
436
+ if (1 == rb_obj_method_arity(value, oj_array_end_id)) {
437
+ p->funcs[TOP_FUN].close_array = close_array;
438
+ p->funcs[ARRAY_FUN].close_array = close_array;
439
+ p->funcs[OBJECT_FUN].close_array = close_array;
440
+ } else {
441
+ p->funcs[TOP_FUN].close_array = close_array_loc;
442
+ p->funcs[ARRAY_FUN].close_array = close_array_loc;
443
+ p->funcs[OBJECT_FUN].close_array = close_array_loc;
444
+ }
231
445
  }
232
446
  if (rb_respond_to(value, oj_add_value_id)) {
233
- p->funcs[TOP_FUN].add_null = add_null;
234
- p->funcs[ARRAY_FUN].add_null = add_null;
235
- p->funcs[OBJECT_FUN].add_null = add_null_key;
236
-
237
- p->funcs[TOP_FUN].add_true = add_true;
238
- p->funcs[ARRAY_FUN].add_true = add_true;
239
- p->funcs[OBJECT_FUN].add_true = add_true_key;
240
-
241
- p->funcs[TOP_FUN].add_false = add_false;
242
- p->funcs[ARRAY_FUN].add_false = add_false;
243
- p->funcs[OBJECT_FUN].add_false = add_false_key;
244
-
245
- p->funcs[TOP_FUN].add_int = add_int;
246
- p->funcs[ARRAY_FUN].add_int = add_int;
247
- p->funcs[OBJECT_FUN].add_int = add_int_key;
248
-
249
- p->funcs[TOP_FUN].add_float = add_float;
250
- p->funcs[ARRAY_FUN].add_float = add_float;
251
- p->funcs[OBJECT_FUN].add_float = add_float_key;
252
-
253
- p->funcs[TOP_FUN].add_big = add_big;
254
- p->funcs[ARRAY_FUN].add_big = add_big;
255
- p->funcs[OBJECT_FUN].add_big = add_big_key;
256
-
257
- p->funcs[TOP_FUN].add_str = add_str;
258
- p->funcs[ARRAY_FUN].add_str = add_str;
259
- p->funcs[OBJECT_FUN].add_str = add_str_key;
447
+ if (2 == rb_obj_method_arity(value, oj_add_value_id)) {
448
+ p->funcs[TOP_FUN].add_null = add_null;
449
+ p->funcs[ARRAY_FUN].add_null = add_null;
450
+ p->funcs[OBJECT_FUN].add_null = add_null_key;
451
+
452
+ p->funcs[TOP_FUN].add_true = add_true;
453
+ p->funcs[ARRAY_FUN].add_true = add_true;
454
+ p->funcs[OBJECT_FUN].add_true = add_true_key;
455
+
456
+ p->funcs[TOP_FUN].add_false = add_false;
457
+ p->funcs[ARRAY_FUN].add_false = add_false;
458
+ p->funcs[OBJECT_FUN].add_false = add_false_key;
459
+
460
+ p->funcs[TOP_FUN].add_int = add_int;
461
+ p->funcs[ARRAY_FUN].add_int = add_int;
462
+ p->funcs[OBJECT_FUN].add_int = add_int_key;
463
+
464
+ p->funcs[TOP_FUN].add_float = add_float;
465
+ p->funcs[ARRAY_FUN].add_float = add_float;
466
+ p->funcs[OBJECT_FUN].add_float = add_float_key;
467
+
468
+ p->funcs[TOP_FUN].add_big = add_big;
469
+ p->funcs[ARRAY_FUN].add_big = add_big;
470
+ p->funcs[OBJECT_FUN].add_big = add_big_key;
471
+
472
+ p->funcs[TOP_FUN].add_str = add_str;
473
+ p->funcs[ARRAY_FUN].add_str = add_str;
474
+ p->funcs[OBJECT_FUN].add_str = add_str_key;
475
+ } else {
476
+ p->funcs[TOP_FUN].add_null = add_null_loc;
477
+ p->funcs[ARRAY_FUN].add_null = add_null_loc;
478
+ p->funcs[OBJECT_FUN].add_null = add_null_key_loc;
479
+
480
+ p->funcs[TOP_FUN].add_true = add_true_loc;
481
+ p->funcs[ARRAY_FUN].add_true = add_true_loc;
482
+ p->funcs[OBJECT_FUN].add_true = add_true_key_loc;
483
+
484
+ p->funcs[TOP_FUN].add_false = add_false_loc;
485
+ p->funcs[ARRAY_FUN].add_false = add_false_loc;
486
+ p->funcs[OBJECT_FUN].add_false = add_false_key_loc;
487
+
488
+ p->funcs[TOP_FUN].add_int = add_int_loc;
489
+ p->funcs[ARRAY_FUN].add_int = add_int_loc;
490
+ p->funcs[OBJECT_FUN].add_int = add_int_key_loc;
491
+
492
+ p->funcs[TOP_FUN].add_float = add_float_loc;
493
+ p->funcs[ARRAY_FUN].add_float = add_float_loc;
494
+ p->funcs[OBJECT_FUN].add_float = add_float_key_loc;
495
+
496
+ p->funcs[TOP_FUN].add_big = add_big_loc;
497
+ p->funcs[ARRAY_FUN].add_big = add_big_loc;
498
+ p->funcs[OBJECT_FUN].add_big = add_big_key_loc;
499
+
500
+ p->funcs[TOP_FUN].add_str = add_str_loc;
501
+ p->funcs[ARRAY_FUN].add_str = add_str_loc;
502
+ p->funcs[OBJECT_FUN].add_str = add_str_key_loc;
503
+ }
260
504
  }
261
505
  return Qnil;
262
506
  }
@@ -283,7 +527,7 @@ static VALUE option(ojParser p, const char *key, VALUE value) {
283
527
 
284
528
  return INT2NUM((int)d->cache_str);
285
529
  }
286
- rb_raise(rb_eArgError, "%s is not an option for the SAJ (Simple API for JSON) delegate", key);
530
+ rb_raise(rb_eArgError, "%s is not an option for the SAJ (Simple API for JSON) saj", key);
287
531
 
288
532
  return Qnil; // Never reached due to the raise but required by the compiler.
289
533
  }
@@ -293,13 +537,13 @@ static VALUE result(ojParser p) {
293
537
  }
294
538
 
295
539
  static void start(ojParser p) {
296
- Delegate d = (Delegate)p->ctx;
540
+ Saj d = (Saj)p->ctx;
297
541
 
298
542
  d->tail = d->keys;
299
543
  }
300
544
 
301
545
  static void dfree(ojParser p) {
302
- Delegate d = (Delegate)p->ctx;
546
+ Saj d = (Saj)p->ctx;
303
547
 
304
548
  if (NULL != d->keys) {
305
549
  xfree(d->keys);
@@ -309,11 +553,11 @@ static void dfree(ojParser p) {
309
553
  }
310
554
 
311
555
  static void mark(ojParser p) {
312
- if (NULL == p->ctx) {
556
+ if (NULL == p || NULL == p->ctx) {
313
557
  return;
314
558
  }
315
- Delegate d = (Delegate)p->ctx;
316
- VALUE *kp;
559
+ Saj d = (Saj)p->ctx;
560
+ VALUE *kp;
317
561
 
318
562
  cache_mark(d->str_cache);
319
563
  if (Qnil != d->handler) {
@@ -330,9 +574,7 @@ static VALUE form_str(const char *str, size_t len) {
330
574
  return rb_str_freeze(rb_utf8_str_new(str, len));
331
575
  }
332
576
 
333
- void oj_set_parser_saj(ojParser p) {
334
- Delegate d = ALLOC(struct _delegate);
335
-
577
+ void oj_init_saj(ojParser p, Saj d) {
336
578
  d->klen = 256;
337
579
  d->keys = ALLOC_N(VALUE, d->klen);
338
580
  d->tail = d->keys;
@@ -346,3 +588,9 @@ void oj_set_parser_saj(ojParser p) {
346
588
  p->mark = mark;
347
589
  p->start = start;
348
590
  }
591
+
592
+ void oj_set_parser_saj(ojParser p) {
593
+ Saj d = ALLOC(struct _saj);
594
+
595
+ oj_init_saj(p, d);
596
+ }
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);
data/ext/oj/sparse.c CHANGED
@@ -953,7 +953,11 @@ CLEANUP:
953
953
  }
954
954
  stack_cleanup(&pi->stack);
955
955
  if (0 != fd) {
956
+ #ifdef _WIN32
957
+ rb_w32_close(fd);
958
+ #else
956
959
  close(fd);
960
+ #endif
957
961
  }
958
962
  if (err_has(&pi->err)) {
959
963
  rb_set_errinfo(Qnil);
@@ -315,8 +315,10 @@ static VALUE stream_writer_flush(VALUE self) {
315
315
  * will create that element in the JSON document and subsequent pushes will add
316
316
  * the elements to that array or object until a pop() is called.
317
317
  */
318
- void oj_stream_writer_init() {
318
+ void oj_stream_writer_init(void) {
319
319
  oj_stream_writer_class = rb_define_class_under(Oj, "StreamWriter", rb_cObject);
320
+ rb_gc_register_address(&oj_stream_writer_class);
321
+ rb_undef_alloc_func(oj_stream_writer_class);
320
322
  rb_define_module_function(oj_stream_writer_class, "new", stream_writer_new, -1);
321
323
  rb_define_method(oj_stream_writer_class, "push_key", stream_writer_push_key, 1);
322
324
  rb_define_method(oj_stream_writer_class, "push_object", stream_writer_push_object, -1);