oj 3.13.14 → 3.13.22

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +32 -0
  3. data/README.md +2 -0
  4. data/ext/oj/buf.h +4 -0
  5. data/ext/oj/compat.c +10 -10
  6. data/ext/oj/custom.c +34 -53
  7. data/ext/oj/dump.c +24 -13
  8. data/ext/oj/dump_compat.c +5 -10
  9. data/ext/oj/dump_object.c +5 -60
  10. data/ext/oj/dump_strict.c +5 -5
  11. data/ext/oj/extconf.rb +5 -4
  12. data/ext/oj/fast.c +15 -13
  13. data/ext/oj/intern.c +6 -9
  14. data/ext/oj/introspect.c +96 -0
  15. data/ext/oj/mimic_json.c +18 -8
  16. data/ext/oj/object.c +42 -41
  17. data/ext/oj/oj.c +27 -4
  18. data/ext/oj/oj.h +4 -1
  19. data/ext/oj/parse.c +111 -76
  20. data/ext/oj/parse.h +2 -0
  21. data/ext/oj/parser.c +61 -4
  22. data/ext/oj/parser.h +12 -0
  23. data/ext/oj/rails.c +5 -10
  24. data/ext/oj/saj2.c +333 -85
  25. data/ext/oj/saj2.h +23 -0
  26. data/ext/oj/sparse.c +4 -0
  27. data/ext/oj/strict.c +13 -13
  28. data/ext/oj/usual.c +82 -129
  29. data/ext/oj/usual.h +68 -0
  30. data/ext/oj/val_stack.c +1 -1
  31. data/ext/oj/validate.c +21 -26
  32. data/ext/oj/wab.c +15 -20
  33. data/lib/oj/saj.rb +20 -6
  34. data/lib/oj/state.rb +1 -1
  35. data/lib/oj/version.rb +1 -1
  36. data/pages/Compatibility.md +1 -1
  37. data/test/bar.rb +3 -1
  38. data/test/helper.rb +8 -2
  39. data/test/json_gem/json_generator_test.rb +3 -4
  40. data/test/json_gem/json_parser_test.rb +8 -1
  41. data/test/json_gem/test_helper.rb +7 -3
  42. data/test/test_compat.rb +25 -0
  43. data/test/test_custom.rb +13 -2
  44. data/test/test_file.rb +23 -7
  45. data/test/test_gc.rb +11 -0
  46. data/test/test_object.rb +3 -10
  47. data/test/test_parser.rb +3 -19
  48. data/test/test_parser_debug.rb +27 -0
  49. data/test/test_parser_saj.rb +92 -2
  50. data/test/test_scp.rb +2 -4
  51. data/test/test_strict.rb +2 -0
  52. data/test/test_various.rb +8 -3
  53. data/test/test_wab.rb +2 -0
  54. data/test/tests.rb +9 -0
  55. data/test/tests_mimic.rb +9 -0
  56. data/test/tests_mimic_addition.rb +9 -0
  57. metadata +7 -107
data/ext/oj/parser.h CHANGED
@@ -80,6 +80,7 @@ typedef struct _ojParser {
80
80
 
81
81
  char token[8];
82
82
  long line;
83
+ long cur; // only set before call to a function
83
84
  long col;
84
85
  int ri;
85
86
  uint32_t ucode;
@@ -87,4 +88,15 @@ typedef struct _ojParser {
87
88
  bool just_one;
88
89
  } * ojParser;
89
90
 
91
+ // Create a new parser without setting the delegate. The parser is
92
+ // wrapped. The parser is (ojParser)DATA_PTR(value) where value is the return
93
+ // from this function. A delegate must be added before the parser can be
94
+ // used. Optionally oj_parser_set_options can be called if the options are not
95
+ // set directly.
96
+ extern VALUE oj_parser_new();
97
+
98
+ // Set set the options from a hash (ropts).
99
+ extern void oj_parser_set_option(ojParser p, VALUE ropts);
100
+
101
+
90
102
  #endif /* OJ_PARSER_H */
data/ext/oj/rails.c CHANGED
@@ -320,7 +320,6 @@ static void dump_time(VALUE obj, int depth, Out out, bool as_ok) {
320
320
  long long sec;
321
321
  long long nsec;
322
322
 
323
- #ifdef HAVE_RB_TIME_TIMESPEC
324
323
  if (16 <= sizeof(struct timespec)) {
325
324
  struct timespec ts = rb_time_timespec(obj);
326
325
 
@@ -330,10 +329,6 @@ static void dump_time(VALUE obj, int depth, Out out, bool as_ok) {
330
329
  sec = NUM2LL(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
331
330
  nsec = NUM2LL(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
332
331
  }
333
- #else
334
- sec = NUM2LL(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
335
- nsec = NUM2LL(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
336
- #endif
337
332
  dump_sec_nano(obj, sec, nsec, out);
338
333
  }
339
334
 
@@ -522,7 +517,7 @@ static void dump_as_string(VALUE obj, int depth, Out out, bool as_ok) {
522
517
  static void dump_as_json(VALUE obj, int depth, Out out, bool as_ok) {
523
518
  volatile VALUE ja;
524
519
 
525
- if (Yes == out->opts->trace) {
520
+ if (RB_UNLIKELY(Yes == out->opts->trace)) {
526
521
  oj_trace("as_json", obj, __FILE__, __LINE__, depth + 1, TraceRubyIn);
527
522
  }
528
523
  // Some classes elect to not take an options argument so check the arity
@@ -532,7 +527,7 @@ static void dump_as_json(VALUE obj, int depth, Out out, bool as_ok) {
532
527
  } else {
533
528
  ja = rb_funcall2(obj, oj_as_json_id, out->argc, out->argv);
534
529
  }
535
- if (Yes == out->opts->trace) {
530
+ if (RB_UNLIKELY(Yes == out->opts->trace)) {
536
531
  oj_trace("as_json", obj, __FILE__, __LINE__, depth + 1, TraceRubyOut);
537
532
  }
538
533
 
@@ -1469,7 +1464,7 @@ static DumpFunc rails_funcs[] = {
1469
1464
  static void dump_rails_val(VALUE obj, int depth, Out out, bool as_ok) {
1470
1465
  int type = rb_type(obj);
1471
1466
 
1472
- if (Yes == out->opts->trace) {
1467
+ if (RB_UNLIKELY(Yes == out->opts->trace)) {
1473
1468
  oj_trace("dump", obj, __FILE__, __LINE__, depth, TraceIn);
1474
1469
  }
1475
1470
  if (MAX_DEPTH < depth) {
@@ -1480,14 +1475,14 @@ static void dump_rails_val(VALUE obj, int depth, Out out, bool as_ok) {
1480
1475
 
1481
1476
  if (NULL != f) {
1482
1477
  f(obj, depth, out, as_ok);
1483
- if (Yes == out->opts->trace) {
1478
+ if (RB_UNLIKELY(Yes == out->opts->trace)) {
1484
1479
  oj_trace("dump", obj, __FILE__, __LINE__, depth, TraceOut);
1485
1480
  }
1486
1481
  return;
1487
1482
  }
1488
1483
  }
1489
1484
  oj_dump_nil(Qnil, depth, out, false);
1490
- if (Yes == out->opts->trace) {
1485
+ if (RB_UNLIKELY(Yes == out->opts->trace)) {
1491
1486
  oj_trace("dump", Qnil, __FILE__, __LINE__, depth, TraceOut);
1492
1487
  }
1493
1488
  }
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
+ }