oj 3.13.17 → 3.16.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (156) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +77 -0
  3. data/README.md +4 -2
  4. data/ext/oj/buf.h +7 -6
  5. data/ext/oj/cache.c +29 -26
  6. data/ext/oj/cache.h +3 -2
  7. data/ext/oj/cache8.c +10 -9
  8. data/ext/oj/circarray.c +7 -5
  9. data/ext/oj/circarray.h +2 -2
  10. data/ext/oj/code.c +5 -12
  11. data/ext/oj/code.h +2 -2
  12. data/ext/oj/compat.c +20 -60
  13. data/ext/oj/custom.c +44 -96
  14. data/ext/oj/debug.c +3 -9
  15. data/ext/oj/dump.c +69 -39
  16. data/ext/oj/dump.h +1 -4
  17. data/ext/oj/dump_compat.c +557 -592
  18. data/ext/oj/dump_leaf.c +3 -5
  19. data/ext/oj/dump_object.c +42 -48
  20. data/ext/oj/dump_strict.c +10 -22
  21. data/ext/oj/encoder.c +1 -1
  22. data/ext/oj/err.c +2 -13
  23. data/ext/oj/err.h +9 -12
  24. data/ext/oj/extconf.rb +16 -6
  25. data/ext/oj/fast.c +76 -106
  26. data/ext/oj/intern.c +63 -51
  27. data/ext/oj/intern.h +3 -7
  28. data/ext/oj/mem.c +318 -0
  29. data/ext/oj/mem.h +53 -0
  30. data/ext/oj/mimic_json.c +43 -30
  31. data/ext/oj/object.c +61 -70
  32. data/ext/oj/odd.c +8 -6
  33. data/ext/oj/odd.h +4 -4
  34. data/ext/oj/oj.c +243 -205
  35. data/ext/oj/oj.h +82 -78
  36. data/ext/oj/parse.c +123 -188
  37. data/ext/oj/parse.h +23 -24
  38. data/ext/oj/parser.c +103 -63
  39. data/ext/oj/parser.h +19 -9
  40. data/ext/oj/rails.c +68 -92
  41. data/ext/oj/reader.c +10 -15
  42. data/ext/oj/reader.h +4 -2
  43. data/ext/oj/resolve.c +3 -4
  44. data/ext/oj/rxclass.c +6 -5
  45. data/ext/oj/rxclass.h +1 -1
  46. data/ext/oj/saj.c +10 -9
  47. data/ext/oj/saj2.c +74 -92
  48. data/ext/oj/saj2.h +23 -0
  49. data/ext/oj/scp.c +3 -14
  50. data/ext/oj/sparse.c +22 -70
  51. data/ext/oj/stream_writer.c +43 -35
  52. data/ext/oj/strict.c +20 -52
  53. data/ext/oj/string_writer.c +60 -34
  54. data/ext/oj/trace.h +31 -4
  55. data/ext/oj/usual.c +125 -150
  56. data/ext/oj/usual.h +69 -0
  57. data/ext/oj/util.h +1 -1
  58. data/ext/oj/val_stack.c +14 -3
  59. data/ext/oj/val_stack.h +8 -7
  60. data/ext/oj/wab.c +25 -57
  61. data/lib/oj/active_support_helper.rb +1 -3
  62. data/lib/oj/bag.rb +7 -1
  63. data/lib/oj/easy_hash.rb +4 -5
  64. data/lib/oj/error.rb +0 -1
  65. data/lib/oj/json.rb +162 -150
  66. data/lib/oj/mimic.rb +6 -2
  67. data/lib/oj/state.rb +9 -6
  68. data/lib/oj/version.rb +1 -2
  69. data/lib/oj.rb +2 -0
  70. data/pages/Compatibility.md +1 -1
  71. data/pages/InstallOptions.md +20 -0
  72. data/pages/Options.md +10 -0
  73. data/test/_test_active.rb +8 -9
  74. data/test/_test_active_mimic.rb +7 -8
  75. data/test/_test_mimic_rails.rb +17 -20
  76. data/test/activerecord/result_test.rb +5 -6
  77. data/test/files.rb +15 -15
  78. data/test/foo.rb +9 -72
  79. data/test/helper.rb +11 -8
  80. data/test/isolated/shared.rb +3 -2
  81. data/test/json_gem/json_addition_test.rb +2 -2
  82. data/test/json_gem/json_common_interface_test.rb +8 -6
  83. data/test/json_gem/json_encoding_test.rb +0 -0
  84. data/test/json_gem/json_ext_parser_test.rb +1 -0
  85. data/test/json_gem/json_fixtures_test.rb +3 -2
  86. data/test/json_gem/json_generator_test.rb +53 -37
  87. data/test/json_gem/json_generic_object_test.rb +11 -11
  88. data/test/json_gem/json_parser_test.rb +47 -47
  89. data/test/json_gem/json_string_matching_test.rb +9 -9
  90. data/test/json_gem/test_helper.rb +7 -3
  91. data/test/mem.rb +13 -12
  92. data/test/perf.rb +21 -26
  93. data/test/perf_compat.rb +31 -33
  94. data/test/perf_dump.rb +28 -28
  95. data/test/perf_fast.rb +80 -82
  96. data/test/perf_file.rb +27 -29
  97. data/test/perf_object.rb +65 -69
  98. data/test/perf_once.rb +12 -11
  99. data/test/perf_parser.rb +42 -48
  100. data/test/perf_saj.rb +46 -54
  101. data/test/perf_scp.rb +57 -69
  102. data/test/perf_simple.rb +41 -39
  103. data/test/perf_strict.rb +68 -70
  104. data/test/perf_wab.rb +67 -69
  105. data/test/prec.rb +5 -5
  106. data/test/sample/change.rb +0 -1
  107. data/test/sample/dir.rb +0 -1
  108. data/test/sample/doc.rb +0 -1
  109. data/test/sample/file.rb +0 -1
  110. data/test/sample/group.rb +0 -1
  111. data/test/sample/hasprops.rb +0 -1
  112. data/test/sample/layer.rb +0 -1
  113. data/test/sample/rect.rb +0 -1
  114. data/test/sample/shape.rb +0 -1
  115. data/test/sample/text.rb +0 -1
  116. data/test/sample.rb +16 -16
  117. data/test/sample_json.rb +8 -8
  118. data/test/test_compat.rb +80 -53
  119. data/test/test_custom.rb +73 -51
  120. data/test/test_debian.rb +7 -10
  121. data/test/test_fast.rb +86 -90
  122. data/test/test_file.rb +28 -35
  123. data/test/test_gc.rb +16 -5
  124. data/test/test_generate.rb +5 -5
  125. data/test/test_hash.rb +4 -4
  126. data/test/test_integer_range.rb +9 -9
  127. data/test/test_null.rb +20 -20
  128. data/test/test_object.rb +94 -96
  129. data/test/test_parser.rb +6 -22
  130. data/test/test_parser_debug.rb +27 -0
  131. data/test/test_parser_saj.rb +61 -22
  132. data/test/test_parser_usual.rb +16 -6
  133. data/test/test_rails.rb +2 -2
  134. data/test/test_saj.rb +10 -8
  135. data/test/test_scp.rb +37 -39
  136. data/test/test_strict.rb +40 -32
  137. data/test/test_various.rb +148 -100
  138. data/test/test_wab.rb +48 -44
  139. data/test/test_writer.rb +47 -47
  140. data/test/tests.rb +13 -4
  141. data/test/tests_mimic.rb +12 -3
  142. data/test/tests_mimic_addition.rb +12 -3
  143. metadata +36 -27
  144. data/test/activesupport4/decoding_test.rb +0 -108
  145. data/test/activesupport4/encoding_test.rb +0 -531
  146. data/test/activesupport4/test_helper.rb +0 -41
  147. data/test/activesupport5/abstract_unit.rb +0 -45
  148. data/test/activesupport5/decoding_test.rb +0 -133
  149. data/test/activesupport5/encoding_test.rb +0 -500
  150. data/test/activesupport5/encoding_test_cases.rb +0 -98
  151. data/test/activesupport5/test_helper.rb +0 -72
  152. data/test/activesupport5/time_zone_test_helpers.rb +0 -39
  153. data/test/bar.rb +0 -11
  154. data/test/baz.rb +0 -16
  155. data/test/bug.rb +0 -16
  156. data/test/zoo.rb +0 -13
data/ext/oj/usual.c CHANGED
@@ -1,6 +1,9 @@
1
1
  // Copyright (c) 2021, Peter Ohler, All rights reserved.
2
2
 
3
+ #include "usual.h"
4
+
3
5
  #include "cache.h"
6
+ #include "mem.h"
4
7
  #include "oj.h"
5
8
  #include "parser.h"
6
9
 
@@ -28,67 +31,12 @@
28
31
 
29
32
  #define DEBUG 0
30
33
 
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
34
  static ID to_f_id = 0;
87
35
  static ID ltlt_id = 0;
88
36
  static ID hset_id = 0;
89
37
 
90
38
  static char *str_dup(const char *s, size_t len) {
91
- char *d = ALLOC_N(char, len + 1);
39
+ char *d = OJ_R_ALLOC_N(char, len + 1);
92
40
 
93
41
  memcpy(d, s, len);
94
42
  d[len] = '\0';
@@ -108,7 +56,7 @@ static VALUE form_attr(const char *str, size_t len) {
108
56
  char buf[256];
109
57
 
110
58
  if (sizeof(buf) - 2 <= len) {
111
- char *b = ALLOC_N(char, len + 2);
59
+ char *b = OJ_R_ALLOC_N(char, len + 2);
112
60
  ID id;
113
61
 
114
62
  *b = '@';
@@ -116,7 +64,7 @@ static VALUE form_attr(const char *str, size_t len) {
116
64
  b[len + 1] = '\0';
117
65
 
118
66
  id = rb_intern3(buf, len + 1, oj_utf8_encoding);
119
- xfree(b);
67
+ OJ_R_FREE(b);
120
68
  return id;
121
69
  }
122
70
  *buf = '@';
@@ -143,8 +91,8 @@ static VALUE resolve_classname(VALUE mod, const char *classname, bool auto_defin
143
91
  static VALUE resolve_classpath(const char *name, size_t len, bool auto_define) {
144
92
  char class_name[1024];
145
93
  VALUE clas;
146
- char * end = class_name + sizeof(class_name) - 1;
147
- char * s;
94
+ char *end = class_name + sizeof(class_name) - 1;
95
+ char *s;
148
96
  const char *n = name;
149
97
 
150
98
  clas = rb_cObject;
@@ -178,27 +126,27 @@ static VALUE form_class_auto(const char *str, size_t len) {
178
126
  return resolve_classpath(str, len, true);
179
127
  }
180
128
 
181
- static void assure_cstack(Delegate d) {
129
+ static void assure_cstack(Usual d) {
182
130
  if (d->cend <= d->ctail + 1) {
183
131
  size_t cap = d->cend - d->chead;
184
132
  long pos = d->ctail - d->chead;
185
133
 
186
134
  cap *= 2;
187
- REALLOC_N(d->chead, struct _col, cap);
135
+ OJ_R_REALLOC_N(d->chead, struct _col, cap);
188
136
  d->ctail = d->chead + pos;
189
137
  d->cend = d->chead + cap;
190
138
  }
191
139
  }
192
140
 
193
141
  static void push(ojParser p, VALUE v) {
194
- Delegate d = (Delegate)p->ctx;
142
+ Usual d = (Usual)p->ctx;
195
143
 
196
144
  if (d->vend <= d->vtail) {
197
145
  size_t cap = d->vend - d->vhead;
198
146
  long pos = d->vtail - d->vhead;
199
147
 
200
148
  cap *= 2;
201
- REALLOC_N(d->vhead, VALUE, cap);
149
+ OJ_R_REALLOC_N(d->vhead, VALUE, cap);
202
150
  d->vtail = d->vhead + pos;
203
151
  d->vend = d->vhead + cap;
204
152
  }
@@ -207,7 +155,7 @@ static void push(ojParser p, VALUE v) {
207
155
  }
208
156
 
209
157
  static VALUE cache_key(ojParser p, Key kp) {
210
- Delegate d = (Delegate)p->ctx;
158
+ Usual d = (Usual)p->ctx;
211
159
 
212
160
  if ((size_t)kp->len < sizeof(kp->buf)) {
213
161
  return cache_intern(d->key_cache, kp->buf, kp->len);
@@ -230,7 +178,7 @@ static VALUE sym_key(ojParser p, Key kp) {
230
178
  }
231
179
 
232
180
  static ID get_attr_id(ojParser p, Key kp) {
233
- Delegate d = (Delegate)p->ctx;
181
+ Usual d = (Usual)p->ctx;
234
182
 
235
183
  if ((size_t)kp->len < sizeof(kp->buf)) {
236
184
  return (ID)cache_intern(d->attr_cache, kp->buf, kp->len);
@@ -239,7 +187,7 @@ static ID get_attr_id(ojParser p, Key kp) {
239
187
  }
240
188
 
241
189
  static void push_key(ojParser p) {
242
- Delegate d = (Delegate)p->ctx;
190
+ Usual d = (Usual)p->ctx;
243
191
  size_t klen = buf_len(&p->key);
244
192
  const char *key = buf_str(&p->key);
245
193
 
@@ -248,7 +196,7 @@ static void push_key(ojParser p) {
248
196
  long pos = d->ktail - d->khead;
249
197
 
250
198
  cap *= 2;
251
- REALLOC_N(d->khead, union _key, cap);
199
+ OJ_R_REALLOC_N(d->khead, union _key, cap);
252
200
  d->ktail = d->khead + pos;
253
201
  d->kend = d->khead + cap;
254
202
  }
@@ -263,14 +211,14 @@ static void push_key(ojParser p) {
263
211
  }
264
212
 
265
213
  static void push2(ojParser p, VALUE v) {
266
- Delegate d = (Delegate)p->ctx;
214
+ Usual d = (Usual)p->ctx;
267
215
 
268
216
  if (d->vend <= d->vtail + 1) {
269
217
  size_t cap = d->vend - d->vhead;
270
218
  long pos = d->vtail - d->vhead;
271
219
 
272
220
  cap *= 2;
273
- REALLOC_N(d->vhead, VALUE, cap);
221
+ OJ_R_REALLOC_N(d->vhead, VALUE, cap);
274
222
  d->vtail = d->vhead + pos;
275
223
  d->vend = d->vhead + cap;
276
224
  }
@@ -281,7 +229,7 @@ static void push2(ojParser p, VALUE v) {
281
229
  }
282
230
 
283
231
  static void open_object(ojParser p) {
284
- Delegate d = (Delegate)p->ctx;
232
+ Usual d = (Usual)p->ctx;
285
233
 
286
234
  assure_cstack(d);
287
235
  d->ctail->vi = d->vtail - d->vhead;
@@ -291,7 +239,7 @@ static void open_object(ojParser p) {
291
239
  }
292
240
 
293
241
  static void open_object_key(ojParser p) {
294
- Delegate d = (Delegate)p->ctx;
242
+ Usual d = (Usual)p->ctx;
295
243
 
296
244
  push_key(p);
297
245
  assure_cstack(d);
@@ -302,7 +250,7 @@ static void open_object_key(ojParser p) {
302
250
  }
303
251
 
304
252
  static void open_array(ojParser p) {
305
- Delegate d = (Delegate)p->ctx;
253
+ Usual d = (Usual)p->ctx;
306
254
 
307
255
  assure_cstack(d);
308
256
  d->ctail->vi = d->vtail - d->vhead;
@@ -312,7 +260,7 @@ static void open_array(ojParser p) {
312
260
  }
313
261
 
314
262
  static void open_array_key(ojParser p) {
315
- Delegate d = (Delegate)p->ctx;
263
+ Usual d = (Usual)p->ctx;
316
264
 
317
265
  push_key(p);
318
266
  assure_cstack(d);
@@ -323,21 +271,21 @@ static void open_array_key(ojParser p) {
323
271
  }
324
272
 
325
273
  static void close_object(ojParser p) {
326
- VALUE * vp;
327
- Delegate d = (Delegate)p->ctx;
274
+ VALUE *vp;
275
+ Usual d = (Usual)p->ctx;
328
276
 
329
277
  d->ctail--;
330
278
 
331
279
  Col c = d->ctail;
332
280
  Key kp = d->khead + c->ki;
333
- VALUE * head = d->vhead + c->vi + 1;
281
+ VALUE *head = d->vhead + c->vi + 1;
334
282
  volatile VALUE obj = rb_hash_new();
335
283
 
336
284
  #if HAVE_RB_HASH_BULK_INSERT
337
285
  for (vp = head; kp < d->ktail; kp++, vp += 2) {
338
286
  *vp = d->get_key(p, kp);
339
287
  if (sizeof(kp->buf) <= (size_t)kp->len) {
340
- xfree(kp->key);
288
+ OJ_R_FREE(kp->key);
341
289
  }
342
290
  }
343
291
  rb_hash_bulk_insert(d->vtail - head, head, obj);
@@ -345,7 +293,7 @@ static void close_object(ojParser p) {
345
293
  for (vp = head; kp < d->ktail; kp++, vp += 2) {
346
294
  rb_hash_aset(obj, d->get_key(p, kp), *(vp + 1));
347
295
  if (sizeof(kp->buf) <= (size_t)kp->len) {
348
- xfree(kp->key);
296
+ OJ_R_FREE(kp->key);
349
297
  }
350
298
  }
351
299
  #endif
@@ -356,20 +304,20 @@ static void close_object(ojParser p) {
356
304
  }
357
305
 
358
306
  static void close_object_class(ojParser p) {
359
- VALUE * vp;
360
- Delegate d = (Delegate)p->ctx;
307
+ VALUE *vp;
308
+ Usual d = (Usual)p->ctx;
361
309
 
362
310
  d->ctail--;
363
311
 
364
312
  Col c = d->ctail;
365
313
  Key kp = d->khead + c->ki;
366
- VALUE * head = d->vhead + c->vi + 1;
314
+ VALUE *head = d->vhead + c->vi + 1;
367
315
  volatile VALUE obj = rb_class_new_instance(0, NULL, d->hash_class);
368
316
 
369
317
  for (vp = head; kp < d->ktail; kp++, vp += 2) {
370
318
  rb_funcall(obj, hset_id, 2, d->get_key(p, kp), *(vp + 1));
371
319
  if (sizeof(kp->buf) <= (size_t)kp->len) {
372
- xfree(kp->key);
320
+ OJ_R_FREE(kp->key);
373
321
  }
374
322
  }
375
323
  d->ktail = d->khead + c->ki;
@@ -379,14 +327,14 @@ static void close_object_class(ojParser p) {
379
327
  }
380
328
 
381
329
  static void close_object_create(ojParser p) {
382
- VALUE * vp;
383
- Delegate d = (Delegate)p->ctx;
330
+ VALUE *vp;
331
+ Usual d = (Usual)p->ctx;
384
332
 
385
333
  d->ctail--;
386
334
 
387
335
  Col c = d->ctail;
388
336
  Key kp = d->khead + c->ki;
389
- VALUE * head = d->vhead + c->vi;
337
+ VALUE *head = d->vhead + c->vi;
390
338
  volatile VALUE obj;
391
339
 
392
340
  if (Qundef == *head) {
@@ -397,7 +345,7 @@ static void close_object_create(ojParser p) {
397
345
  for (vp = head; kp < d->ktail; kp++, vp += 2) {
398
346
  *vp = d->get_key(p, kp);
399
347
  if (sizeof(kp->buf) <= (size_t)kp->len) {
400
- xfree(kp->key);
348
+ OJ_R_FREE(kp->key);
401
349
  }
402
350
  }
403
351
  rb_hash_bulk_insert(d->vtail - head, head, obj);
@@ -405,7 +353,7 @@ static void close_object_create(ojParser p) {
405
353
  for (vp = head; kp < d->ktail; kp++, vp += 2) {
406
354
  rb_hash_aset(obj, d->get_key(p, kp), *(vp + 1));
407
355
  if (sizeof(kp->buf) <= (size_t)kp->len) {
408
- xfree(kp->key);
356
+ OJ_R_FREE(kp->key);
409
357
  }
410
358
  }
411
359
  #endif
@@ -414,7 +362,7 @@ static void close_object_create(ojParser p) {
414
362
  for (vp = head; kp < d->ktail; kp++, vp += 2) {
415
363
  rb_funcall(obj, hset_id, 2, d->get_key(p, kp), *(vp + 1));
416
364
  if (sizeof(kp->buf) <= (size_t)kp->len) {
417
- xfree(kp->key);
365
+ OJ_R_FREE(kp->key);
418
366
  }
419
367
  }
420
368
  }
@@ -429,7 +377,7 @@ static void close_object_create(ojParser p) {
429
377
  for (vp = head; kp < d->ktail; kp++, vp += 2) {
430
378
  *vp = d->get_key(p, kp);
431
379
  if (sizeof(kp->buf) <= (size_t)kp->len) {
432
- xfree(kp->key);
380
+ OJ_R_FREE(kp->key);
433
381
  }
434
382
  }
435
383
  rb_hash_bulk_insert(d->vtail - head, head, arg);
@@ -437,7 +385,7 @@ static void close_object_create(ojParser p) {
437
385
  for (vp = head; kp < d->ktail; kp++, vp += 2) {
438
386
  rb_hash_aset(arg, d->get_key(p, kp), *(vp + 1));
439
387
  if (sizeof(kp->buf) <= (size_t)kp->len) {
440
- xfree(kp->key);
388
+ OJ_R_FREE(kp->key);
441
389
  }
442
390
  }
443
391
  #endif
@@ -447,7 +395,7 @@ static void close_object_create(ojParser p) {
447
395
  for (vp = head; kp < d->ktail; kp++, vp += 2) {
448
396
  rb_ivar_set(obj, get_attr_id(p, kp), *(vp + 1));
449
397
  if (sizeof(kp->buf) <= (size_t)kp->len) {
450
- xfree(kp->key);
398
+ OJ_R_FREE(kp->key);
451
399
  }
452
400
  }
453
401
  }
@@ -459,10 +407,10 @@ static void close_object_create(ojParser p) {
459
407
  }
460
408
 
461
409
  static void close_array(ojParser p) {
462
- Delegate d = (Delegate)p->ctx;
410
+ Usual d = (Usual)p->ctx;
463
411
 
464
412
  d->ctail--;
465
- VALUE * head = d->vhead + d->ctail->vi + 1;
413
+ VALUE *head = d->vhead + d->ctail->vi + 1;
466
414
  volatile VALUE a = rb_ary_new_from_values(d->vtail - head, head);
467
415
 
468
416
  d->vtail = head;
@@ -471,11 +419,11 @@ static void close_array(ojParser p) {
471
419
  }
472
420
 
473
421
  static void close_array_class(ojParser p) {
474
- VALUE * vp;
475
- Delegate d = (Delegate)p->ctx;
422
+ VALUE *vp;
423
+ Usual d = (Usual)p->ctx;
476
424
 
477
425
  d->ctail--;
478
- VALUE * head = d->vhead + d->ctail->vi + 1;
426
+ VALUE *head = d->vhead + d->ctail->vi + 1;
479
427
  volatile VALUE a = rb_class_new_instance(0, NULL, d->array_class);
480
428
 
481
429
  for (vp = head; vp < d->vtail; vp++) {
@@ -585,9 +533,9 @@ static void add_big_as_ruby_key(ojParser p) {
585
533
  }
586
534
 
587
535
  static void add_str(ojParser p) {
588
- Delegate d = (Delegate)p->ctx;
536
+ Usual d = (Usual)p->ctx;
589
537
  volatile VALUE rstr;
590
- const char * str = buf_str(&p->buf);
538
+ const char *str = buf_str(&p->buf);
591
539
  size_t len = buf_len(&p->buf);
592
540
 
593
541
  if (len < d->cache_str) {
@@ -599,9 +547,9 @@ static void add_str(ojParser p) {
599
547
  }
600
548
 
601
549
  static void add_str_key(ojParser p) {
602
- Delegate d = (Delegate)p->ctx;
550
+ Usual d = (Usual)p->ctx;
603
551
  volatile VALUE rstr;
604
- const char * str = buf_str(&p->buf);
552
+ const char *str = buf_str(&p->buf);
605
553
  size_t len = buf_len(&p->buf);
606
554
 
607
555
  if (len < d->cache_str) {
@@ -614,11 +562,11 @@ static void add_str_key(ojParser p) {
614
562
  }
615
563
 
616
564
  static void add_str_key_create(ojParser p) {
617
- Delegate d = (Delegate)p->ctx;
565
+ Usual d = (Usual)p->ctx;
618
566
  volatile VALUE rstr;
619
- const char * str = buf_str(&p->buf);
567
+ const char *str = buf_str(&p->buf);
620
568
  size_t len = buf_len(&p->buf);
621
- const char * key = buf_str(&p->key);
569
+ const char *key = buf_str(&p->key);
622
570
  size_t klen = buf_len(&p->key);
623
571
 
624
572
  if (klen == (size_t)d->create_id_len && 0 == strncmp(d->create_id, key, klen)) {
@@ -648,16 +596,19 @@ static void add_str_key_create(ojParser p) {
648
596
  }
649
597
 
650
598
  static VALUE result(ojParser p) {
651
- Delegate d = (Delegate)p->ctx;
599
+ Usual d = (Usual)p->ctx;
652
600
 
653
601
  if (d->vhead < d->vtail) {
654
602
  return *d->vhead;
655
603
  }
604
+ if (d->raise_on_empty) {
605
+ rb_raise(oj_parse_error_class, "empty string");
606
+ }
656
607
  return Qnil;
657
608
  }
658
609
 
659
610
  static void start(ojParser p) {
660
- Delegate d = (Delegate)p->ctx;
611
+ Usual d = (Usual)p->ctx;
661
612
 
662
613
  d->vtail = d->vhead;
663
614
  d->ctail = d->chead;
@@ -665,7 +616,7 @@ static void start(ojParser p) {
665
616
  }
666
617
 
667
618
  static void dfree(ojParser p) {
668
- Delegate d = (Delegate)p->ctx;
619
+ Usual d = (Usual)p->ctx;
669
620
 
670
621
  cache_free(d->str_cache);
671
622
  cache_free(d->attr_cache);
@@ -675,20 +626,20 @@ static void dfree(ojParser p) {
675
626
  if (NULL != d->class_cache) {
676
627
  cache_free(d->class_cache);
677
628
  }
678
- xfree(d->vhead);
679
- xfree(d->chead);
680
- xfree(d->khead);
681
- xfree(d->create_id);
682
- xfree(p->ctx);
629
+ OJ_R_FREE(d->vhead);
630
+ OJ_R_FREE(d->chead);
631
+ OJ_R_FREE(d->khead);
632
+ OJ_R_FREE(d->create_id);
633
+ OJ_R_FREE(p->ctx);
683
634
  p->ctx = NULL;
684
635
  }
685
636
 
686
637
  static void mark(ojParser p) {
687
- if (NULL == p->ctx) {
638
+ if (NULL == p || NULL == p->ctx) {
688
639
  return;
689
640
  }
690
- Delegate d = (Delegate)p->ctx;
691
- VALUE * vp;
641
+ Usual d = (Usual)p->ctx;
642
+ VALUE *vp;
692
643
 
693
644
  if (NULL == d) {
694
645
  return;
@@ -720,13 +671,13 @@ struct opt {
720
671
  };
721
672
 
722
673
  static VALUE opt_array_class(ojParser p, VALUE value) {
723
- Delegate d = (Delegate)p->ctx;
674
+ Usual d = (Usual)p->ctx;
724
675
 
725
676
  return d->array_class;
726
677
  }
727
678
 
728
679
  static VALUE opt_array_class_set(ojParser p, VALUE value) {
729
- Delegate d = (Delegate)p->ctx;
680
+ Usual d = (Usual)p->ctx;
730
681
 
731
682
  if (Qnil == value) {
732
683
  p->funcs[TOP_FUN].close_array = close_array;
@@ -747,13 +698,13 @@ static VALUE opt_array_class_set(ojParser p, VALUE value) {
747
698
  }
748
699
 
749
700
  static VALUE opt_cache_keys(ojParser p, VALUE value) {
750
- Delegate d = (Delegate)p->ctx;
701
+ Usual d = (Usual)p->ctx;
751
702
 
752
703
  return d->cache_keys ? Qtrue : Qfalse;
753
704
  }
754
705
 
755
706
  static VALUE opt_cache_keys_set(ojParser p, VALUE value) {
756
- Delegate d = (Delegate)p->ctx;
707
+ Usual d = (Usual)p->ctx;
757
708
 
758
709
  if (Qtrue == value) {
759
710
  d->cache_keys = true;
@@ -775,14 +726,14 @@ static VALUE opt_cache_keys_set(ojParser p, VALUE value) {
775
726
  }
776
727
 
777
728
  static VALUE opt_cache_strings(ojParser p, VALUE value) {
778
- Delegate d = (Delegate)p->ctx;
729
+ Usual d = (Usual)p->ctx;
779
730
 
780
731
  return INT2NUM((int)d->cache_str);
781
732
  }
782
733
 
783
734
  static VALUE opt_cache_strings_set(ojParser p, VALUE value) {
784
- Delegate d = (Delegate)p->ctx;
785
- int limit = NUM2INT(value);
735
+ Usual d = (Usual)p->ctx;
736
+ int limit = NUM2INT(value);
786
737
 
787
738
  if (CACHE_MAX_KEY < limit) {
788
739
  limit = CACHE_MAX_KEY;
@@ -795,14 +746,14 @@ static VALUE opt_cache_strings_set(ojParser p, VALUE value) {
795
746
  }
796
747
 
797
748
  static VALUE opt_cache_expunge(ojParser p, VALUE value) {
798
- Delegate d = (Delegate)p->ctx;
749
+ Usual d = (Usual)p->ctx;
799
750
 
800
751
  return INT2NUM((int)d->cache_xrate);
801
752
  }
802
753
 
803
754
  static VALUE opt_cache_expunge_set(ojParser p, VALUE value) {
804
- Delegate d = (Delegate)p->ctx;
805
- int rate = NUM2INT(value);
755
+ Usual d = (Usual)p->ctx;
756
+ int rate = NUM2INT(value);
806
757
 
807
758
  if (rate < 0) {
808
759
  rate = 0;
@@ -819,26 +770,26 @@ static VALUE opt_cache_expunge_set(ojParser p, VALUE value) {
819
770
  }
820
771
 
821
772
  static VALUE opt_capacity(ojParser p, VALUE value) {
822
- Delegate d = (Delegate)p->ctx;
773
+ Usual d = (Usual)p->ctx;
823
774
 
824
775
  return ULONG2NUM(d->vend - d->vhead);
825
776
  }
826
777
 
827
778
  static VALUE opt_capacity_set(ojParser p, VALUE value) {
828
- Delegate d = (Delegate)p->ctx;
829
- long cap = NUM2LONG(value);
779
+ Usual d = (Usual)p->ctx;
780
+ long cap = NUM2LONG(value);
830
781
 
831
782
  if (d->vend - d->vhead < cap) {
832
783
  long pos = d->vtail - d->vhead;
833
784
 
834
- REALLOC_N(d->vhead, VALUE, cap);
785
+ OJ_R_REALLOC_N(d->vhead, VALUE, cap);
835
786
  d->vtail = d->vhead + pos;
836
787
  d->vend = d->vhead + cap;
837
788
  }
838
789
  if (d->kend - d->khead < cap) {
839
790
  long pos = d->ktail - d->khead;
840
791
 
841
- REALLOC_N(d->khead, union _key, cap);
792
+ OJ_R_REALLOC_N(d->khead, union _key, cap);
842
793
  d->ktail = d->khead + pos;
843
794
  d->kend = d->khead + cap;
844
795
  }
@@ -846,13 +797,13 @@ static VALUE opt_capacity_set(ojParser p, VALUE value) {
846
797
  }
847
798
 
848
799
  static VALUE opt_class_cache(ojParser p, VALUE value) {
849
- Delegate d = (Delegate)p->ctx;
800
+ Usual d = (Usual)p->ctx;
850
801
 
851
802
  return (NULL != d->class_cache) ? Qtrue : Qfalse;
852
803
  }
853
804
 
854
805
  static VALUE opt_class_cache_set(ojParser p, VALUE value) {
855
- Delegate d = (Delegate)p->ctx;
806
+ Usual d = (Usual)p->ctx;
856
807
 
857
808
  if (Qtrue == value) {
858
809
  if (NULL == d->class_cache) {
@@ -866,7 +817,7 @@ static VALUE opt_class_cache_set(ojParser p, VALUE value) {
866
817
  }
867
818
 
868
819
  static VALUE opt_create_id(ojParser p, VALUE value) {
869
- Delegate d = (Delegate)p->ctx;
820
+ Usual d = (Usual)p->ctx;
870
821
 
871
822
  if (NULL == d->create_id) {
872
823
  return Qnil;
@@ -875,7 +826,7 @@ static VALUE opt_create_id(ojParser p, VALUE value) {
875
826
  }
876
827
 
877
828
  static VALUE opt_create_id_set(ojParser p, VALUE value) {
878
- Delegate d = (Delegate)p->ctx;
829
+ Usual d = (Usual)p->ctx;
879
830
 
880
831
  if (Qnil == value) {
881
832
  d->create_id = NULL;
@@ -924,7 +875,7 @@ static VALUE opt_decimal(ojParser p, VALUE value) {
924
875
  }
925
876
 
926
877
  static VALUE opt_decimal_set(ojParser p, VALUE value) {
927
- const char * mode;
878
+ const char *mode;
928
879
  volatile VALUE s;
929
880
 
930
881
  switch (rb_type(value)) {
@@ -985,13 +936,13 @@ static VALUE opt_decimal_set(ojParser p, VALUE value) {
985
936
  }
986
937
 
987
938
  static VALUE opt_hash_class(ojParser p, VALUE value) {
988
- Delegate d = (Delegate)p->ctx;
939
+ Usual d = (Usual)p->ctx;
989
940
 
990
941
  return d->hash_class;
991
942
  }
992
943
 
993
944
  static VALUE opt_hash_class_set(ojParser p, VALUE value) {
994
- Delegate d = (Delegate)p->ctx;
945
+ Usual d = (Usual)p->ctx;
995
946
 
996
947
  if (Qnil != value) {
997
948
  rb_check_type(value, T_CLASS);
@@ -1015,13 +966,13 @@ static VALUE opt_hash_class_set(ojParser p, VALUE value) {
1015
966
  }
1016
967
 
1017
968
  static VALUE opt_ignore_json_create(ojParser p, VALUE value) {
1018
- Delegate d = (Delegate)p->ctx;
969
+ Usual d = (Usual)p->ctx;
1019
970
 
1020
971
  return d->ignore_json_create ? Qtrue : Qfalse;
1021
972
  }
1022
973
 
1023
974
  static VALUE opt_ignore_json_create_set(ojParser p, VALUE value) {
1024
- Delegate d = (Delegate)p->ctx;
975
+ Usual d = (Usual)p->ctx;
1025
976
 
1026
977
  d->ignore_json_create = (Qtrue == value);
1027
978
 
@@ -1029,7 +980,7 @@ static VALUE opt_ignore_json_create_set(ojParser p, VALUE value) {
1029
980
  }
1030
981
 
1031
982
  static VALUE opt_missing_class(ojParser p, VALUE value) {
1032
- Delegate d = (Delegate)p->ctx;
983
+ Usual d = (Usual)p->ctx;
1033
984
 
1034
985
  switch (d->miss_class) {
1035
986
  case MISS_AUTO: return ID2SYM(rb_intern("auto"));
@@ -1040,8 +991,8 @@ static VALUE opt_missing_class(ojParser p, VALUE value) {
1040
991
  }
1041
992
 
1042
993
  static VALUE opt_missing_class_set(ojParser p, VALUE value) {
1043
- Delegate d = (Delegate)p->ctx;
1044
- const char * mode;
994
+ Usual d = (Usual)p->ctx;
995
+ const char *mode;
1045
996
  volatile VALUE s;
1046
997
 
1047
998
  switch (rb_type(value)) {
@@ -1091,13 +1042,13 @@ static VALUE opt_omit_null_set(ojParser p, VALUE value) {
1091
1042
  }
1092
1043
 
1093
1044
  static VALUE opt_symbol_keys(ojParser p, VALUE value) {
1094
- Delegate d = (Delegate)p->ctx;
1045
+ Usual d = (Usual)p->ctx;
1095
1046
 
1096
1047
  return (NULL != d->sym_cache) ? Qtrue : Qfalse;
1097
1048
  }
1098
1049
 
1099
1050
  static VALUE opt_symbol_keys_set(ojParser p, VALUE value) {
1100
- Delegate d = (Delegate)p->ctx;
1051
+ Usual d = (Usual)p->ctx;
1101
1052
 
1102
1053
  if (Qtrue == value) {
1103
1054
  d->sym_cache = cache_create(0, form_sym, true, false);
@@ -1118,6 +1069,20 @@ static VALUE opt_symbol_keys_set(ojParser p, VALUE value) {
1118
1069
  return (NULL != d->sym_cache) ? Qtrue : Qfalse;
1119
1070
  }
1120
1071
 
1072
+ static VALUE opt_raise_on_empty(ojParser p, VALUE value) {
1073
+ Usual d = (Usual)p->ctx;
1074
+
1075
+ return d->raise_on_empty ? Qtrue : Qfalse;
1076
+ }
1077
+
1078
+ static VALUE opt_raise_on_empty_set(ojParser p, VALUE value) {
1079
+ Usual d = (Usual)p->ctx;
1080
+
1081
+ d->raise_on_empty = (Qtrue == value);
1082
+
1083
+ return d->raise_on_empty ? Qtrue : Qfalse;
1084
+ }
1085
+
1121
1086
  static VALUE option(ojParser p, const char *key, VALUE value) {
1122
1087
  struct opt *op;
1123
1088
  struct opt opts[] = {
@@ -1147,6 +1112,8 @@ static VALUE option(ojParser p, const char *key, VALUE value) {
1147
1112
  {.name = "omit_null=", .func = opt_omit_null_set},
1148
1113
  {.name = "symbol_keys", .func = opt_symbol_keys},
1149
1114
  {.name = "symbol_keys=", .func = opt_symbol_keys_set},
1115
+ {.name = "raise_on_empty", .func = opt_raise_on_empty},
1116
+ {.name = "raise_on_empty=", .func = opt_raise_on_empty_set},
1150
1117
  {.name = NULL},
1151
1118
  };
1152
1119
 
@@ -1162,26 +1129,26 @@ static VALUE option(ojParser p, const char *key, VALUE value) {
1162
1129
 
1163
1130
  ///// the set up //////////////////////////////////////////////////////////////
1164
1131
 
1165
- void oj_set_parser_usual(ojParser p) {
1166
- Delegate d = ALLOC(struct _delegate);
1167
- int cap = 4096;
1132
+ void oj_init_usual(ojParser p, Usual d) {
1133
+ int cap = 4096;
1168
1134
 
1169
- d->vhead = ALLOC_N(VALUE, cap);
1135
+ d->vhead = OJ_R_ALLOC_N(VALUE, cap);
1170
1136
  d->vend = d->vhead + cap;
1171
1137
  d->vtail = d->vhead;
1172
1138
 
1173
- d->khead = ALLOC_N(union _key, cap);
1139
+ d->khead = OJ_R_ALLOC_N(union _key, cap);
1174
1140
  d->kend = d->khead + cap;
1175
1141
  d->ktail = d->khead;
1176
1142
 
1177
1143
  cap = 256;
1178
- d->chead = ALLOC_N(struct _col, cap);
1144
+ d->chead = OJ_R_ALLOC_N(struct _col, cap);
1179
1145
  d->cend = d->chead + cap;
1180
1146
  d->ctail = d->chead;
1181
1147
 
1182
1148
  d->get_key = cache_key;
1183
1149
  d->cache_keys = true;
1184
1150
  d->ignore_json_create = false;
1151
+ d->raise_on_empty = false;
1185
1152
  d->cache_str = 6;
1186
1153
  d->array_class = Qnil;
1187
1154
  d->hash_class = Qnil;
@@ -1235,6 +1202,8 @@ void oj_set_parser_usual(ojParser p) {
1235
1202
  d->class_cache = NULL;
1236
1203
  d->key_cache = d->str_cache;
1237
1204
 
1205
+ // The parser fields are set but the functions can be replaced by a
1206
+ // delegate that wraps the usual delegate.
1238
1207
  p->ctx = (void *)d;
1239
1208
  p->option = option;
1240
1209
  p->result = result;
@@ -1252,3 +1221,9 @@ void oj_set_parser_usual(ojParser p) {
1252
1221
  hset_id = rb_intern("[]=");
1253
1222
  }
1254
1223
  }
1224
+
1225
+ void oj_set_parser_usual(ojParser p) {
1226
+ Usual d = OJ_R_ALLOC(struct _usual);
1227
+
1228
+ oj_init_usual(p, d);
1229
+ }