oj 3.10.1 → 3.11.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 +1 -1
- data/ext/oj/buf.h +2 -30
- data/ext/oj/cache8.h +1 -29
- data/ext/oj/circarray.c +4 -8
- data/ext/oj/circarray.h +1 -4
- data/ext/oj/code.c +3 -6
- data/ext/oj/code.h +1 -4
- data/ext/oj/compat.c +1 -4
- data/ext/oj/custom.c +2 -5
- data/ext/oj/dump.c +24 -14
- data/ext/oj/dump.h +1 -4
- data/ext/oj/dump_compat.c +1 -4
- data/ext/oj/dump_leaf.c +2 -5
- data/ext/oj/dump_object.c +2 -5
- data/ext/oj/dump_strict.c +1 -4
- data/ext/oj/encode.h +1 -29
- data/ext/oj/err.c +1 -4
- data/ext/oj/err.h +1 -29
- data/ext/oj/fast.c +14 -42
- data/ext/oj/hash.c +4 -32
- data/ext/oj/hash.h +1 -29
- data/ext/oj/hash_test.c +1 -29
- data/ext/oj/mimic_json.c +9 -8
- data/ext/oj/object.c +4 -6
- data/ext/oj/odd.c +1 -4
- data/ext/oj/odd.h +1 -4
- data/ext/oj/oj.c +43 -10
- data/ext/oj/oj.h +6 -5
- data/ext/oj/parse.c +124 -49
- data/ext/oj/parse.h +3 -5
- data/ext/oj/rails.c +1 -5
- data/ext/oj/rails.h +1 -4
- data/ext/oj/reader.c +5 -8
- data/ext/oj/reader.h +2 -5
- data/ext/oj/resolve.c +1 -4
- data/ext/oj/resolve.h +1 -4
- data/ext/oj/rxclass.c +3 -6
- data/ext/oj/rxclass.h +1 -4
- data/ext/oj/saj.c +6 -9
- data/ext/oj/scp.c +1 -4
- data/ext/oj/sparse.c +56 -27
- data/ext/oj/stream_writer.c +4 -9
- data/ext/oj/strict.c +3 -6
- data/ext/oj/string_writer.c +1 -4
- data/ext/oj/trace.c +5 -8
- data/ext/oj/trace.h +1 -4
- data/ext/oj/util.c +1 -1
- data/ext/oj/util.h +1 -1
- data/ext/oj/val_stack.c +1 -29
- data/ext/oj/val_stack.h +1 -29
- data/ext/oj/wab.c +1 -4
- data/lib/oj/mimic.rb +45 -1
- data/lib/oj/version.rb +1 -1
- data/lib/oj.rb +0 -8
- data/pages/Modes.md +1 -0
- data/pages/Options.md +23 -11
- data/pages/Rails.md +39 -0
- data/test/bar.rb +21 -8
- 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 +16 -3
- data/test/test_custom.rb +11 -0
- data/test/test_object.rb +8 -0
- data/test/test_rails.rb +9 -0
- data/test/test_various.rb +2 -2
- metadata +87 -85
data/ext/oj/hash.h
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
|
#ifndef OJ_HASH_H
|
32
4
|
#define 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
|
data/ext/oj/mimic_json.c
CHANGED
@@ -1,7 +1,4 @@
|
|
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"
|
@@ -367,7 +364,6 @@ mimic_generate_core(int argc, VALUE *argv, Options copts) {
|
|
367
364
|
struct _out out;
|
368
365
|
VALUE rstr;
|
369
366
|
|
370
|
-
// TBD
|
371
367
|
memset(buf, 0, sizeof(buf));
|
372
368
|
|
373
369
|
out.buf = buf;
|
@@ -513,7 +509,7 @@ mimic_parse_core(int argc, VALUE *argv, VALUE self, bool bang) {
|
|
513
509
|
pi.options.create_ok = No;
|
514
510
|
pi.options.allow_nan = (bang ? Yes : No);
|
515
511
|
pi.options.nilnil = No;
|
516
|
-
pi.options.bigdec_load =
|
512
|
+
pi.options.bigdec_load = RubyDec;
|
517
513
|
pi.options.mode = CompatMode;
|
518
514
|
pi.max_depth = 100;
|
519
515
|
|
@@ -563,6 +559,9 @@ mimic_parse_core(int argc, VALUE *argv, VALUE self, bool bang) {
|
|
563
559
|
pi.options.array_class = v;
|
564
560
|
}
|
565
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
|
+
}
|
566
565
|
v = rb_hash_lookup(ropts, oj_max_nesting_sym);
|
567
566
|
if (Qtrue == v) {
|
568
567
|
pi.max_depth = 100;
|
@@ -686,7 +685,8 @@ static struct _options mimic_object_to_json_options = {
|
|
686
685
|
No, // class_cache
|
687
686
|
RubyTime, // time_format
|
688
687
|
No, // bigdec_as_num
|
689
|
-
|
688
|
+
RubyDec, // bigdec_load
|
689
|
+
false, // compat_bigdec
|
690
690
|
No, // to_hash
|
691
691
|
No, // to_json
|
692
692
|
No, // as_json
|
@@ -707,7 +707,7 @@ static struct _options mimic_object_to_json_options = {
|
|
707
707
|
oj_json_class,// create_id
|
708
708
|
10, // create_id_len
|
709
709
|
3, // sec_prec
|
710
|
-
|
710
|
+
0, // float_prec
|
711
711
|
"%0.16g", // float_fmt
|
712
712
|
Qnil, // hash_class
|
713
713
|
Qnil, // array_class
|
@@ -841,6 +841,7 @@ oj_mimic_json_methods(VALUE json) {
|
|
841
841
|
}
|
842
842
|
// Pull in the JSON::State mimic file.
|
843
843
|
state_class = rb_const_get_at(generator, rb_intern("State"));
|
844
|
+
rb_gc_register_mark_object(state_class);
|
844
845
|
|
845
846
|
symbolize_names_sym = ID2SYM(rb_intern("symbolize_names")); rb_gc_register_address(&symbolize_names_sym);
|
846
847
|
}
|
data/ext/oj/object.c
CHANGED
@@ -1,7 +1,4 @@
|
|
1
|
-
|
2
|
-
* Copyright (c) 2012, Peter Ohler
|
3
|
-
* All rights reserved.
|
4
|
-
*/
|
1
|
+
// Copyright (c) 2012 Peter Ohler. All rights reserved.
|
5
2
|
|
6
3
|
#include <stdint.h>
|
7
4
|
#include <stdio.h>
|
@@ -295,7 +292,7 @@ hat_num(ParseInfo pi, Val parent, Val kval, NumInfo ni) {
|
|
295
292
|
// offset and then a conversion to UTC keeps makes the time
|
296
293
|
// match the expected value.
|
297
294
|
parent->val = rb_funcall2(parent->val, oj_utc_id, 0, 0);
|
298
|
-
} else if (ni->
|
295
|
+
} else if (ni->has_exp) {
|
299
296
|
int64_t t = (int64_t)(ni->i + ni->exp);
|
300
297
|
struct _timeInfo ti;
|
301
298
|
VALUE args[8];
|
@@ -669,7 +666,8 @@ static void
|
|
669
666
|
array_append_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
|
670
667
|
volatile VALUE rval = Qnil;
|
671
668
|
|
672
|
-
|
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)) {
|
673
671
|
if ('i' == str[1]) {
|
674
672
|
long i = read_long(str + 2, len - 2);
|
675
673
|
|
data/ext/oj/odd.c
CHANGED
data/ext/oj/odd.h
CHANGED
data/ext/oj/oj.c
CHANGED
@@ -1,7 +1,4 @@
|
|
1
|
-
|
2
|
-
* Copyright (c) 2012, Peter Ohler
|
3
|
-
* All rights reserved.
|
4
|
-
*/
|
1
|
+
// Copyright (c) 2012 Peter Ohler. All rights reserved.
|
5
2
|
|
6
3
|
#include <stdlib.h>
|
7
4
|
#include <errno.h>
|
@@ -91,6 +88,7 @@ VALUE oj_slash_string;
|
|
91
88
|
VALUE oj_allow_nan_sym;
|
92
89
|
VALUE oj_array_class_sym;
|
93
90
|
VALUE oj_create_additions_sym;
|
91
|
+
VALUE oj_decimal_class_sym;
|
94
92
|
VALUE oj_hash_class_sym;
|
95
93
|
VALUE oj_indent_sym;
|
96
94
|
VALUE oj_object_class_sym;
|
@@ -109,12 +107,14 @@ static VALUE bigdecimal_load_sym;
|
|
109
107
|
static VALUE bigdecimal_sym;
|
110
108
|
static VALUE circular_sym;
|
111
109
|
static VALUE class_cache_sym;
|
110
|
+
static VALUE compat_bigdecimal_sym;
|
112
111
|
static VALUE compat_sym;
|
113
112
|
static VALUE create_id_sym;
|
114
113
|
static VALUE custom_sym;
|
115
114
|
static VALUE empty_string_sym;
|
116
115
|
static VALUE escape_mode_sym;
|
117
116
|
static VALUE integer_range_sym;
|
117
|
+
static VALUE fast_sym;
|
118
118
|
static VALUE float_prec_sym;
|
119
119
|
static VALUE float_sym;
|
120
120
|
static VALUE huge_sym;
|
@@ -169,6 +169,7 @@ struct _options oj_default_options = {
|
|
169
169
|
UnixTime, // time_format
|
170
170
|
NotSet, // bigdec_as_num
|
171
171
|
AutoDec, // bigdec_load
|
172
|
+
false, // compat_bigdec
|
172
173
|
No, // to_hash
|
173
174
|
No, // to_json
|
174
175
|
No, // as_json
|
@@ -230,7 +231,8 @@ struct _options oj_default_options = {
|
|
230
231
|
* - *:mode* [_:object_|_:strict_|_:compat_|_:null_|_:custom_|_:rails_|_:wab_] load and dump modes to use for JSON
|
231
232
|
* - *:time_format* [_:unix_|_:unix_zone_|_:xmlschema_|_:ruby_] time format when dumping
|
232
233
|
* - *:bigdecimal_as_decimal* [_Boolean_|_nil_] dump BigDecimal as a decimal number or as a String
|
233
|
-
* - *:bigdecimal_load* [_:bigdecimal_|_:float_|_:auto_] load decimals as BigDecimal instead of as a Float. :auto pick the most precise for the number of digits.
|
234
|
+
* - *:bigdecimal_load* [_:bigdecimal_|_:float_|_:auto_|_:fast_] load decimals as BigDecimal instead of as a Float. :auto pick the most precise for the number of digits. :float should be the same as ruby. :fast may require rounding but is must faster.
|
235
|
+
* - *:compat_bigdecimal* [_true_|_false_] load decimals as BigDecimal instead of as a Float when in compat or rails mode.
|
234
236
|
* - *:create_id* [_String_|_nil_] create id for json compatible object encoding, default is 'json_class'
|
235
237
|
* - *:create_additions* [_Boolean_|_nil_] if true allow creation of instances using create_id on load.
|
236
238
|
* - *:second_precision* [_Fixnum_|_nil_] number of digits after the decimal when dumping the seconds portion of time
|
@@ -331,9 +333,11 @@ get_def_opts(VALUE self) {
|
|
331
333
|
switch (oj_default_options.bigdec_load) {
|
332
334
|
case BigDec: rb_hash_aset(opts, bigdecimal_load_sym, bigdecimal_sym);break;
|
333
335
|
case FloatDec: rb_hash_aset(opts, bigdecimal_load_sym, float_sym); break;
|
336
|
+
case FastDec: rb_hash_aset(opts, bigdecimal_load_sym, fast_sym); break;
|
334
337
|
case AutoDec:
|
335
338
|
default: rb_hash_aset(opts, bigdecimal_load_sym, auto_sym); break;
|
336
339
|
}
|
340
|
+
rb_hash_aset(opts, compat_bigdecimal_sym, oj_default_options.compat_bigdec ? Qtrue : Qfalse);
|
337
341
|
rb_hash_aset(opts, create_id_sym, (NULL == oj_default_options.create_id) ? Qnil : rb_str_new2(oj_default_options.create_id));
|
338
342
|
rb_hash_aset(opts, oj_space_sym, (0 == oj_default_options.dump_opts.after_size) ? Qnil : rb_str_new2(oj_default_options.dump_opts.after_sep));
|
339
343
|
rb_hash_aset(opts, oj_space_before_sym, (0 == oj_default_options.dump_opts.before_size) ? Qnil : rb_str_new2(oj_default_options.dump_opts.before_sep));
|
@@ -379,6 +383,7 @@ get_def_opts(VALUE self) {
|
|
379
383
|
* - *:escape* [_:newline_|_:json_|_:xss_safe_|_:ascii_|_unicode_xss_|_nil_] mode encodes all high-bit characters as escaped sequences if :ascii, :json is standand UTF-8 JSON encoding, :newline is the same as :json but newlines are not escaped, :unicode_xss allows unicode but escapes &, <, and >, and any \u20xx characters along with some others, and :xss_safe escapes &, <, and >, and some others.
|
380
384
|
* - *:bigdecimal_as_decimal* [_Boolean_|_nil_] dump BigDecimal as a decimal number or as a String.
|
381
385
|
* - *:bigdecimal_load* [_:bigdecimal_|_:float_|_:auto_|_nil_] load decimals as BigDecimal instead of as a Float. :auto pick the most precise for the number of digits.
|
386
|
+
* - *:compat_bigdecimal* [_true_|_false_] load decimals as BigDecimal instead of as a Float in compat mode.
|
382
387
|
* - *:mode* [_:object_|_:strict_|_:compat_|_:null_|_:custom_|_:rails_|_:wab_] load and dump mode to use for JSON :strict raises an exception when a non-supported Object is encountered. :compat attempts to extract variable values from an Object using to_json() or to_hash() then it walks the Object's variables if neither is found. The :object mode ignores to_hash() and to_json() methods and encodes variables using code internal to the Oj gem. The :null mode ignores non-supported Objects and replaces them with a null. The :custom mode honors all dump options. The :rails more mimics rails and Active behavior.
|
383
388
|
* - *:time_format* [_:unix_|_:xmlschema_|_:ruby_] time format when dumping in :compat mode :unix decimal number denoting the number of seconds since 1/1/1970, :unix_zone decimal number denoting the number of seconds since 1/1/1970 plus the utc_offset in the exponent, :xmlschema date-time format taken from XML Schema as a String, :ruby Time.to_s formatted String.
|
384
389
|
* - *:create_id* [_String_|_nil_] create id for json compatible object encoding
|
@@ -574,12 +579,29 @@ oj_parse_options(VALUE ropts, Options copts) {
|
|
574
579
|
copts->bigdec_load = BigDec;
|
575
580
|
} else if (float_sym == v) {
|
576
581
|
copts->bigdec_load = FloatDec;
|
582
|
+
} else if (fast_sym == v) {
|
583
|
+
copts->bigdec_load = FastDec;
|
577
584
|
} else if (auto_sym == v || Qfalse == v) {
|
578
585
|
copts->bigdec_load = AutoDec;
|
579
586
|
} else {
|
580
587
|
rb_raise(rb_eArgError, ":bigdecimal_load must be :bigdecimal, :float, or :auto.");
|
581
588
|
}
|
582
589
|
}
|
590
|
+
if (Qnil != (v = rb_hash_lookup(ropts, compat_bigdecimal_sym))) {
|
591
|
+
copts->compat_bigdec = (Qtrue == v);
|
592
|
+
}
|
593
|
+
if (Qtrue == rb_funcall(ropts, oj_has_key_id, 1, oj_decimal_class_sym)) {
|
594
|
+
v = rb_hash_lookup(ropts, oj_decimal_class_sym);
|
595
|
+
if (rb_cFloat == v) {
|
596
|
+
copts->compat_bigdec = FloatDec;
|
597
|
+
} else if (oj_bigdecimal_class == v) {
|
598
|
+
copts->compat_bigdec = BigDec;
|
599
|
+
} else if (Qnil == v) {
|
600
|
+
copts->compat_bigdec = AutoDec;
|
601
|
+
} else {
|
602
|
+
rb_raise(rb_eArgError, ":decimal_class must be BigDecimal, Float, or nil.");
|
603
|
+
}
|
604
|
+
}
|
583
605
|
if (Qtrue == rb_funcall(ropts, oj_has_key_id, 1, create_id_sym)) {
|
584
606
|
v = rb_hash_lookup(ropts, create_id_sym);
|
585
607
|
if (Qnil == v) {
|
@@ -803,7 +825,7 @@ oj_parse_opt_match_string(RxClass rc, VALUE ropts) {
|
|
803
825
|
}
|
804
826
|
|
805
827
|
/* Document-method: load
|
806
|
-
* call-seq: load(json, options) { _|_obj, start, len_|_ }
|
828
|
+
* call-seq: load(json, options={}) { _|_obj, start, len_|_ }
|
807
829
|
*
|
808
830
|
* Parses a JSON document String into a Object, Hash, Array, String, Fixnum,
|
809
831
|
* Float, true, false, or nil according to the default mode or the mode
|
@@ -887,7 +909,7 @@ load(int argc, VALUE *argv, VALUE self) {
|
|
887
909
|
}
|
888
910
|
|
889
911
|
/* Document-method: load_file
|
890
|
-
* call-seq: load_file(path, options) { _|_obj, start, len_|_ }
|
912
|
+
* call-seq: load_file(path, options={}) { _|_obj, start, len_|_ }
|
891
913
|
*
|
892
914
|
* Parses a JSON document String into a Object, Hash, Array, String, Fixnum,
|
893
915
|
* Float, true, false, or nil according to the default mode or the mode
|
@@ -1045,7 +1067,7 @@ safe_load(VALUE self, VALUE doc) {
|
|
1045
1067
|
*/
|
1046
1068
|
|
1047
1069
|
/* Document-method: dump
|
1048
|
-
* call-seq: dump(obj, options)
|
1070
|
+
* call-seq: dump(obj, options={})
|
1049
1071
|
*
|
1050
1072
|
* Dumps an Object (obj) to a string.
|
1051
1073
|
* - *obj* [_Object_] Object to serialize as an JSON document String
|
@@ -1143,7 +1165,7 @@ to_json(int argc, VALUE *argv, VALUE self) {
|
|
1143
1165
|
}
|
1144
1166
|
|
1145
1167
|
/* Document-method: to_file
|
1146
|
-
* call-seq: to_file(file_path, obj, options)
|
1168
|
+
* call-seq: to_file(file_path, obj, options={})
|
1147
1169
|
*
|
1148
1170
|
* Dumps an Object to the specified file.
|
1149
1171
|
* - *file* [_String_] _path file path to write the JSON document to
|
@@ -1166,7 +1188,7 @@ to_file(int argc, VALUE *argv, VALUE self) {
|
|
1166
1188
|
}
|
1167
1189
|
|
1168
1190
|
/* Document-method: to_stream
|
1169
|
-
* call-seq: to_stream(io, obj, options)
|
1191
|
+
* call-seq: to_stream(io, obj, options={})
|
1170
1192
|
*
|
1171
1193
|
* Dumps an Object to the specified IO stream.
|
1172
1194
|
* - *io* [_IO_] IO stream to write the JSON document to
|
@@ -1627,13 +1649,21 @@ Init_oj() {
|
|
1627
1649
|
rb_require("oj/schandler");
|
1628
1650
|
|
1629
1651
|
oj_bag_class = rb_const_get_at(Oj, rb_intern("Bag"));
|
1652
|
+
rb_gc_register_mark_object(oj_bag_class);
|
1630
1653
|
oj_bigdecimal_class = rb_const_get(rb_cObject, rb_intern("BigDecimal"));
|
1654
|
+
rb_gc_register_mark_object(oj_bigdecimal_class);
|
1631
1655
|
oj_date_class = rb_const_get(rb_cObject, rb_intern("Date"));
|
1656
|
+
rb_gc_register_mark_object(oj_date_class);
|
1632
1657
|
oj_datetime_class = rb_const_get(rb_cObject, rb_intern("DateTime"));
|
1658
|
+
rb_gc_register_mark_object(oj_datetime_class);
|
1633
1659
|
oj_enumerable_class = rb_const_get(rb_cObject, rb_intern("Enumerable"));
|
1660
|
+
rb_gc_register_mark_object(oj_enumerable_class);
|
1634
1661
|
oj_parse_error_class = rb_const_get_at(Oj, rb_intern("ParseError"));
|
1662
|
+
rb_gc_register_mark_object(oj_parse_error_class);
|
1635
1663
|
oj_stringio_class = rb_const_get(rb_cObject, rb_intern("StringIO"));
|
1664
|
+
rb_gc_register_mark_object(oj_stringio_class);
|
1636
1665
|
oj_struct_class = rb_const_get(rb_cObject, rb_intern("Struct"));
|
1666
|
+
rb_gc_register_mark_object(oj_struct_class);
|
1637
1667
|
oj_json_parser_error_class = rb_eEncodingError; // replaced if mimic is called
|
1638
1668
|
oj_json_generator_error_class = rb_eEncodingError; // replaced if mimic is called
|
1639
1669
|
|
@@ -1648,12 +1678,14 @@ Init_oj() {
|
|
1648
1678
|
bigdecimal_sym = ID2SYM(rb_intern("bigdecimal")); rb_gc_register_address(&bigdecimal_sym);
|
1649
1679
|
circular_sym = ID2SYM(rb_intern("circular")); rb_gc_register_address(&circular_sym);
|
1650
1680
|
class_cache_sym = ID2SYM(rb_intern("class_cache")); rb_gc_register_address(&class_cache_sym);
|
1681
|
+
compat_bigdecimal_sym = ID2SYM(rb_intern("compat_bigdecimal"));rb_gc_register_address(&compat_bigdecimal_sym);
|
1651
1682
|
compat_sym = ID2SYM(rb_intern("compat")); rb_gc_register_address(&compat_sym);
|
1652
1683
|
create_id_sym = ID2SYM(rb_intern("create_id")); rb_gc_register_address(&create_id_sym);
|
1653
1684
|
custom_sym = ID2SYM(rb_intern("custom")); rb_gc_register_address(&custom_sym);
|
1654
1685
|
empty_string_sym = ID2SYM(rb_intern("empty_string")); rb_gc_register_address(&empty_string_sym);
|
1655
1686
|
escape_mode_sym = ID2SYM(rb_intern("escape_mode")); rb_gc_register_address(&escape_mode_sym);
|
1656
1687
|
integer_range_sym = ID2SYM(rb_intern("integer_range")); rb_gc_register_address(&integer_range_sym);
|
1688
|
+
fast_sym = ID2SYM(rb_intern("fast")); rb_gc_register_address(&fast_sym);
|
1657
1689
|
float_prec_sym = ID2SYM(rb_intern("float_precision")); rb_gc_register_address(&float_prec_sym);
|
1658
1690
|
float_sym = ID2SYM(rb_intern("float")); rb_gc_register_address(&float_sym);
|
1659
1691
|
huge_sym = ID2SYM(rb_intern("huge")); rb_gc_register_address(&huge_sym);
|
@@ -1672,6 +1704,7 @@ Init_oj() {
|
|
1672
1704
|
oj_array_nl_sym = ID2SYM(rb_intern("array_nl")); rb_gc_register_address(&oj_array_nl_sym);
|
1673
1705
|
oj_ascii_only_sym = ID2SYM(rb_intern("ascii_only")); rb_gc_register_address(&oj_ascii_only_sym);
|
1674
1706
|
oj_create_additions_sym = ID2SYM(rb_intern("create_additions"));rb_gc_register_address(&oj_create_additions_sym);
|
1707
|
+
oj_decimal_class_sym = ID2SYM(rb_intern("decimal_class")); rb_gc_register_address(&oj_decimal_class_sym);
|
1675
1708
|
oj_hash_class_sym = ID2SYM(rb_intern("hash_class")); rb_gc_register_address(&oj_hash_class_sym);
|
1676
1709
|
oj_indent_sym = ID2SYM(rb_intern("indent")); rb_gc_register_address(&oj_indent_sym);
|
1677
1710
|
oj_max_nesting_sym = ID2SYM(rb_intern("max_nesting")); rb_gc_register_address(&oj_max_nesting_sym);
|
data/ext/oj/oj.h
CHANGED
@@ -1,7 +1,4 @@
|
|
1
|
-
|
2
|
-
* Copyright (c) 2011, Peter Ohler
|
3
|
-
* All rights reserved.
|
4
|
-
*/
|
1
|
+
// Copyright (c) 2011 Peter Ohler. All rights reserved.
|
5
2
|
|
6
3
|
#ifndef OJ_H
|
7
4
|
#define OJ_H
|
@@ -77,7 +74,9 @@ typedef enum {
|
|
77
74
|
typedef enum {
|
78
75
|
BigDec = 'b',
|
79
76
|
FloatDec = 'f',
|
80
|
-
AutoDec = 'a'
|
77
|
+
AutoDec = 'a',
|
78
|
+
FastDec = 'F',
|
79
|
+
RubyDec = 'r',
|
81
80
|
} BigLoad;
|
82
81
|
|
83
82
|
typedef enum {
|
@@ -136,6 +135,7 @@ typedef struct _options {
|
|
136
135
|
char time_format; // TimeFormat
|
137
136
|
char bigdec_as_num; // YesNo
|
138
137
|
char bigdec_load; // BigLoad
|
138
|
+
char compat_bigdec; // boolean (0 or 1)
|
139
139
|
char to_hash; // YesNo
|
140
140
|
char to_json; // YesNo
|
141
141
|
char as_json; // YesNo
|
@@ -311,6 +311,7 @@ extern VALUE oj_array_class_sym;
|
|
311
311
|
extern VALUE oj_array_nl_sym;
|
312
312
|
extern VALUE oj_ascii_only_sym;
|
313
313
|
extern VALUE oj_create_additions_sym;
|
314
|
+
extern VALUE oj_decimal_class_sym;
|
314
315
|
extern VALUE oj_hash_class_sym;
|
315
316
|
extern VALUE oj_indent_sym;
|
316
317
|
extern VALUE oj_max_nesting_sym;
|
data/ext/oj/parse.c
CHANGED
@@ -1,7 +1,4 @@
|
|
1
|
-
|
2
|
-
* Copyright (c) 2013, Peter Ohler
|
3
|
-
* All rights reserved.
|
4
|
-
*/
|
1
|
+
// Copyright (c) 2013 Peter Ohler. All rights reserved.
|
5
2
|
|
6
3
|
#include <stdlib.h>
|
7
4
|
#include <stdio.h>
|
@@ -215,18 +212,6 @@ read_escaped_str(ParseInfo pi, const char *start) {
|
|
215
212
|
case '"': buf_append(&buf, '"'); break;
|
216
213
|
case '/': buf_append(&buf, '/'); break;
|
217
214
|
case '\\': buf_append(&buf, '\\'); break;
|
218
|
-
case '\'':
|
219
|
-
// The json gem claims this is not an error despite the
|
220
|
-
// ECMA-404 indicating it is not valid.
|
221
|
-
if (CompatMode == pi->options.mode) {
|
222
|
-
buf_append(&buf, '\'');
|
223
|
-
} else {
|
224
|
-
pi->cur = s;
|
225
|
-
oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "invalid escaped character");
|
226
|
-
buf_cleanup(&buf);
|
227
|
-
return;
|
228
|
-
}
|
229
|
-
break;
|
230
215
|
case 'u':
|
231
216
|
s++;
|
232
217
|
if (0 == (code = read_hex(pi, s)) && err_has(&pi->err)) {
|
@@ -266,6 +251,12 @@ read_escaped_str(ParseInfo pi, const char *start) {
|
|
266
251
|
}
|
267
252
|
break;
|
268
253
|
default:
|
254
|
+
// The json gem claims this is not an error despite the
|
255
|
+
// ECMA-404 indicating it is not valid.
|
256
|
+
if (CompatMode == pi->options.mode) {
|
257
|
+
buf_append(&buf, *s);
|
258
|
+
break;
|
259
|
+
}
|
269
260
|
pi->cur = s;
|
270
261
|
oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "invalid escaped character");
|
271
262
|
buf_cleanup(&buf);
|
@@ -393,8 +384,14 @@ read_num(ParseInfo pi) {
|
|
393
384
|
ni.infinity = 0;
|
394
385
|
ni.nan = 0;
|
395
386
|
ni.neg = 0;
|
396
|
-
ni.
|
397
|
-
|
387
|
+
ni.has_exp = 0;
|
388
|
+
if (CompatMode == pi->options.mode) {
|
389
|
+
ni.no_big = !pi->options.compat_bigdec;
|
390
|
+
ni.bigdec_load = pi->options.compat_bigdec;
|
391
|
+
} else {
|
392
|
+
ni.no_big = (FloatDec == pi->options.bigdec_load || FastDec == pi->options.bigdec_load || RubyDec == pi->options.bigdec_load);
|
393
|
+
ni.bigdec_load = pi->options.bigdec_load;
|
394
|
+
}
|
398
395
|
|
399
396
|
if ('-' == *pi->cur) {
|
400
397
|
pi->cur++;
|
@@ -453,6 +450,7 @@ read_num(ParseInfo pi) {
|
|
453
450
|
// except when mimicing the JSON gem or in strict mode.
|
454
451
|
if (StrictMode == pi->options.mode || CompatMode == pi->options.mode) {
|
455
452
|
int pos = (int)(pi->cur - ni.str);
|
453
|
+
|
456
454
|
if (1 == pos || (2 == pos && ni.neg)) {
|
457
455
|
oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number");
|
458
456
|
return;
|
@@ -468,18 +466,26 @@ read_num(ParseInfo pi) {
|
|
468
466
|
if (0 < ni.num || 0 < ni.i) {
|
469
467
|
dec_cnt++;
|
470
468
|
}
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
469
|
+
if (INT64_MAX <= ni.div) {
|
470
|
+
if (!ni.no_big) {
|
471
|
+
ni.big = true;
|
472
|
+
}
|
473
|
+
} else {
|
474
|
+
ni.num = ni.num * 10 + d;
|
475
|
+
ni.div *= 10;
|
476
|
+
ni.di++;
|
477
|
+
if (INT64_MAX <= ni.div || DEC_MAX < dec_cnt) {
|
478
|
+
if (!ni.no_big) {
|
479
|
+
ni.big = true;
|
480
|
+
}
|
481
|
+
}
|
476
482
|
}
|
477
483
|
}
|
478
484
|
}
|
479
485
|
if ('e' == *pi->cur || 'E' == *pi->cur) {
|
480
486
|
int eneg = 0;
|
481
487
|
|
482
|
-
ni.
|
488
|
+
ni.has_exp = 1;
|
483
489
|
pi->cur++;
|
484
490
|
if ('-' == *pi->cur) {
|
485
491
|
pi->cur++;
|
@@ -490,7 +496,7 @@ read_num(ParseInfo pi) {
|
|
490
496
|
for (; '0' <= *pi->cur && *pi->cur <= '9'; pi->cur++) {
|
491
497
|
ni.exp = ni.exp * 10 + (*pi->cur - '0');
|
492
498
|
if (EXP_MAX <= ni.exp) {
|
493
|
-
ni.big =
|
499
|
+
ni.big = true;
|
494
500
|
}
|
495
501
|
}
|
496
502
|
if (eneg) {
|
@@ -510,7 +516,11 @@ read_num(ParseInfo pi) {
|
|
510
516
|
ni.nan = 1;
|
511
517
|
}
|
512
518
|
}
|
513
|
-
if (
|
519
|
+
if (CompatMode == pi->options.mode) {
|
520
|
+
if (pi->options.compat_bigdec) {
|
521
|
+
ni.big = 1;
|
522
|
+
}
|
523
|
+
} else if (BigDec == pi->options.bigdec_load) {
|
514
524
|
ni.big = 1;
|
515
525
|
}
|
516
526
|
if (0 == parent) {
|
@@ -750,6 +760,59 @@ parse_big_decimal(VALUE str) {
|
|
750
760
|
return rb_funcall(rb_cObject, oj_bigdecimal_id, 1, str);
|
751
761
|
}
|
752
762
|
|
763
|
+
static long double exp_plus[] = {
|
764
|
+
1.0,
|
765
|
+
1.0e1,
|
766
|
+
1.0e2,
|
767
|
+
1.0e3,
|
768
|
+
1.0e4,
|
769
|
+
1.0e5,
|
770
|
+
1.0e6,
|
771
|
+
1.0e7,
|
772
|
+
1.0e8,
|
773
|
+
1.0e9,
|
774
|
+
1.0e10,
|
775
|
+
1.0e11,
|
776
|
+
1.0e12,
|
777
|
+
1.0e13,
|
778
|
+
1.0e14,
|
779
|
+
1.0e15,
|
780
|
+
1.0e16,
|
781
|
+
1.0e17,
|
782
|
+
1.0e18,
|
783
|
+
1.0e19,
|
784
|
+
1.0e20,
|
785
|
+
1.0e21,
|
786
|
+
1.0e22,
|
787
|
+
1.0e23,
|
788
|
+
1.0e24,
|
789
|
+
1.0e25,
|
790
|
+
1.0e26,
|
791
|
+
1.0e27,
|
792
|
+
1.0e28,
|
793
|
+
1.0e29,
|
794
|
+
1.0e30,
|
795
|
+
1.0e31,
|
796
|
+
1.0e32,
|
797
|
+
1.0e33,
|
798
|
+
1.0e34,
|
799
|
+
1.0e35,
|
800
|
+
1.0e36,
|
801
|
+
1.0e37,
|
802
|
+
1.0e38,
|
803
|
+
1.0e39,
|
804
|
+
1.0e40,
|
805
|
+
1.0e41,
|
806
|
+
1.0e42,
|
807
|
+
1.0e43,
|
808
|
+
1.0e44,
|
809
|
+
1.0e45,
|
810
|
+
1.0e46,
|
811
|
+
1.0e47,
|
812
|
+
1.0e48,
|
813
|
+
1.0e49,
|
814
|
+
};
|
815
|
+
|
753
816
|
VALUE
|
754
817
|
oj_num_as_value(NumInfo ni) {
|
755
818
|
volatile VALUE rnum = Qnil;
|
@@ -762,7 +825,7 @@ oj_num_as_value(NumInfo ni) {
|
|
762
825
|
}
|
763
826
|
} else if (ni->nan) {
|
764
827
|
rnum = rb_float_new(0.0/0.0);
|
765
|
-
} else if (1 == ni->div && 0 == ni->exp) { // fixnum
|
828
|
+
} else if (1 == ni->div && 0 == ni->exp && !ni->has_exp) { // fixnum
|
766
829
|
if (ni->big) {
|
767
830
|
if (256 > ni->len) {
|
768
831
|
char buf[256];
|
@@ -793,33 +856,39 @@ oj_num_as_value(NumInfo ni) {
|
|
793
856
|
if (ni->no_big) {
|
794
857
|
rnum = rb_funcall(rnum, rb_intern("to_f"), 0);
|
795
858
|
}
|
796
|
-
} else {
|
797
|
-
|
798
|
-
long double d = (long double)ni->i * (long double)ni->div + (long double)ni->num;
|
859
|
+
} else if (FastDec == ni->bigdec_load) {
|
860
|
+
long double ld = (long double)ni->i * (long double)ni->div + (long double)ni->num;
|
799
861
|
int x = (int)((int64_t)ni->exp - ni->di);
|
800
862
|
|
801
|
-
|
802
|
-
|
803
|
-
|
804
|
-
|
805
|
-
|
806
|
-
|
807
|
-
rnum = rb_rescue2(parse_big_decimal, bd, rescue_big_decimal, bd, rb_eException, 0);
|
808
|
-
if (ni->no_big) {
|
809
|
-
rnum = rb_funcall(rnum, rb_intern("to_f"), 0);
|
810
|
-
}
|
811
|
-
} else {
|
812
|
-
d = roundl(d);
|
813
|
-
if (0 < x) {
|
814
|
-
d *= powl(10.0L, x);
|
815
|
-
} else if (0 > x) {
|
816
|
-
d /= powl(10.0L, -x);
|
863
|
+
if (0 < x) {
|
864
|
+
if (x < (int)(sizeof(exp_plus) / sizeof(*exp_plus))) {
|
865
|
+
ld *= exp_plus[x];
|
866
|
+
} else {
|
867
|
+
ld *= powl(10.0, x);
|
817
868
|
}
|
818
|
-
|
819
|
-
|
869
|
+
} else if (x < 0) {
|
870
|
+
if (-x < (int)(sizeof(exp_plus) / sizeof(*exp_plus))) {
|
871
|
+
ld /= exp_plus[-x];
|
872
|
+
} else {
|
873
|
+
ld /= powl(10.0, -x);
|
820
874
|
}
|
821
|
-
rnum = rb_float_new((double)d);
|
822
875
|
}
|
876
|
+
if (ni->neg) {
|
877
|
+
ld = -ld;
|
878
|
+
}
|
879
|
+
rnum = rb_float_new((double)ld);
|
880
|
+
} else if (RubyDec == ni->bigdec_load) {
|
881
|
+
volatile VALUE sv = rb_str_new(ni->str, ni->len);
|
882
|
+
|
883
|
+
rnum = rb_funcall(sv, rb_intern("to_f"), 0);
|
884
|
+
} else {
|
885
|
+
char *end;
|
886
|
+
double d = strtod(ni->str, &end);
|
887
|
+
|
888
|
+
if ((long)ni->len != (long)(end - ni->str)) {
|
889
|
+
rb_raise(oj_parse_error_class, "Invalid float");
|
890
|
+
}
|
891
|
+
rnum = rb_float_new(d);
|
823
892
|
}
|
824
893
|
}
|
825
894
|
return rnum;
|
@@ -841,6 +910,12 @@ oj_set_error_at(ParseInfo pi, VALUE err_clas, const char* file, int line, const
|
|
841
910
|
if (p + 3 < end) {
|
842
911
|
*p++ = ' ';
|
843
912
|
*p++ = '(';
|
913
|
+
*p++ = 'a';
|
914
|
+
*p++ = 'f';
|
915
|
+
*p++ = 't';
|
916
|
+
*p++ = 'e';
|
917
|
+
*p++ = 'r';
|
918
|
+
*p++ = ' ';
|
844
919
|
start = p;
|
845
920
|
for (vp = pi->stack.head; vp < pi->stack.tail; vp++) {
|
846
921
|
if (end <= p + 1 + vp->klen) {
|
data/ext/oj/parse.h
CHANGED
@@ -1,7 +1,4 @@
|
|
1
|
-
|
2
|
-
* Copyright (c) 2011, Peter Ohler
|
3
|
-
* All rights reserved.
|
4
|
-
*/
|
1
|
+
// Copyright (c) 2011 Peter Ohler. All rights reserved.
|
5
2
|
|
6
3
|
#ifndef OJ_PARSE_H
|
7
4
|
#define OJ_PARSE_H
|
@@ -31,8 +28,9 @@ typedef struct _numInfo {
|
|
31
28
|
int infinity;
|
32
29
|
int nan;
|
33
30
|
int neg;
|
34
|
-
int
|
31
|
+
int has_exp;
|
35
32
|
int no_big;
|
33
|
+
int bigdec_load;
|
36
34
|
} *NumInfo;
|
37
35
|
|
38
36
|
typedef struct _parseInfo {
|