oj 3.13.14 → 3.13.22

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 (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/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);
data/ext/oj/strict.c CHANGED
@@ -50,13 +50,13 @@ VALUE oj_calc_hash_key(ParseInfo pi, Val parent) {
50
50
  }
51
51
 
52
52
  static void hash_end(ParseInfo pi) {
53
- if (Yes == pi->options.trace) {
53
+ if (RB_UNLIKELY(Yes == pi->options.trace)) {
54
54
  oj_trace_parse_hash_end(pi, __FILE__, __LINE__);
55
55
  }
56
56
  }
57
57
 
58
58
  static void array_end(ParseInfo pi) {
59
- if (Yes == pi->options.trace) {
59
+ if (RB_UNLIKELY(Yes == pi->options.trace)) {
60
60
  oj_trace_parse_array_end(pi, __FILE__, __LINE__);
61
61
  }
62
62
  }
@@ -66,7 +66,7 @@ static VALUE noop_hash_key(ParseInfo pi, const char *key, size_t klen) {
66
66
  }
67
67
 
68
68
  static void add_value(ParseInfo pi, VALUE val) {
69
- if (Yes == pi->options.trace) {
69
+ if (RB_UNLIKELY(Yes == pi->options.trace)) {
70
70
  oj_trace_parse_call("add_value", pi, __FILE__, __LINE__, val);
71
71
  }
72
72
  pi->stack.head->val = val;
@@ -76,7 +76,7 @@ static void add_cstr(ParseInfo pi, const char *str, size_t len, const char *orig
76
76
  volatile VALUE rstr = oj_cstr_to_value(str, len, (size_t)pi->options.cache_str);
77
77
 
78
78
  pi->stack.head->val = rstr;
79
- if (Yes == pi->options.trace) {
79
+ if (RB_UNLIKELY(Yes == pi->options.trace)) {
80
80
  oj_trace_parse_call("add_string", pi, __FILE__, __LINE__, rstr);
81
81
  }
82
82
  }
@@ -86,7 +86,7 @@ static void add_num(ParseInfo pi, NumInfo ni) {
86
86
  oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number or other value");
87
87
  }
88
88
  pi->stack.head->val = oj_num_as_value(ni);
89
- if (Yes == pi->options.trace) {
89
+ if (RB_UNLIKELY(Yes == pi->options.trace)) {
90
90
  oj_trace_parse_call("add_number", pi, __FILE__, __LINE__, pi->stack.head->val);
91
91
  }
92
92
  }
@@ -95,7 +95,7 @@ static VALUE start_hash(ParseInfo pi) {
95
95
  if (Qnil != pi->options.hash_class) {
96
96
  return rb_class_new_instance(0, NULL, pi->options.hash_class);
97
97
  }
98
- if (Yes == pi->options.trace) {
98
+ if (RB_UNLIKELY(Yes == pi->options.trace)) {
99
99
  oj_trace_parse_in("start_hash", pi, __FILE__, __LINE__);
100
100
  }
101
101
  return rb_hash_new();
@@ -107,7 +107,7 @@ static void hash_set_cstr(ParseInfo pi, Val parent, const char *str, size_t len,
107
107
  rb_hash_aset(stack_peek(&pi->stack)->val,
108
108
  oj_calc_hash_key(pi, parent),
109
109
  rstr);
110
- if (Yes == pi->options.trace) {
110
+ if (RB_UNLIKELY(Yes == pi->options.trace)) {
111
111
  oj_trace_parse_call("set_string", pi, __FILE__, __LINE__, rstr);
112
112
  }
113
113
  }
@@ -122,7 +122,7 @@ static void hash_set_num(ParseInfo pi, Val parent, NumInfo ni) {
122
122
  rb_hash_aset(stack_peek(&pi->stack)->val,
123
123
  oj_calc_hash_key(pi, parent),
124
124
  v);
125
- if (Yes == pi->options.trace) {
125
+ if (RB_UNLIKELY(Yes == pi->options.trace)) {
126
126
  oj_trace_parse_call("set_number", pi, __FILE__, __LINE__, v);
127
127
  }
128
128
  }
@@ -131,13 +131,13 @@ static void hash_set_value(ParseInfo pi, Val parent, VALUE value) {
131
131
  rb_hash_aset(stack_peek(&pi->stack)->val,
132
132
  oj_calc_hash_key(pi, parent),
133
133
  value);
134
- if (Yes == pi->options.trace) {
134
+ if (RB_UNLIKELY(Yes == pi->options.trace)) {
135
135
  oj_trace_parse_call("set_value", pi, __FILE__, __LINE__, value);
136
136
  }
137
137
  }
138
138
 
139
139
  static VALUE start_array(ParseInfo pi) {
140
- if (Yes == pi->options.trace) {
140
+ if (RB_UNLIKELY(Yes == pi->options.trace)) {
141
141
  oj_trace_parse_in("start_array", pi, __FILE__, __LINE__);
142
142
  }
143
143
  return rb_ary_new();
@@ -147,7 +147,7 @@ static void array_append_cstr(ParseInfo pi, const char *str, size_t len, const c
147
147
  volatile VALUE rstr = oj_cstr_to_value(str, len, (size_t)pi->options.cache_str);
148
148
 
149
149
  rb_ary_push(stack_peek(&pi->stack)->val, rstr);
150
- if (Yes == pi->options.trace) {
150
+ if (RB_UNLIKELY(Yes == pi->options.trace)) {
151
151
  oj_trace_parse_call("append_string", pi, __FILE__, __LINE__, rstr);
152
152
  }
153
153
  }
@@ -160,14 +160,14 @@ static void array_append_num(ParseInfo pi, NumInfo ni) {
160
160
  }
161
161
  v = oj_num_as_value(ni);
162
162
  rb_ary_push(stack_peek(&pi->stack)->val, v);
163
- if (Yes == pi->options.trace) {
163
+ if (RB_UNLIKELY(Yes == pi->options.trace)) {
164
164
  oj_trace_parse_call("append_number", pi, __FILE__, __LINE__, v);
165
165
  }
166
166
  }
167
167
 
168
168
  static void array_append_value(ParseInfo pi, VALUE value) {
169
169
  rb_ary_push(stack_peek(&pi->stack)->val, value);
170
- if (Yes == pi->options.trace) {
170
+ if (RB_UNLIKELY(Yes == pi->options.trace)) {
171
171
  oj_trace_parse_call("append_value", pi, __FILE__, __LINE__, value);
172
172
  }
173
173
  }
data/ext/oj/usual.c CHANGED
@@ -3,6 +3,7 @@
3
3
  #include "cache.h"
4
4
  #include "oj.h"
5
5
  #include "parser.h"
6
+ #include "usual.h"
6
7
 
7
8
  // The Usual delegate builds Ruby objects during parsing. It makes use of
8
9
  // three stacks. The first is the value stack. This is where parsed values are
@@ -28,61 +29,6 @@
28
29
 
29
30
  #define DEBUG 0
30
31
 
31
- // Used to mark the start of each Hash, Array, or Object. The members point at
32
- // positions of the start in the value stack and if not an Array into the key
33
- // stack.
34
- typedef struct _col {
35
- long vi; // value stack index
36
- long ki; // key stack index if an hash else -1 for an array
37
- } * Col;
38
-
39
- typedef union _key {
40
- struct {
41
- int16_t len;
42
- char buf[30];
43
- };
44
- struct {
45
- int16_t xlen; // should be the same as len
46
- char * key;
47
- };
48
- } * Key;
49
-
50
- #define MISS_AUTO 'A'
51
- #define MISS_RAISE 'R'
52
- #define MISS_IGNORE 'I'
53
-
54
- typedef struct _delegate {
55
- VALUE *vhead;
56
- VALUE *vtail;
57
- VALUE *vend;
58
-
59
- Col chead;
60
- Col ctail;
61
- Col cend;
62
-
63
- Key khead;
64
- Key ktail;
65
- Key kend;
66
-
67
- VALUE (*get_key)(ojParser p, Key kp);
68
- struct _cache *key_cache; // same as str_cache or sym_cache
69
- struct _cache *str_cache;
70
- struct _cache *sym_cache;
71
- struct _cache *class_cache;
72
- struct _cache *attr_cache;
73
-
74
- VALUE array_class;
75
- VALUE hash_class;
76
-
77
- char * create_id;
78
- uint8_t create_id_len;
79
- uint8_t cache_str;
80
- uint8_t cache_xrate;
81
- uint8_t miss_class;
82
- bool cache_keys;
83
- bool ignore_json_create;
84
- } * Delegate;
85
-
86
32
  static ID to_f_id = 0;
87
33
  static ID ltlt_id = 0;
88
34
  static ID hset_id = 0;
@@ -178,7 +124,7 @@ static VALUE form_class_auto(const char *str, size_t len) {
178
124
  return resolve_classpath(str, len, true);
179
125
  }
180
126
 
181
- static void assure_cstack(Delegate d) {
127
+ static void assure_cstack(Usual d) {
182
128
  if (d->cend <= d->ctail + 1) {
183
129
  size_t cap = d->cend - d->chead;
184
130
  long pos = d->ctail - d->chead;
@@ -191,7 +137,7 @@ static void assure_cstack(Delegate d) {
191
137
  }
192
138
 
193
139
  static void push(ojParser p, VALUE v) {
194
- Delegate d = (Delegate)p->ctx;
140
+ Usual d = (Usual)p->ctx;
195
141
 
196
142
  if (d->vend <= d->vtail) {
197
143
  size_t cap = d->vend - d->vhead;
@@ -207,7 +153,7 @@ static void push(ojParser p, VALUE v) {
207
153
  }
208
154
 
209
155
  static VALUE cache_key(ojParser p, Key kp) {
210
- Delegate d = (Delegate)p->ctx;
156
+ Usual d = (Usual)p->ctx;
211
157
 
212
158
  if ((size_t)kp->len < sizeof(kp->buf)) {
213
159
  return cache_intern(d->key_cache, kp->buf, kp->len);
@@ -230,7 +176,7 @@ static VALUE sym_key(ojParser p, Key kp) {
230
176
  }
231
177
 
232
178
  static ID get_attr_id(ojParser p, Key kp) {
233
- Delegate d = (Delegate)p->ctx;
179
+ Usual d = (Usual)p->ctx;
234
180
 
235
181
  if ((size_t)kp->len < sizeof(kp->buf)) {
236
182
  return (ID)cache_intern(d->attr_cache, kp->buf, kp->len);
@@ -239,7 +185,7 @@ static ID get_attr_id(ojParser p, Key kp) {
239
185
  }
240
186
 
241
187
  static void push_key(ojParser p) {
242
- Delegate d = (Delegate)p->ctx;
188
+ Usual d = (Usual)p->ctx;
243
189
  size_t klen = buf_len(&p->key);
244
190
  const char *key = buf_str(&p->key);
245
191
 
@@ -263,7 +209,7 @@ static void push_key(ojParser p) {
263
209
  }
264
210
 
265
211
  static void push2(ojParser p, VALUE v) {
266
- Delegate d = (Delegate)p->ctx;
212
+ Usual d = (Usual)p->ctx;
267
213
 
268
214
  if (d->vend <= d->vtail + 1) {
269
215
  size_t cap = d->vend - d->vhead;
@@ -281,7 +227,7 @@ static void push2(ojParser p, VALUE v) {
281
227
  }
282
228
 
283
229
  static void open_object(ojParser p) {
284
- Delegate d = (Delegate)p->ctx;
230
+ Usual d = (Usual)p->ctx;
285
231
 
286
232
  assure_cstack(d);
287
233
  d->ctail->vi = d->vtail - d->vhead;
@@ -291,7 +237,7 @@ static void open_object(ojParser p) {
291
237
  }
292
238
 
293
239
  static void open_object_key(ojParser p) {
294
- Delegate d = (Delegate)p->ctx;
240
+ Usual d = (Usual)p->ctx;
295
241
 
296
242
  push_key(p);
297
243
  assure_cstack(d);
@@ -302,7 +248,7 @@ static void open_object_key(ojParser p) {
302
248
  }
303
249
 
304
250
  static void open_array(ojParser p) {
305
- Delegate d = (Delegate)p->ctx;
251
+ Usual d = (Usual)p->ctx;
306
252
 
307
253
  assure_cstack(d);
308
254
  d->ctail->vi = d->vtail - d->vhead;
@@ -312,7 +258,7 @@ static void open_array(ojParser p) {
312
258
  }
313
259
 
314
260
  static void open_array_key(ojParser p) {
315
- Delegate d = (Delegate)p->ctx;
261
+ Usual d = (Usual)p->ctx;
316
262
 
317
263
  push_key(p);
318
264
  assure_cstack(d);
@@ -324,7 +270,7 @@ static void open_array_key(ojParser p) {
324
270
 
325
271
  static void close_object(ojParser p) {
326
272
  VALUE * vp;
327
- Delegate d = (Delegate)p->ctx;
273
+ Usual d = (Usual)p->ctx;
328
274
 
329
275
  d->ctail--;
330
276
 
@@ -357,7 +303,7 @@ static void close_object(ojParser p) {
357
303
 
358
304
  static void close_object_class(ojParser p) {
359
305
  VALUE * vp;
360
- Delegate d = (Delegate)p->ctx;
306
+ Usual d = (Usual)p->ctx;
361
307
 
362
308
  d->ctail--;
363
309
 
@@ -380,7 +326,7 @@ static void close_object_class(ojParser p) {
380
326
 
381
327
  static void close_object_create(ojParser p) {
382
328
  VALUE * vp;
383
- Delegate d = (Delegate)p->ctx;
329
+ Usual d = (Usual)p->ctx;
384
330
 
385
331
  d->ctail--;
386
332
 
@@ -459,7 +405,7 @@ static void close_object_create(ojParser p) {
459
405
  }
460
406
 
461
407
  static void close_array(ojParser p) {
462
- Delegate d = (Delegate)p->ctx;
408
+ Usual d = (Usual)p->ctx;
463
409
 
464
410
  d->ctail--;
465
411
  VALUE * head = d->vhead + d->ctail->vi + 1;
@@ -472,7 +418,7 @@ static void close_array(ojParser p) {
472
418
 
473
419
  static void close_array_class(ojParser p) {
474
420
  VALUE * vp;
475
- Delegate d = (Delegate)p->ctx;
421
+ Usual d = (Usual)p->ctx;
476
422
 
477
423
  d->ctail--;
478
424
  VALUE * head = d->vhead + d->ctail->vi + 1;
@@ -585,7 +531,7 @@ static void add_big_as_ruby_key(ojParser p) {
585
531
  }
586
532
 
587
533
  static void add_str(ojParser p) {
588
- Delegate d = (Delegate)p->ctx;
534
+ Usual d = (Usual)p->ctx;
589
535
  volatile VALUE rstr;
590
536
  const char * str = buf_str(&p->buf);
591
537
  size_t len = buf_len(&p->buf);
@@ -599,7 +545,7 @@ static void add_str(ojParser p) {
599
545
  }
600
546
 
601
547
  static void add_str_key(ojParser p) {
602
- Delegate d = (Delegate)p->ctx;
548
+ Usual d = (Usual)p->ctx;
603
549
  volatile VALUE rstr;
604
550
  const char * str = buf_str(&p->buf);
605
551
  size_t len = buf_len(&p->buf);
@@ -614,7 +560,7 @@ static void add_str_key(ojParser p) {
614
560
  }
615
561
 
616
562
  static void add_str_key_create(ojParser p) {
617
- Delegate d = (Delegate)p->ctx;
563
+ Usual d = (Usual)p->ctx;
618
564
  volatile VALUE rstr;
619
565
  const char * str = buf_str(&p->buf);
620
566
  size_t len = buf_len(&p->buf);
@@ -648,7 +594,7 @@ static void add_str_key_create(ojParser p) {
648
594
  }
649
595
 
650
596
  static VALUE result(ojParser p) {
651
- Delegate d = (Delegate)p->ctx;
597
+ Usual d = (Usual)p->ctx;
652
598
 
653
599
  if (d->vhead < d->vtail) {
654
600
  return *d->vhead;
@@ -657,7 +603,7 @@ static VALUE result(ojParser p) {
657
603
  }
658
604
 
659
605
  static void start(ojParser p) {
660
- Delegate d = (Delegate)p->ctx;
606
+ Usual d = (Usual)p->ctx;
661
607
 
662
608
  d->vtail = d->vhead;
663
609
  d->ctail = d->chead;
@@ -665,7 +611,7 @@ static void start(ojParser p) {
665
611
  }
666
612
 
667
613
  static void dfree(ojParser p) {
668
- Delegate d = (Delegate)p->ctx;
614
+ Usual d = (Usual)p->ctx;
669
615
 
670
616
  cache_free(d->str_cache);
671
617
  cache_free(d->attr_cache);
@@ -684,10 +630,10 @@ static void dfree(ojParser p) {
684
630
  }
685
631
 
686
632
  static void mark(ojParser p) {
687
- if (NULL == p->ctx) {
633
+ if (NULL == p || NULL == p->ctx) {
688
634
  return;
689
635
  }
690
- Delegate d = (Delegate)p->ctx;
636
+ Usual d = (Usual)p->ctx;
691
637
  VALUE * vp;
692
638
 
693
639
  if (NULL == d) {
@@ -720,13 +666,13 @@ struct opt {
720
666
  };
721
667
 
722
668
  static VALUE opt_array_class(ojParser p, VALUE value) {
723
- Delegate d = (Delegate)p->ctx;
669
+ Usual d = (Usual)p->ctx;
724
670
 
725
671
  return d->array_class;
726
672
  }
727
673
 
728
674
  static VALUE opt_array_class_set(ojParser p, VALUE value) {
729
- Delegate d = (Delegate)p->ctx;
675
+ Usual d = (Usual)p->ctx;
730
676
 
731
677
  if (Qnil == value) {
732
678
  p->funcs[TOP_FUN].close_array = close_array;
@@ -747,13 +693,13 @@ static VALUE opt_array_class_set(ojParser p, VALUE value) {
747
693
  }
748
694
 
749
695
  static VALUE opt_cache_keys(ojParser p, VALUE value) {
750
- Delegate d = (Delegate)p->ctx;
696
+ Usual d = (Usual)p->ctx;
751
697
 
752
698
  return d->cache_keys ? Qtrue : Qfalse;
753
699
  }
754
700
 
755
701
  static VALUE opt_cache_keys_set(ojParser p, VALUE value) {
756
- Delegate d = (Delegate)p->ctx;
702
+ Usual d = (Usual)p->ctx;
757
703
 
758
704
  if (Qtrue == value) {
759
705
  d->cache_keys = true;
@@ -775,13 +721,13 @@ static VALUE opt_cache_keys_set(ojParser p, VALUE value) {
775
721
  }
776
722
 
777
723
  static VALUE opt_cache_strings(ojParser p, VALUE value) {
778
- Delegate d = (Delegate)p->ctx;
724
+ Usual d = (Usual)p->ctx;
779
725
 
780
726
  return INT2NUM((int)d->cache_str);
781
727
  }
782
728
 
783
729
  static VALUE opt_cache_strings_set(ojParser p, VALUE value) {
784
- Delegate d = (Delegate)p->ctx;
730
+ Usual d = (Usual)p->ctx;
785
731
  int limit = NUM2INT(value);
786
732
 
787
733
  if (CACHE_MAX_KEY < limit) {
@@ -795,13 +741,13 @@ static VALUE opt_cache_strings_set(ojParser p, VALUE value) {
795
741
  }
796
742
 
797
743
  static VALUE opt_cache_expunge(ojParser p, VALUE value) {
798
- Delegate d = (Delegate)p->ctx;
744
+ Usual d = (Usual)p->ctx;
799
745
 
800
746
  return INT2NUM((int)d->cache_xrate);
801
747
  }
802
748
 
803
749
  static VALUE opt_cache_expunge_set(ojParser p, VALUE value) {
804
- Delegate d = (Delegate)p->ctx;
750
+ Usual d = (Usual)p->ctx;
805
751
  int rate = NUM2INT(value);
806
752
 
807
753
  if (rate < 0) {
@@ -819,13 +765,13 @@ static VALUE opt_cache_expunge_set(ojParser p, VALUE value) {
819
765
  }
820
766
 
821
767
  static VALUE opt_capacity(ojParser p, VALUE value) {
822
- Delegate d = (Delegate)p->ctx;
768
+ Usual d = (Usual)p->ctx;
823
769
 
824
770
  return ULONG2NUM(d->vend - d->vhead);
825
771
  }
826
772
 
827
773
  static VALUE opt_capacity_set(ojParser p, VALUE value) {
828
- Delegate d = (Delegate)p->ctx;
774
+ Usual d = (Usual)p->ctx;
829
775
  long cap = NUM2LONG(value);
830
776
 
831
777
  if (d->vend - d->vhead < cap) {
@@ -846,13 +792,13 @@ static VALUE opt_capacity_set(ojParser p, VALUE value) {
846
792
  }
847
793
 
848
794
  static VALUE opt_class_cache(ojParser p, VALUE value) {
849
- Delegate d = (Delegate)p->ctx;
795
+ Usual d = (Usual)p->ctx;
850
796
 
851
797
  return (NULL != d->class_cache) ? Qtrue : Qfalse;
852
798
  }
853
799
 
854
800
  static VALUE opt_class_cache_set(ojParser p, VALUE value) {
855
- Delegate d = (Delegate)p->ctx;
801
+ Usual d = (Usual)p->ctx;
856
802
 
857
803
  if (Qtrue == value) {
858
804
  if (NULL == d->class_cache) {
@@ -866,7 +812,7 @@ static VALUE opt_class_cache_set(ojParser p, VALUE value) {
866
812
  }
867
813
 
868
814
  static VALUE opt_create_id(ojParser p, VALUE value) {
869
- Delegate d = (Delegate)p->ctx;
815
+ Usual d = (Usual)p->ctx;
870
816
 
871
817
  if (NULL == d->create_id) {
872
818
  return Qnil;
@@ -875,7 +821,7 @@ static VALUE opt_create_id(ojParser p, VALUE value) {
875
821
  }
876
822
 
877
823
  static VALUE opt_create_id_set(ojParser p, VALUE value) {
878
- Delegate d = (Delegate)p->ctx;
824
+ Usual d = (Usual)p->ctx;
879
825
 
880
826
  if (Qnil == value) {
881
827
  d->create_id = NULL;
@@ -985,13 +931,13 @@ static VALUE opt_decimal_set(ojParser p, VALUE value) {
985
931
  }
986
932
 
987
933
  static VALUE opt_hash_class(ojParser p, VALUE value) {
988
- Delegate d = (Delegate)p->ctx;
934
+ Usual d = (Usual)p->ctx;
989
935
 
990
936
  return d->hash_class;
991
937
  }
992
938
 
993
939
  static VALUE opt_hash_class_set(ojParser p, VALUE value) {
994
- Delegate d = (Delegate)p->ctx;
940
+ Usual d = (Usual)p->ctx;
995
941
 
996
942
  if (Qnil != value) {
997
943
  rb_check_type(value, T_CLASS);
@@ -1015,13 +961,13 @@ static VALUE opt_hash_class_set(ojParser p, VALUE value) {
1015
961
  }
1016
962
 
1017
963
  static VALUE opt_ignore_json_create(ojParser p, VALUE value) {
1018
- Delegate d = (Delegate)p->ctx;
964
+ Usual d = (Usual)p->ctx;
1019
965
 
1020
966
  return d->ignore_json_create ? Qtrue : Qfalse;
1021
967
  }
1022
968
 
1023
969
  static VALUE opt_ignore_json_create_set(ojParser p, VALUE value) {
1024
- Delegate d = (Delegate)p->ctx;
970
+ Usual d = (Usual)p->ctx;
1025
971
 
1026
972
  d->ignore_json_create = (Qtrue == value);
1027
973
 
@@ -1029,7 +975,7 @@ static VALUE opt_ignore_json_create_set(ojParser p, VALUE value) {
1029
975
  }
1030
976
 
1031
977
  static VALUE opt_missing_class(ojParser p, VALUE value) {
1032
- Delegate d = (Delegate)p->ctx;
978
+ Usual d = (Usual)p->ctx;
1033
979
 
1034
980
  switch (d->miss_class) {
1035
981
  case MISS_AUTO: return ID2SYM(rb_intern("auto"));
@@ -1040,7 +986,7 @@ static VALUE opt_missing_class(ojParser p, VALUE value) {
1040
986
  }
1041
987
 
1042
988
  static VALUE opt_missing_class_set(ojParser p, VALUE value) {
1043
- Delegate d = (Delegate)p->ctx;
989
+ Usual d = (Usual)p->ctx;
1044
990
  const char * mode;
1045
991
  volatile VALUE s;
1046
992
 
@@ -1091,13 +1037,13 @@ static VALUE opt_omit_null_set(ojParser p, VALUE value) {
1091
1037
  }
1092
1038
 
1093
1039
  static VALUE opt_symbol_keys(ojParser p, VALUE value) {
1094
- Delegate d = (Delegate)p->ctx;
1040
+ Usual d = (Usual)p->ctx;
1095
1041
 
1096
1042
  return (NULL != d->sym_cache) ? Qtrue : Qfalse;
1097
1043
  }
1098
1044
 
1099
1045
  static VALUE opt_symbol_keys_set(ojParser p, VALUE value) {
1100
- Delegate d = (Delegate)p->ctx;
1046
+ Usual d = (Usual)p->ctx;
1101
1047
 
1102
1048
  if (Qtrue == value) {
1103
1049
  d->sym_cache = cache_create(0, form_sym, true, false);
@@ -1121,33 +1067,33 @@ static VALUE opt_symbol_keys_set(ojParser p, VALUE value) {
1121
1067
  static VALUE option(ojParser p, const char *key, VALUE value) {
1122
1068
  struct opt *op;
1123
1069
  struct opt opts[] = {
1124
- {.name = "array_class", .func = opt_array_class},
1125
- {.name = "array_class=", .func = opt_array_class_set},
1126
- {.name = "cache_keys", .func = opt_cache_keys},
1127
- {.name = "cache_keys=", .func = opt_cache_keys_set},
1128
- {.name = "cache_strings", .func = opt_cache_strings},
1129
- {.name = "cache_strings=", .func = opt_cache_strings_set},
1130
- {.name = "cache_expunge", .func = opt_cache_expunge},
1131
- {.name = "cache_expunge=", .func = opt_cache_expunge_set},
1132
- {.name = "capacity", .func = opt_capacity},
1133
- {.name = "capacity=", .func = opt_capacity_set},
1134
- {.name = "class_cache", .func = opt_class_cache},
1135
- {.name = "class_cache=", .func = opt_class_cache_set},
1136
- {.name = "create_id", .func = opt_create_id},
1137
- {.name = "create_id=", .func = opt_create_id_set},
1138
- {.name = "decimal", .func = opt_decimal},
1139
- {.name = "decimal=", .func = opt_decimal_set},
1140
- {.name = "hash_class", .func = opt_hash_class},
1141
- {.name = "hash_class=", .func = opt_hash_class_set},
1142
- {.name = "ignore_json_create", .func = opt_ignore_json_create},
1143
- {.name = "ignore_json_create=", .func = opt_ignore_json_create_set},
1144
- {.name = "missing_class", .func = opt_missing_class},
1145
- {.name = "missing_class=", .func = opt_missing_class_set},
1146
- {.name = "omit_null", .func = opt_omit_null},
1147
- {.name = "omit_null=", .func = opt_omit_null_set},
1148
- {.name = "symbol_keys", .func = opt_symbol_keys},
1149
- {.name = "symbol_keys=", .func = opt_symbol_keys_set},
1150
- {.name = NULL},
1070
+ {.name = "array_class", .func = opt_array_class},
1071
+ {.name = "array_class=", .func = opt_array_class_set},
1072
+ {.name = "cache_keys", .func = opt_cache_keys},
1073
+ {.name = "cache_keys=", .func = opt_cache_keys_set},
1074
+ {.name = "cache_strings", .func = opt_cache_strings},
1075
+ {.name = "cache_strings=", .func = opt_cache_strings_set},
1076
+ {.name = "cache_expunge", .func = opt_cache_expunge},
1077
+ {.name = "cache_expunge=", .func = opt_cache_expunge_set},
1078
+ {.name = "capacity", .func = opt_capacity},
1079
+ {.name = "capacity=", .func = opt_capacity_set},
1080
+ {.name = "class_cache", .func = opt_class_cache},
1081
+ {.name = "class_cache=", .func = opt_class_cache_set},
1082
+ {.name = "create_id", .func = opt_create_id},
1083
+ {.name = "create_id=", .func = opt_create_id_set},
1084
+ {.name = "decimal", .func = opt_decimal},
1085
+ {.name = "decimal=", .func = opt_decimal_set},
1086
+ {.name = "hash_class", .func = opt_hash_class},
1087
+ {.name = "hash_class=", .func = opt_hash_class_set},
1088
+ {.name = "ignore_json_create", .func = opt_ignore_json_create},
1089
+ {.name = "ignore_json_create=", .func = opt_ignore_json_create_set},
1090
+ {.name = "missing_class", .func = opt_missing_class},
1091
+ {.name = "missing_class=", .func = opt_missing_class_set},
1092
+ {.name = "omit_null", .func = opt_omit_null},
1093
+ {.name = "omit_null=", .func = opt_omit_null_set},
1094
+ {.name = "symbol_keys", .func = opt_symbol_keys},
1095
+ {.name = "symbol_keys=", .func = opt_symbol_keys_set},
1096
+ {.name = NULL},
1151
1097
  };
1152
1098
 
1153
1099
  for (op = opts; NULL != op->name; op++) {
@@ -1162,8 +1108,7 @@ static VALUE option(ojParser p, const char *key, VALUE value) {
1162
1108
 
1163
1109
  ///// the set up //////////////////////////////////////////////////////////////
1164
1110
 
1165
- void oj_set_parser_usual(ojParser p) {
1166
- Delegate d = ALLOC(struct _delegate);
1111
+ void oj_init_usual(ojParser p, Usual d) {
1167
1112
  int cap = 4096;
1168
1113
 
1169
1114
  d->vhead = ALLOC_N(VALUE, cap);
@@ -1235,6 +1180,8 @@ void oj_set_parser_usual(ojParser p) {
1235
1180
  d->class_cache = NULL;
1236
1181
  d->key_cache = d->str_cache;
1237
1182
 
1183
+ // The parser fields are set but the functions can be replaced by a
1184
+ // delegate that wraps the usual delegate.
1238
1185
  p->ctx = (void *)d;
1239
1186
  p->option = option;
1240
1187
  p->result = result;
@@ -1252,3 +1199,9 @@ void oj_set_parser_usual(ojParser p) {
1252
1199
  hset_id = rb_intern("[]=");
1253
1200
  }
1254
1201
  }
1202
+
1203
+ void oj_set_parser_usual(ojParser p) {
1204
+ Usual d = ALLOC(struct _usual);
1205
+
1206
+ oj_init_usual(p, d);
1207
+ }