oj 3.7.4 → 3.11.2
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 +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;
|