oj 3.13.23 → 3.16.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +81 -0
- data/README.md +2 -2
- data/ext/oj/buf.h +7 -6
- data/ext/oj/cache.c +29 -26
- data/ext/oj/cache.h +3 -2
- data/ext/oj/cache8.c +10 -9
- data/ext/oj/circarray.c +7 -5
- data/ext/oj/circarray.h +2 -2
- data/ext/oj/code.c +5 -12
- data/ext/oj/code.h +2 -2
- data/ext/oj/compat.c +20 -60
- data/ext/oj/custom.c +26 -59
- data/ext/oj/debug.c +3 -9
- data/ext/oj/dump.c +103 -53
- data/ext/oj/dump.h +1 -4
- data/ext/oj/dump_compat.c +557 -592
- data/ext/oj/dump_leaf.c +3 -5
- data/ext/oj/dump_object.c +42 -48
- data/ext/oj/dump_strict.c +10 -22
- data/ext/oj/encoder.c +1 -1
- data/ext/oj/err.c +2 -13
- data/ext/oj/err.h +9 -12
- data/ext/oj/extconf.rb +16 -7
- data/ext/oj/fast.c +60 -92
- data/ext/oj/intern.c +62 -47
- data/ext/oj/intern.h +3 -7
- data/ext/oj/mem.c +318 -0
- data/ext/oj/mem.h +53 -0
- data/ext/oj/mimic_json.c +51 -32
- data/ext/oj/object.c +33 -43
- data/ext/oj/odd.c +8 -6
- data/ext/oj/odd.h +4 -4
- data/ext/oj/oj.c +243 -212
- data/ext/oj/oj.h +83 -81
- data/ext/oj/parse.c +94 -148
- data/ext/oj/parse.h +21 -24
- data/ext/oj/parser.c +80 -67
- data/ext/oj/parser.h +7 -8
- data/ext/oj/rails.c +70 -92
- data/ext/oj/reader.c +9 -14
- data/ext/oj/reader.h +4 -2
- data/ext/oj/resolve.c +3 -4
- data/ext/oj/rxclass.c +6 -5
- data/ext/oj/rxclass.h +1 -1
- data/ext/oj/saj.c +10 -9
- data/ext/oj/saj2.c +37 -49
- data/ext/oj/saj2.h +1 -1
- data/ext/oj/scp.c +3 -14
- data/ext/oj/sparse.c +22 -70
- data/ext/oj/stream_writer.c +45 -41
- data/ext/oj/strict.c +20 -52
- data/ext/oj/string_writer.c +64 -38
- data/ext/oj/trace.h +31 -4
- data/ext/oj/usual.c +125 -114
- data/ext/oj/usual.h +7 -6
- data/ext/oj/util.h +1 -1
- data/ext/oj/val_stack.c +13 -2
- data/ext/oj/val_stack.h +8 -7
- data/ext/oj/wab.c +25 -57
- data/lib/oj/active_support_helper.rb +1 -3
- data/lib/oj/bag.rb +7 -1
- data/lib/oj/easy_hash.rb +4 -5
- data/lib/oj/error.rb +0 -1
- data/lib/oj/json.rb +162 -150
- data/lib/oj/mimic.rb +7 -7
- data/lib/oj/schandler.rb +5 -4
- data/lib/oj/state.rb +8 -5
- data/lib/oj/version.rb +1 -2
- data/lib/oj.rb +2 -0
- data/pages/InstallOptions.md +20 -0
- data/pages/Options.md +4 -0
- data/test/_test_active.rb +8 -9
- data/test/_test_active_mimic.rb +7 -8
- data/test/_test_mimic_rails.rb +17 -20
- data/test/activerecord/result_test.rb +5 -6
- data/test/activesupport6/encoding_test.rb +63 -28
- data/test/activesupport7/abstract_unit.rb +4 -1
- data/test/activesupport7/encoding_test.rb +72 -22
- data/test/files.rb +15 -15
- data/test/foo.rb +18 -69
- data/test/helper.rb +5 -8
- data/test/isolated/shared.rb +3 -2
- data/test/json_gem/json_addition_test.rb +2 -2
- data/test/json_gem/json_common_interface_test.rb +8 -6
- data/test/json_gem/json_encoding_test.rb +0 -0
- data/test/json_gem/json_ext_parser_test.rb +1 -0
- data/test/json_gem/json_fixtures_test.rb +3 -2
- data/test/json_gem/json_generator_test.rb +50 -33
- data/test/json_gem/json_generic_object_test.rb +11 -11
- data/test/json_gem/json_parser_test.rb +46 -46
- data/test/json_gem/json_string_matching_test.rb +9 -9
- data/test/mem.rb +13 -12
- data/test/perf.rb +21 -26
- data/test/perf_compat.rb +31 -33
- data/test/perf_dump.rb +28 -28
- data/test/perf_fast.rb +80 -82
- data/test/perf_file.rb +27 -29
- data/test/perf_object.rb +65 -69
- data/test/perf_once.rb +12 -11
- data/test/perf_parser.rb +42 -48
- data/test/perf_saj.rb +46 -54
- data/test/perf_scp.rb +57 -69
- data/test/perf_simple.rb +41 -39
- data/test/perf_strict.rb +68 -70
- data/test/perf_wab.rb +67 -69
- data/test/prec.rb +5 -5
- data/test/sample/change.rb +0 -1
- data/test/sample/dir.rb +0 -1
- data/test/sample/doc.rb +0 -1
- data/test/sample/file.rb +0 -1
- data/test/sample/group.rb +0 -1
- data/test/sample/hasprops.rb +0 -1
- data/test/sample/layer.rb +0 -1
- data/test/sample/rect.rb +0 -1
- data/test/sample/shape.rb +0 -1
- data/test/sample/text.rb +0 -1
- data/test/sample.rb +16 -16
- data/test/sample_json.rb +8 -8
- data/test/test_compat.rb +81 -54
- data/test/test_custom.rb +63 -52
- data/test/test_debian.rb +7 -10
- data/test/test_fast.rb +86 -90
- data/test/test_file.rb +24 -29
- data/test/test_gc.rb +5 -5
- data/test/test_generate.rb +5 -5
- data/test/test_hash.rb +4 -4
- data/test/test_integer_range.rb +9 -9
- data/test/test_null.rb +20 -20
- data/test/test_object.rb +92 -87
- data/test/test_parser.rb +4 -4
- data/test/test_parser_debug.rb +5 -5
- data/test/test_parser_saj.rb +27 -25
- data/test/test_parser_usual.rb +44 -6
- data/test/test_rails.rb +2 -2
- data/test/test_saj.rb +10 -8
- data/test/test_scp.rb +35 -35
- data/test/test_strict.rb +38 -32
- data/test/test_various.rb +146 -97
- data/test/test_wab.rb +46 -44
- data/test/test_writer.rb +63 -47
- data/test/tests.rb +7 -7
- data/test/tests_mimic.rb +6 -6
- data/test/tests_mimic_addition.rb +6 -6
- metadata +46 -26
- data/test/activesupport4/decoding_test.rb +0 -108
- data/test/activesupport4/encoding_test.rb +0 -531
- data/test/activesupport4/test_helper.rb +0 -41
- data/test/activesupport5/abstract_unit.rb +0 -45
- data/test/activesupport5/decoding_test.rb +0 -133
- data/test/activesupport5/encoding_test.rb +0 -500
- data/test/activesupport5/encoding_test_cases.rb +0 -98
- data/test/activesupport5/test_helper.rb +0 -72
- data/test/activesupport5/time_zone_test_helpers.rb +0 -39
- data/test/bar.rb +0 -11
- data/test/baz.rb +0 -16
- data/test/bug.rb +0 -16
- data/test/zoo.rb +0 -13
data/ext/oj/trace.h
CHANGED
@@ -17,12 +17,39 @@ typedef enum {
|
|
17
17
|
|
18
18
|
struct _parseInfo;
|
19
19
|
|
20
|
-
extern void
|
21
|
-
oj_trace(const char *func, VALUE obj, const char *file, int line, int depth, TraceWhere where);
|
20
|
+
extern void oj_trace(const char *func, VALUE obj, const char *file, int line, int depth, TraceWhere where);
|
22
21
|
extern void oj_trace_parse_in(const char *func, struct _parseInfo *pi, const char *file, int line);
|
23
|
-
extern void
|
24
|
-
oj_trace_parse_call(const char *func, struct _parseInfo *pi, const char *file, int line, VALUE obj);
|
22
|
+
extern void oj_trace_parse_call(const char *func, struct _parseInfo *pi, const char *file, int line, VALUE obj);
|
25
23
|
extern void oj_trace_parse_hash_end(struct _parseInfo *pi, const char *file, int line);
|
26
24
|
extern void oj_trace_parse_array_end(struct _parseInfo *pi, const char *file, int line);
|
27
25
|
|
26
|
+
#ifdef OJ_ENABLE_TRACE_LOG
|
27
|
+
#define TRACE(option, func, obj, depth, where) \
|
28
|
+
if (RB_UNLIKELY(Yes == option)) { \
|
29
|
+
oj_trace(func, obj, __FILE__, __LINE__, depth, where); \
|
30
|
+
}
|
31
|
+
#define TRACE_PARSE_IN(option, func, pi) \
|
32
|
+
if (RB_UNLIKELY(Yes == option)) { \
|
33
|
+
oj_trace_parse_in(func, pi, __FILE__, __LINE__); \
|
34
|
+
}
|
35
|
+
#define TRACE_PARSE_CALL(option, func, pi, obj) \
|
36
|
+
if (RB_UNLIKELY(Yes == option)) { \
|
37
|
+
oj_trace_parse_call(func, pi, __FILE__, __LINE__, obj); \
|
38
|
+
}
|
39
|
+
#define TRACE_PARSE_HASH_END(option, pi) \
|
40
|
+
if (RB_UNLIKELY(Yes == option)) { \
|
41
|
+
oj_trace_parse_hash_end(pi, __FILE__, __LINE__); \
|
42
|
+
}
|
43
|
+
#define TRACE_PARSE_ARRAY_END(option, pi) \
|
44
|
+
if (RB_UNLIKELY(Yes == option)) { \
|
45
|
+
oj_trace_parse_array_end(pi, __FILE__, __LINE__); \
|
46
|
+
}
|
47
|
+
#else
|
48
|
+
#define TRACE(option, func, obj, depth, where)
|
49
|
+
#define TRACE_PARSE_IN(option, func, pi)
|
50
|
+
#define TRACE_PARSE_CALL(option, func, pi, obj)
|
51
|
+
#define TRACE_PARSE_HASH_END(option, pi)
|
52
|
+
#define TRACE_PARSE_ARRAY_END(option, pi)
|
53
|
+
#endif
|
54
|
+
|
28
55
|
#endif /* OJ_TRACE_H */
|
data/ext/oj/usual.c
CHANGED
@@ -1,9 +1,11 @@
|
|
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
|
-
#include "usual.h"
|
7
9
|
|
8
10
|
// The Usual delegate builds Ruby objects during parsing. It makes use of
|
9
11
|
// three stacks. The first is the value stack. This is where parsed values are
|
@@ -34,7 +36,7 @@ static ID ltlt_id = 0;
|
|
34
36
|
static ID hset_id = 0;
|
35
37
|
|
36
38
|
static char *str_dup(const char *s, size_t len) {
|
37
|
-
char *d =
|
39
|
+
char *d = OJ_R_ALLOC_N(char, len + 1);
|
38
40
|
|
39
41
|
memcpy(d, s, len);
|
40
42
|
d[len] = '\0';
|
@@ -54,7 +56,7 @@ static VALUE form_attr(const char *str, size_t len) {
|
|
54
56
|
char buf[256];
|
55
57
|
|
56
58
|
if (sizeof(buf) - 2 <= len) {
|
57
|
-
char *b =
|
59
|
+
char *b = OJ_R_ALLOC_N(char, len + 2);
|
58
60
|
ID id;
|
59
61
|
|
60
62
|
*b = '@';
|
@@ -62,7 +64,7 @@ static VALUE form_attr(const char *str, size_t len) {
|
|
62
64
|
b[len + 1] = '\0';
|
63
65
|
|
64
66
|
id = rb_intern3(buf, len + 1, oj_utf8_encoding);
|
65
|
-
|
67
|
+
OJ_R_FREE(b);
|
66
68
|
return id;
|
67
69
|
}
|
68
70
|
*buf = '@';
|
@@ -89,8 +91,8 @@ static VALUE resolve_classname(VALUE mod, const char *classname, bool auto_defin
|
|
89
91
|
static VALUE resolve_classpath(const char *name, size_t len, bool auto_define) {
|
90
92
|
char class_name[1024];
|
91
93
|
VALUE clas;
|
92
|
-
char
|
93
|
-
char
|
94
|
+
char *end = class_name + sizeof(class_name) - 1;
|
95
|
+
char *s;
|
94
96
|
const char *n = name;
|
95
97
|
|
96
98
|
clas = rb_cObject;
|
@@ -130,7 +132,7 @@ static void assure_cstack(Usual d) {
|
|
130
132
|
long pos = d->ctail - d->chead;
|
131
133
|
|
132
134
|
cap *= 2;
|
133
|
-
|
135
|
+
OJ_R_REALLOC_N(d->chead, struct _col, cap);
|
134
136
|
d->ctail = d->chead + pos;
|
135
137
|
d->cend = d->chead + cap;
|
136
138
|
}
|
@@ -144,7 +146,7 @@ static void push(ojParser p, VALUE v) {
|
|
144
146
|
long pos = d->vtail - d->vhead;
|
145
147
|
|
146
148
|
cap *= 2;
|
147
|
-
|
149
|
+
OJ_R_REALLOC_N(d->vhead, VALUE, cap);
|
148
150
|
d->vtail = d->vhead + pos;
|
149
151
|
d->vend = d->vhead + cap;
|
150
152
|
}
|
@@ -185,7 +187,7 @@ static ID get_attr_id(ojParser p, Key kp) {
|
|
185
187
|
}
|
186
188
|
|
187
189
|
static void push_key(ojParser p) {
|
188
|
-
Usual
|
190
|
+
Usual d = (Usual)p->ctx;
|
189
191
|
size_t klen = buf_len(&p->key);
|
190
192
|
const char *key = buf_str(&p->key);
|
191
193
|
|
@@ -194,7 +196,7 @@ static void push_key(ojParser p) {
|
|
194
196
|
long pos = d->ktail - d->khead;
|
195
197
|
|
196
198
|
cap *= 2;
|
197
|
-
|
199
|
+
OJ_R_REALLOC_N(d->khead, union _key, cap);
|
198
200
|
d->ktail = d->khead + pos;
|
199
201
|
d->kend = d->khead + cap;
|
200
202
|
}
|
@@ -216,7 +218,7 @@ static void push2(ojParser p, VALUE v) {
|
|
216
218
|
long pos = d->vtail - d->vhead;
|
217
219
|
|
218
220
|
cap *= 2;
|
219
|
-
|
221
|
+
OJ_R_REALLOC_N(d->vhead, VALUE, cap);
|
220
222
|
d->vtail = d->vhead + pos;
|
221
223
|
d->vend = d->vhead + cap;
|
222
224
|
}
|
@@ -269,53 +271,49 @@ static void open_array_key(ojParser p) {
|
|
269
271
|
}
|
270
272
|
|
271
273
|
static void close_object(ojParser p) {
|
272
|
-
VALUE *
|
273
|
-
Usual
|
274
|
+
VALUE *vp;
|
275
|
+
Usual d = (Usual)p->ctx;
|
274
276
|
|
275
277
|
d->ctail--;
|
276
278
|
|
277
279
|
Col c = d->ctail;
|
278
280
|
Key kp = d->khead + c->ki;
|
279
|
-
VALUE
|
281
|
+
VALUE *head = d->vhead + c->vi + 1;
|
280
282
|
volatile VALUE obj = rb_hash_new();
|
281
283
|
|
282
|
-
#if HAVE_RB_HASH_BULK_INSERT
|
283
284
|
for (vp = head; kp < d->ktail; kp++, vp += 2) {
|
284
285
|
*vp = d->get_key(p, kp);
|
285
286
|
if (sizeof(kp->buf) <= (size_t)kp->len) {
|
286
|
-
|
287
|
+
OJ_R_FREE(kp->key);
|
287
288
|
}
|
288
289
|
}
|
289
290
|
rb_hash_bulk_insert(d->vtail - head, head, obj);
|
290
|
-
#else
|
291
|
-
for (vp = head; kp < d->ktail; kp++, vp += 2) {
|
292
|
-
rb_hash_aset(obj, d->get_key(p, kp), *(vp + 1));
|
293
|
-
if (sizeof(kp->buf) <= (size_t)kp->len) {
|
294
|
-
xfree(kp->key);
|
295
|
-
}
|
296
|
-
}
|
297
|
-
#endif
|
298
291
|
d->ktail = d->khead + c->ki;
|
292
|
+
|
299
293
|
d->vtail = head;
|
300
294
|
head--;
|
301
295
|
*head = obj;
|
296
|
+
if (1 == d->vtail - d->vhead && rb_block_given_p()) {
|
297
|
+
d->vtail = d->vhead;
|
298
|
+
rb_yield(obj);
|
299
|
+
}
|
302
300
|
}
|
303
301
|
|
304
302
|
static void close_object_class(ojParser p) {
|
305
|
-
VALUE *
|
306
|
-
Usual
|
303
|
+
VALUE *vp;
|
304
|
+
Usual d = (Usual)p->ctx;
|
307
305
|
|
308
306
|
d->ctail--;
|
309
307
|
|
310
308
|
Col c = d->ctail;
|
311
309
|
Key kp = d->khead + c->ki;
|
312
|
-
VALUE
|
310
|
+
VALUE *head = d->vhead + c->vi + 1;
|
313
311
|
volatile VALUE obj = rb_class_new_instance(0, NULL, d->hash_class);
|
314
312
|
|
315
313
|
for (vp = head; kp < d->ktail; kp++, vp += 2) {
|
316
314
|
rb_funcall(obj, hset_id, 2, d->get_key(p, kp), *(vp + 1));
|
317
315
|
if (sizeof(kp->buf) <= (size_t)kp->len) {
|
318
|
-
|
316
|
+
OJ_R_FREE(kp->key);
|
319
317
|
}
|
320
318
|
}
|
321
319
|
d->ktail = d->khead + c->ki;
|
@@ -325,42 +323,33 @@ static void close_object_class(ojParser p) {
|
|
325
323
|
}
|
326
324
|
|
327
325
|
static void close_object_create(ojParser p) {
|
328
|
-
VALUE *
|
329
|
-
Usual
|
326
|
+
VALUE *vp;
|
327
|
+
Usual d = (Usual)p->ctx;
|
330
328
|
|
331
329
|
d->ctail--;
|
332
330
|
|
333
331
|
Col c = d->ctail;
|
334
332
|
Key kp = d->khead + c->ki;
|
335
|
-
VALUE
|
333
|
+
VALUE *head = d->vhead + c->vi;
|
336
334
|
volatile VALUE obj;
|
337
335
|
|
338
336
|
if (Qundef == *head) {
|
339
337
|
head++;
|
340
338
|
if (Qnil == d->hash_class) {
|
341
339
|
obj = rb_hash_new();
|
342
|
-
#if HAVE_RB_HASH_BULK_INSERT
|
343
340
|
for (vp = head; kp < d->ktail; kp++, vp += 2) {
|
344
341
|
*vp = d->get_key(p, kp);
|
345
342
|
if (sizeof(kp->buf) <= (size_t)kp->len) {
|
346
|
-
|
343
|
+
OJ_R_FREE(kp->key);
|
347
344
|
}
|
348
345
|
}
|
349
346
|
rb_hash_bulk_insert(d->vtail - head, head, obj);
|
350
|
-
#else
|
351
|
-
for (vp = head; kp < d->ktail; kp++, vp += 2) {
|
352
|
-
rb_hash_aset(obj, d->get_key(p, kp), *(vp + 1));
|
353
|
-
if (sizeof(kp->buf) <= (size_t)kp->len) {
|
354
|
-
xfree(kp->key);
|
355
|
-
}
|
356
|
-
}
|
357
|
-
#endif
|
358
347
|
} else {
|
359
348
|
obj = rb_class_new_instance(0, NULL, d->hash_class);
|
360
349
|
for (vp = head; kp < d->ktail; kp++, vp += 2) {
|
361
350
|
rb_funcall(obj, hset_id, 2, d->get_key(p, kp), *(vp + 1));
|
362
351
|
if (sizeof(kp->buf) <= (size_t)kp->len) {
|
363
|
-
|
352
|
+
OJ_R_FREE(kp->key);
|
364
353
|
}
|
365
354
|
}
|
366
355
|
}
|
@@ -371,29 +360,20 @@ static void close_object_create(ojParser p) {
|
|
371
360
|
if (!d->ignore_json_create && rb_respond_to(clas, oj_json_create_id)) {
|
372
361
|
volatile VALUE arg = rb_hash_new();
|
373
362
|
|
374
|
-
#if HAVE_RB_HASH_BULK_INSERT
|
375
363
|
for (vp = head; kp < d->ktail; kp++, vp += 2) {
|
376
364
|
*vp = d->get_key(p, kp);
|
377
365
|
if (sizeof(kp->buf) <= (size_t)kp->len) {
|
378
|
-
|
366
|
+
OJ_R_FREE(kp->key);
|
379
367
|
}
|
380
368
|
}
|
381
369
|
rb_hash_bulk_insert(d->vtail - head, head, arg);
|
382
|
-
#else
|
383
|
-
for (vp = head; kp < d->ktail; kp++, vp += 2) {
|
384
|
-
rb_hash_aset(arg, d->get_key(p, kp), *(vp + 1));
|
385
|
-
if (sizeof(kp->buf) <= (size_t)kp->len) {
|
386
|
-
xfree(kp->key);
|
387
|
-
}
|
388
|
-
}
|
389
|
-
#endif
|
390
370
|
obj = rb_funcall(clas, oj_json_create_id, 1, arg);
|
391
371
|
} else {
|
392
372
|
obj = rb_class_new_instance(0, NULL, clas);
|
393
373
|
for (vp = head; kp < d->ktail; kp++, vp += 2) {
|
394
374
|
rb_ivar_set(obj, get_attr_id(p, kp), *(vp + 1));
|
395
375
|
if (sizeof(kp->buf) <= (size_t)kp->len) {
|
396
|
-
|
376
|
+
OJ_R_FREE(kp->key);
|
397
377
|
}
|
398
378
|
}
|
399
379
|
}
|
@@ -408,7 +388,7 @@ static void close_array(ojParser p) {
|
|
408
388
|
Usual d = (Usual)p->ctx;
|
409
389
|
|
410
390
|
d->ctail--;
|
411
|
-
VALUE
|
391
|
+
VALUE *head = d->vhead + d->ctail->vi + 1;
|
412
392
|
volatile VALUE a = rb_ary_new_from_values(d->vtail - head, head);
|
413
393
|
|
414
394
|
d->vtail = head;
|
@@ -417,11 +397,11 @@ static void close_array(ojParser p) {
|
|
417
397
|
}
|
418
398
|
|
419
399
|
static void close_array_class(ojParser p) {
|
420
|
-
VALUE *
|
421
|
-
Usual
|
400
|
+
VALUE *vp;
|
401
|
+
Usual d = (Usual)p->ctx;
|
422
402
|
|
423
403
|
d->ctail--;
|
424
|
-
VALUE
|
404
|
+
VALUE *head = d->vhead + d->ctail->vi + 1;
|
425
405
|
volatile VALUE a = rb_class_new_instance(0, NULL, d->array_class);
|
426
406
|
|
427
407
|
for (vp = head; vp < d->vtail; vp++) {
|
@@ -531,9 +511,9 @@ static void add_big_as_ruby_key(ojParser p) {
|
|
531
511
|
}
|
532
512
|
|
533
513
|
static void add_str(ojParser p) {
|
534
|
-
Usual
|
514
|
+
Usual d = (Usual)p->ctx;
|
535
515
|
volatile VALUE rstr;
|
536
|
-
const char
|
516
|
+
const char *str = buf_str(&p->buf);
|
537
517
|
size_t len = buf_len(&p->buf);
|
538
518
|
|
539
519
|
if (len < d->cache_str) {
|
@@ -545,9 +525,9 @@ static void add_str(ojParser p) {
|
|
545
525
|
}
|
546
526
|
|
547
527
|
static void add_str_key(ojParser p) {
|
548
|
-
Usual
|
528
|
+
Usual d = (Usual)p->ctx;
|
549
529
|
volatile VALUE rstr;
|
550
|
-
const char
|
530
|
+
const char *str = buf_str(&p->buf);
|
551
531
|
size_t len = buf_len(&p->buf);
|
552
532
|
|
553
533
|
if (len < d->cache_str) {
|
@@ -560,11 +540,11 @@ static void add_str_key(ojParser p) {
|
|
560
540
|
}
|
561
541
|
|
562
542
|
static void add_str_key_create(ojParser p) {
|
563
|
-
Usual
|
543
|
+
Usual d = (Usual)p->ctx;
|
564
544
|
volatile VALUE rstr;
|
565
|
-
const char
|
545
|
+
const char *str = buf_str(&p->buf);
|
566
546
|
size_t len = buf_len(&p->buf);
|
567
|
-
const char
|
547
|
+
const char *key = buf_str(&p->key);
|
568
548
|
size_t klen = buf_len(&p->key);
|
569
549
|
|
570
550
|
if (klen == (size_t)d->create_id_len && 0 == strncmp(d->create_id, key, klen)) {
|
@@ -597,7 +577,21 @@ static VALUE result(ojParser p) {
|
|
597
577
|
Usual d = (Usual)p->ctx;
|
598
578
|
|
599
579
|
if (d->vhead < d->vtail) {
|
600
|
-
|
580
|
+
long cnt = d->vtail - d->vhead;
|
581
|
+
volatile VALUE ary;
|
582
|
+
volatile VALUE *vp;
|
583
|
+
|
584
|
+
if (1 == cnt) {
|
585
|
+
return *d->vhead;
|
586
|
+
}
|
587
|
+
ary = rb_ary_new();
|
588
|
+
for (vp = d->vhead; vp < d->vtail; vp++) {
|
589
|
+
rb_ary_push(ary, *vp);
|
590
|
+
}
|
591
|
+
return ary;
|
592
|
+
}
|
593
|
+
if (d->raise_on_empty) {
|
594
|
+
rb_raise(oj_parse_error_class, "empty string");
|
601
595
|
}
|
602
596
|
return Qnil;
|
603
597
|
}
|
@@ -621,11 +615,11 @@ static void dfree(ojParser p) {
|
|
621
615
|
if (NULL != d->class_cache) {
|
622
616
|
cache_free(d->class_cache);
|
623
617
|
}
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
|
628
|
-
|
618
|
+
OJ_R_FREE(d->vhead);
|
619
|
+
OJ_R_FREE(d->chead);
|
620
|
+
OJ_R_FREE(d->khead);
|
621
|
+
OJ_R_FREE(d->create_id);
|
622
|
+
OJ_R_FREE(p->ctx);
|
629
623
|
p->ctx = NULL;
|
630
624
|
}
|
631
625
|
|
@@ -633,8 +627,8 @@ static void mark(ojParser p) {
|
|
633
627
|
if (NULL == p || NULL == p->ctx) {
|
634
628
|
return;
|
635
629
|
}
|
636
|
-
Usual
|
637
|
-
VALUE *
|
630
|
+
Usual d = (Usual)p->ctx;
|
631
|
+
VALUE *vp;
|
638
632
|
|
639
633
|
if (NULL == d) {
|
640
634
|
return;
|
@@ -728,7 +722,7 @@ static VALUE opt_cache_strings(ojParser p, VALUE value) {
|
|
728
722
|
|
729
723
|
static VALUE opt_cache_strings_set(ojParser p, VALUE value) {
|
730
724
|
Usual d = (Usual)p->ctx;
|
731
|
-
int
|
725
|
+
int limit = NUM2INT(value);
|
732
726
|
|
733
727
|
if (CACHE_MAX_KEY < limit) {
|
734
728
|
limit = CACHE_MAX_KEY;
|
@@ -748,7 +742,7 @@ static VALUE opt_cache_expunge(ojParser p, VALUE value) {
|
|
748
742
|
|
749
743
|
static VALUE opt_cache_expunge_set(ojParser p, VALUE value) {
|
750
744
|
Usual d = (Usual)p->ctx;
|
751
|
-
int
|
745
|
+
int rate = NUM2INT(value);
|
752
746
|
|
753
747
|
if (rate < 0) {
|
754
748
|
rate = 0;
|
@@ -772,19 +766,19 @@ static VALUE opt_capacity(ojParser p, VALUE value) {
|
|
772
766
|
|
773
767
|
static VALUE opt_capacity_set(ojParser p, VALUE value) {
|
774
768
|
Usual d = (Usual)p->ctx;
|
775
|
-
long
|
769
|
+
long cap = NUM2LONG(value);
|
776
770
|
|
777
771
|
if (d->vend - d->vhead < cap) {
|
778
772
|
long pos = d->vtail - d->vhead;
|
779
773
|
|
780
|
-
|
774
|
+
OJ_R_REALLOC_N(d->vhead, VALUE, cap);
|
781
775
|
d->vtail = d->vhead + pos;
|
782
776
|
d->vend = d->vhead + cap;
|
783
777
|
}
|
784
778
|
if (d->kend - d->khead < cap) {
|
785
779
|
long pos = d->ktail - d->khead;
|
786
780
|
|
787
|
-
|
781
|
+
OJ_R_REALLOC_N(d->khead, union _key, cap);
|
788
782
|
d->ktail = d->khead + pos;
|
789
783
|
d->kend = d->khead + cap;
|
790
784
|
}
|
@@ -840,8 +834,8 @@ static VALUE opt_create_id_set(ojParser p, VALUE value) {
|
|
840
834
|
rb_check_type(value, T_STRING);
|
841
835
|
size_t len = RSTRING_LEN(value);
|
842
836
|
|
843
|
-
if (1 << sizeof(d->create_id_len) <= len) {
|
844
|
-
rb_raise(rb_eArgError, "The create_id values is limited to %d bytes.", 1 << sizeof(d->create_id_len));
|
837
|
+
if (1 << (8 * sizeof(d->create_id_len)) <= len) {
|
838
|
+
rb_raise(rb_eArgError, "The create_id values is limited to %d bytes.", 1 << (8 * sizeof(d->create_id_len)));
|
845
839
|
}
|
846
840
|
d->create_id_len = (uint8_t)len;
|
847
841
|
d->create_id = str_dup(RSTRING_PTR(value), len);
|
@@ -870,7 +864,7 @@ static VALUE opt_decimal(ojParser p, VALUE value) {
|
|
870
864
|
}
|
871
865
|
|
872
866
|
static VALUE opt_decimal_set(ojParser p, VALUE value) {
|
873
|
-
const char
|
867
|
+
const char *mode;
|
874
868
|
volatile VALUE s;
|
875
869
|
|
876
870
|
switch (rb_type(value)) {
|
@@ -986,8 +980,8 @@ static VALUE opt_missing_class(ojParser p, VALUE value) {
|
|
986
980
|
}
|
987
981
|
|
988
982
|
static VALUE opt_missing_class_set(ojParser p, VALUE value) {
|
989
|
-
Usual
|
990
|
-
const char
|
983
|
+
Usual d = (Usual)p->ctx;
|
984
|
+
const char *mode;
|
991
985
|
volatile VALUE s;
|
992
986
|
|
993
987
|
switch (rb_type(value)) {
|
@@ -1064,36 +1058,52 @@ static VALUE opt_symbol_keys_set(ojParser p, VALUE value) {
|
|
1064
1058
|
return (NULL != d->sym_cache) ? Qtrue : Qfalse;
|
1065
1059
|
}
|
1066
1060
|
|
1061
|
+
static VALUE opt_raise_on_empty(ojParser p, VALUE value) {
|
1062
|
+
Usual d = (Usual)p->ctx;
|
1063
|
+
|
1064
|
+
return d->raise_on_empty ? Qtrue : Qfalse;
|
1065
|
+
}
|
1066
|
+
|
1067
|
+
static VALUE opt_raise_on_empty_set(ojParser p, VALUE value) {
|
1068
|
+
Usual d = (Usual)p->ctx;
|
1069
|
+
|
1070
|
+
d->raise_on_empty = (Qtrue == value);
|
1071
|
+
|
1072
|
+
return d->raise_on_empty ? Qtrue : Qfalse;
|
1073
|
+
}
|
1074
|
+
|
1067
1075
|
static VALUE option(ojParser p, const char *key, VALUE value) {
|
1068
1076
|
struct opt *op;
|
1069
1077
|
struct opt opts[] = {
|
1070
|
-
|
1071
|
-
|
1072
|
-
|
1073
|
-
|
1074
|
-
|
1075
|
-
|
1076
|
-
|
1077
|
-
|
1078
|
-
|
1079
|
-
|
1080
|
-
|
1081
|
-
|
1082
|
-
|
1083
|
-
|
1084
|
-
|
1085
|
-
|
1086
|
-
|
1087
|
-
|
1088
|
-
|
1089
|
-
|
1090
|
-
|
1091
|
-
|
1092
|
-
|
1093
|
-
|
1094
|
-
|
1095
|
-
|
1096
|
-
|
1078
|
+
{.name = "array_class", .func = opt_array_class},
|
1079
|
+
{.name = "array_class=", .func = opt_array_class_set},
|
1080
|
+
{.name = "cache_keys", .func = opt_cache_keys},
|
1081
|
+
{.name = "cache_keys=", .func = opt_cache_keys_set},
|
1082
|
+
{.name = "cache_strings", .func = opt_cache_strings},
|
1083
|
+
{.name = "cache_strings=", .func = opt_cache_strings_set},
|
1084
|
+
{.name = "cache_expunge", .func = opt_cache_expunge},
|
1085
|
+
{.name = "cache_expunge=", .func = opt_cache_expunge_set},
|
1086
|
+
{.name = "capacity", .func = opt_capacity},
|
1087
|
+
{.name = "capacity=", .func = opt_capacity_set},
|
1088
|
+
{.name = "class_cache", .func = opt_class_cache},
|
1089
|
+
{.name = "class_cache=", .func = opt_class_cache_set},
|
1090
|
+
{.name = "create_id", .func = opt_create_id},
|
1091
|
+
{.name = "create_id=", .func = opt_create_id_set},
|
1092
|
+
{.name = "decimal", .func = opt_decimal},
|
1093
|
+
{.name = "decimal=", .func = opt_decimal_set},
|
1094
|
+
{.name = "hash_class", .func = opt_hash_class},
|
1095
|
+
{.name = "hash_class=", .func = opt_hash_class_set},
|
1096
|
+
{.name = "ignore_json_create", .func = opt_ignore_json_create},
|
1097
|
+
{.name = "ignore_json_create=", .func = opt_ignore_json_create_set},
|
1098
|
+
{.name = "missing_class", .func = opt_missing_class},
|
1099
|
+
{.name = "missing_class=", .func = opt_missing_class_set},
|
1100
|
+
{.name = "omit_null", .func = opt_omit_null},
|
1101
|
+
{.name = "omit_null=", .func = opt_omit_null_set},
|
1102
|
+
{.name = "symbol_keys", .func = opt_symbol_keys},
|
1103
|
+
{.name = "symbol_keys=", .func = opt_symbol_keys_set},
|
1104
|
+
{.name = "raise_on_empty", .func = opt_raise_on_empty},
|
1105
|
+
{.name = "raise_on_empty=", .func = opt_raise_on_empty_set},
|
1106
|
+
{.name = NULL},
|
1097
1107
|
};
|
1098
1108
|
|
1099
1109
|
for (op = opts; NULL != op->name; op++) {
|
@@ -1109,24 +1119,25 @@ static VALUE option(ojParser p, const char *key, VALUE value) {
|
|
1109
1119
|
///// the set up //////////////////////////////////////////////////////////////
|
1110
1120
|
|
1111
1121
|
void oj_init_usual(ojParser p, Usual d) {
|
1112
|
-
int
|
1122
|
+
int cap = 4096;
|
1113
1123
|
|
1114
|
-
d->vhead =
|
1124
|
+
d->vhead = OJ_R_ALLOC_N(VALUE, cap);
|
1115
1125
|
d->vend = d->vhead + cap;
|
1116
1126
|
d->vtail = d->vhead;
|
1117
1127
|
|
1118
|
-
d->khead =
|
1128
|
+
d->khead = OJ_R_ALLOC_N(union _key, cap);
|
1119
1129
|
d->kend = d->khead + cap;
|
1120
1130
|
d->ktail = d->khead;
|
1121
1131
|
|
1122
1132
|
cap = 256;
|
1123
|
-
d->chead =
|
1133
|
+
d->chead = OJ_R_ALLOC_N(struct _col, cap);
|
1124
1134
|
d->cend = d->chead + cap;
|
1125
1135
|
d->ctail = d->chead;
|
1126
1136
|
|
1127
1137
|
d->get_key = cache_key;
|
1128
1138
|
d->cache_keys = true;
|
1129
1139
|
d->ignore_json_create = false;
|
1140
|
+
d->raise_on_empty = false;
|
1130
1141
|
d->cache_str = 6;
|
1131
1142
|
d->array_class = Qnil;
|
1132
1143
|
d->hash_class = Qnil;
|
@@ -1201,7 +1212,7 @@ void oj_init_usual(ojParser p, Usual d) {
|
|
1201
1212
|
}
|
1202
1213
|
|
1203
1214
|
void oj_set_parser_usual(ojParser p) {
|
1204
|
-
Usual d =
|
1215
|
+
Usual d = OJ_R_ALLOC(struct _usual);
|
1205
1216
|
|
1206
1217
|
oj_init_usual(p, d);
|
1207
1218
|
}
|
data/ext/oj/usual.h
CHANGED
@@ -13,7 +13,7 @@ struct _ojParser;
|
|
13
13
|
typedef struct _col {
|
14
14
|
long vi; // value stack index
|
15
15
|
long ki; // key stack index if an hash else -1 for an array
|
16
|
-
} *
|
16
|
+
} *Col;
|
17
17
|
|
18
18
|
typedef union _key {
|
19
19
|
struct {
|
@@ -22,9 +22,9 @@ typedef union _key {
|
|
22
22
|
};
|
23
23
|
struct {
|
24
24
|
int16_t xlen; // should be the same as len
|
25
|
-
char
|
25
|
+
char *key;
|
26
26
|
};
|
27
|
-
} *
|
27
|
+
} *Key;
|
28
28
|
|
29
29
|
#define MISS_AUTO 'A'
|
30
30
|
#define MISS_RAISE 'R'
|
@@ -43,7 +43,7 @@ typedef struct _usual {
|
|
43
43
|
Key ktail;
|
44
44
|
Key kend;
|
45
45
|
|
46
|
-
VALUE (*get_key)(
|
46
|
+
VALUE (*get_key)(struct _ojParser *p, Key kp);
|
47
47
|
struct _cache *key_cache; // same as str_cache or sym_cache
|
48
48
|
struct _cache *str_cache;
|
49
49
|
struct _cache *sym_cache;
|
@@ -53,14 +53,15 @@ typedef struct _usual {
|
|
53
53
|
VALUE array_class;
|
54
54
|
VALUE hash_class;
|
55
55
|
|
56
|
-
char
|
56
|
+
char *create_id;
|
57
57
|
uint8_t create_id_len;
|
58
58
|
uint8_t cache_str;
|
59
59
|
uint8_t cache_xrate;
|
60
60
|
uint8_t miss_class;
|
61
61
|
bool cache_keys;
|
62
62
|
bool ignore_json_create;
|
63
|
-
|
63
|
+
bool raise_on_empty;
|
64
|
+
} *Usual;
|
64
65
|
|
65
66
|
// Initialize the parser with the usual delegate. If the usual delegate is
|
66
67
|
// wrapped then this function is called first and then the parser functions
|
data/ext/oj/util.h
CHANGED
data/ext/oj/val_stack.c
CHANGED
@@ -8,7 +8,7 @@
|
|
8
8
|
#include "odd.h"
|
9
9
|
#include "oj.h"
|
10
10
|
|
11
|
-
static void
|
11
|
+
static void stack_mark(void *ptr) {
|
12
12
|
ValStack stack = (ValStack)ptr;
|
13
13
|
Val v;
|
14
14
|
|
@@ -46,6 +46,17 @@ static void mark(void *ptr) {
|
|
46
46
|
#endif
|
47
47
|
}
|
48
48
|
|
49
|
+
static const rb_data_type_t oj_stack_type = {
|
50
|
+
"Oj/stack",
|
51
|
+
{
|
52
|
+
stack_mark,
|
53
|
+
NULL,
|
54
|
+
NULL,
|
55
|
+
},
|
56
|
+
0,
|
57
|
+
0,
|
58
|
+
};
|
59
|
+
|
49
60
|
VALUE
|
50
61
|
oj_stack_init(ValStack stack) {
|
51
62
|
#ifdef HAVE_PTHREAD_MUTEX_INIT
|
@@ -70,7 +81,7 @@ oj_stack_init(ValStack stack) {
|
|
70
81
|
stack->head->clen = 0;
|
71
82
|
stack->head->next = NEXT_NONE;
|
72
83
|
|
73
|
-
return
|
84
|
+
return TypedData_Wrap_Struct(oj_cstack_class, &oj_stack_type, stack);
|
74
85
|
}
|
75
86
|
|
76
87
|
const char *oj_stack_next_string(ValNext n) {
|