oj 3.11.5 → 3.16.5
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1421 -0
- data/README.md +19 -5
- data/RELEASE_NOTES.md +61 -0
- data/ext/oj/buf.h +20 -6
- data/ext/oj/cache.c +329 -0
- data/ext/oj/cache.h +22 -0
- data/ext/oj/cache8.c +10 -9
- data/ext/oj/circarray.c +8 -6
- data/ext/oj/circarray.h +2 -2
- data/ext/oj/code.c +19 -33
- data/ext/oj/code.h +2 -2
- data/ext/oj/compat.c +27 -77
- data/ext/oj/custom.c +86 -179
- data/ext/oj/debug.c +126 -0
- data/ext/oj/dump.c +256 -249
- data/ext/oj/dump.h +26 -12
- data/ext/oj/dump_compat.c +565 -642
- data/ext/oj/dump_leaf.c +17 -63
- data/ext/oj/dump_object.c +65 -187
- data/ext/oj/dump_strict.c +27 -51
- data/ext/oj/encoder.c +43 -0
- data/ext/oj/err.c +2 -13
- data/ext/oj/err.h +24 -8
- data/ext/oj/extconf.rb +21 -6
- data/ext/oj/fast.c +149 -149
- data/ext/oj/intern.c +313 -0
- data/ext/oj/intern.h +22 -0
- data/ext/oj/mem.c +318 -0
- data/ext/oj/mem.h +53 -0
- data/ext/oj/mimic_json.c +121 -106
- data/ext/oj/object.c +85 -162
- data/ext/oj/odd.c +89 -67
- data/ext/oj/odd.h +15 -15
- data/ext/oj/oj.c +542 -411
- data/ext/oj/oj.h +99 -73
- data/ext/oj/parse.c +175 -187
- data/ext/oj/parse.h +26 -24
- data/ext/oj/parser.c +1600 -0
- data/ext/oj/parser.h +101 -0
- data/ext/oj/rails.c +112 -159
- data/ext/oj/rails.h +1 -1
- data/ext/oj/reader.c +11 -14
- data/ext/oj/reader.h +4 -2
- data/ext/oj/resolve.c +5 -24
- data/ext/oj/rxclass.c +7 -6
- data/ext/oj/rxclass.h +1 -1
- data/ext/oj/saj.c +22 -33
- data/ext/oj/saj2.c +584 -0
- data/ext/oj/saj2.h +23 -0
- data/ext/oj/scp.c +5 -28
- data/ext/oj/sparse.c +28 -72
- data/ext/oj/stream_writer.c +50 -40
- data/ext/oj/strict.c +56 -61
- data/ext/oj/string_writer.c +72 -39
- data/ext/oj/trace.h +31 -4
- data/ext/oj/usual.c +1218 -0
- data/ext/oj/usual.h +69 -0
- data/ext/oj/util.h +1 -1
- data/ext/oj/val_stack.c +14 -3
- data/ext/oj/val_stack.h +8 -7
- data/ext/oj/validate.c +46 -0
- data/ext/oj/wab.c +63 -88
- 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 +1 -2
- data/lib/oj/json.rb +162 -150
- data/lib/oj/mimic.rb +9 -7
- data/lib/oj/saj.rb +20 -6
- data/lib/oj/schandler.rb +5 -4
- data/lib/oj/state.rb +12 -8
- data/lib/oj/version.rb +1 -2
- data/lib/oj.rb +2 -0
- data/pages/Compatibility.md +1 -1
- data/pages/InstallOptions.md +20 -0
- data/pages/JsonGem.md +15 -0
- data/pages/Modes.md +8 -3
- data/pages/Options.md +43 -5
- data/pages/Parser.md +309 -0
- data/pages/Rails.md +14 -2
- 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/{activesupport5 → activesupport7}/abstract_unit.rb +16 -12
- data/test/{activesupport5 → activesupport7}/decoding_test.rb +2 -10
- data/test/{activesupport5 → activesupport7}/encoding_test.rb +86 -50
- data/test/{activesupport5 → activesupport7}/encoding_test_cases.rb +6 -0
- data/test/{activesupport5 → activesupport7}/time_zone_test_helpers.rb +8 -0
- data/test/files.rb +15 -15
- data/test/foo.rb +16 -45
- data/test/helper.rb +11 -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 +56 -38
- data/test/json_gem/json_generic_object_test.rb +11 -11
- data/test/json_gem/json_parser_test.rb +54 -47
- data/test/json_gem/json_string_matching_test.rb +9 -9
- data/test/json_gem/test_helper.rb +7 -3
- data/test/mem.rb +34 -0
- data/test/perf.rb +22 -27
- data/test/perf_compat.rb +31 -33
- data/test/perf_dump.rb +50 -0
- 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 +59 -0
- data/test/perf_parser.rb +183 -0
- data/test/perf_saj.rb +46 -54
- data/test/perf_scp.rb +58 -69
- data/test/perf_simple.rb +41 -39
- data/test/perf_strict.rb +74 -82
- 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 +95 -43
- data/test/test_custom.rb +73 -51
- data/test/test_debian.rb +7 -10
- data/test/test_fast.rb +135 -79
- data/test/test_file.rb +41 -30
- data/test/test_gc.rb +16 -5
- data/test/test_generate.rb +5 -5
- data/test/test_hash.rb +5 -5
- data/test/test_integer_range.rb +9 -9
- data/test/test_null.rb +20 -20
- data/test/test_object.rb +99 -96
- data/test/test_parser.rb +11 -0
- data/test/test_parser_debug.rb +27 -0
- data/test/test_parser_saj.rb +337 -0
- data/test/test_parser_usual.rb +251 -0
- data/test/test_rails.rb +2 -2
- data/test/test_saj.rb +10 -8
- data/test/test_scp.rb +37 -39
- data/test/test_strict.rb +40 -32
- data/test/test_various.rb +165 -84
- data/test/test_wab.rb +48 -44
- data/test/test_writer.rb +47 -47
- data/test/tests.rb +13 -5
- data/test/tests_mimic.rb +12 -3
- data/test/tests_mimic_addition.rb +12 -3
- metadata +74 -128
- data/ext/oj/hash.c +0 -131
- data/ext/oj/hash.h +0 -19
- data/ext/oj/hash_test.c +0 -491
- 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/test_helper.rb +0 -72
- data/test/bar.rb +0 -35
- data/test/baz.rb +0 -16
- data/test/zoo.rb +0 -13
data/ext/oj/saj2.c
ADDED
@@ -0,0 +1,584 @@
|
|
1
|
+
// Copyright (c) 2021, Peter Ohler, All rights reserved.
|
2
|
+
|
3
|
+
#include "saj2.h"
|
4
|
+
|
5
|
+
#include "cache.h"
|
6
|
+
#include "mem.h"
|
7
|
+
#include "oj.h"
|
8
|
+
#include "parser.h"
|
9
|
+
|
10
|
+
static VALUE get_key(ojParser p) {
|
11
|
+
Saj d = (Saj)p->ctx;
|
12
|
+
const char *key = buf_str(&p->key);
|
13
|
+
size_t len = buf_len(&p->key);
|
14
|
+
volatile VALUE rkey;
|
15
|
+
|
16
|
+
if (d->cache_keys) {
|
17
|
+
rkey = cache_intern(d->str_cache, key, len);
|
18
|
+
} else {
|
19
|
+
rkey = rb_utf8_str_new(key, len);
|
20
|
+
}
|
21
|
+
return rkey;
|
22
|
+
}
|
23
|
+
|
24
|
+
static void push_key(Saj d, VALUE key) {
|
25
|
+
if (d->klen <= (size_t)(d->tail - d->keys)) {
|
26
|
+
size_t off = d->tail - d->keys;
|
27
|
+
|
28
|
+
d->klen += d->klen / 2;
|
29
|
+
OJ_R_REALLOC_N(d->keys, VALUE, d->klen);
|
30
|
+
d->tail = d->keys + off;
|
31
|
+
}
|
32
|
+
*d->tail = key;
|
33
|
+
d->tail++;
|
34
|
+
}
|
35
|
+
|
36
|
+
static void noop(ojParser p) {
|
37
|
+
}
|
38
|
+
|
39
|
+
static void open_object(ojParser p) {
|
40
|
+
rb_funcall(((Saj)p->ctx)->handler, oj_hash_start_id, 1, Qnil);
|
41
|
+
}
|
42
|
+
|
43
|
+
static void open_object_loc(ojParser p) {
|
44
|
+
rb_funcall(((Saj)p->ctx)->handler, oj_hash_start_id, 3, Qnil, LONG2FIX(p->line), LONG2FIX(p->cur - p->col));
|
45
|
+
}
|
46
|
+
|
47
|
+
static void open_object_key(ojParser p) {
|
48
|
+
Saj d = (Saj)p->ctx;
|
49
|
+
volatile VALUE key = get_key(p);
|
50
|
+
|
51
|
+
push_key(d, key);
|
52
|
+
rb_funcall(d->handler, oj_hash_start_id, 1, key);
|
53
|
+
}
|
54
|
+
|
55
|
+
static void open_object_loc_key(ojParser p) {
|
56
|
+
Saj d = (Saj)p->ctx;
|
57
|
+
volatile VALUE key = get_key(p);
|
58
|
+
|
59
|
+
push_key(d, key);
|
60
|
+
rb_funcall(d->handler, oj_hash_start_id, 3, key, LONG2FIX(p->line), LONG2FIX(p->cur - p->col));
|
61
|
+
}
|
62
|
+
|
63
|
+
static void open_array(ojParser p) {
|
64
|
+
rb_funcall(((Saj)p->ctx)->handler, oj_array_start_id, 1, Qnil);
|
65
|
+
}
|
66
|
+
|
67
|
+
static void open_array_loc(ojParser p) {
|
68
|
+
rb_funcall(((Saj)p->ctx)->handler, oj_array_start_id, 3, Qnil, LONG2FIX(p->line), LONG2FIX(p->cur - p->col));
|
69
|
+
}
|
70
|
+
|
71
|
+
static void open_array_key(ojParser p) {
|
72
|
+
Saj d = (Saj)p->ctx;
|
73
|
+
volatile VALUE key = get_key(p);
|
74
|
+
|
75
|
+
push_key(d, key);
|
76
|
+
rb_funcall(d->handler, oj_array_start_id, 1, key);
|
77
|
+
}
|
78
|
+
|
79
|
+
static void open_array_loc_key(ojParser p) {
|
80
|
+
Saj d = (Saj)p->ctx;
|
81
|
+
volatile VALUE key = get_key(p);
|
82
|
+
|
83
|
+
push_key(d, key);
|
84
|
+
rb_funcall(d->handler, oj_array_start_id, 3, key, LONG2FIX(p->line), LONG2FIX(p->cur - p->col));
|
85
|
+
}
|
86
|
+
|
87
|
+
static void close_object(ojParser p) {
|
88
|
+
Saj d = (Saj)p->ctx;
|
89
|
+
VALUE key = Qnil;
|
90
|
+
|
91
|
+
if (OBJECT_FUN == p->stack[p->depth]) {
|
92
|
+
d->tail--;
|
93
|
+
if (d->tail < d->keys) {
|
94
|
+
rb_raise(rb_eIndexError, "accessing key stack");
|
95
|
+
}
|
96
|
+
key = *d->tail;
|
97
|
+
}
|
98
|
+
rb_funcall(d->handler, oj_hash_end_id, 1, key);
|
99
|
+
}
|
100
|
+
|
101
|
+
static void close_object_loc(ojParser p) {
|
102
|
+
Saj d = (Saj)p->ctx;
|
103
|
+
VALUE key = Qnil;
|
104
|
+
|
105
|
+
if (OBJECT_FUN == p->stack[p->depth]) {
|
106
|
+
d->tail--;
|
107
|
+
if (d->tail < d->keys) {
|
108
|
+
rb_raise(rb_eIndexError, "accessing key stack");
|
109
|
+
}
|
110
|
+
key = *d->tail;
|
111
|
+
}
|
112
|
+
rb_funcall(d->handler, oj_hash_end_id, 3, key, LONG2FIX(p->line), LONG2FIX(p->cur - p->col));
|
113
|
+
}
|
114
|
+
|
115
|
+
static void close_array(ojParser p) {
|
116
|
+
Saj d = (Saj)p->ctx;
|
117
|
+
VALUE key = Qnil;
|
118
|
+
|
119
|
+
if (OBJECT_FUN == p->stack[p->depth]) {
|
120
|
+
d->tail--;
|
121
|
+
if (d->tail < d->keys) {
|
122
|
+
rb_raise(rb_eIndexError, "accessing key stack");
|
123
|
+
}
|
124
|
+
key = *d->tail;
|
125
|
+
}
|
126
|
+
rb_funcall(d->handler, oj_array_end_id, 1, key);
|
127
|
+
}
|
128
|
+
|
129
|
+
static void close_array_loc(ojParser p) {
|
130
|
+
Saj d = (Saj)p->ctx;
|
131
|
+
VALUE key = Qnil;
|
132
|
+
|
133
|
+
if (OBJECT_FUN == p->stack[p->depth]) {
|
134
|
+
d->tail--;
|
135
|
+
if (d->tail < d->keys) {
|
136
|
+
rb_raise(rb_eIndexError, "accessing key stack");
|
137
|
+
}
|
138
|
+
key = *d->tail;
|
139
|
+
}
|
140
|
+
rb_funcall(d->handler, oj_array_end_id, 3, key, LONG2FIX(p->line), LONG2FIX(p->cur - p->col));
|
141
|
+
}
|
142
|
+
|
143
|
+
static void add_null(ojParser p) {
|
144
|
+
rb_funcall(((Saj)p->ctx)->handler, oj_add_value_id, 2, Qnil, Qnil);
|
145
|
+
}
|
146
|
+
|
147
|
+
static void add_null_loc(ojParser p) {
|
148
|
+
rb_funcall(((Saj)p->ctx)->handler, oj_add_value_id, 4, Qnil, Qnil, LONG2FIX(p->line), LONG2FIX(p->cur - p->col));
|
149
|
+
}
|
150
|
+
|
151
|
+
static void add_null_key(ojParser p) {
|
152
|
+
rb_funcall(((Saj)p->ctx)->handler, oj_add_value_id, 2, Qnil, get_key(p));
|
153
|
+
}
|
154
|
+
|
155
|
+
static void add_null_key_loc(ojParser p) {
|
156
|
+
rb_funcall(((Saj)p->ctx)->handler,
|
157
|
+
oj_add_value_id,
|
158
|
+
4,
|
159
|
+
Qnil,
|
160
|
+
get_key(p),
|
161
|
+
LONG2FIX(p->line),
|
162
|
+
LONG2FIX(p->cur - p->col));
|
163
|
+
}
|
164
|
+
|
165
|
+
static void add_true(ojParser p) {
|
166
|
+
rb_funcall(((Saj)p->ctx)->handler, oj_add_value_id, 2, Qtrue, Qnil);
|
167
|
+
}
|
168
|
+
|
169
|
+
static void add_true_loc(ojParser p) {
|
170
|
+
rb_funcall(((Saj)p->ctx)->handler, oj_add_value_id, 4, Qtrue, Qnil, LONG2FIX(p->line), LONG2FIX(p->cur - p->col));
|
171
|
+
}
|
172
|
+
|
173
|
+
static void add_true_key(ojParser p) {
|
174
|
+
rb_funcall(((Saj)p->ctx)->handler, oj_add_value_id, 2, Qtrue, get_key(p));
|
175
|
+
}
|
176
|
+
|
177
|
+
static void add_true_key_loc(ojParser p) {
|
178
|
+
rb_funcall(((Saj)p->ctx)->handler,
|
179
|
+
oj_add_value_id,
|
180
|
+
4,
|
181
|
+
Qtrue,
|
182
|
+
get_key(p),
|
183
|
+
LONG2FIX(p->line),
|
184
|
+
LONG2FIX(p->cur - p->col));
|
185
|
+
}
|
186
|
+
|
187
|
+
static void add_false(ojParser p) {
|
188
|
+
rb_funcall(((Saj)p->ctx)->handler, oj_add_value_id, 2, Qfalse, Qnil);
|
189
|
+
}
|
190
|
+
|
191
|
+
static void add_false_loc(ojParser p) {
|
192
|
+
rb_funcall(((Saj)p->ctx)->handler, oj_add_value_id, 4, Qfalse, Qnil, LONG2FIX(p->line), LONG2FIX(p->cur - p->col));
|
193
|
+
}
|
194
|
+
|
195
|
+
static void add_false_key(ojParser p) {
|
196
|
+
rb_funcall(((Saj)p->ctx)->handler, oj_add_value_id, 2, Qfalse, get_key(p));
|
197
|
+
}
|
198
|
+
|
199
|
+
static void add_false_key_loc(ojParser p) {
|
200
|
+
rb_funcall(((Saj)p->ctx)->handler,
|
201
|
+
oj_add_value_id,
|
202
|
+
4,
|
203
|
+
Qfalse,
|
204
|
+
get_key(p),
|
205
|
+
LONG2FIX(p->line),
|
206
|
+
LONG2FIX(p->cur - p->col));
|
207
|
+
}
|
208
|
+
|
209
|
+
static void add_int(ojParser p) {
|
210
|
+
rb_funcall(((Saj)p->ctx)->handler, oj_add_value_id, 2, LONG2NUM(p->num.fixnum), Qnil);
|
211
|
+
}
|
212
|
+
|
213
|
+
static void add_int_loc(ojParser p) {
|
214
|
+
rb_funcall(((Saj)p->ctx)->handler,
|
215
|
+
oj_add_value_id,
|
216
|
+
4,
|
217
|
+
LONG2NUM(p->num.fixnum),
|
218
|
+
Qnil,
|
219
|
+
LONG2FIX(p->line),
|
220
|
+
LONG2FIX(p->cur - p->col));
|
221
|
+
}
|
222
|
+
|
223
|
+
static void add_int_key(ojParser p) {
|
224
|
+
rb_funcall(((Saj)p->ctx)->handler, oj_add_value_id, 2, LONG2NUM(p->num.fixnum), get_key(p));
|
225
|
+
}
|
226
|
+
|
227
|
+
static void add_int_key_loc(ojParser p) {
|
228
|
+
rb_funcall(((Saj)p->ctx)->handler,
|
229
|
+
oj_add_value_id,
|
230
|
+
4,
|
231
|
+
LONG2NUM(p->num.fixnum),
|
232
|
+
get_key(p),
|
233
|
+
LONG2FIX(p->line),
|
234
|
+
LONG2FIX(p->cur - p->col));
|
235
|
+
}
|
236
|
+
|
237
|
+
static void add_float(ojParser p) {
|
238
|
+
rb_funcall(((Saj)p->ctx)->handler, oj_add_value_id, 2, rb_float_new(p->num.dub), Qnil);
|
239
|
+
}
|
240
|
+
|
241
|
+
static void add_float_loc(ojParser p) {
|
242
|
+
rb_funcall(((Saj)p->ctx)->handler,
|
243
|
+
oj_add_value_id,
|
244
|
+
4,
|
245
|
+
rb_float_new(p->num.dub),
|
246
|
+
Qnil,
|
247
|
+
LONG2FIX(p->line),
|
248
|
+
LONG2FIX(p->cur - p->col));
|
249
|
+
}
|
250
|
+
|
251
|
+
static void add_float_key(ojParser p) {
|
252
|
+
rb_funcall(((Saj)p->ctx)->handler, oj_add_value_id, 2, rb_float_new(p->num.dub), get_key(p));
|
253
|
+
}
|
254
|
+
|
255
|
+
static void add_float_key_loc(ojParser p) {
|
256
|
+
rb_funcall(((Saj)p->ctx)->handler,
|
257
|
+
oj_add_value_id,
|
258
|
+
4,
|
259
|
+
rb_float_new(p->num.dub),
|
260
|
+
get_key(p),
|
261
|
+
LONG2FIX(p->line),
|
262
|
+
LONG2FIX(p->cur - p->col));
|
263
|
+
}
|
264
|
+
|
265
|
+
static void add_big(ojParser p) {
|
266
|
+
rb_funcall(((Saj)p->ctx)->handler,
|
267
|
+
oj_add_value_id,
|
268
|
+
2,
|
269
|
+
rb_funcall(rb_cObject, oj_bigdecimal_id, 1, rb_str_new(buf_str(&p->buf), buf_len(&p->buf))),
|
270
|
+
Qnil);
|
271
|
+
}
|
272
|
+
|
273
|
+
static void add_big_loc(ojParser p) {
|
274
|
+
rb_funcall(((Saj)p->ctx)->handler,
|
275
|
+
oj_add_value_id,
|
276
|
+
4,
|
277
|
+
rb_funcall(rb_cObject, oj_bigdecimal_id, 1, rb_str_new(buf_str(&p->buf), buf_len(&p->buf))),
|
278
|
+
Qnil,
|
279
|
+
LONG2FIX(p->line),
|
280
|
+
LONG2FIX(p->cur - p->col));
|
281
|
+
}
|
282
|
+
|
283
|
+
static void add_big_key(ojParser p) {
|
284
|
+
rb_funcall(((Saj)p->ctx)->handler,
|
285
|
+
oj_add_value_id,
|
286
|
+
2,
|
287
|
+
rb_funcall(rb_cObject, oj_bigdecimal_id, 1, rb_str_new(buf_str(&p->buf), buf_len(&p->buf))),
|
288
|
+
get_key(p));
|
289
|
+
}
|
290
|
+
|
291
|
+
static void add_big_key_loc(ojParser p) {
|
292
|
+
rb_funcall(((Saj)p->ctx)->handler,
|
293
|
+
oj_add_value_id,
|
294
|
+
4,
|
295
|
+
rb_funcall(rb_cObject, oj_bigdecimal_id, 1, rb_str_new(buf_str(&p->buf), buf_len(&p->buf))),
|
296
|
+
get_key(p),
|
297
|
+
LONG2FIX(p->line),
|
298
|
+
LONG2FIX(p->cur - p->col));
|
299
|
+
}
|
300
|
+
|
301
|
+
static void add_str(ojParser p) {
|
302
|
+
Saj d = (Saj)p->ctx;
|
303
|
+
volatile VALUE rstr;
|
304
|
+
const char *str = buf_str(&p->buf);
|
305
|
+
size_t len = buf_len(&p->buf);
|
306
|
+
|
307
|
+
if (d->cache_str < len) {
|
308
|
+
rstr = cache_intern(d->str_cache, str, len);
|
309
|
+
} else {
|
310
|
+
rstr = rb_utf8_str_new(str, len);
|
311
|
+
}
|
312
|
+
rb_funcall(d->handler, oj_add_value_id, 2, rstr, Qnil);
|
313
|
+
}
|
314
|
+
|
315
|
+
static void add_str_loc(ojParser p) {
|
316
|
+
Saj d = (Saj)p->ctx;
|
317
|
+
volatile VALUE rstr;
|
318
|
+
const char *str = buf_str(&p->buf);
|
319
|
+
size_t len = buf_len(&p->buf);
|
320
|
+
|
321
|
+
if (d->cache_str < len) {
|
322
|
+
rstr = cache_intern(d->str_cache, str, len);
|
323
|
+
} else {
|
324
|
+
rstr = rb_utf8_str_new(str, len);
|
325
|
+
}
|
326
|
+
rb_funcall(d->handler, oj_add_value_id, 4, rstr, Qnil, LONG2FIX(p->line), LONG2FIX(p->cur - p->col));
|
327
|
+
}
|
328
|
+
|
329
|
+
static void add_str_key(ojParser p) {
|
330
|
+
Saj d = (Saj)p->ctx;
|
331
|
+
volatile VALUE rstr;
|
332
|
+
const char *str = buf_str(&p->buf);
|
333
|
+
size_t len = buf_len(&p->buf);
|
334
|
+
|
335
|
+
if (d->cache_str < len) {
|
336
|
+
rstr = cache_intern(d->str_cache, str, len);
|
337
|
+
} else {
|
338
|
+
rstr = rb_utf8_str_new(str, len);
|
339
|
+
}
|
340
|
+
rb_funcall(d->handler, oj_add_value_id, 2, rstr, get_key(p));
|
341
|
+
}
|
342
|
+
|
343
|
+
static void add_str_key_loc(ojParser p) {
|
344
|
+
Saj d = (Saj)p->ctx;
|
345
|
+
volatile VALUE rstr;
|
346
|
+
const char *str = buf_str(&p->buf);
|
347
|
+
size_t len = buf_len(&p->buf);
|
348
|
+
|
349
|
+
if (d->cache_str < len) {
|
350
|
+
rstr = cache_intern(d->str_cache, str, len);
|
351
|
+
} else {
|
352
|
+
rstr = rb_utf8_str_new(str, len);
|
353
|
+
}
|
354
|
+
rb_funcall(d->handler, oj_add_value_id, 4, rstr, get_key(p), LONG2FIX(p->line), LONG2FIX(p->cur - p->col));
|
355
|
+
}
|
356
|
+
|
357
|
+
static void reset(ojParser p) {
|
358
|
+
Funcs end = p->funcs + 3;
|
359
|
+
Funcs f;
|
360
|
+
|
361
|
+
for (f = p->funcs; f < end; f++) {
|
362
|
+
f->add_null = noop;
|
363
|
+
f->add_true = noop;
|
364
|
+
f->add_false = noop;
|
365
|
+
f->add_int = noop;
|
366
|
+
f->add_float = noop;
|
367
|
+
f->add_big = noop;
|
368
|
+
f->add_str = noop;
|
369
|
+
f->open_array = noop;
|
370
|
+
f->close_array = noop;
|
371
|
+
f->open_object = noop;
|
372
|
+
f->close_object = noop;
|
373
|
+
}
|
374
|
+
}
|
375
|
+
|
376
|
+
static VALUE option(ojParser p, const char *key, VALUE value) {
|
377
|
+
Saj d = (Saj)p->ctx;
|
378
|
+
|
379
|
+
if (0 == strcmp(key, "handler")) {
|
380
|
+
return d->handler;
|
381
|
+
}
|
382
|
+
if (0 == strcmp(key, "handler=")) {
|
383
|
+
d->tail = d->keys;
|
384
|
+
d->handler = value;
|
385
|
+
reset(p);
|
386
|
+
if (rb_respond_to(value, oj_hash_start_id)) {
|
387
|
+
if (1 == rb_obj_method_arity(value, oj_hash_start_id)) {
|
388
|
+
p->funcs[TOP_FUN].open_object = open_object;
|
389
|
+
p->funcs[ARRAY_FUN].open_object = open_object;
|
390
|
+
p->funcs[OBJECT_FUN].open_object = open_object_key;
|
391
|
+
} else {
|
392
|
+
p->funcs[TOP_FUN].open_object = open_object_loc;
|
393
|
+
p->funcs[ARRAY_FUN].open_object = open_object_loc;
|
394
|
+
p->funcs[OBJECT_FUN].open_object = open_object_loc_key;
|
395
|
+
}
|
396
|
+
}
|
397
|
+
if (rb_respond_to(value, oj_array_start_id)) {
|
398
|
+
if (1 == rb_obj_method_arity(value, oj_array_start_id)) {
|
399
|
+
p->funcs[TOP_FUN].open_array = open_array;
|
400
|
+
p->funcs[ARRAY_FUN].open_array = open_array;
|
401
|
+
p->funcs[OBJECT_FUN].open_array = open_array_key;
|
402
|
+
} else {
|
403
|
+
p->funcs[TOP_FUN].open_array = open_array_loc;
|
404
|
+
p->funcs[ARRAY_FUN].open_array = open_array_loc;
|
405
|
+
p->funcs[OBJECT_FUN].open_array = open_array_loc_key;
|
406
|
+
}
|
407
|
+
}
|
408
|
+
if (rb_respond_to(value, oj_hash_end_id)) {
|
409
|
+
if (1 == rb_obj_method_arity(value, oj_hash_end_id)) {
|
410
|
+
p->funcs[TOP_FUN].close_object = close_object;
|
411
|
+
p->funcs[ARRAY_FUN].close_object = close_object;
|
412
|
+
p->funcs[OBJECT_FUN].close_object = close_object;
|
413
|
+
} else {
|
414
|
+
p->funcs[TOP_FUN].close_object = close_object_loc;
|
415
|
+
p->funcs[ARRAY_FUN].close_object = close_object_loc;
|
416
|
+
p->funcs[OBJECT_FUN].close_object = close_object_loc;
|
417
|
+
}
|
418
|
+
}
|
419
|
+
if (rb_respond_to(value, oj_array_end_id)) {
|
420
|
+
if (1 == rb_obj_method_arity(value, oj_array_end_id)) {
|
421
|
+
p->funcs[TOP_FUN].close_array = close_array;
|
422
|
+
p->funcs[ARRAY_FUN].close_array = close_array;
|
423
|
+
p->funcs[OBJECT_FUN].close_array = close_array;
|
424
|
+
} else {
|
425
|
+
p->funcs[TOP_FUN].close_array = close_array_loc;
|
426
|
+
p->funcs[ARRAY_FUN].close_array = close_array_loc;
|
427
|
+
p->funcs[OBJECT_FUN].close_array = close_array_loc;
|
428
|
+
}
|
429
|
+
}
|
430
|
+
if (rb_respond_to(value, oj_add_value_id)) {
|
431
|
+
if (2 == rb_obj_method_arity(value, oj_add_value_id)) {
|
432
|
+
p->funcs[TOP_FUN].add_null = add_null;
|
433
|
+
p->funcs[ARRAY_FUN].add_null = add_null;
|
434
|
+
p->funcs[OBJECT_FUN].add_null = add_null_key;
|
435
|
+
|
436
|
+
p->funcs[TOP_FUN].add_true = add_true;
|
437
|
+
p->funcs[ARRAY_FUN].add_true = add_true;
|
438
|
+
p->funcs[OBJECT_FUN].add_true = add_true_key;
|
439
|
+
|
440
|
+
p->funcs[TOP_FUN].add_false = add_false;
|
441
|
+
p->funcs[ARRAY_FUN].add_false = add_false;
|
442
|
+
p->funcs[OBJECT_FUN].add_false = add_false_key;
|
443
|
+
|
444
|
+
p->funcs[TOP_FUN].add_int = add_int;
|
445
|
+
p->funcs[ARRAY_FUN].add_int = add_int;
|
446
|
+
p->funcs[OBJECT_FUN].add_int = add_int_key;
|
447
|
+
|
448
|
+
p->funcs[TOP_FUN].add_float = add_float;
|
449
|
+
p->funcs[ARRAY_FUN].add_float = add_float;
|
450
|
+
p->funcs[OBJECT_FUN].add_float = add_float_key;
|
451
|
+
|
452
|
+
p->funcs[TOP_FUN].add_big = add_big;
|
453
|
+
p->funcs[ARRAY_FUN].add_big = add_big;
|
454
|
+
p->funcs[OBJECT_FUN].add_big = add_big_key;
|
455
|
+
|
456
|
+
p->funcs[TOP_FUN].add_str = add_str;
|
457
|
+
p->funcs[ARRAY_FUN].add_str = add_str;
|
458
|
+
p->funcs[OBJECT_FUN].add_str = add_str_key;
|
459
|
+
} else {
|
460
|
+
p->funcs[TOP_FUN].add_null = add_null_loc;
|
461
|
+
p->funcs[ARRAY_FUN].add_null = add_null_loc;
|
462
|
+
p->funcs[OBJECT_FUN].add_null = add_null_key_loc;
|
463
|
+
|
464
|
+
p->funcs[TOP_FUN].add_true = add_true_loc;
|
465
|
+
p->funcs[ARRAY_FUN].add_true = add_true_loc;
|
466
|
+
p->funcs[OBJECT_FUN].add_true = add_true_key_loc;
|
467
|
+
|
468
|
+
p->funcs[TOP_FUN].add_false = add_false_loc;
|
469
|
+
p->funcs[ARRAY_FUN].add_false = add_false_loc;
|
470
|
+
p->funcs[OBJECT_FUN].add_false = add_false_key_loc;
|
471
|
+
|
472
|
+
p->funcs[TOP_FUN].add_int = add_int_loc;
|
473
|
+
p->funcs[ARRAY_FUN].add_int = add_int_loc;
|
474
|
+
p->funcs[OBJECT_FUN].add_int = add_int_key_loc;
|
475
|
+
|
476
|
+
p->funcs[TOP_FUN].add_float = add_float_loc;
|
477
|
+
p->funcs[ARRAY_FUN].add_float = add_float_loc;
|
478
|
+
p->funcs[OBJECT_FUN].add_float = add_float_key_loc;
|
479
|
+
|
480
|
+
p->funcs[TOP_FUN].add_big = add_big_loc;
|
481
|
+
p->funcs[ARRAY_FUN].add_big = add_big_loc;
|
482
|
+
p->funcs[OBJECT_FUN].add_big = add_big_key_loc;
|
483
|
+
|
484
|
+
p->funcs[TOP_FUN].add_str = add_str_loc;
|
485
|
+
p->funcs[ARRAY_FUN].add_str = add_str_loc;
|
486
|
+
p->funcs[OBJECT_FUN].add_str = add_str_key_loc;
|
487
|
+
}
|
488
|
+
}
|
489
|
+
return Qnil;
|
490
|
+
}
|
491
|
+
if (0 == strcmp(key, "cache_keys")) {
|
492
|
+
return d->cache_keys ? Qtrue : Qfalse;
|
493
|
+
}
|
494
|
+
if (0 == strcmp(key, "cache_keys=")) {
|
495
|
+
d->cache_keys = (Qtrue == value);
|
496
|
+
|
497
|
+
return d->cache_keys ? Qtrue : Qfalse;
|
498
|
+
}
|
499
|
+
if (0 == strcmp(key, "cache_strings")) {
|
500
|
+
return INT2NUM((int)d->cache_str);
|
501
|
+
}
|
502
|
+
if (0 == strcmp(key, "cache_strings=")) {
|
503
|
+
int limit = NUM2INT(value);
|
504
|
+
|
505
|
+
if (CACHE_MAX_KEY < limit) {
|
506
|
+
limit = CACHE_MAX_KEY;
|
507
|
+
} else if (limit < 0) {
|
508
|
+
limit = 0;
|
509
|
+
}
|
510
|
+
d->cache_str = limit;
|
511
|
+
|
512
|
+
return INT2NUM((int)d->cache_str);
|
513
|
+
}
|
514
|
+
rb_raise(rb_eArgError, "%s is not an option for the SAJ (Simple API for JSON) saj", key);
|
515
|
+
|
516
|
+
return Qnil; // Never reached due to the raise but required by the compiler.
|
517
|
+
}
|
518
|
+
|
519
|
+
static VALUE result(ojParser p) {
|
520
|
+
return Qnil;
|
521
|
+
}
|
522
|
+
|
523
|
+
static void start(ojParser p) {
|
524
|
+
Saj d = (Saj)p->ctx;
|
525
|
+
|
526
|
+
d->tail = d->keys;
|
527
|
+
}
|
528
|
+
|
529
|
+
static void dfree(ojParser p) {
|
530
|
+
Saj d = (Saj)p->ctx;
|
531
|
+
|
532
|
+
if (NULL != d->keys) {
|
533
|
+
OJ_R_FREE(d->keys);
|
534
|
+
}
|
535
|
+
cache_free(d->str_cache);
|
536
|
+
OJ_R_FREE(p->ctx);
|
537
|
+
}
|
538
|
+
|
539
|
+
static void mark(ojParser p) {
|
540
|
+
if (NULL == p || NULL == p->ctx) {
|
541
|
+
return;
|
542
|
+
}
|
543
|
+
Saj d = (Saj)p->ctx;
|
544
|
+
VALUE *kp;
|
545
|
+
|
546
|
+
cache_mark(d->str_cache);
|
547
|
+
if (Qnil != d->handler) {
|
548
|
+
rb_gc_mark(d->handler);
|
549
|
+
}
|
550
|
+
if (!d->cache_keys) {
|
551
|
+
for (kp = d->keys; kp < d->tail; kp++) {
|
552
|
+
rb_gc_mark(*kp);
|
553
|
+
}
|
554
|
+
}
|
555
|
+
}
|
556
|
+
|
557
|
+
static VALUE form_str(const char *str, size_t len) {
|
558
|
+
return rb_str_freeze(rb_utf8_str_new(str, len));
|
559
|
+
}
|
560
|
+
|
561
|
+
void oj_init_saj(ojParser p, Saj d) {
|
562
|
+
d->klen = 256;
|
563
|
+
d->keys = OJ_R_ALLOC_N(VALUE, d->klen);
|
564
|
+
d->tail = d->keys;
|
565
|
+
d->handler = Qnil;
|
566
|
+
d->str_cache = cache_create(0, form_str, true, false);
|
567
|
+
d->cache_str = 16;
|
568
|
+
d->cache_keys = true;
|
569
|
+
d->thread_safe = false;
|
570
|
+
|
571
|
+
p->ctx = (void *)d;
|
572
|
+
reset(p);
|
573
|
+
p->option = option;
|
574
|
+
p->result = result;
|
575
|
+
p->free = dfree;
|
576
|
+
p->mark = mark;
|
577
|
+
p->start = start;
|
578
|
+
}
|
579
|
+
|
580
|
+
void oj_set_parser_saj(ojParser p) {
|
581
|
+
Saj d = OJ_R_ALLOC(struct _saj);
|
582
|
+
|
583
|
+
oj_init_saj(p, d);
|
584
|
+
}
|
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/scp.c
CHANGED
@@ -9,6 +9,7 @@
|
|
9
9
|
#include <unistd.h>
|
10
10
|
|
11
11
|
#include "encode.h"
|
12
|
+
#include "intern.h"
|
12
13
|
#include "oj.h"
|
13
14
|
#include "parse.h"
|
14
15
|
|
@@ -32,8 +33,7 @@ static VALUE noop_hash_key(ParseInfo pi, const char *key, size_t klen) {
|
|
32
33
|
return Qundef;
|
33
34
|
}
|
34
35
|
|
35
|
-
static void
|
36
|
-
noop_hash_set_cstr(ParseInfo pi, Val kval, const char *str, size_t len, const char *orig) {
|
36
|
+
static void noop_hash_set_cstr(ParseInfo pi, Val kval, const char *str, size_t len, const char *orig) {
|
37
37
|
}
|
38
38
|
|
39
39
|
static void noop_hash_set_num(ParseInfo pi, Val kval, NumInfo ni) {
|
@@ -82,19 +82,6 @@ static void end_array(ParseInfo pi) {
|
|
82
82
|
rb_funcall(pi->handler, oj_array_end_id, 0);
|
83
83
|
}
|
84
84
|
|
85
|
-
static VALUE calc_hash_key(ParseInfo pi, Val kval) {
|
86
|
-
volatile VALUE rkey = kval->key_val;
|
87
|
-
|
88
|
-
if (Qundef == rkey) {
|
89
|
-
rkey = rb_str_new(kval->key, kval->klen);
|
90
|
-
rkey = oj_encode(rkey);
|
91
|
-
if (Yes == pi->options.sym_key) {
|
92
|
-
rkey = rb_str_intern(rkey);
|
93
|
-
}
|
94
|
-
}
|
95
|
-
return rkey;
|
96
|
-
}
|
97
|
-
|
98
85
|
static VALUE hash_key(ParseInfo pi, const char *key, size_t klen) {
|
99
86
|
return rb_funcall(pi->handler, oj_hash_key_id, 1, rb_str_new(key, klen));
|
100
87
|
}
|
@@ -103,12 +90,7 @@ static void hash_set_cstr(ParseInfo pi, Val kval, const char *str, size_t len, c
|
|
103
90
|
volatile VALUE rstr = rb_str_new(str, len);
|
104
91
|
|
105
92
|
rstr = oj_encode(rstr);
|
106
|
-
rb_funcall(pi->handler,
|
107
|
-
oj_hash_set_id,
|
108
|
-
3,
|
109
|
-
stack_peek(&pi->stack)->val,
|
110
|
-
calc_hash_key(pi, kval),
|
111
|
-
rstr);
|
93
|
+
rb_funcall(pi->handler, oj_hash_set_id, 3, stack_peek(&pi->stack)->val, oj_calc_hash_key(pi, kval), rstr);
|
112
94
|
}
|
113
95
|
|
114
96
|
static void hash_set_num(ParseInfo pi, Val kval, NumInfo ni) {
|
@@ -116,17 +98,12 @@ static void hash_set_num(ParseInfo pi, Val kval, NumInfo ni) {
|
|
116
98
|
oj_hash_set_id,
|
117
99
|
3,
|
118
100
|
stack_peek(&pi->stack)->val,
|
119
|
-
|
101
|
+
oj_calc_hash_key(pi, kval),
|
120
102
|
oj_num_as_value(ni));
|
121
103
|
}
|
122
104
|
|
123
105
|
static void hash_set_value(ParseInfo pi, Val kval, VALUE value) {
|
124
|
-
rb_funcall(pi->handler,
|
125
|
-
oj_hash_set_id,
|
126
|
-
3,
|
127
|
-
stack_peek(&pi->stack)->val,
|
128
|
-
calc_hash_key(pi, kval),
|
129
|
-
value);
|
106
|
+
rb_funcall(pi->handler, oj_hash_set_id, 3, stack_peek(&pi->stack)->val, oj_calc_hash_key(pi, kval), value);
|
130
107
|
}
|
131
108
|
|
132
109
|
static void array_append_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
|