oj 3.11.0 → 3.11.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/README.md +2 -1
- data/ext/oj/buf.h +34 -38
- data/ext/oj/cache8.c +59 -62
- data/ext/oj/cache8.h +8 -7
- data/ext/oj/circarray.c +33 -35
- data/ext/oj/circarray.h +11 -9
- data/ext/oj/code.c +170 -174
- data/ext/oj/code.h +21 -20
- data/ext/oj/compat.c +159 -166
- data/ext/oj/custom.c +802 -851
- data/ext/oj/dump.c +766 -778
- data/ext/oj/dump.h +49 -51
- data/ext/oj/dump_compat.c +1 -0
- data/ext/oj/dump_leaf.c +116 -157
- data/ext/oj/dump_object.c +609 -628
- data/ext/oj/dump_strict.c +318 -327
- data/ext/oj/encode.h +3 -4
- data/ext/oj/err.c +39 -25
- data/ext/oj/err.h +24 -15
- data/ext/oj/extconf.rb +2 -1
- data/ext/oj/fast.c +1008 -1038
- data/ext/oj/hash.c +62 -66
- data/ext/oj/hash.h +7 -6
- data/ext/oj/hash_test.c +450 -443
- data/ext/oj/mimic_json.c +413 -402
- data/ext/oj/object.c +559 -528
- data/ext/oj/odd.c +123 -128
- data/ext/oj/odd.h +27 -25
- data/ext/oj/oj.c +1131 -924
- data/ext/oj/oj.h +286 -298
- data/ext/oj/parse.c +938 -930
- data/ext/oj/parse.h +70 -69
- data/ext/oj/rails.c +836 -839
- data/ext/oj/rails.h +7 -7
- data/ext/oj/reader.c +135 -140
- data/ext/oj/reader.h +66 -79
- data/ext/oj/resolve.c +43 -43
- data/ext/oj/resolve.h +3 -2
- data/ext/oj/rxclass.c +67 -68
- data/ext/oj/rxclass.h +12 -10
- data/ext/oj/saj.c +451 -479
- data/ext/oj/scp.c +93 -103
- data/ext/oj/sparse.c +770 -730
- data/ext/oj/stream_writer.c +120 -149
- data/ext/oj/strict.c +71 -86
- data/ext/oj/string_writer.c +198 -243
- data/ext/oj/trace.c +29 -33
- data/ext/oj/trace.h +14 -11
- data/ext/oj/util.c +103 -103
- data/ext/oj/util.h +3 -2
- data/ext/oj/val_stack.c +47 -47
- data/ext/oj/val_stack.h +79 -86
- data/ext/oj/wab.c +291 -309
- data/lib/oj/bag.rb +1 -0
- data/lib/oj/easy_hash.rb +5 -4
- data/lib/oj/mimic.rb +0 -12
- data/lib/oj/version.rb +1 -1
- data/test/activerecord/result_test.rb +7 -2
- data/test/foo.rb +35 -32
- data/test/helper.rb +10 -0
- data/test/json_gem/json_generator_test.rb +15 -3
- data/test/json_gem/test_helper.rb +8 -0
- data/test/test_compat.rb +2 -2
- data/test/test_generate.rb +21 -0
- data/test/test_hash.rb +10 -0
- data/test/test_scp.rb +1 -1
- metadata +4 -2
data/ext/oj/stream_writer.c
CHANGED
@@ -1,19 +1,18 @@
|
|
1
1
|
// Copyright (c) 2012, 2017 Peter Ohler. All rights reserved.
|
2
|
+
// Licensed under the MIT License. See LICENSE file in the project root for license details.
|
2
3
|
|
3
4
|
#include <errno.h>
|
4
|
-
|
5
5
|
#include <ruby.h>
|
6
6
|
|
7
7
|
#include "encode.h"
|
8
8
|
|
9
|
-
extern VALUE
|
9
|
+
extern VALUE Oj;
|
10
10
|
|
11
|
-
static void
|
12
|
-
|
13
|
-
StreamWriter sw;
|
11
|
+
static void stream_writer_free(void *ptr) {
|
12
|
+
StreamWriter sw;
|
14
13
|
|
15
14
|
if (0 == ptr) {
|
16
|
-
|
15
|
+
return;
|
17
16
|
}
|
18
17
|
sw = (StreamWriter)ptr;
|
19
18
|
xfree(sw->sw.out.buf);
|
@@ -21,41 +20,38 @@ stream_writer_free(void *ptr) {
|
|
21
20
|
xfree(ptr);
|
22
21
|
}
|
23
22
|
|
24
|
-
static void
|
25
|
-
|
26
|
-
sw->sw.out.cur = sw->sw.out.buf;
|
23
|
+
static void stream_writer_reset_buf(StreamWriter sw) {
|
24
|
+
sw->sw.out.cur = sw->sw.out.buf;
|
27
25
|
*sw->sw.out.cur = '\0';
|
28
26
|
}
|
29
27
|
|
30
|
-
static void
|
31
|
-
|
32
|
-
ssize_t size = sw->sw.out.cur - sw->sw.out.buf;
|
28
|
+
static void stream_writer_write(StreamWriter sw) {
|
29
|
+
ssize_t size = sw->sw.out.cur - sw->sw.out.buf;
|
33
30
|
|
34
31
|
switch (sw->type) {
|
35
32
|
case STRING_IO:
|
36
33
|
case STREAM_IO: {
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
34
|
+
volatile VALUE rs = rb_str_new(sw->sw.out.buf, size);
|
35
|
+
|
36
|
+
// Oddly enough, when pushing ASCII characters with UTF-8 encoding or
|
37
|
+
// even ASCII-8BIT does not change the output encoding. Pushing any
|
38
|
+
// non-ASCII no matter what the encoding changes the output encoding
|
39
|
+
// to ASCII-8BIT if it the string is not forced to UTF-8 here.
|
40
|
+
rs = oj_encode(rs);
|
41
|
+
rb_funcall(sw->stream, oj_write_id, 1, rs);
|
42
|
+
break;
|
46
43
|
}
|
47
44
|
case FILE_IO:
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
default:
|
53
|
-
rb_raise(rb_eArgError, "expected an IO Object.");
|
45
|
+
if (size != write(sw->fd, sw->sw.out.buf, size)) {
|
46
|
+
rb_raise(rb_eIOError, "Write failed. [_%d_:%s]\n", errno, strerror(errno));
|
47
|
+
}
|
48
|
+
break;
|
49
|
+
default: rb_raise(rb_eArgError, "expected an IO Object.");
|
54
50
|
}
|
55
51
|
stream_writer_reset_buf(sw);
|
56
52
|
}
|
57
53
|
|
58
|
-
static VALUE
|
54
|
+
static VALUE buffer_size_sym = Qundef;
|
59
55
|
|
60
56
|
/* Document-method: new
|
61
57
|
* call-seq: new(io, options)
|
@@ -73,62 +69,60 @@ static VALUE buffer_size_sym = Qundef;
|
|
73
69
|
* - *io* [_IO_] stream to write to
|
74
70
|
* - *options* [_Hash_] formating options
|
75
71
|
*/
|
76
|
-
static VALUE
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
VALUE
|
81
|
-
|
82
|
-
StreamWriter sw;
|
72
|
+
static VALUE stream_writer_new(int argc, VALUE *argv, VALUE self) {
|
73
|
+
StreamWriterType type = STREAM_IO;
|
74
|
+
int fd = 0;
|
75
|
+
VALUE stream = argv[0];
|
76
|
+
VALUE clas = rb_obj_class(stream);
|
77
|
+
StreamWriter sw;
|
83
78
|
#if !IS_WINDOWS
|
84
|
-
VALUE
|
79
|
+
VALUE s;
|
85
80
|
#endif
|
86
81
|
|
87
82
|
if (oj_stringio_class == clas) {
|
88
|
-
|
83
|
+
type = STRING_IO;
|
89
84
|
#if !IS_WINDOWS
|
90
85
|
} else if (rb_respond_to(stream, oj_fileno_id) &&
|
91
|
-
|
92
|
-
|
93
|
-
type = FILE_IO;
|
86
|
+
Qnil != (s = rb_funcall(stream, oj_fileno_id, 0)) && 0 != (fd = FIX2INT(s))) {
|
87
|
+
type = FILE_IO;
|
94
88
|
#endif
|
95
89
|
} else if (rb_respond_to(stream, oj_write_id)) {
|
96
|
-
|
90
|
+
type = STREAM_IO;
|
97
91
|
} else {
|
98
|
-
|
92
|
+
rb_raise(rb_eArgError, "expected an IO Object.");
|
99
93
|
}
|
100
94
|
sw = ALLOC(struct _streamWriter);
|
101
95
|
if (2 == argc && T_HASH == rb_type(argv[1])) {
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
96
|
+
volatile VALUE v;
|
97
|
+
int buf_size = 0;
|
98
|
+
|
99
|
+
if (Qundef == buffer_size_sym) {
|
100
|
+
buffer_size_sym = ID2SYM(rb_intern("buffer_size"));
|
101
|
+
rb_gc_register_address(&buffer_size_sym);
|
102
|
+
}
|
103
|
+
if (Qnil != (v = rb_hash_lookup(argv[1], buffer_size_sym))) {
|
110
104
|
#ifdef RUBY_INTEGER_UNIFICATION
|
111
|
-
|
112
|
-
|
113
|
-
|
105
|
+
if (rb_cInteger != rb_obj_class(v)) {
|
106
|
+
rb_raise(rb_eArgError, ":buffer size must be a Integer.");
|
107
|
+
}
|
114
108
|
#else
|
115
|
-
|
116
|
-
|
117
|
-
|
109
|
+
if (T_FIXNUM != rb_type(v)) {
|
110
|
+
rb_raise(rb_eArgError, ":buffer size must be a Integer.");
|
111
|
+
}
|
118
112
|
#endif
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
113
|
+
buf_size = FIX2INT(v);
|
114
|
+
}
|
115
|
+
oj_str_writer_init(&sw->sw, buf_size);
|
116
|
+
oj_parse_options(argv[1], &sw->sw.opts);
|
117
|
+
sw->flush_limit = buf_size;
|
124
118
|
} else {
|
125
|
-
|
126
|
-
|
119
|
+
oj_str_writer_init(&sw->sw, 4096);
|
120
|
+
sw->flush_limit = 0;
|
127
121
|
}
|
128
122
|
sw->sw.out.indent = sw->sw.opts.indent;
|
129
|
-
sw->stream
|
130
|
-
sw->type
|
131
|
-
sw->fd
|
123
|
+
sw->stream = stream;
|
124
|
+
sw->type = type;
|
125
|
+
sw->fd = fd;
|
132
126
|
|
133
127
|
return Data_Wrap_Struct(oj_stream_writer_class, 0, stream_writer_free, sw);
|
134
128
|
}
|
@@ -142,14 +136,13 @@ stream_writer_new(int argc, VALUE *argv, VALUE self) {
|
|
142
136
|
*
|
143
137
|
* - *key* [_String_] the key pending for the next push
|
144
138
|
*/
|
145
|
-
static VALUE
|
146
|
-
|
147
|
-
StreamWriter sw = (StreamWriter)DATA_PTR(self);
|
139
|
+
static VALUE stream_writer_push_key(VALUE self, VALUE key) {
|
140
|
+
StreamWriter sw = (StreamWriter)DATA_PTR(self);
|
148
141
|
|
149
142
|
rb_check_type(key, T_STRING);
|
150
143
|
oj_str_writer_push_key(&sw->sw, StringValuePtr(key));
|
151
144
|
if (sw->flush_limit < sw->sw.out.cur - sw->sw.out.buf) {
|
152
|
-
|
145
|
+
stream_writer_write(sw);
|
153
146
|
}
|
154
147
|
return Qnil;
|
155
148
|
}
|
@@ -162,28 +155,23 @@ stream_writer_push_key(VALUE self, VALUE key) {
|
|
162
155
|
*
|
163
156
|
* - *key* [_String_] the key if adding to an object in the JSON document
|
164
157
|
*/
|
165
|
-
static VALUE
|
166
|
-
|
167
|
-
StreamWriter sw = (StreamWriter)DATA_PTR(self);
|
158
|
+
static VALUE stream_writer_push_object(int argc, VALUE *argv, VALUE self) {
|
159
|
+
StreamWriter sw = (StreamWriter)DATA_PTR(self);
|
168
160
|
|
169
161
|
switch (argc) {
|
170
|
-
case 0:
|
171
|
-
oj_str_writer_push_object(&sw->sw, 0);
|
172
|
-
break;
|
162
|
+
case 0: oj_str_writer_push_object(&sw->sw, 0); break;
|
173
163
|
case 1:
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
default:
|
182
|
-
rb_raise(rb_eArgError, "Wrong number of argument to 'push_object'.");
|
183
|
-
break;
|
164
|
+
if (Qnil == argv[0]) {
|
165
|
+
oj_str_writer_push_object(&sw->sw, 0);
|
166
|
+
} else {
|
167
|
+
rb_check_type(argv[0], T_STRING);
|
168
|
+
oj_str_writer_push_object(&sw->sw, StringValuePtr(argv[0]));
|
169
|
+
}
|
170
|
+
break;
|
171
|
+
default: rb_raise(rb_eArgError, "Wrong number of argument to 'push_object'."); break;
|
184
172
|
}
|
185
173
|
if (sw->flush_limit < sw->sw.out.cur - sw->sw.out.buf) {
|
186
|
-
|
174
|
+
stream_writer_write(sw);
|
187
175
|
}
|
188
176
|
return Qnil;
|
189
177
|
}
|
@@ -196,28 +184,23 @@ stream_writer_push_object(int argc, VALUE *argv, VALUE self) {
|
|
196
184
|
*
|
197
185
|
* - *key* [_String_] the key if adding to an object in the JSON document
|
198
186
|
*/
|
199
|
-
static VALUE
|
200
|
-
|
201
|
-
StreamWriter sw = (StreamWriter)DATA_PTR(self);
|
187
|
+
static VALUE stream_writer_push_array(int argc, VALUE *argv, VALUE self) {
|
188
|
+
StreamWriter sw = (StreamWriter)DATA_PTR(self);
|
202
189
|
|
203
190
|
switch (argc) {
|
204
|
-
case 0:
|
205
|
-
oj_str_writer_push_array(&sw->sw, 0);
|
206
|
-
break;
|
191
|
+
case 0: oj_str_writer_push_array(&sw->sw, 0); break;
|
207
192
|
case 1:
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
default:
|
216
|
-
rb_raise(rb_eArgError, "Wrong number of argument to 'push_object'.");
|
217
|
-
break;
|
193
|
+
if (Qnil == argv[0]) {
|
194
|
+
oj_str_writer_push_array(&sw->sw, 0);
|
195
|
+
} else {
|
196
|
+
rb_check_type(argv[0], T_STRING);
|
197
|
+
oj_str_writer_push_array(&sw->sw, StringValuePtr(argv[0]));
|
198
|
+
}
|
199
|
+
break;
|
200
|
+
default: rb_raise(rb_eArgError, "Wrong number of argument to 'push_object'."); break;
|
218
201
|
}
|
219
202
|
if (sw->flush_limit < sw->sw.out.cur - sw->sw.out.buf) {
|
220
|
-
|
203
|
+
stream_writer_write(sw);
|
221
204
|
}
|
222
205
|
return Qnil;
|
223
206
|
}
|
@@ -229,28 +212,23 @@ stream_writer_push_array(int argc, VALUE *argv, VALUE self) {
|
|
229
212
|
* - *value* [_Object_] value to add to the JSON document
|
230
213
|
* - *key* [_String_] the key if adding to an object in the JSON document
|
231
214
|
*/
|
232
|
-
static VALUE
|
233
|
-
|
234
|
-
StreamWriter sw = (StreamWriter)DATA_PTR(self);
|
215
|
+
static VALUE stream_writer_push_value(int argc, VALUE *argv, VALUE self) {
|
216
|
+
StreamWriter sw = (StreamWriter)DATA_PTR(self);
|
235
217
|
|
236
218
|
switch (argc) {
|
237
|
-
case 1:
|
238
|
-
oj_str_writer_push_value((StrWriter)DATA_PTR(self), *argv, 0);
|
239
|
-
break;
|
219
|
+
case 1: oj_str_writer_push_value((StrWriter)DATA_PTR(self), *argv, 0); break;
|
240
220
|
case 2:
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
default:
|
249
|
-
rb_raise(rb_eArgError, "Wrong number of argument to 'push_value'.");
|
250
|
-
break;
|
221
|
+
if (Qnil == argv[1]) {
|
222
|
+
oj_str_writer_push_value((StrWriter)DATA_PTR(self), *argv, 0);
|
223
|
+
} else {
|
224
|
+
rb_check_type(argv[1], T_STRING);
|
225
|
+
oj_str_writer_push_value((StrWriter)DATA_PTR(self), *argv, StringValuePtr(argv[1]));
|
226
|
+
}
|
227
|
+
break;
|
228
|
+
default: rb_raise(rb_eArgError, "Wrong number of argument to 'push_value'."); break;
|
251
229
|
}
|
252
230
|
if (sw->flush_limit < sw->sw.out.cur - sw->sw.out.buf) {
|
253
|
-
|
231
|
+
stream_writer_write(sw);
|
254
232
|
}
|
255
233
|
return Qnil;
|
256
234
|
}
|
@@ -264,29 +242,26 @@ stream_writer_push_value(int argc, VALUE *argv, VALUE self) {
|
|
264
242
|
* - *value* [_Object_] value to add to the JSON document
|
265
243
|
* - *key* [_String_] the key if adding to an object in the JSON document
|
266
244
|
*/
|
267
|
-
static VALUE
|
268
|
-
|
269
|
-
StreamWriter sw = (StreamWriter)DATA_PTR(self);
|
245
|
+
static VALUE stream_writer_push_json(int argc, VALUE *argv, VALUE self) {
|
246
|
+
StreamWriter sw = (StreamWriter)DATA_PTR(self);
|
270
247
|
|
271
248
|
rb_check_type(argv[0], T_STRING);
|
272
249
|
switch (argc) {
|
273
|
-
case 1:
|
274
|
-
oj_str_writer_push_json((StrWriter)DATA_PTR(self), StringValuePtr(*argv), 0);
|
275
|
-
break;
|
250
|
+
case 1: oj_str_writer_push_json((StrWriter)DATA_PTR(self), StringValuePtr(*argv), 0); break;
|
276
251
|
case 2:
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
252
|
+
if (Qnil == argv[1]) {
|
253
|
+
oj_str_writer_push_json((StrWriter)DATA_PTR(self), StringValuePtr(*argv), 0);
|
254
|
+
} else {
|
255
|
+
rb_check_type(argv[1], T_STRING);
|
256
|
+
oj_str_writer_push_json((StrWriter)DATA_PTR(self),
|
257
|
+
StringValuePtr(*argv),
|
258
|
+
StringValuePtr(argv[1]));
|
259
|
+
}
|
260
|
+
break;
|
261
|
+
default: rb_raise(rb_eArgError, "Wrong number of argument to 'push_json'."); break;
|
287
262
|
}
|
288
263
|
if (sw->flush_limit < sw->sw.out.cur - sw->sw.out.buf) {
|
289
|
-
|
264
|
+
stream_writer_write(sw);
|
290
265
|
}
|
291
266
|
return Qnil;
|
292
267
|
}
|
@@ -297,13 +272,12 @@ stream_writer_push_json(int argc, VALUE *argv, VALUE self) {
|
|
297
272
|
* Pops up a level in the JSON document closing the array or object that is
|
298
273
|
* currently open.
|
299
274
|
*/
|
300
|
-
static VALUE
|
301
|
-
|
302
|
-
StreamWriter sw = (StreamWriter)DATA_PTR(self);
|
275
|
+
static VALUE stream_writer_pop(VALUE self) {
|
276
|
+
StreamWriter sw = (StreamWriter)DATA_PTR(self);
|
303
277
|
|
304
278
|
oj_str_writer_pop(&sw->sw);
|
305
279
|
if (sw->flush_limit < sw->sw.out.cur - sw->sw.out.buf) {
|
306
|
-
|
280
|
+
stream_writer_write(sw);
|
307
281
|
}
|
308
282
|
return Qnil;
|
309
283
|
}
|
@@ -314,9 +288,8 @@ stream_writer_pop(VALUE self) {
|
|
314
288
|
* Pops all level in the JSON document closing all the array or object that is
|
315
289
|
* currently open.
|
316
290
|
*/
|
317
|
-
static VALUE
|
318
|
-
|
319
|
-
StreamWriter sw = (StreamWriter)DATA_PTR(self);
|
291
|
+
static VALUE stream_writer_pop_all(VALUE self) {
|
292
|
+
StreamWriter sw = (StreamWriter)DATA_PTR(self);
|
320
293
|
|
321
294
|
oj_str_writer_pop_all(&sw->sw);
|
322
295
|
stream_writer_write(sw);
|
@@ -329,8 +302,7 @@ stream_writer_pop_all(VALUE self) {
|
|
329
302
|
*
|
330
303
|
* Flush any remaining characters in the buffer.
|
331
304
|
*/
|
332
|
-
static VALUE
|
333
|
-
stream_writer_flush(VALUE self) {
|
305
|
+
static VALUE stream_writer_flush(VALUE self) {
|
334
306
|
stream_writer_write((StreamWriter)DATA_PTR(self));
|
335
307
|
|
336
308
|
return Qnil;
|
@@ -343,8 +315,7 @@ stream_writer_flush(VALUE self) {
|
|
343
315
|
* will create that element in the JSON document and subsequent pushes will add
|
344
316
|
* the elements to that array or object until a pop() is called.
|
345
317
|
*/
|
346
|
-
void
|
347
|
-
oj_stream_writer_init() {
|
318
|
+
void oj_stream_writer_init() {
|
348
319
|
oj_stream_writer_class = rb_define_class_under(Oj, "StreamWriter", rb_cObject);
|
349
320
|
rb_define_module_function(oj_stream_writer_class, "new", stream_writer_new, -1);
|
350
321
|
rb_define_method(oj_stream_writer_class, "push_key", stream_writer_push_key, 1);
|
data/ext/oj/strict.c
CHANGED
@@ -1,207 +1,192 @@
|
|
1
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.
|
2
3
|
|
3
|
-
#include <stdlib.h>
|
4
4
|
#include <stdio.h>
|
5
|
+
#include <stdlib.h>
|
5
6
|
#include <string.h>
|
6
7
|
#include <unistd.h>
|
7
8
|
|
8
|
-
#include "
|
9
|
+
#include "encode.h"
|
9
10
|
#include "err.h"
|
11
|
+
#include "oj.h"
|
10
12
|
#include "parse.h"
|
11
|
-
#include "encode.h"
|
12
13
|
#include "trace.h"
|
13
14
|
|
14
|
-
static void
|
15
|
-
hash_end(ParseInfo pi) {
|
15
|
+
static void hash_end(ParseInfo pi) {
|
16
16
|
if (Yes == pi->options.trace) {
|
17
|
-
|
17
|
+
oj_trace_parse_hash_end(pi, __FILE__, __LINE__);
|
18
18
|
}
|
19
19
|
}
|
20
20
|
|
21
|
-
static void
|
22
|
-
array_end(ParseInfo pi) {
|
21
|
+
static void array_end(ParseInfo pi) {
|
23
22
|
if (Yes == pi->options.trace) {
|
24
|
-
|
23
|
+
oj_trace_parse_array_end(pi, __FILE__, __LINE__);
|
25
24
|
}
|
26
25
|
}
|
27
26
|
|
28
|
-
static VALUE
|
29
|
-
noop_hash_key(ParseInfo pi, const char *key, size_t klen) {
|
27
|
+
static VALUE noop_hash_key(ParseInfo pi, const char *key, size_t klen) {
|
30
28
|
return Qundef;
|
31
29
|
}
|
32
30
|
|
33
|
-
static void
|
34
|
-
add_value(ParseInfo pi, VALUE val) {
|
31
|
+
static void add_value(ParseInfo pi, VALUE val) {
|
35
32
|
if (Yes == pi->options.trace) {
|
36
|
-
|
33
|
+
oj_trace_parse_call("add_value", pi, __FILE__, __LINE__, val);
|
37
34
|
}
|
38
35
|
pi->stack.head->val = val;
|
39
36
|
}
|
40
37
|
|
41
|
-
static void
|
42
|
-
|
43
|
-
volatile VALUE rstr = rb_str_new(str, len);
|
38
|
+
static void add_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
|
39
|
+
volatile VALUE rstr = rb_str_new(str, len);
|
44
40
|
|
45
|
-
rstr
|
41
|
+
rstr = oj_encode(rstr);
|
46
42
|
pi->stack.head->val = rstr;
|
47
43
|
if (Yes == pi->options.trace) {
|
48
|
-
|
44
|
+
oj_trace_parse_call("add_string", pi, __FILE__, __LINE__, rstr);
|
49
45
|
}
|
50
46
|
}
|
51
47
|
|
52
|
-
static void
|
53
|
-
add_num(ParseInfo pi, NumInfo ni) {
|
48
|
+
static void add_num(ParseInfo pi, NumInfo ni) {
|
54
49
|
if (ni->infinity || ni->nan) {
|
55
|
-
|
50
|
+
oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number or other value");
|
56
51
|
}
|
57
52
|
pi->stack.head->val = oj_num_as_value(ni);
|
58
53
|
if (Yes == pi->options.trace) {
|
59
|
-
|
54
|
+
oj_trace_parse_call("add_number", pi, __FILE__, __LINE__, pi->stack.head->val);
|
60
55
|
}
|
61
56
|
}
|
62
57
|
|
63
|
-
static VALUE
|
64
|
-
start_hash(ParseInfo pi) {
|
58
|
+
static VALUE start_hash(ParseInfo pi) {
|
65
59
|
if (Qnil != pi->options.hash_class) {
|
66
|
-
|
60
|
+
return rb_class_new_instance(0, NULL, pi->options.hash_class);
|
67
61
|
}
|
68
62
|
if (Yes == pi->options.trace) {
|
69
|
-
|
63
|
+
oj_trace_parse_in("start_hash", pi, __FILE__, __LINE__);
|
70
64
|
}
|
71
65
|
return rb_hash_new();
|
72
66
|
}
|
73
67
|
|
74
|
-
static VALUE
|
75
|
-
|
76
|
-
volatile VALUE rkey = parent->key_val;
|
68
|
+
static VALUE calc_hash_key(ParseInfo pi, Val parent) {
|
69
|
+
volatile VALUE rkey = parent->key_val;
|
77
70
|
|
78
71
|
if (Qundef == rkey) {
|
79
|
-
|
72
|
+
rkey = rb_str_new(parent->key, parent->klen);
|
80
73
|
}
|
81
74
|
rkey = oj_encode(rkey);
|
82
75
|
if (Yes == pi->options.sym_key) {
|
83
|
-
|
76
|
+
rkey = rb_str_intern(rkey);
|
84
77
|
}
|
85
78
|
return rkey;
|
86
79
|
}
|
87
80
|
|
88
|
-
static void
|
89
|
-
|
90
|
-
volatile VALUE rstr = rb_str_new(str, len);
|
81
|
+
static void hash_set_cstr(ParseInfo pi, Val parent, const char *str, size_t len, const char *orig) {
|
82
|
+
volatile VALUE rstr = rb_str_new(str, len);
|
91
83
|
|
92
84
|
rstr = oj_encode(rstr);
|
93
85
|
rb_hash_aset(stack_peek(&pi->stack)->val, calc_hash_key(pi, parent), rstr);
|
94
86
|
if (Yes == pi->options.trace) {
|
95
|
-
|
87
|
+
oj_trace_parse_call("set_string", pi, __FILE__, __LINE__, rstr);
|
96
88
|
}
|
97
89
|
}
|
98
90
|
|
99
|
-
static void
|
100
|
-
|
101
|
-
volatile VALUE v;
|
91
|
+
static void hash_set_num(ParseInfo pi, Val parent, NumInfo ni) {
|
92
|
+
volatile VALUE v;
|
102
93
|
|
103
94
|
if (ni->infinity || ni->nan) {
|
104
|
-
|
95
|
+
oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number or other value");
|
105
96
|
}
|
106
97
|
v = oj_num_as_value(ni);
|
107
98
|
rb_hash_aset(stack_peek(&pi->stack)->val, calc_hash_key(pi, parent), v);
|
108
99
|
if (Yes == pi->options.trace) {
|
109
|
-
|
100
|
+
oj_trace_parse_call("set_number", pi, __FILE__, __LINE__, v);
|
110
101
|
}
|
111
102
|
}
|
112
103
|
|
113
|
-
static void
|
114
|
-
hash_set_value(ParseInfo pi, Val parent, VALUE value) {
|
104
|
+
static void hash_set_value(ParseInfo pi, Val parent, VALUE value) {
|
115
105
|
rb_hash_aset(stack_peek(&pi->stack)->val, calc_hash_key(pi, parent), value);
|
116
106
|
if (Yes == pi->options.trace) {
|
117
|
-
|
107
|
+
oj_trace_parse_call("set_value", pi, __FILE__, __LINE__, value);
|
118
108
|
}
|
119
109
|
}
|
120
110
|
|
121
|
-
static VALUE
|
122
|
-
start_array(ParseInfo pi) {
|
111
|
+
static VALUE start_array(ParseInfo pi) {
|
123
112
|
if (Yes == pi->options.trace) {
|
124
|
-
|
113
|
+
oj_trace_parse_in("start_array", pi, __FILE__, __LINE__);
|
125
114
|
}
|
126
115
|
return rb_ary_new();
|
127
116
|
}
|
128
117
|
|
129
|
-
static void
|
130
|
-
|
131
|
-
volatile VALUE rstr = rb_str_new(str, len);
|
118
|
+
static void array_append_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
|
119
|
+
volatile VALUE rstr = rb_str_new(str, len);
|
132
120
|
|
133
121
|
rstr = oj_encode(rstr);
|
134
122
|
rb_ary_push(stack_peek(&pi->stack)->val, rstr);
|
135
123
|
if (Yes == pi->options.trace) {
|
136
|
-
|
124
|
+
oj_trace_parse_call("append_string", pi, __FILE__, __LINE__, rstr);
|
137
125
|
}
|
138
126
|
}
|
139
127
|
|
140
|
-
static void
|
141
|
-
|
142
|
-
volatile VALUE v;
|
128
|
+
static void array_append_num(ParseInfo pi, NumInfo ni) {
|
129
|
+
volatile VALUE v;
|
143
130
|
|
144
131
|
if (ni->infinity || ni->nan) {
|
145
|
-
|
132
|
+
oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number or other value");
|
146
133
|
}
|
147
134
|
v = oj_num_as_value(ni);
|
148
135
|
rb_ary_push(stack_peek(&pi->stack)->val, v);
|
149
136
|
if (Yes == pi->options.trace) {
|
150
|
-
|
137
|
+
oj_trace_parse_call("append_number", pi, __FILE__, __LINE__, v);
|
151
138
|
}
|
152
139
|
}
|
153
140
|
|
154
|
-
static void
|
155
|
-
array_append_value(ParseInfo pi, VALUE value) {
|
141
|
+
static void array_append_value(ParseInfo pi, VALUE value) {
|
156
142
|
rb_ary_push(stack_peek(&pi->stack)->val, value);
|
157
143
|
if (Yes == pi->options.trace) {
|
158
|
-
|
159
|
-
}
|
160
|
-
}
|
161
|
-
|
162
|
-
void
|
163
|
-
|
164
|
-
pi->
|
165
|
-
pi->
|
166
|
-
pi->
|
167
|
-
pi->
|
168
|
-
pi->
|
169
|
-
pi->
|
170
|
-
pi->
|
171
|
-
pi->
|
172
|
-
pi->
|
173
|
-
pi->array_append_num = array_append_num;
|
144
|
+
oj_trace_parse_call("append_value", pi, __FILE__, __LINE__, value);
|
145
|
+
}
|
146
|
+
}
|
147
|
+
|
148
|
+
void oj_set_strict_callbacks(ParseInfo pi) {
|
149
|
+
pi->start_hash = start_hash;
|
150
|
+
pi->end_hash = hash_end;
|
151
|
+
pi->hash_key = noop_hash_key;
|
152
|
+
pi->hash_set_cstr = hash_set_cstr;
|
153
|
+
pi->hash_set_num = hash_set_num;
|
154
|
+
pi->hash_set_value = hash_set_value;
|
155
|
+
pi->start_array = start_array;
|
156
|
+
pi->end_array = array_end;
|
157
|
+
pi->array_append_cstr = array_append_cstr;
|
158
|
+
pi->array_append_num = array_append_num;
|
174
159
|
pi->array_append_value = array_append_value;
|
175
|
-
pi->add_cstr
|
176
|
-
pi->add_num
|
177
|
-
pi->add_value
|
178
|
-
pi->expect_value
|
160
|
+
pi->add_cstr = add_cstr;
|
161
|
+
pi->add_num = add_num;
|
162
|
+
pi->add_value = add_value;
|
163
|
+
pi->expect_value = 1;
|
179
164
|
}
|
180
165
|
|
181
166
|
VALUE
|
182
167
|
oj_strict_parse(int argc, VALUE *argv, VALUE self) {
|
183
|
-
struct _parseInfo
|
168
|
+
struct _parseInfo pi;
|
184
169
|
|
185
170
|
parse_info_init(&pi);
|
186
|
-
pi.options
|
187
|
-
pi.handler
|
171
|
+
pi.options = oj_default_options;
|
172
|
+
pi.handler = Qnil;
|
188
173
|
pi.err_class = Qnil;
|
189
174
|
oj_set_strict_callbacks(&pi);
|
190
175
|
|
191
176
|
if (T_STRING == rb_type(*argv)) {
|
192
|
-
|
177
|
+
return oj_pi_parse(argc, argv, &pi, 0, 0, true);
|
193
178
|
} else {
|
194
|
-
|
179
|
+
return oj_pi_sparse(argc, argv, &pi, 0);
|
195
180
|
}
|
196
181
|
}
|
197
182
|
|
198
183
|
VALUE
|
199
184
|
oj_strict_parse_cstr(int argc, VALUE *argv, char *json, size_t len) {
|
200
|
-
struct _parseInfo
|
185
|
+
struct _parseInfo pi;
|
201
186
|
|
202
187
|
parse_info_init(&pi);
|
203
|
-
pi.options
|
204
|
-
pi.handler
|
188
|
+
pi.options = oj_default_options;
|
189
|
+
pi.handler = Qnil;
|
205
190
|
pi.err_class = Qnil;
|
206
191
|
oj_set_strict_callbacks(&pi);
|
207
192
|
|