oj 3.7.4 → 3.11.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +12 -4
- data/ext/oj/buf.h +6 -34
- data/ext/oj/cache8.c +3 -3
- data/ext/oj/cache8.h +5 -33
- data/ext/oj/circarray.c +5 -9
- data/ext/oj/circarray.h +5 -8
- data/ext/oj/code.c +3 -6
- data/ext/oj/code.h +7 -10
- data/ext/oj/compat.c +11 -14
- data/ext/oj/custom.c +108 -75
- data/ext/oj/dump.c +132 -92
- data/ext/oj/dump.h +6 -7
- data/ext/oj/dump_compat.c +37 -34
- data/ext/oj/dump_leaf.c +3 -6
- data/ext/oj/dump_object.c +23 -17
- data/ext/oj/dump_strict.c +7 -9
- data/ext/oj/encode.h +6 -32
- data/ext/oj/err.c +2 -5
- data/ext/oj/err.h +6 -34
- data/ext/oj/extconf.rb +6 -0
- data/ext/oj/fast.c +39 -56
- data/ext/oj/hash.c +11 -39
- data/ext/oj/hash.h +5 -33
- data/ext/oj/hash_test.c +3 -31
- data/ext/oj/mimic_json.c +65 -44
- data/ext/oj/object.c +38 -69
- data/ext/oj/odd.c +18 -17
- data/ext/oj/odd.h +6 -9
- data/ext/oj/oj.c +139 -93
- data/ext/oj/oj.h +43 -35
- data/ext/oj/parse.c +164 -60
- data/ext/oj/parse.h +30 -31
- data/ext/oj/rails.c +119 -83
- data/ext/oj/rails.h +4 -7
- data/ext/oj/reader.c +5 -8
- data/ext/oj/reader.h +7 -10
- data/ext/oj/resolve.c +4 -7
- data/ext/oj/resolve.h +4 -7
- data/ext/oj/rxclass.c +8 -11
- data/ext/oj/rxclass.h +8 -11
- data/ext/oj/saj.c +9 -12
- data/ext/oj/scp.c +4 -7
- data/ext/oj/sparse.c +67 -33
- data/ext/oj/stream_writer.c +16 -15
- data/ext/oj/strict.c +9 -12
- data/ext/oj/string_writer.c +27 -8
- data/ext/oj/trace.c +5 -8
- data/ext/oj/trace.h +9 -12
- data/ext/oj/util.c +136 -0
- data/ext/oj/util.h +19 -0
- data/ext/oj/val_stack.c +28 -36
- data/ext/oj/val_stack.h +19 -50
- data/ext/oj/wab.c +29 -29
- data/lib/oj.rb +0 -8
- data/lib/oj/json.rb +1 -1
- data/lib/oj/mimic.rb +46 -2
- data/lib/oj/version.rb +2 -2
- data/pages/Modes.md +47 -45
- data/pages/Options.md +43 -10
- data/pages/Rails.md +60 -21
- data/pages/Security.md +1 -1
- data/test/activesupport5/abstract_unit.rb +45 -0
- data/test/activesupport5/decoding_test.rb +68 -60
- data/test/activesupport5/encoding_test.rb +111 -96
- data/test/activesupport5/encoding_test_cases.rb +33 -25
- data/test/activesupport5/test_helper.rb +43 -21
- data/test/activesupport5/time_zone_test_helpers.rb +18 -3
- data/test/activesupport6/abstract_unit.rb +44 -0
- data/test/activesupport6/decoding_test.rb +133 -0
- data/test/activesupport6/encoding_test.rb +507 -0
- data/test/activesupport6/encoding_test_cases.rb +98 -0
- data/test/activesupport6/test_common.rb +17 -0
- data/test/activesupport6/test_helper.rb +163 -0
- data/test/activesupport6/time_zone_test_helpers.rb +39 -0
- data/test/bar.rb +24 -6
- data/test/baz.rb +16 -0
- data/test/foo.rb +26 -57
- 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/prec.rb +23 -0
- data/test/sample_json.rb +1 -1
- data/test/test_compat.rb +21 -10
- data/test/test_custom.rb +135 -8
- data/test/test_integer_range.rb +1 -2
- data/test/test_object.rb +35 -2
- data/test/test_rails.rb +35 -0
- data/test/test_strict.rb +24 -1
- data/test/test_various.rb +52 -63
- data/test/test_writer.rb +19 -2
- data/test/tests.rb +1 -0
- data/test/zoo.rb +13 -0
- metadata +100 -75
data/ext/oj/hash.h
CHANGED
@@ -1,39 +1,11 @@
|
|
1
|
-
|
2
|
-
* Copyright (c) 2011, Peter Ohler
|
3
|
-
* All rights reserved.
|
4
|
-
*
|
5
|
-
* Redistribution and use in source and binary forms, with or without
|
6
|
-
* modification, are permitted provided that the following conditions are met:
|
7
|
-
*
|
8
|
-
* - Redistributions of source code must retain the above copyright notice, this
|
9
|
-
* list of conditions and the following disclaimer.
|
10
|
-
*
|
11
|
-
* - Redistributions in binary form must reproduce the above copyright notice,
|
12
|
-
* this list of conditions and the following disclaimer in the documentation
|
13
|
-
* and/or other materials provided with the distribution.
|
14
|
-
*
|
15
|
-
* - Neither the name of Peter Ohler nor the names of its contributors may be
|
16
|
-
* used to endorse or promote products derived from this software without
|
17
|
-
* specific prior written permission.
|
18
|
-
*
|
19
|
-
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
20
|
-
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
21
|
-
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
22
|
-
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
23
|
-
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
24
|
-
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
25
|
-
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
26
|
-
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
27
|
-
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
28
|
-
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
29
|
-
*/
|
1
|
+
// Copyright (c) 2011 Peter Ohler. All rights reserved.
|
30
2
|
|
31
|
-
#ifndef
|
32
|
-
#define
|
3
|
+
#ifndef OJ_HASH_H
|
4
|
+
#define OJ_HASH_H
|
33
5
|
|
34
6
|
#include "ruby.h"
|
35
7
|
|
36
|
-
typedef struct
|
8
|
+
typedef struct _hash *Hash;
|
37
9
|
|
38
10
|
extern void oj_hash_init();
|
39
11
|
|
@@ -43,4 +15,4 @@ extern ID oj_attr_hash_get(const char *key, size_t len, ID **slotp);
|
|
43
15
|
extern void oj_hash_print();
|
44
16
|
extern char* oj_strndup(const char *s, size_t len);
|
45
17
|
|
46
|
-
#endif /*
|
18
|
+
#endif /* OJ_HASH_H */
|
data/ext/oj/hash_test.c
CHANGED
@@ -1,32 +1,4 @@
|
|
1
|
-
|
2
|
-
* Copyright (c) 2011, Peter Ohler
|
3
|
-
* All rights reserved.
|
4
|
-
*
|
5
|
-
* Redistribution and use in source and binary forms, with or without
|
6
|
-
* modification, are permitted provided that the following conditions are met:
|
7
|
-
*
|
8
|
-
* - Redistributions of source code must retain the above copyright notice, this
|
9
|
-
* list of conditions and the following disclaimer.
|
10
|
-
*
|
11
|
-
* - Redistributions in binary form must reproduce the above copyright notice,
|
12
|
-
* this list of conditions and the following disclaimer in the documentation
|
13
|
-
* and/or other materials provided with the distribution.
|
14
|
-
*
|
15
|
-
* - Neither the name of Peter Ohler nor the names of its contributors may be
|
16
|
-
* used to endorse or promote products derived from this software without
|
17
|
-
* specific prior written permission.
|
18
|
-
*
|
19
|
-
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
20
|
-
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
21
|
-
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
22
|
-
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
23
|
-
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
24
|
-
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
25
|
-
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
26
|
-
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
27
|
-
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
28
|
-
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
29
|
-
*/
|
1
|
+
// Copyright (c) 2011 Peter Ohler. All rights reserved.
|
30
2
|
|
31
3
|
// if windows, comment out the whole file. It's only a performance test.
|
32
4
|
#ifndef _WIN32
|
@@ -39,12 +11,12 @@
|
|
39
11
|
#define __STDC_FORMAT_MACROS
|
40
12
|
#include <inttypes.h>
|
41
13
|
|
42
|
-
typedef struct
|
14
|
+
typedef struct _strLen {
|
43
15
|
const char *str;
|
44
16
|
size_t len;
|
45
17
|
} *StrLen;
|
46
18
|
|
47
|
-
static struct
|
19
|
+
static struct _strLen data[] = {
|
48
20
|
{ "Gem::Version", 12 },
|
49
21
|
{ "TracePoint", 10 },
|
50
22
|
{ "Complex::compatible", 19 },
|
data/ext/oj/mimic_json.c
CHANGED
@@ -1,14 +1,11 @@
|
|
1
|
-
|
2
|
-
* Copyright (c) 2012, 2017, Peter Ohler
|
3
|
-
* All rights reserved.
|
4
|
-
*/
|
1
|
+
// Copyright (c) 2012, 2017 Peter Ohler. All rights reserved.
|
5
2
|
|
6
3
|
#include "oj.h"
|
7
4
|
#include "encode.h"
|
8
5
|
#include "dump.h"
|
9
6
|
#include "parse.h"
|
10
7
|
|
11
|
-
static VALUE symbolize_names_sym;
|
8
|
+
static VALUE symbolize_names_sym = Qundef;
|
12
9
|
|
13
10
|
extern const char oj_json_class[];
|
14
11
|
|
@@ -26,30 +23,30 @@ static VALUE state_class;
|
|
26
23
|
// mimic JSON documentation
|
27
24
|
|
28
25
|
/* Document-module: JSON::Ext
|
29
|
-
*
|
26
|
+
*
|
30
27
|
* The Ext module is a placeholder in the mimic JSON module used for
|
31
28
|
* compatibility only.
|
32
29
|
*/
|
33
30
|
/* Document-class: JSON::Ext::Parser
|
34
|
-
*
|
31
|
+
*
|
35
32
|
* The JSON::Ext::Parser is a placeholder in the mimic JSON module used for
|
36
33
|
* compatibility only.
|
37
34
|
*/
|
38
35
|
/* Document-class: JSON::Ext::Generator
|
39
|
-
*
|
36
|
+
*
|
40
37
|
* The JSON::Ext::Generator is a placeholder in the mimic JSON module used for
|
41
38
|
* compatibility only.
|
42
39
|
*/
|
43
40
|
|
44
41
|
/* Document-method: parser=
|
45
42
|
* call-seq: parser=(parser)
|
46
|
-
*
|
43
|
+
*
|
47
44
|
* Does nothing other than provide compatibility.
|
48
45
|
* - *parser* [_Object_] ignored
|
49
46
|
*/
|
50
47
|
/* Document-method: generator=
|
51
48
|
* call-seq: generator=(generator)
|
52
|
-
*
|
49
|
+
*
|
53
50
|
* Does nothing other than provide compatibility.
|
54
51
|
* - *generator* [_Object_] ignored
|
55
52
|
*/
|
@@ -167,7 +164,7 @@ oj_parse_mimic_dump_options(VALUE ropts, Options copts) {
|
|
167
164
|
if (Qnil != (v = rb_hash_lookup(ropts, oj_ascii_only_sym))) {
|
168
165
|
// generate seems to assume anything except nil and false are true.
|
169
166
|
if (Qfalse == v) {
|
170
|
-
copts->escape_mode = JXEsc;
|
167
|
+
copts->escape_mode = JXEsc;
|
171
168
|
} else {
|
172
169
|
copts->escape_mode = ASCIIEsc;
|
173
170
|
}
|
@@ -184,9 +181,9 @@ mimic_limit_arg(VALUE a) {
|
|
184
181
|
|
185
182
|
/* Document-method: dump
|
186
183
|
* call-seq: dump(obj, anIO=nil, limit=nil)
|
187
|
-
*
|
184
|
+
*
|
188
185
|
* Encodes an object as a JSON String.
|
189
|
-
*
|
186
|
+
*
|
190
187
|
* - *obj* [_Object_] object to convert to encode as JSON
|
191
188
|
* - *anIO* [_IO_] an IO that allows writing
|
192
189
|
* - *limit* [_Fixnum_] ignored
|
@@ -196,9 +193,10 @@ mimic_limit_arg(VALUE a) {
|
|
196
193
|
static VALUE
|
197
194
|
mimic_dump(int argc, VALUE *argv, VALUE self) {
|
198
195
|
char buf[4096];
|
199
|
-
struct
|
200
|
-
struct
|
196
|
+
struct _out out;
|
197
|
+
struct _options copts = oj_default_options;
|
201
198
|
VALUE rstr;
|
199
|
+
VALUE active_hack[1];
|
202
200
|
|
203
201
|
copts.str_rx.head = NULL;
|
204
202
|
copts.str_rx.tail = NULL;
|
@@ -216,9 +214,10 @@ mimic_dump(int argc, VALUE *argv, VALUE self) {
|
|
216
214
|
*/
|
217
215
|
copts.dump_opts.max_depth = MAX_DEPTH; // when using dump there is no limit
|
218
216
|
out.omit_nil = copts.dump_opts.omit_nil;
|
217
|
+
|
219
218
|
if (2 <= argc) {
|
220
219
|
int limit;
|
221
|
-
|
220
|
+
|
222
221
|
// The json gem take a more liberal approach to optional
|
223
222
|
// arguments. Expected are (obj, anIO=nil, limit=nil) yet the io
|
224
223
|
// argument can be left off completely and the 2nd argument is then
|
@@ -230,7 +229,15 @@ mimic_dump(int argc, VALUE *argv, VALUE self) {
|
|
230
229
|
copts.dump_opts.max_depth = limit;
|
231
230
|
}
|
232
231
|
}
|
233
|
-
|
232
|
+
// ActiveSupport in active_support/core_ext/object/json.rb check the
|
233
|
+
// optional argument type to to_json and it the argument is a
|
234
|
+
// ::JSON::State it calls the JSON gem code otherwise it calls the active
|
235
|
+
// support encoder code. To make sure the desired branch is called a
|
236
|
+
// default ::JSON::State argument is passed in. Basically a hack to get
|
237
|
+
// around the active support hack so two wrongs make a right this time.
|
238
|
+
active_hack[0] = rb_funcall(state_class, oj_new_id, 0);
|
239
|
+
oj_dump_obj_to_json_using_params(*argv, &copts, &out, 1, active_hack);
|
240
|
+
|
234
241
|
if (0 == out.buf) {
|
235
242
|
rb_raise(rb_eNoMemError, "Not enough memory.");
|
236
243
|
}
|
@@ -285,11 +292,11 @@ mimic_walk(VALUE key, VALUE obj, VALUE proc) {
|
|
285
292
|
|
286
293
|
/* Document-method: restore
|
287
294
|
* call-seq: restore(source, proc=nil)
|
288
|
-
*
|
295
|
+
*
|
289
296
|
* Loads a Ruby Object from a JSON source that can be either a String or an
|
290
|
-
* IO. If Proc is given or a block is
|
297
|
+
* IO. If Proc is given or a block is provided it is called with each nested
|
291
298
|
* element of the loaded Object.
|
292
|
-
*
|
299
|
+
*
|
293
300
|
* - *source* [_String_|IO] JSON source
|
294
301
|
* - *proc* [_Proc_] to yield to on each element or nil
|
295
302
|
*
|
@@ -298,11 +305,11 @@ mimic_walk(VALUE key, VALUE obj, VALUE proc) {
|
|
298
305
|
|
299
306
|
/* Document-method: load
|
300
307
|
* call-seq: load(source, proc=nil)
|
301
|
-
*
|
308
|
+
*
|
302
309
|
* Loads a Ruby Object from a JSON source that can be either a String or an
|
303
|
-
* IO. If Proc is given or a block is
|
310
|
+
* IO. If Proc is given or a block is provided it is called with each nested
|
304
311
|
* element of the loaded Object.
|
305
|
-
*
|
312
|
+
*
|
306
313
|
* - *source* [_String_|IO] JSON source
|
307
314
|
* - *proc* [_Proc_] to yield to on each element or nil
|
308
315
|
*
|
@@ -330,10 +337,10 @@ mimic_load(int argc, VALUE *argv, VALUE self) {
|
|
330
337
|
|
331
338
|
/* Document-method: []
|
332
339
|
* call-seq: [](obj, opts={})
|
333
|
-
*
|
340
|
+
*
|
334
341
|
* If the obj argument is a String then it is assumed to be a JSON String and
|
335
342
|
* parsed otherwise the obj is encoded as a JSON String.
|
336
|
-
*
|
343
|
+
*
|
337
344
|
* - *obj* [_String_|Hash|Array] object to convert
|
338
345
|
* - *opts* [_Hash_] same options as either generate or parse
|
339
346
|
*
|
@@ -354,9 +361,11 @@ mimic_dump_load(int argc, VALUE *argv, VALUE self) {
|
|
354
361
|
static VALUE
|
355
362
|
mimic_generate_core(int argc, VALUE *argv, Options copts) {
|
356
363
|
char buf[4096];
|
357
|
-
struct
|
364
|
+
struct _out out;
|
358
365
|
VALUE rstr;
|
359
366
|
|
367
|
+
memset(buf, 0, sizeof(buf));
|
368
|
+
|
360
369
|
out.buf = buf;
|
361
370
|
out.end = buf + sizeof(buf) - 10;
|
362
371
|
out.allocated = false;
|
@@ -396,11 +405,11 @@ mimic_generate_core(int argc, VALUE *argv, Options copts) {
|
|
396
405
|
|
397
406
|
/* Document-method: generate
|
398
407
|
* call-seq: generate(obj, opts=nil)
|
399
|
-
*
|
408
|
+
*
|
400
409
|
* Encode obj as a JSON String. The obj argument must be a Hash, Array, or
|
401
410
|
* respond to to_h or to_json. Options other than those listed such as
|
402
411
|
* +:allow_nan+ or +:max_nesting+ are ignored.
|
403
|
-
*
|
412
|
+
*
|
404
413
|
* - *obj* [_Object_|Hash|Array] object to convert to a JSON String
|
405
414
|
* - *opts* [_Hash_] options
|
406
415
|
* - - *:indent* [_String_] String to use for indentation.
|
@@ -414,7 +423,7 @@ mimic_generate_core(int argc, VALUE *argv, Options copts) {
|
|
414
423
|
*/
|
415
424
|
VALUE
|
416
425
|
oj_mimic_generate(int argc, VALUE *argv, VALUE self) {
|
417
|
-
struct
|
426
|
+
struct _options copts = oj_default_options;
|
418
427
|
|
419
428
|
copts.str_rx.head = NULL;
|
420
429
|
copts.str_rx.tail = NULL;
|
@@ -432,7 +441,7 @@ oj_mimic_generate(int argc, VALUE *argv, VALUE self) {
|
|
432
441
|
*/
|
433
442
|
VALUE
|
434
443
|
oj_mimic_pretty_generate(int argc, VALUE *argv, VALUE self) {
|
435
|
-
struct
|
444
|
+
struct _options copts = oj_default_options;
|
436
445
|
VALUE rargs[2];
|
437
446
|
volatile VALUE h;
|
438
447
|
|
@@ -461,7 +470,7 @@ oj_mimic_pretty_generate(int argc, VALUE *argv, VALUE self) {
|
|
461
470
|
rb_hash_aset(h, oj_array_nl_sym, rb_str_new2("\n"));
|
462
471
|
}
|
463
472
|
rargs[1] = rb_funcall(state_class, oj_new_id, 1, h);
|
464
|
-
|
473
|
+
|
465
474
|
copts.str_rx.head = NULL;
|
466
475
|
copts.str_rx.tail = NULL;
|
467
476
|
strcpy(copts.dump_opts.indent_str, " ");
|
@@ -481,7 +490,7 @@ oj_mimic_pretty_generate(int argc, VALUE *argv, VALUE self) {
|
|
481
490
|
|
482
491
|
static VALUE
|
483
492
|
mimic_parse_core(int argc, VALUE *argv, VALUE self, bool bang) {
|
484
|
-
struct
|
493
|
+
struct _parseInfo pi;
|
485
494
|
VALUE ropts;
|
486
495
|
VALUE args[1];
|
487
496
|
|
@@ -500,7 +509,7 @@ mimic_parse_core(int argc, VALUE *argv, VALUE self, bool bang) {
|
|
500
509
|
pi.options.create_ok = No;
|
501
510
|
pi.options.allow_nan = (bang ? Yes : No);
|
502
511
|
pi.options.nilnil = No;
|
503
|
-
pi.options.bigdec_load =
|
512
|
+
pi.options.bigdec_load = RubyDec;
|
504
513
|
pi.options.mode = CompatMode;
|
505
514
|
pi.max_depth = 100;
|
506
515
|
|
@@ -510,6 +519,9 @@ mimic_parse_core(int argc, VALUE *argv, VALUE self, bool bang) {
|
|
510
519
|
if (T_HASH != rb_type(ropts)) {
|
511
520
|
rb_raise(rb_eArgError, "options must be a hash.");
|
512
521
|
}
|
522
|
+
if (Qundef == symbolize_names_sym) {
|
523
|
+
symbolize_names_sym = ID2SYM(rb_intern("symbolize_names")); rb_gc_register_address(&symbolize_names_sym);
|
524
|
+
}
|
513
525
|
if (Qnil != (v = rb_hash_lookup(ropts, symbolize_names_sym))) {
|
514
526
|
pi.options.sym_key = (Qtrue == v) ? Yes : No;
|
515
527
|
}
|
@@ -547,6 +559,9 @@ mimic_parse_core(int argc, VALUE *argv, VALUE self, bool bang) {
|
|
547
559
|
pi.options.array_class = v;
|
548
560
|
}
|
549
561
|
}
|
562
|
+
if (Qtrue == rb_funcall(ropts, oj_has_key_id, 1, oj_decimal_class_sym)) {
|
563
|
+
pi.options.compat_bigdec = (oj_bigdecimal_class == rb_hash_lookup(ropts, oj_decimal_class_sym));
|
564
|
+
}
|
550
565
|
v = rb_hash_lookup(ropts, oj_max_nesting_sym);
|
551
566
|
if (Qtrue == v) {
|
552
567
|
pi.max_depth = 100;
|
@@ -602,9 +617,9 @@ mimic_parse_bang(int argc, VALUE *argv, VALUE self) {
|
|
602
617
|
|
603
618
|
/* Document-method: recurse_proc
|
604
619
|
* call-seq: recurse_proc(obj, &proc)
|
605
|
-
*
|
620
|
+
*
|
606
621
|
* Yields to the proc for every element in the obj recursively.
|
607
|
-
*
|
622
|
+
*
|
608
623
|
* - *obj* [_Hash_|Array] object to walk
|
609
624
|
* - *proc* [_Proc_] to yield to on each element
|
610
625
|
*/
|
@@ -631,7 +646,7 @@ mimic_set_create_id(VALUE self, VALUE id) {
|
|
631
646
|
Check_Type(id, T_STRING);
|
632
647
|
|
633
648
|
if (NULL != oj_default_options.create_id) {
|
634
|
-
if (oj_json_class != oj_default_options.create_id
|
649
|
+
if (oj_json_class != oj_default_options.create_id) {
|
635
650
|
xfree((char*)oj_default_options.create_id);
|
636
651
|
}
|
637
652
|
oj_default_options.create_id = NULL;
|
@@ -660,7 +675,7 @@ mimic_create_id(VALUE self) {
|
|
660
675
|
return rb_str_new_cstr(oj_json_class);
|
661
676
|
}
|
662
677
|
|
663
|
-
static struct
|
678
|
+
static struct _options mimic_object_to_json_options = {
|
664
679
|
0, // indent
|
665
680
|
No, // circular
|
666
681
|
No, // auto_define
|
@@ -670,10 +685,12 @@ static struct _Options mimic_object_to_json_options = {
|
|
670
685
|
No, // class_cache
|
671
686
|
RubyTime, // time_format
|
672
687
|
No, // bigdec_as_num
|
673
|
-
|
688
|
+
RubyDec, // bigdec_load
|
689
|
+
false, // compat_bigdec
|
674
690
|
No, // to_hash
|
675
691
|
No, // to_json
|
676
692
|
No, // as_json
|
693
|
+
No, // raw_json
|
677
694
|
No, // nilnil
|
678
695
|
No, // empty_string
|
679
696
|
Yes, // allow_gc
|
@@ -682,12 +699,15 @@ static struct _Options mimic_object_to_json_options = {
|
|
682
699
|
No, // create_ok
|
683
700
|
No, // allow_nan
|
684
701
|
No, // trace
|
685
|
-
|
686
|
-
|
702
|
+
No, // safe
|
703
|
+
false, // sec_prec_set
|
704
|
+
No, // ignore_under
|
705
|
+
0, // int_range_min
|
706
|
+
0, // int_range_max
|
687
707
|
oj_json_class,// create_id
|
688
708
|
10, // create_id_len
|
689
709
|
3, // sec_prec
|
690
|
-
|
710
|
+
0, // float_prec
|
691
711
|
"%0.16g", // float_fmt
|
692
712
|
Qnil, // hash_class
|
693
713
|
Qnil, // array_class
|
@@ -717,9 +737,9 @@ static struct _Options mimic_object_to_json_options = {
|
|
717
737
|
static VALUE
|
718
738
|
mimic_object_to_json(int argc, VALUE *argv, VALUE self) {
|
719
739
|
char buf[4096];
|
720
|
-
struct
|
740
|
+
struct _out out;
|
721
741
|
VALUE rstr;
|
722
|
-
struct
|
742
|
+
struct _options copts = oj_default_options;
|
723
743
|
|
724
744
|
copts.str_rx.head = NULL;
|
725
745
|
copts.str_rx.tail = NULL;
|
@@ -821,6 +841,7 @@ oj_mimic_json_methods(VALUE json) {
|
|
821
841
|
}
|
822
842
|
// Pull in the JSON::State mimic file.
|
823
843
|
state_class = rb_const_get_at(generator, rb_intern("State"));
|
844
|
+
rb_gc_register_mark_object(state_class);
|
824
845
|
|
825
846
|
symbolize_names_sym = ID2SYM(rb_intern("symbolize_names")); rb_gc_register_address(&symbolize_names_sym);
|
826
847
|
}
|
@@ -834,7 +855,7 @@ oj_define_mimic_json(int argc, VALUE *argv, VALUE self) {
|
|
834
855
|
VALUE dummy;
|
835
856
|
VALUE verbose;
|
836
857
|
VALUE json;
|
837
|
-
|
858
|
+
|
838
859
|
// Either set the paths to indicate JSON has been loaded or replaces the
|
839
860
|
// methods if it has been loaded.
|
840
861
|
if (rb_const_defined_at(rb_cObject, rb_intern("JSON"))) {
|
data/ext/oj/object.c
CHANGED
@@ -1,8 +1,6 @@
|
|
1
|
-
|
2
|
-
* Copyright (c) 2012, Peter Ohler
|
3
|
-
* All rights reserved.
|
4
|
-
*/
|
1
|
+
// Copyright (c) 2012 Peter Ohler. All rights reserved.
|
5
2
|
|
3
|
+
#include <stdint.h>
|
6
4
|
#include <stdio.h>
|
7
5
|
#include <time.h>
|
8
6
|
|
@@ -14,6 +12,7 @@
|
|
14
12
|
#include "odd.h"
|
15
13
|
#include "encode.h"
|
16
14
|
#include "trace.h"
|
15
|
+
#include "util.h"
|
17
16
|
|
18
17
|
inline static long
|
19
18
|
read_long(const char *str, size_t len) {
|
@@ -274,7 +273,10 @@ hat_num(ParseInfo pi, Val parent, Val kval, NumInfo ni) {
|
|
274
273
|
if (2 == kval->klen) {
|
275
274
|
switch (kval->key[1]) {
|
276
275
|
case 't': // time as a float
|
277
|
-
{
|
276
|
+
if (0 == ni->div || 9 < ni->di) {
|
277
|
+
rb_raise(rb_eArgError, "Invalid time decimal representation.");
|
278
|
+
//parent->val = rb_time_nano_new(0, 0);
|
279
|
+
} else {
|
278
280
|
int64_t nsec = ni->num * 1000000000LL / ni->div;
|
279
281
|
|
280
282
|
if (ni->neg) {
|
@@ -290,25 +292,20 @@ hat_num(ParseInfo pi, Val parent, Val kval, NumInfo ni) {
|
|
290
292
|
// offset and then a conversion to UTC keeps makes the time
|
291
293
|
// match the expected value.
|
292
294
|
parent->val = rb_funcall2(parent->val, oj_utc_id, 0, 0);
|
293
|
-
} else if (ni->
|
294
|
-
|
295
|
-
struct
|
296
|
-
VALUE
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
args[4] = LONG2NUM(st->tm_min);
|
308
|
-
args[5] = rb_float_new((double)st->tm_sec + ((double)nsec + 0.5) / 1000000000.0);
|
309
|
-
args[6] = LONG2NUM(ni->exp);
|
310
|
-
parent->val = rb_funcall2(rb_cTime, oj_new_id, 7, args);
|
311
|
-
}
|
295
|
+
} else if (ni->has_exp) {
|
296
|
+
int64_t t = (int64_t)(ni->i + ni->exp);
|
297
|
+
struct _timeInfo ti;
|
298
|
+
VALUE args[8];
|
299
|
+
|
300
|
+
sec_as_time(t, &ti);
|
301
|
+
args[0] = LONG2NUM((long)(ti.year));
|
302
|
+
args[1] = LONG2NUM(ti.mon);
|
303
|
+
args[2] = LONG2NUM(ti.day);
|
304
|
+
args[3] = LONG2NUM(ti.hour);
|
305
|
+
args[4] = LONG2NUM(ti.min);
|
306
|
+
args[5] = rb_float_new((double)ti.sec + ((double)nsec + 0.5) / 1000000000.0);
|
307
|
+
args[6] = LONG2NUM(ni->exp);
|
308
|
+
parent->val = rb_funcall2(rb_cTime, oj_new_id, 7, args);
|
312
309
|
} else {
|
313
310
|
parent->val = rb_time_nano_new(ni->i, (long)nsec);
|
314
311
|
}
|
@@ -403,23 +400,6 @@ hat_value(ParseInfo pi, Val parent, const char *key, size_t klen, volatile VALUE
|
|
403
400
|
return 0;
|
404
401
|
}
|
405
402
|
|
406
|
-
static void
|
407
|
-
copy_ivars(VALUE target, VALUE src) {
|
408
|
-
volatile VALUE vars = rb_funcall(src, oj_instance_variables_id, 0);
|
409
|
-
volatile VALUE *np = RARRAY_PTR(vars);
|
410
|
-
ID vid;
|
411
|
-
int i, cnt = (int)RARRAY_LEN(vars);
|
412
|
-
const char *attr;
|
413
|
-
|
414
|
-
for (i = cnt; 0 < i; i--, np++) {
|
415
|
-
vid = rb_to_id(*np);
|
416
|
-
attr = rb_id2name(vid);
|
417
|
-
if ('@' == *attr) {
|
418
|
-
rb_ivar_set(target, vid, rb_ivar_get(src, vid));
|
419
|
-
}
|
420
|
-
}
|
421
|
-
}
|
422
|
-
|
423
403
|
void
|
424
404
|
oj_set_obj_ivar(Val parent, Val kval, VALUE value) {
|
425
405
|
const char *key = kval->key;
|
@@ -427,19 +407,7 @@ oj_set_obj_ivar(Val parent, Val kval, VALUE value) {
|
|
427
407
|
ID var_id;
|
428
408
|
ID *slot;
|
429
409
|
|
430
|
-
|
431
|
-
if (5 == klen && 0 == strncmp("~mesg", key, klen)) {
|
432
|
-
VALUE args[1];
|
433
|
-
volatile VALUE prev = parent->val;
|
434
|
-
|
435
|
-
args[0] = value;
|
436
|
-
parent->val = rb_class_new_instance(1, args, rb_class_of(parent->val));
|
437
|
-
copy_ivars(parent->val, prev);
|
438
|
-
} else if (3 == klen && 0 == strncmp("~bt", key, klen)) {
|
439
|
-
rb_funcall(parent->val, rb_intern("set_backtrace"), 1, value);
|
440
|
-
}
|
441
|
-
}
|
442
|
-
#if HAVE_LIBPTHREAD
|
410
|
+
#ifdef HAVE_PTHREAD_MUTEX_INIT
|
443
411
|
pthread_mutex_lock(&oj_cache_mutex);
|
444
412
|
#else
|
445
413
|
rb_mutex_lock(oj_cache_mutex);
|
@@ -473,7 +441,7 @@ oj_set_obj_ivar(Val parent, Val kval, VALUE value) {
|
|
473
441
|
}
|
474
442
|
*slot = var_id;
|
475
443
|
}
|
476
|
-
#
|
444
|
+
#ifdef HAVE_PTHREAD_MUTEX_INIT
|
477
445
|
pthread_mutex_unlock(&oj_cache_mutex);
|
478
446
|
#else
|
479
447
|
rb_mutex_unlock(oj_cache_mutex);
|
@@ -491,7 +459,7 @@ hash_set_cstr(ParseInfo pi, Val kval, const char *str, size_t len, const char *o
|
|
491
459
|
WHICH_TYPE:
|
492
460
|
switch (rb_type(parent->val)) {
|
493
461
|
case T_NIL:
|
494
|
-
parent->odd_args =
|
462
|
+
parent->odd_args = NULL; // make sure it is NULL in case not odd
|
495
463
|
if ('^' != *key || !hat_cstr(pi, parent, kval, str, len)) {
|
496
464
|
parent->val = rb_hash_new();
|
497
465
|
goto WHICH_TYPE;
|
@@ -513,7 +481,7 @@ hash_set_cstr(ParseInfo pi, Val kval, const char *str, size_t len, const char *o
|
|
513
481
|
oj_set_obj_ivar(parent, kval, rval);
|
514
482
|
break;
|
515
483
|
case T_CLASS:
|
516
|
-
if (
|
484
|
+
if (NULL == parent->odd_args) {
|
517
485
|
oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "%s is not an odd class", rb_class2name(rb_obj_class(parent->val)));
|
518
486
|
return;
|
519
487
|
} else {
|
@@ -549,7 +517,7 @@ hash_set_num(ParseInfo pi, Val kval, NumInfo ni) {
|
|
549
517
|
WHICH_TYPE:
|
550
518
|
switch (rb_type(parent->val)) {
|
551
519
|
case T_NIL:
|
552
|
-
parent->odd_args =
|
520
|
+
parent->odd_args = NULL; // make sure it is NULL in case not odd
|
553
521
|
if ('^' != *key || !hat_num(pi, parent, kval, ni)) {
|
554
522
|
parent->val = rb_hash_new();
|
555
523
|
goto WHICH_TYPE;
|
@@ -569,7 +537,7 @@ hash_set_num(ParseInfo pi, Val kval, NumInfo ni) {
|
|
569
537
|
}
|
570
538
|
break;
|
571
539
|
case T_CLASS:
|
572
|
-
if (
|
540
|
+
if (NULL == parent->odd_args) {
|
573
541
|
oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "%s is not an odd class", rb_class2name(rb_obj_class(parent->val)));
|
574
542
|
return;
|
575
543
|
} else {
|
@@ -604,7 +572,7 @@ hash_set_value(ParseInfo pi, Val kval, VALUE value) {
|
|
604
572
|
WHICH_TYPE:
|
605
573
|
switch (rb_type(parent->val)) {
|
606
574
|
case T_NIL:
|
607
|
-
parent->odd_args =
|
575
|
+
parent->odd_args = NULL; // make sure it is NULL in case not odd
|
608
576
|
if ('^' != *key || !hat_value(pi, parent, key, klen, value)) {
|
609
577
|
parent->val = rb_hash_new();
|
610
578
|
goto WHICH_TYPE;
|
@@ -645,7 +613,7 @@ hash_set_value(ParseInfo pi, Val kval, VALUE value) {
|
|
645
613
|
break;
|
646
614
|
case T_MODULE:
|
647
615
|
case T_CLASS:
|
648
|
-
if (
|
616
|
+
if (NULL == parent->odd_args) {
|
649
617
|
oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "%s is not an odd class", rb_class2name(rb_obj_class(parent->val)));
|
650
618
|
return;
|
651
619
|
} else if (0 != oj_odd_set_arg(parent->odd_args, key, klen, value)) {
|
@@ -677,17 +645,17 @@ start_hash(ParseInfo pi) {
|
|
677
645
|
}
|
678
646
|
|
679
647
|
static void
|
680
|
-
end_hash(
|
648
|
+
end_hash(ParseInfo pi) {
|
681
649
|
Val parent = stack_peek(&pi->stack);
|
682
650
|
|
683
651
|
if (Qnil == parent->val) {
|
684
652
|
parent->val = rb_hash_new();
|
685
|
-
} else if (
|
653
|
+
} else if (NULL != parent->odd_args) {
|
686
654
|
OddArgs oa = parent->odd_args;
|
687
655
|
|
688
656
|
parent->val = rb_funcall2(oa->odd->create_obj, oa->odd->create_op, oa->odd->attr_cnt, oa->args);
|
689
657
|
oj_odd_free(oa);
|
690
|
-
parent->odd_args =
|
658
|
+
parent->odd_args = NULL;
|
691
659
|
}
|
692
660
|
if (Yes == pi->options.trace) {
|
693
661
|
oj_trace_parse_hash_end(pi, __FILE__, __LINE__);
|
@@ -697,8 +665,9 @@ end_hash(struct _ParseInfo *pi) {
|
|
697
665
|
static void
|
698
666
|
array_append_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
|
699
667
|
volatile VALUE rval = Qnil;
|
700
|
-
|
701
|
-
|
668
|
+
|
669
|
+
// orig lets us know whether the string was ^r1 or \u005er1
|
670
|
+
if (3 <= len && 0 != pi->circ_array && '^' == orig[0] && 0 == rb_array_len(stack_peek(&pi->stack)->val)) {
|
702
671
|
if ('i' == str[1]) {
|
703
672
|
long i = read_long(str + 2, len - 2);
|
704
673
|
|
@@ -726,7 +695,7 @@ array_append_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
|
|
726
695
|
static void
|
727
696
|
array_append_num(ParseInfo pi, NumInfo ni) {
|
728
697
|
volatile VALUE rval = oj_num_as_value(ni);
|
729
|
-
|
698
|
+
|
730
699
|
rb_ary_push(stack_peek(&pi->stack)->val, rval);
|
731
700
|
if (Yes == pi->options.trace) {
|
732
701
|
oj_trace_parse_call("append_number", pi, __FILE__, __LINE__, rval);
|
@@ -765,7 +734,7 @@ oj_set_object_callbacks(ParseInfo pi) {
|
|
765
734
|
|
766
735
|
VALUE
|
767
736
|
oj_object_parse(int argc, VALUE *argv, VALUE self) {
|
768
|
-
struct
|
737
|
+
struct _parseInfo pi;
|
769
738
|
|
770
739
|
parse_info_init(&pi);
|
771
740
|
pi.options = oj_default_options;
|
@@ -782,7 +751,7 @@ oj_object_parse(int argc, VALUE *argv, VALUE self) {
|
|
782
751
|
|
783
752
|
VALUE
|
784
753
|
oj_object_parse_cstr(int argc, VALUE *argv, char *json, size_t len) {
|
785
|
-
struct
|
754
|
+
struct _parseInfo pi;
|
786
755
|
|
787
756
|
parse_info_init(&pi);
|
788
757
|
pi.options = oj_default_options;
|