oj 3.10.6 → 3.12.1
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/README.md +6 -1
- data/ext/oj/buf.h +36 -68
- data/ext/oj/cache8.c +59 -62
- data/ext/oj/cache8.h +9 -36
- data/ext/oj/circarray.c +36 -42
- data/ext/oj/circarray.h +12 -13
- data/ext/oj/code.c +172 -179
- data/ext/oj/code.h +22 -24
- data/ext/oj/compat.c +176 -181
- data/ext/oj/custom.c +800 -864
- data/ext/oj/dump.c +774 -776
- data/ext/oj/dump.h +50 -55
- data/ext/oj/dump_compat.c +2 -4
- data/ext/oj/dump_leaf.c +118 -162
- data/ext/oj/dump_object.c +610 -632
- data/ext/oj/dump_strict.c +319 -331
- data/ext/oj/encode.h +4 -33
- data/ext/oj/err.c +40 -29
- data/ext/oj/err.h +25 -44
- data/ext/oj/extconf.rb +2 -1
- data/ext/oj/fast.c +1054 -1081
- data/ext/oj/hash.c +102 -97
- data/ext/oj/hash.h +10 -35
- data/ext/oj/hash_test.c +451 -472
- data/ext/oj/mimic_json.c +415 -402
- data/ext/oj/object.c +588 -532
- data/ext/oj/odd.c +124 -132
- data/ext/oj/odd.h +28 -29
- data/ext/oj/oj.c +1186 -906
- data/ext/oj/oj.h +289 -298
- data/ext/oj/parse.c +946 -870
- data/ext/oj/parse.h +81 -79
- data/ext/oj/rails.c +837 -842
- data/ext/oj/rails.h +8 -11
- data/ext/oj/reader.c +139 -147
- data/ext/oj/reader.h +68 -84
- data/ext/oj/resolve.c +44 -47
- data/ext/oj/resolve.h +4 -6
- data/ext/oj/rxclass.c +69 -73
- data/ext/oj/rxclass.h +13 -14
- data/ext/oj/saj.c +453 -484
- data/ext/oj/scp.c +88 -113
- data/ext/oj/sparse.c +783 -714
- data/ext/oj/stream_writer.c +123 -157
- data/ext/oj/strict.c +133 -106
- data/ext/oj/string_writer.c +199 -247
- data/ext/oj/trace.c +34 -41
- data/ext/oj/trace.h +15 -15
- data/ext/oj/util.c +104 -104
- data/ext/oj/util.h +4 -3
- data/ext/oj/val_stack.c +48 -76
- data/ext/oj/val_stack.h +80 -115
- data/ext/oj/wab.c +321 -325
- data/lib/oj.rb +0 -8
- data/lib/oj/bag.rb +1 -0
- data/lib/oj/easy_hash.rb +5 -4
- data/lib/oj/mimic.rb +47 -13
- data/lib/oj/version.rb +1 -1
- data/pages/Modes.md +1 -0
- data/pages/Options.md +23 -11
- data/test/activerecord/result_test.rb +7 -2
- data/test/foo.rb +8 -40
- data/test/helper.rb +10 -0
- data/test/json_gem/json_common_interface_test.rb +8 -3
- data/test/json_gem/json_generator_test.rb +15 -3
- data/test/json_gem/test_helper.rb +8 -0
- data/test/perf.rb +1 -1
- data/test/perf_scp.rb +11 -10
- data/test/perf_strict.rb +17 -23
- data/test/prec.rb +23 -0
- data/test/sample_json.rb +1 -1
- data/test/test_compat.rb +16 -3
- data/test/test_custom.rb +11 -0
- data/test/test_fast.rb +32 -2
- data/test/test_generate.rb +21 -0
- data/test/test_hash.rb +10 -0
- data/test/test_rails.rb +9 -0
- data/test/test_scp.rb +1 -1
- data/test/test_various.rb +4 -2
- metadata +89 -85
data/ext/oj/compat.c
CHANGED
@@ -1,298 +1,293 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
* All rights reserved.
|
4
|
-
*/
|
1
|
+
// Copyright (c) 2012 Peter Ohler. All rights reserved.
|
2
|
+
// Licensed under the MIT License. See LICENSE file in the project root for license details.
|
5
3
|
|
6
4
|
#include <stdio.h>
|
7
5
|
|
8
|
-
#include "
|
6
|
+
#include "encode.h"
|
9
7
|
#include "err.h"
|
8
|
+
#include "hash.h"
|
9
|
+
#include "oj.h"
|
10
10
|
#include "parse.h"
|
11
11
|
#include "resolve.h"
|
12
|
-
#include "hash.h"
|
13
|
-
#include "encode.h"
|
14
12
|
#include "trace.h"
|
15
13
|
|
16
|
-
static void
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
(int)pi->options.create_id_len == klen &&
|
28
|
-
0 == strncmp(pi->options.create_id, key, klen)) {
|
29
|
-
|
30
|
-
parent->classname = oj_strndup(str, len);
|
31
|
-
parent->clen = len;
|
14
|
+
static void hash_set_cstr(ParseInfo pi, Val kval, const char *str, size_t len, const char *orig) {
|
15
|
+
const char * key = kval->key;
|
16
|
+
int klen = kval->klen;
|
17
|
+
Val parent = stack_peek(&pi->stack);
|
18
|
+
volatile VALUE rkey = kval->key_val;
|
19
|
+
|
20
|
+
if (Qundef == rkey && Yes == pi->options.create_ok && NULL != pi->options.create_id &&
|
21
|
+
*pi->options.create_id == *key && (int)pi->options.create_id_len == klen &&
|
22
|
+
0 == strncmp(pi->options.create_id, key, klen)) {
|
23
|
+
parent->classname = oj_strndup(str, len);
|
24
|
+
parent->clen = len;
|
32
25
|
} else {
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
26
|
+
volatile VALUE rstr = oj_cstr_to_value(str, len, (size_t)pi->options.cache_str);
|
27
|
+
|
28
|
+
if (Qundef == rkey) {
|
29
|
+
if (Yes != pi->options.cache_keys) {
|
30
|
+
rkey = rb_str_new(key, klen);
|
31
|
+
rkey = oj_encode(rkey);
|
32
|
+
if (Yes == pi->options.sym_key) {
|
33
|
+
rkey = rb_str_intern(rkey);
|
34
|
+
}
|
35
|
+
} else {
|
36
|
+
VALUE *slot;
|
37
|
+
|
38
|
+
if (Yes == pi->options.sym_key) {
|
39
|
+
if (Qnil == (rkey = oj_sym_hash_get(key, klen, &slot))) {
|
40
|
+
rkey = rb_str_new(key, klen);
|
41
|
+
rkey = oj_encode(rkey);
|
42
|
+
rkey = rb_str_intern(rkey);
|
43
|
+
*slot = rkey;
|
44
|
+
rb_gc_register_address(slot);
|
45
|
+
}
|
46
|
+
} else {
|
47
|
+
if (Qnil == (rkey = oj_str_hash_get(key, klen, &slot))) {
|
48
|
+
rkey = rb_str_new(key, klen);
|
49
|
+
rkey = oj_encode(rkey);
|
50
|
+
*slot = rkey;
|
51
|
+
rb_gc_register_address(slot);
|
52
|
+
}
|
53
|
+
}
|
54
|
+
}
|
55
|
+
}
|
56
|
+
if (Yes == pi->options.create_ok && NULL != pi->options.str_rx.head) {
|
57
|
+
VALUE clas = oj_rxclass_match(&pi->options.str_rx, str, (int)len);
|
58
|
+
|
59
|
+
if (Qnil != clas) {
|
60
|
+
rstr = rb_funcall(clas, oj_json_create_id, 1, rstr);
|
61
|
+
}
|
62
|
+
}
|
63
|
+
if (rb_cHash != rb_obj_class(parent->val)) {
|
64
|
+
// The rb_hash_set would still work but the unit tests for the
|
65
|
+
// json gem require the less efficient []= method be called to set
|
66
|
+
// values. Even using the store method to set the values will fail
|
67
|
+
// the unit tests.
|
68
|
+
rb_funcall(parent->val, rb_intern("[]="), 2, rkey, rstr);
|
69
|
+
} else {
|
70
|
+
rb_hash_aset(parent->val, rkey, rstr);
|
71
|
+
}
|
72
|
+
if (Yes == pi->options.trace) {
|
73
|
+
oj_trace_parse_call("set_string", pi, __FILE__, __LINE__, rstr);
|
74
|
+
}
|
62
75
|
}
|
63
76
|
}
|
64
77
|
|
65
|
-
static VALUE
|
66
|
-
|
67
|
-
volatile VALUE h;
|
78
|
+
static VALUE start_hash(ParseInfo pi) {
|
79
|
+
volatile VALUE h;
|
68
80
|
|
69
81
|
if (Qnil != pi->options.hash_class) {
|
70
|
-
|
82
|
+
h = rb_class_new_instance(0, NULL, pi->options.hash_class);
|
71
83
|
} else {
|
72
|
-
|
84
|
+
h = rb_hash_new();
|
73
85
|
}
|
74
86
|
if (Yes == pi->options.trace) {
|
75
|
-
|
87
|
+
oj_trace_parse_in("start_hash", pi, __FILE__, __LINE__);
|
76
88
|
}
|
77
89
|
return h;
|
78
90
|
}
|
79
91
|
|
80
|
-
static void
|
81
|
-
|
82
|
-
Val parent = stack_peek(&pi->stack);
|
92
|
+
static void end_hash(struct _parseInfo *pi) {
|
93
|
+
Val parent = stack_peek(&pi->stack);
|
83
94
|
|
84
95
|
if (0 != parent->classname) {
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
96
|
+
volatile VALUE clas;
|
97
|
+
|
98
|
+
clas = oj_name2class(pi, parent->classname, parent->clen, 0, rb_eArgError);
|
99
|
+
if (Qundef != clas) { // else an error
|
100
|
+
ID creatable = rb_intern("json_creatable?");
|
101
|
+
|
102
|
+
if (!rb_respond_to(clas, creatable) || Qtrue == rb_funcall(clas, creatable, 0)) {
|
103
|
+
parent->val = rb_funcall(clas, oj_json_create_id, 1, parent->val);
|
104
|
+
}
|
105
|
+
}
|
106
|
+
if (0 != parent->classname) {
|
107
|
+
xfree((char *)parent->classname);
|
108
|
+
parent->classname = 0;
|
109
|
+
}
|
99
110
|
}
|
100
111
|
if (Yes == pi->options.trace) {
|
101
|
-
|
112
|
+
oj_trace_parse_hash_end(pi, __FILE__, __LINE__);
|
102
113
|
}
|
103
114
|
}
|
104
115
|
|
105
|
-
static
|
106
|
-
|
107
|
-
volatile VALUE rkey = parent->key_val;
|
116
|
+
static void add_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
|
117
|
+
volatile VALUE rstr = oj_cstr_to_value(str, len, (size_t)pi->options.cache_str);
|
108
118
|
|
109
|
-
if (Qundef == rkey) {
|
110
|
-
rkey = rb_str_new(parent->key, parent->klen);
|
111
|
-
}
|
112
|
-
rkey = oj_encode(rkey);
|
113
|
-
if (Yes == pi->options.sym_key) {
|
114
|
-
rkey = rb_str_intern(rkey);
|
115
|
-
}
|
116
|
-
return rkey;
|
117
|
-
}
|
118
|
-
|
119
|
-
static void
|
120
|
-
add_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
|
121
|
-
volatile VALUE rstr = rb_str_new(str, len);
|
122
|
-
|
123
|
-
rstr = oj_encode(rstr);
|
124
119
|
if (Yes == pi->options.create_ok && NULL != pi->options.str_rx.head) {
|
125
|
-
|
120
|
+
VALUE clas = oj_rxclass_match(&pi->options.str_rx, str, (int)len);
|
126
121
|
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
122
|
+
if (Qnil != clas) {
|
123
|
+
pi->stack.head->val = rb_funcall(clas, oj_json_create_id, 1, rstr);
|
124
|
+
return;
|
125
|
+
}
|
131
126
|
}
|
132
127
|
pi->stack.head->val = rstr;
|
133
128
|
if (Yes == pi->options.trace) {
|
134
|
-
|
129
|
+
oj_trace_parse_call("add_string", pi, __FILE__, __LINE__, rstr);
|
135
130
|
}
|
136
131
|
}
|
137
132
|
|
138
|
-
static void
|
139
|
-
add_num(ParseInfo pi, NumInfo ni) {
|
133
|
+
static void add_num(ParseInfo pi, NumInfo ni) {
|
140
134
|
pi->stack.head->val = oj_num_as_value(ni);
|
141
135
|
if (Yes == pi->options.trace) {
|
142
|
-
|
136
|
+
oj_trace_parse_call("add_number", pi, __FILE__, __LINE__, pi->stack.head->val);
|
143
137
|
}
|
144
138
|
}
|
145
139
|
|
146
|
-
static void
|
147
|
-
|
148
|
-
volatile VALUE rval = oj_num_as_value(ni);
|
140
|
+
static void hash_set_num(struct _parseInfo *pi, Val parent, NumInfo ni) {
|
141
|
+
volatile VALUE rval = oj_num_as_value(ni);
|
149
142
|
|
150
143
|
if (!oj_use_hash_alt && rb_cHash != rb_obj_class(parent->val)) {
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
144
|
+
// The rb_hash_set would still work but the unit tests for the
|
145
|
+
// json gem require the less efficient []= method be called to set
|
146
|
+
// values. Even using the store method to set the values will fail
|
147
|
+
// the unit tests.
|
148
|
+
rb_funcall(stack_peek(&pi->stack)->val,
|
149
|
+
rb_intern("[]="),
|
150
|
+
2,
|
151
|
+
oj_calc_hash_key(pi, parent),
|
152
|
+
rval);
|
156
153
|
} else {
|
157
|
-
|
154
|
+
rb_hash_aset(stack_peek(&pi->stack)->val, oj_calc_hash_key(pi, parent), rval);
|
158
155
|
}
|
159
156
|
if (Yes == pi->options.trace) {
|
160
|
-
|
157
|
+
oj_trace_parse_call("set_number", pi, __FILE__, __LINE__, rval);
|
161
158
|
}
|
162
159
|
}
|
163
160
|
|
164
|
-
static void
|
165
|
-
hash_set_value(ParseInfo pi, Val parent, VALUE value) {
|
161
|
+
static void hash_set_value(ParseInfo pi, Val parent, VALUE value) {
|
166
162
|
if (rb_cHash != rb_obj_class(parent->val)) {
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
163
|
+
// The rb_hash_set would still work but the unit tests for the
|
164
|
+
// json gem require the less efficient []= method be called to set
|
165
|
+
// values. Even using the store method to set the values will fail
|
166
|
+
// the unit tests.
|
167
|
+
rb_funcall(stack_peek(&pi->stack)->val,
|
168
|
+
rb_intern("[]="),
|
169
|
+
2,
|
170
|
+
oj_calc_hash_key(pi, parent),
|
171
|
+
value);
|
172
172
|
} else {
|
173
|
-
|
173
|
+
rb_hash_aset(stack_peek(&pi->stack)->val, oj_calc_hash_key(pi, parent), value);
|
174
174
|
}
|
175
175
|
if (Yes == pi->options.trace) {
|
176
|
-
|
176
|
+
oj_trace_parse_call("set_value", pi, __FILE__, __LINE__, value);
|
177
177
|
}
|
178
178
|
}
|
179
179
|
|
180
|
-
static VALUE
|
181
|
-
start_array(ParseInfo pi) {
|
180
|
+
static VALUE start_array(ParseInfo pi) {
|
182
181
|
if (Qnil != pi->options.array_class) {
|
183
|
-
|
182
|
+
return rb_class_new_instance(0, NULL, pi->options.array_class);
|
184
183
|
}
|
185
184
|
if (Yes == pi->options.trace) {
|
186
|
-
|
185
|
+
oj_trace_parse_in("start_array", pi, __FILE__, __LINE__);
|
187
186
|
}
|
188
187
|
return rb_ary_new();
|
189
188
|
}
|
190
189
|
|
191
|
-
static void
|
192
|
-
|
193
|
-
|
194
|
-
volatile VALUE rval = oj_num_as_value(ni);
|
190
|
+
static void array_append_num(ParseInfo pi, NumInfo ni) {
|
191
|
+
Val parent = stack_peek(&pi->stack);
|
192
|
+
volatile VALUE rval = oj_num_as_value(ni);
|
195
193
|
|
196
194
|
if (!oj_use_array_alt && rb_cArray != rb_obj_class(parent->val)) {
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
195
|
+
// The rb_ary_push would still work but the unit tests for the json
|
196
|
+
// gem require the less efficient << method be called to push the
|
197
|
+
// values.
|
198
|
+
rb_funcall(parent->val, rb_intern("<<"), 1, rval);
|
201
199
|
} else {
|
202
|
-
|
200
|
+
rb_ary_push(parent->val, rval);
|
203
201
|
}
|
204
202
|
if (Yes == pi->options.trace) {
|
205
|
-
|
203
|
+
oj_trace_parse_call("append_number", pi, __FILE__, __LINE__, rval);
|
206
204
|
}
|
207
205
|
}
|
208
206
|
|
209
|
-
static void
|
210
|
-
|
211
|
-
volatile VALUE rstr = rb_str_new(str, len);
|
207
|
+
static void array_append_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
|
208
|
+
volatile VALUE rstr = oj_cstr_to_value(str, len, (size_t)pi->options.cache_str);
|
212
209
|
|
213
|
-
rstr = oj_encode(rstr);
|
214
210
|
if (Yes == pi->options.create_ok && NULL != pi->options.str_rx.head) {
|
215
|
-
|
211
|
+
VALUE clas = oj_rxclass_match(&pi->options.str_rx, str, (int)len);
|
216
212
|
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
213
|
+
if (Qnil != clas) {
|
214
|
+
rb_ary_push(stack_peek(&pi->stack)->val, rb_funcall(clas, oj_json_create_id, 1, rstr));
|
215
|
+
return;
|
216
|
+
}
|
221
217
|
}
|
222
218
|
rb_ary_push(stack_peek(&pi->stack)->val, rstr);
|
223
219
|
if (Yes == pi->options.trace) {
|
224
|
-
|
220
|
+
oj_trace_parse_call("append_string", pi, __FILE__, __LINE__, rstr);
|
225
221
|
}
|
226
222
|
}
|
227
223
|
|
228
|
-
void
|
229
|
-
oj_set_compat_callbacks(ParseInfo pi) {
|
224
|
+
void oj_set_compat_callbacks(ParseInfo pi) {
|
230
225
|
oj_set_strict_callbacks(pi);
|
231
|
-
pi->start_hash
|
232
|
-
pi->end_hash
|
233
|
-
pi->hash_set_cstr
|
234
|
-
pi->hash_set_num
|
235
|
-
pi->hash_set_value
|
236
|
-
pi->add_num
|
237
|
-
pi->add_cstr
|
226
|
+
pi->start_hash = start_hash;
|
227
|
+
pi->end_hash = end_hash;
|
228
|
+
pi->hash_set_cstr = hash_set_cstr;
|
229
|
+
pi->hash_set_num = hash_set_num;
|
230
|
+
pi->hash_set_value = hash_set_value;
|
231
|
+
pi->add_num = add_num;
|
232
|
+
pi->add_cstr = add_cstr;
|
238
233
|
pi->array_append_cstr = array_append_cstr;
|
239
|
-
pi->start_array
|
240
|
-
pi->array_append_num
|
234
|
+
pi->start_array = start_array;
|
235
|
+
pi->array_append_num = array_append_num;
|
241
236
|
}
|
242
237
|
|
243
238
|
VALUE
|
244
239
|
oj_compat_parse(int argc, VALUE *argv, VALUE self) {
|
245
|
-
struct _parseInfo
|
240
|
+
struct _parseInfo pi;
|
246
241
|
|
247
242
|
parse_info_init(&pi);
|
248
|
-
pi.options
|
249
|
-
pi.handler
|
250
|
-
pi.err_class
|
251
|
-
pi.max_depth
|
252
|
-
pi.options.allow_nan
|
253
|
-
pi.options.nilnil
|
243
|
+
pi.options = oj_default_options;
|
244
|
+
pi.handler = Qnil;
|
245
|
+
pi.err_class = Qnil;
|
246
|
+
pi.max_depth = 0;
|
247
|
+
pi.options.allow_nan = Yes;
|
248
|
+
pi.options.nilnil = Yes;
|
254
249
|
pi.options.empty_string = No;
|
255
250
|
oj_set_compat_callbacks(&pi);
|
256
251
|
|
257
252
|
if (T_STRING == rb_type(*argv)) {
|
258
|
-
|
253
|
+
return oj_pi_parse(argc, argv, &pi, 0, 0, false);
|
259
254
|
} else {
|
260
|
-
|
255
|
+
return oj_pi_sparse(argc, argv, &pi, 0);
|
261
256
|
}
|
262
257
|
}
|
263
258
|
|
264
259
|
VALUE
|
265
260
|
oj_compat_load(int argc, VALUE *argv, VALUE self) {
|
266
|
-
struct _parseInfo
|
261
|
+
struct _parseInfo pi;
|
267
262
|
|
268
263
|
parse_info_init(&pi);
|
269
|
-
pi.options
|
270
|
-
pi.handler
|
271
|
-
pi.err_class
|
272
|
-
pi.max_depth
|
273
|
-
pi.options.allow_nan
|
274
|
-
pi.options.nilnil
|
264
|
+
pi.options = oj_default_options;
|
265
|
+
pi.handler = Qnil;
|
266
|
+
pi.err_class = Qnil;
|
267
|
+
pi.max_depth = 0;
|
268
|
+
pi.options.allow_nan = Yes;
|
269
|
+
pi.options.nilnil = Yes;
|
275
270
|
pi.options.empty_string = Yes;
|
276
271
|
oj_set_compat_callbacks(&pi);
|
277
272
|
|
278
273
|
if (T_STRING == rb_type(*argv)) {
|
279
|
-
|
274
|
+
return oj_pi_parse(argc, argv, &pi, 0, 0, false);
|
280
275
|
} else {
|
281
|
-
|
276
|
+
return oj_pi_sparse(argc, argv, &pi, 0);
|
282
277
|
}
|
283
278
|
}
|
284
279
|
|
285
280
|
VALUE
|
286
281
|
oj_compat_parse_cstr(int argc, VALUE *argv, char *json, size_t len) {
|
287
|
-
struct _parseInfo
|
282
|
+
struct _parseInfo pi;
|
288
283
|
|
289
284
|
parse_info_init(&pi);
|
290
|
-
pi.options
|
291
|
-
pi.handler
|
292
|
-
pi.err_class
|
293
|
-
pi.max_depth
|
285
|
+
pi.options = oj_default_options;
|
286
|
+
pi.handler = Qnil;
|
287
|
+
pi.err_class = Qnil;
|
288
|
+
pi.max_depth = 0;
|
294
289
|
pi.options.allow_nan = Yes;
|
295
|
-
pi.options.nilnil
|
290
|
+
pi.options.nilnil = Yes;
|
296
291
|
oj_set_compat_callbacks(&pi);
|
297
292
|
|
298
293
|
return oj_pi_parse(argc, argv, &pi, json, len, false);
|