oj 3.7.4 → 3.13.23
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/CHANGELOG.md +1360 -0
- data/README.md +31 -8
- data/RELEASE_NOTES.md +61 -0
- data/ext/oj/buf.h +53 -72
- data/ext/oj/cache.c +326 -0
- data/ext/oj/cache.h +21 -0
- data/ext/oj/cache8.c +61 -64
- data/ext/oj/cache8.h +12 -39
- data/ext/oj/circarray.c +37 -43
- data/ext/oj/circarray.h +16 -17
- data/ext/oj/code.c +165 -179
- data/ext/oj/code.h +27 -29
- data/ext/oj/compat.c +174 -194
- data/ext/oj/custom.c +790 -866
- data/ext/oj/debug.c +132 -0
- data/ext/oj/dump.c +848 -863
- data/ext/oj/dump.h +81 -67
- data/ext/oj/dump_compat.c +85 -123
- data/ext/oj/dump_leaf.c +100 -188
- data/ext/oj/dump_object.c +527 -656
- data/ext/oj/dump_strict.c +315 -338
- data/ext/oj/encode.h +7 -34
- data/ext/oj/encoder.c +43 -0
- data/ext/oj/err.c +40 -29
- data/ext/oj/err.h +48 -48
- data/ext/oj/extconf.rb +17 -4
- data/ext/oj/fast.c +1073 -1088
- data/ext/oj/intern.c +298 -0
- data/ext/oj/intern.h +26 -0
- data/ext/oj/mimic_json.c +469 -436
- data/ext/oj/object.c +532 -599
- data/ext/oj/odd.c +154 -138
- data/ext/oj/odd.h +37 -38
- data/ext/oj/oj.c +1333 -986
- data/ext/oj/oj.h +336 -316
- data/ext/oj/parse.c +1002 -846
- data/ext/oj/parse.h +92 -87
- data/ext/oj/parser.c +1587 -0
- data/ext/oj/parser.h +102 -0
- data/ext/oj/rails.c +888 -878
- data/ext/oj/rails.h +11 -14
- data/ext/oj/reader.c +141 -147
- data/ext/oj/reader.h +73 -89
- data/ext/oj/resolve.c +41 -62
- data/ext/oj/resolve.h +7 -9
- data/ext/oj/rxclass.c +71 -75
- data/ext/oj/rxclass.h +18 -19
- data/ext/oj/saj.c +443 -486
- data/ext/oj/saj2.c +596 -0
- data/ext/oj/saj2.h +23 -0
- data/ext/oj/scp.c +88 -113
- data/ext/oj/sparse.c +787 -709
- data/ext/oj/stream_writer.c +133 -159
- data/ext/oj/strict.c +127 -118
- data/ext/oj/string_writer.c +230 -249
- data/ext/oj/trace.c +34 -41
- data/ext/oj/trace.h +19 -19
- data/ext/oj/usual.c +1207 -0
- data/ext/oj/usual.h +68 -0
- data/ext/oj/util.c +136 -0
- data/ext/oj/util.h +20 -0
- data/ext/oj/val_stack.c +60 -68
- data/ext/oj/val_stack.h +91 -129
- data/ext/oj/validate.c +46 -0
- data/ext/oj/wab.c +342 -353
- data/lib/oj/bag.rb +1 -0
- data/lib/oj/easy_hash.rb +5 -4
- data/lib/oj/error.rb +1 -1
- data/lib/oj/json.rb +1 -1
- data/lib/oj/mimic.rb +48 -14
- data/lib/oj/saj.rb +20 -6
- data/lib/oj/state.rb +9 -8
- data/lib/oj/version.rb +2 -2
- data/lib/oj.rb +0 -8
- data/pages/Compatibility.md +1 -1
- data/pages/JsonGem.md +15 -0
- data/pages/Modes.md +53 -46
- data/pages/Options.md +78 -11
- data/pages/Parser.md +309 -0
- data/pages/Rails.md +73 -22
- data/pages/Security.md +1 -1
- data/test/activerecord/result_test.rb +7 -2
- 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/activesupport7/abstract_unit.rb +49 -0
- data/test/activesupport7/decoding_test.rb +125 -0
- data/test/activesupport7/encoding_test.rb +486 -0
- data/test/activesupport7/encoding_test_cases.rb +104 -0
- data/test/activesupport7/time_zone_test_helpers.rb +47 -0
- data/test/bar.rb +6 -12
- data/test/baz.rb +16 -0
- data/test/bug.rb +16 -0
- data/test/foo.rb +69 -75
- data/test/helper.rb +16 -0
- data/test/json_gem/json_common_interface_test.rb +8 -3
- data/test/json_gem/json_generator_test.rb +21 -8
- data/test/json_gem/json_parser_test.rb +8 -1
- data/test/json_gem/test_helper.rb +12 -0
- data/test/mem.rb +33 -0
- data/test/perf.rb +1 -1
- data/test/perf_dump.rb +50 -0
- data/test/perf_once.rb +58 -0
- data/test/perf_parser.rb +189 -0
- data/test/perf_scp.rb +11 -10
- data/test/perf_strict.rb +17 -23
- data/test/prec.rb +23 -0
- data/test/sample_json.rb +1 -1
- data/test/test_compat.rb +46 -10
- data/test/test_custom.rb +145 -7
- data/test/test_fast.rb +62 -2
- data/test/test_file.rb +23 -7
- data/test/test_gc.rb +11 -0
- data/test/test_generate.rb +21 -0
- data/test/test_hash.rb +11 -1
- data/test/test_integer_range.rb +1 -2
- data/test/test_object.rb +43 -12
- data/test/test_parser.rb +11 -0
- data/test/test_parser_debug.rb +27 -0
- data/test/test_parser_saj.rb +335 -0
- data/test/test_parser_usual.rb +217 -0
- data/test/test_rails.rb +35 -0
- data/test/test_saj.rb +1 -1
- data/test/test_scp.rb +3 -5
- data/test/test_strict.rb +26 -1
- data/test/test_various.rb +86 -65
- data/test/test_wab.rb +2 -0
- data/test/test_writer.rb +19 -2
- data/test/tests.rb +10 -1
- data/test/tests_mimic.rb +9 -0
- data/test/tests_mimic_addition.rb +9 -0
- data/test/zoo.rb +13 -0
- metadata +63 -110
- data/ext/oj/hash.c +0 -163
- data/ext/oj/hash.h +0 -46
- data/ext/oj/hash_test.c +0 -512
data/ext/oj/mimic_json.c
CHANGED
|
@@ -1,69 +1,65 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
* All rights reserved.
|
|
4
|
-
*/
|
|
1
|
+
// Copyright (c) 2012, 2017 Peter Ohler. All rights reserved.
|
|
2
|
+
// Licensed under the MIT License. See LICENSE file in the project root for license details.
|
|
5
3
|
|
|
6
|
-
#include "oj.h"
|
|
7
|
-
#include "encode.h"
|
|
8
4
|
#include "dump.h"
|
|
5
|
+
#include "encode.h"
|
|
6
|
+
#include "oj.h"
|
|
9
7
|
#include "parse.h"
|
|
10
8
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
extern const char oj_json_class[];
|
|
9
|
+
extern const char oj_json_class[];
|
|
14
10
|
|
|
15
|
-
VALUE
|
|
16
|
-
VALUE
|
|
17
|
-
VALUE
|
|
18
|
-
VALUE
|
|
19
|
-
VALUE
|
|
20
|
-
VALUE
|
|
21
|
-
VALUE
|
|
22
|
-
VALUE
|
|
11
|
+
VALUE oj_array_nl_sym;
|
|
12
|
+
VALUE oj_ascii_only_sym;
|
|
13
|
+
VALUE oj_json_generator_error_class;
|
|
14
|
+
VALUE oj_json_parser_error_class;
|
|
15
|
+
VALUE oj_max_nesting_sym;
|
|
16
|
+
VALUE oj_object_nl_sym;
|
|
17
|
+
VALUE oj_space_before_sym;
|
|
18
|
+
VALUE oj_space_sym;
|
|
23
19
|
|
|
24
|
-
static VALUE
|
|
20
|
+
static VALUE state_class = Qundef;
|
|
25
21
|
|
|
26
22
|
// mimic JSON documentation
|
|
27
23
|
|
|
28
24
|
/* Document-module: JSON::Ext
|
|
29
|
-
*
|
|
25
|
+
*
|
|
30
26
|
* The Ext module is a placeholder in the mimic JSON module used for
|
|
31
27
|
* compatibility only.
|
|
32
28
|
*/
|
|
33
29
|
/* Document-class: JSON::Ext::Parser
|
|
34
|
-
*
|
|
30
|
+
*
|
|
35
31
|
* The JSON::Ext::Parser is a placeholder in the mimic JSON module used for
|
|
36
32
|
* compatibility only.
|
|
37
33
|
*/
|
|
38
34
|
/* Document-class: JSON::Ext::Generator
|
|
39
|
-
*
|
|
35
|
+
*
|
|
40
36
|
* The JSON::Ext::Generator is a placeholder in the mimic JSON module used for
|
|
41
37
|
* compatibility only.
|
|
42
38
|
*/
|
|
43
39
|
|
|
44
40
|
/* Document-method: parser=
|
|
45
41
|
* call-seq: parser=(parser)
|
|
46
|
-
*
|
|
42
|
+
*
|
|
47
43
|
* Does nothing other than provide compatibility.
|
|
48
44
|
* - *parser* [_Object_] ignored
|
|
49
45
|
*/
|
|
50
46
|
/* Document-method: generator=
|
|
51
47
|
* call-seq: generator=(generator)
|
|
52
|
-
*
|
|
48
|
+
*
|
|
53
49
|
* Does nothing other than provide compatibility.
|
|
54
50
|
* - *generator* [_Object_] ignored
|
|
55
51
|
*/
|
|
56
52
|
|
|
57
53
|
VALUE
|
|
58
54
|
oj_get_json_err_class(const char *err_classname) {
|
|
59
|
-
volatile VALUE
|
|
60
|
-
volatile VALUE
|
|
61
|
-
volatile VALUE
|
|
55
|
+
volatile VALUE json_module;
|
|
56
|
+
volatile VALUE clas;
|
|
57
|
+
volatile VALUE json_error_class;
|
|
62
58
|
|
|
63
59
|
if (rb_const_defined_at(rb_cObject, rb_intern("JSON"))) {
|
|
64
|
-
|
|
60
|
+
json_module = rb_const_get_at(rb_cObject, rb_intern("JSON"));
|
|
65
61
|
} else {
|
|
66
|
-
|
|
62
|
+
json_module = rb_define_module("JSON");
|
|
67
63
|
}
|
|
68
64
|
if (rb_const_defined_at(json_module, rb_intern("JSONError"))) {
|
|
69
65
|
json_error_class = rb_const_get(json_module, rb_intern("JSONError"));
|
|
@@ -71,225 +67,236 @@ oj_get_json_err_class(const char *err_classname) {
|
|
|
71
67
|
json_error_class = rb_define_class_under(json_module, "JSONError", rb_eStandardError);
|
|
72
68
|
}
|
|
73
69
|
if (0 == strcmp(err_classname, "JSONError")) {
|
|
74
|
-
|
|
70
|
+
clas = json_error_class;
|
|
75
71
|
} else {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
72
|
+
if (rb_const_defined_at(json_module, rb_intern(err_classname))) {
|
|
73
|
+
clas = rb_const_get(json_module, rb_intern(err_classname));
|
|
74
|
+
} else {
|
|
75
|
+
clas = rb_define_class_under(json_module, err_classname, json_error_class);
|
|
76
|
+
}
|
|
81
77
|
}
|
|
82
78
|
return clas;
|
|
83
79
|
}
|
|
84
80
|
|
|
85
|
-
void
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
size_t len;
|
|
81
|
+
void oj_parse_mimic_dump_options(VALUE ropts, Options copts) {
|
|
82
|
+
VALUE v;
|
|
83
|
+
size_t len;
|
|
89
84
|
|
|
90
85
|
if (T_HASH != rb_type(ropts)) {
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
86
|
+
if (rb_respond_to(ropts, oj_to_hash_id)) {
|
|
87
|
+
ropts = rb_funcall(ropts, oj_to_hash_id, 0);
|
|
88
|
+
} else if (rb_respond_to(ropts, oj_to_h_id)) {
|
|
89
|
+
ropts = rb_funcall(ropts, oj_to_h_id, 0);
|
|
90
|
+
} else if (Qnil == ropts) {
|
|
91
|
+
return;
|
|
92
|
+
} else {
|
|
93
|
+
rb_raise(rb_eArgError, "options must be a hash.");
|
|
94
|
+
}
|
|
100
95
|
}
|
|
101
96
|
v = rb_hash_lookup(ropts, oj_max_nesting_sym);
|
|
102
97
|
if (Qtrue == v) {
|
|
103
|
-
|
|
98
|
+
copts->dump_opts.max_depth = 100;
|
|
104
99
|
} else if (Qfalse == v || Qnil == v) {
|
|
105
|
-
|
|
100
|
+
copts->dump_opts.max_depth = MAX_DEPTH;
|
|
106
101
|
} else if (T_FIXNUM == rb_type(v)) {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
102
|
+
copts->dump_opts.max_depth = NUM2INT(v);
|
|
103
|
+
if (0 >= copts->dump_opts.max_depth) {
|
|
104
|
+
copts->dump_opts.max_depth = MAX_DEPTH;
|
|
105
|
+
}
|
|
111
106
|
}
|
|
112
107
|
if (Qnil != (v = rb_hash_lookup(ropts, oj_allow_nan_sym))) {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
108
|
+
if (Qtrue == v) {
|
|
109
|
+
copts->dump_opts.nan_dump = WordNan;
|
|
110
|
+
} else {
|
|
111
|
+
copts->dump_opts.nan_dump = RaiseNan;
|
|
112
|
+
}
|
|
118
113
|
}
|
|
119
114
|
if (Qnil != (v = rb_hash_lookup(ropts, oj_indent_sym))) {
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
115
|
+
rb_check_type(v, T_STRING);
|
|
116
|
+
if (sizeof(copts->dump_opts.indent_str) <= (len = RSTRING_LEN(v))) {
|
|
117
|
+
rb_raise(rb_eArgError,
|
|
118
|
+
"indent string is limited to %lu characters.",
|
|
119
|
+
(unsigned long)sizeof(copts->dump_opts.indent_str));
|
|
120
|
+
}
|
|
121
|
+
strcpy(copts->dump_opts.indent_str, StringValuePtr(v));
|
|
122
|
+
copts->dump_opts.indent_size = (uint8_t)len;
|
|
123
|
+
copts->dump_opts.use = true;
|
|
127
124
|
}
|
|
128
125
|
if (Qnil != (v = rb_hash_lookup(ropts, oj_space_sym))) {
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
126
|
+
rb_check_type(v, T_STRING);
|
|
127
|
+
if (sizeof(copts->dump_opts.after_sep) <= (len = RSTRING_LEN(v))) {
|
|
128
|
+
rb_raise(rb_eArgError,
|
|
129
|
+
"space string is limited to %lu characters.",
|
|
130
|
+
(unsigned long)sizeof(copts->dump_opts.after_sep));
|
|
131
|
+
}
|
|
132
|
+
strcpy(copts->dump_opts.after_sep, StringValuePtr(v));
|
|
133
|
+
copts->dump_opts.after_size = (uint8_t)len;
|
|
134
|
+
copts->dump_opts.use = true;
|
|
136
135
|
}
|
|
137
136
|
if (Qnil != (v = rb_hash_lookup(ropts, oj_space_before_sym))) {
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
137
|
+
rb_check_type(v, T_STRING);
|
|
138
|
+
if (sizeof(copts->dump_opts.before_sep) <= (len = RSTRING_LEN(v))) {
|
|
139
|
+
rb_raise(rb_eArgError,
|
|
140
|
+
"space_before string is limited to %lu characters.",
|
|
141
|
+
(unsigned long)sizeof(copts->dump_opts.before_sep));
|
|
142
|
+
}
|
|
143
|
+
strcpy(copts->dump_opts.before_sep, StringValuePtr(v));
|
|
144
|
+
copts->dump_opts.before_size = (uint8_t)len;
|
|
145
|
+
copts->dump_opts.use = true;
|
|
145
146
|
}
|
|
146
147
|
if (Qnil != (v = rb_hash_lookup(ropts, oj_object_nl_sym))) {
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
148
|
+
rb_check_type(v, T_STRING);
|
|
149
|
+
if (sizeof(copts->dump_opts.hash_nl) <= (len = RSTRING_LEN(v))) {
|
|
150
|
+
rb_raise(rb_eArgError,
|
|
151
|
+
"object_nl string is limited to %lu characters.",
|
|
152
|
+
(unsigned long)sizeof(copts->dump_opts.hash_nl));
|
|
153
|
+
}
|
|
154
|
+
strcpy(copts->dump_opts.hash_nl, StringValuePtr(v));
|
|
155
|
+
copts->dump_opts.hash_size = (uint8_t)len;
|
|
156
|
+
copts->dump_opts.use = true;
|
|
154
157
|
}
|
|
155
158
|
if (Qnil != (v = rb_hash_lookup(ropts, oj_array_nl_sym))) {
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
159
|
+
rb_check_type(v, T_STRING);
|
|
160
|
+
if (sizeof(copts->dump_opts.array_nl) <= (len = RSTRING_LEN(v))) {
|
|
161
|
+
rb_raise(rb_eArgError,
|
|
162
|
+
"array_nl string is limited to %lu characters.",
|
|
163
|
+
(unsigned long)sizeof(copts->dump_opts.array_nl));
|
|
164
|
+
}
|
|
165
|
+
strcpy(copts->dump_opts.array_nl, StringValuePtr(v));
|
|
166
|
+
copts->dump_opts.array_size = (uint8_t)len;
|
|
167
|
+
copts->dump_opts.use = true;
|
|
163
168
|
}
|
|
164
169
|
if (Qnil != (v = rb_hash_lookup(ropts, oj_quirks_mode_sym))) {
|
|
165
|
-
|
|
170
|
+
copts->quirks_mode = (Qtrue == v) ? Yes : No;
|
|
166
171
|
}
|
|
167
172
|
if (Qnil != (v = rb_hash_lookup(ropts, oj_ascii_only_sym))) {
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
173
|
+
// generate seems to assume anything except nil and false are true.
|
|
174
|
+
if (Qfalse == v) {
|
|
175
|
+
copts->escape_mode = JXEsc;
|
|
176
|
+
} else {
|
|
177
|
+
copts->escape_mode = ASCIIEsc;
|
|
178
|
+
}
|
|
174
179
|
}
|
|
175
180
|
}
|
|
176
181
|
|
|
177
|
-
static int
|
|
178
|
-
mimic_limit_arg(VALUE a) {
|
|
182
|
+
static int mimic_limit_arg(VALUE a) {
|
|
179
183
|
if (Qnil == a || T_FIXNUM != rb_type(a)) {
|
|
180
|
-
|
|
184
|
+
return -1;
|
|
181
185
|
}
|
|
182
186
|
return NUM2INT(a);
|
|
183
187
|
}
|
|
184
188
|
|
|
185
189
|
/* Document-method: dump
|
|
186
190
|
* call-seq: dump(obj, anIO=nil, limit=nil)
|
|
187
|
-
*
|
|
191
|
+
*
|
|
188
192
|
* Encodes an object as a JSON String.
|
|
189
|
-
*
|
|
193
|
+
*
|
|
190
194
|
* - *obj* [_Object_] object to convert to encode as JSON
|
|
191
195
|
* - *anIO* [_IO_] an IO that allows writing
|
|
192
196
|
* - *limit* [_Fixnum_] ignored
|
|
193
197
|
*
|
|
194
198
|
* Returns [_String_] a JSON string.
|
|
195
199
|
*/
|
|
196
|
-
static VALUE
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
VALUE rstr;
|
|
200
|
+
static VALUE mimic_dump(int argc, VALUE *argv, VALUE self) {
|
|
201
|
+
struct _out out;
|
|
202
|
+
struct _options copts = oj_default_options;
|
|
203
|
+
VALUE rstr;
|
|
204
|
+
VALUE active_hack[1];
|
|
202
205
|
|
|
203
206
|
copts.str_rx.head = NULL;
|
|
204
207
|
copts.str_rx.tail = NULL;
|
|
205
|
-
|
|
206
|
-
out
|
|
207
|
-
|
|
208
|
-
out.caller
|
|
208
|
+
|
|
209
|
+
oj_out_init(&out);
|
|
210
|
+
|
|
211
|
+
out.caller = CALLER_DUMP;
|
|
209
212
|
copts.escape_mode = JXEsc;
|
|
210
|
-
copts.mode
|
|
213
|
+
copts.mode = CompatMode;
|
|
211
214
|
|
|
212
215
|
/* seems like this is not correct
|
|
213
216
|
if (No == copts.nilnil && Qnil == *argv) {
|
|
214
|
-
|
|
217
|
+
rb_raise(rb_eTypeError, "nil not allowed.");
|
|
215
218
|
}
|
|
216
219
|
*/
|
|
217
|
-
copts.dump_opts.max_depth = MAX_DEPTH;
|
|
218
|
-
out.omit_nil
|
|
220
|
+
copts.dump_opts.max_depth = MAX_DEPTH; // when using dump there is no limit
|
|
221
|
+
out.omit_nil = copts.dump_opts.omit_nil;
|
|
222
|
+
|
|
219
223
|
if (2 <= argc) {
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
}
|
|
233
|
-
|
|
224
|
+
int limit;
|
|
225
|
+
|
|
226
|
+
// The json gem take a more liberal approach to optional
|
|
227
|
+
// arguments. Expected are (obj, anIO=nil, limit=nil) yet the io
|
|
228
|
+
// argument can be left off completely and the 2nd argument is then
|
|
229
|
+
// the limit.
|
|
230
|
+
if (0 <= (limit = mimic_limit_arg(argv[1]))) {
|
|
231
|
+
copts.dump_opts.max_depth = limit;
|
|
232
|
+
}
|
|
233
|
+
if (3 <= argc && 0 <= (limit = mimic_limit_arg(argv[2]))) {
|
|
234
|
+
copts.dump_opts.max_depth = limit;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
// ActiveSupport in active_support/core_ext/object/json.rb check the
|
|
238
|
+
// optional argument type to to_json and it the argument is a
|
|
239
|
+
// ::JSON::State it calls the JSON gem code otherwise it calls the active
|
|
240
|
+
// support encoder code. To make sure the desired branch is called a
|
|
241
|
+
// default ::JSON::State argument is passed in. Basically a hack to get
|
|
242
|
+
// around the active support hack so two wrongs make a right this time.
|
|
243
|
+
active_hack[0] = rb_funcall(state_class, oj_new_id, 0);
|
|
244
|
+
oj_dump_obj_to_json_using_params(*argv, &copts, &out, 1, active_hack);
|
|
245
|
+
|
|
234
246
|
if (0 == out.buf) {
|
|
235
|
-
|
|
247
|
+
rb_raise(rb_eNoMemError, "Not enough memory.");
|
|
236
248
|
}
|
|
237
249
|
rstr = rb_str_new2(out.buf);
|
|
238
250
|
rstr = oj_encode(rstr);
|
|
239
251
|
if (2 <= argc && Qnil != argv[1] && rb_respond_to(argv[1], oj_write_id)) {
|
|
240
|
-
|
|
241
|
-
|
|
252
|
+
VALUE io = argv[1];
|
|
253
|
+
VALUE args[1];
|
|
242
254
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
}
|
|
247
|
-
if (out.allocated) {
|
|
248
|
-
xfree(out.buf);
|
|
255
|
+
*args = rstr;
|
|
256
|
+
rb_funcall2(io, oj_write_id, 1, args);
|
|
257
|
+
rstr = io;
|
|
249
258
|
}
|
|
259
|
+
|
|
260
|
+
oj_out_free(&out);
|
|
261
|
+
|
|
250
262
|
return rstr;
|
|
251
263
|
}
|
|
252
264
|
|
|
253
265
|
// This is the signature for the hash_foreach callback also.
|
|
254
|
-
static int
|
|
255
|
-
mimic_walk(VALUE key, VALUE obj, VALUE proc) {
|
|
266
|
+
static int mimic_walk(VALUE key, VALUE obj, VALUE proc) {
|
|
256
267
|
switch (rb_type(obj)) {
|
|
257
|
-
case T_HASH:
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
break;
|
|
269
|
-
}
|
|
270
|
-
default:
|
|
271
|
-
break;
|
|
268
|
+
case T_HASH: rb_hash_foreach(obj, mimic_walk, proc); break;
|
|
269
|
+
case T_ARRAY: {
|
|
270
|
+
size_t cnt = RARRAY_LEN(obj);
|
|
271
|
+
size_t i;
|
|
272
|
+
|
|
273
|
+
for (i = 0; i < cnt; i++) {
|
|
274
|
+
mimic_walk(Qnil, RARRAY_AREF(obj, i), proc);
|
|
275
|
+
}
|
|
276
|
+
break;
|
|
277
|
+
}
|
|
278
|
+
default: break;
|
|
272
279
|
}
|
|
273
280
|
if (Qnil == proc) {
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
281
|
+
if (rb_block_given_p()) {
|
|
282
|
+
rb_yield(obj);
|
|
283
|
+
}
|
|
277
284
|
} else {
|
|
278
|
-
|
|
285
|
+
VALUE args[1];
|
|
279
286
|
|
|
280
|
-
|
|
281
|
-
|
|
287
|
+
*args = obj;
|
|
288
|
+
rb_proc_call_with_block(proc, 1, args, Qnil);
|
|
282
289
|
}
|
|
283
290
|
return ST_CONTINUE;
|
|
284
291
|
}
|
|
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,30 +305,29 @@ 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
|
*
|
|
309
316
|
* Returns [_Object_] the decode Object.
|
|
310
317
|
*/
|
|
311
|
-
static VALUE
|
|
312
|
-
|
|
313
|
-
VALUE
|
|
314
|
-
VALUE p = Qnil;
|
|
318
|
+
static VALUE mimic_load(int argc, VALUE *argv, VALUE self) {
|
|
319
|
+
VALUE obj;
|
|
320
|
+
VALUE p = Qnil;
|
|
315
321
|
|
|
316
322
|
obj = oj_compat_load(argc, argv, self);
|
|
317
323
|
if (2 <= argc) {
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
324
|
+
if (rb_cProc == rb_obj_class(argv[1])) {
|
|
325
|
+
p = argv[1];
|
|
326
|
+
} else if (3 <= argc) {
|
|
327
|
+
if (rb_cProc == rb_obj_class(argv[2])) {
|
|
328
|
+
p = argv[2];
|
|
329
|
+
}
|
|
330
|
+
}
|
|
325
331
|
}
|
|
326
332
|
mimic_walk(Qnil, obj, p);
|
|
327
333
|
|
|
@@ -330,61 +336,75 @@ mimic_load(int argc, VALUE *argv, VALUE self) {
|
|
|
330
336
|
|
|
331
337
|
/* Document-method: []
|
|
332
338
|
* call-seq: [](obj, opts={})
|
|
333
|
-
*
|
|
339
|
+
*
|
|
334
340
|
* If the obj argument is a String then it is assumed to be a JSON String and
|
|
335
341
|
* parsed otherwise the obj is encoded as a JSON String.
|
|
336
|
-
*
|
|
342
|
+
*
|
|
337
343
|
* - *obj* [_String_|Hash|Array] object to convert
|
|
338
344
|
* - *opts* [_Hash_] same options as either generate or parse
|
|
339
345
|
*
|
|
340
346
|
* Returns [_Object_]
|
|
341
347
|
*/
|
|
342
|
-
static VALUE
|
|
343
|
-
mimic_dump_load(int argc, VALUE *argv, VALUE self) {
|
|
348
|
+
static VALUE mimic_dump_load(int argc, VALUE *argv, VALUE self) {
|
|
344
349
|
if (1 > argc) {
|
|
345
|
-
|
|
350
|
+
rb_raise(rb_eArgError, "wrong number of arguments (0 for 1)");
|
|
346
351
|
} else if (T_STRING == rb_type(*argv)) {
|
|
347
|
-
|
|
352
|
+
return mimic_load(argc, argv, self);
|
|
348
353
|
} else {
|
|
349
|
-
|
|
354
|
+
return mimic_dump(argc, argv, self);
|
|
350
355
|
}
|
|
351
356
|
return Qnil;
|
|
352
357
|
}
|
|
353
358
|
|
|
354
|
-
static VALUE
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
out.
|
|
362
|
-
|
|
363
|
-
out
|
|
364
|
-
|
|
359
|
+
static VALUE mimic_generate_core(int argc, VALUE *argv, Options copts) {
|
|
360
|
+
struct _out out;
|
|
361
|
+
VALUE rstr;
|
|
362
|
+
|
|
363
|
+
if (0 == argc) {
|
|
364
|
+
rb_raise(rb_eArgError, "wrong number of arguments (0))");
|
|
365
|
+
}
|
|
366
|
+
memset(out.stack_buffer, 0, sizeof(out.stack_buffer));
|
|
367
|
+
|
|
368
|
+
oj_out_init(&out);
|
|
369
|
+
|
|
370
|
+
out.omit_nil = copts->dump_opts.omit_nil;
|
|
371
|
+
out.caller = CALLER_GENERATE;
|
|
365
372
|
// For obj.to_json or generate nan is not allowed but if called from dump
|
|
366
373
|
// it is.
|
|
367
374
|
copts->dump_opts.nan_dump = RaiseNan;
|
|
368
|
-
copts->mode
|
|
369
|
-
copts->to_json
|
|
375
|
+
copts->mode = CompatMode;
|
|
376
|
+
copts->to_json = Yes;
|
|
370
377
|
if (2 == argc && Qnil != argv[1]) {
|
|
371
|
-
|
|
378
|
+
oj_parse_mimic_dump_options(argv[1], copts);
|
|
372
379
|
}
|
|
373
380
|
/* seems like this is not correct
|
|
374
381
|
if (No == copts->nilnil && Qnil == *argv) {
|
|
375
|
-
|
|
382
|
+
rb_raise(rb_eTypeError, "nil not allowed.");
|
|
376
383
|
}
|
|
377
384
|
*/
|
|
378
|
-
|
|
379
|
-
|
|
385
|
+
if (1 < argc) {
|
|
386
|
+
oj_dump_obj_to_json_using_params(*argv, copts, &out, argc - 1, argv + 1);
|
|
387
|
+
} else {
|
|
388
|
+
VALUE active_hack[1];
|
|
389
|
+
|
|
390
|
+
if (Qundef == state_class) {
|
|
391
|
+
rb_warn(
|
|
392
|
+
"Oj::Rails.mimic_JSON was called implicitly. "
|
|
393
|
+
"Call it explicitly beforehand if you want to remove this warning."
|
|
394
|
+
);
|
|
395
|
+
oj_define_mimic_json(0, NULL, Qnil);
|
|
396
|
+
}
|
|
397
|
+
active_hack[0] = rb_funcall(state_class, oj_new_id, 0);
|
|
398
|
+
oj_dump_obj_to_json_using_params(*argv, copts, &out, 1, active_hack);
|
|
399
|
+
}
|
|
380
400
|
if (0 == out.buf) {
|
|
381
|
-
|
|
401
|
+
rb_raise(rb_eNoMemError, "Not enough memory.");
|
|
382
402
|
}
|
|
383
403
|
rstr = rb_str_new2(out.buf);
|
|
384
404
|
rstr = oj_encode(rstr);
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
405
|
+
|
|
406
|
+
oj_out_free(&out);
|
|
407
|
+
|
|
388
408
|
return rstr;
|
|
389
409
|
}
|
|
390
410
|
|
|
@@ -396,11 +416,11 @@ mimic_generate_core(int argc, VALUE *argv, Options copts) {
|
|
|
396
416
|
|
|
397
417
|
/* Document-method: generate
|
|
398
418
|
* call-seq: generate(obj, opts=nil)
|
|
399
|
-
*
|
|
419
|
+
*
|
|
400
420
|
* Encode obj as a JSON String. The obj argument must be a Hash, Array, or
|
|
401
421
|
* respond to to_h or to_json. Options other than those listed such as
|
|
402
422
|
* +:allow_nan+ or +:max_nesting+ are ignored.
|
|
403
|
-
*
|
|
423
|
+
*
|
|
404
424
|
* - *obj* [_Object_|Hash|Array] object to convert to a JSON String
|
|
405
425
|
* - *opts* [_Hash_] options
|
|
406
426
|
* - - *:indent* [_String_] String to use for indentation.
|
|
@@ -408,13 +428,14 @@ mimic_generate_core(int argc, VALUE *argv, Options copts) {
|
|
|
408
428
|
* - *:space_before* [_String_] String placed before a : delimiter
|
|
409
429
|
* - *:object_nl* [_String_] String placed after a JSON object
|
|
410
430
|
* - *:array_nl* [_String_] String placed after a JSON array
|
|
411
|
-
* - *:ascii_only* [_Boolean_] if not nil or false then use only ascii characters in the output.
|
|
431
|
+
* - *:ascii_only* [_Boolean_] if not nil or false then use only ascii characters in the output.
|
|
432
|
+
* Note JSON.generate does support this even if it is not documented.
|
|
412
433
|
*
|
|
413
434
|
* Returns [_String_] generated JSON.
|
|
414
435
|
*/
|
|
415
436
|
VALUE
|
|
416
437
|
oj_mimic_generate(int argc, VALUE *argv, VALUE self) {
|
|
417
|
-
struct
|
|
438
|
+
struct _options copts = oj_default_options;
|
|
418
439
|
|
|
419
440
|
copts.str_rx.head = NULL;
|
|
420
441
|
copts.str_rx.tail = NULL;
|
|
@@ -432,36 +453,46 @@ oj_mimic_generate(int argc, VALUE *argv, VALUE self) {
|
|
|
432
453
|
*/
|
|
433
454
|
VALUE
|
|
434
455
|
oj_mimic_pretty_generate(int argc, VALUE *argv, VALUE self) {
|
|
435
|
-
struct
|
|
436
|
-
VALUE
|
|
437
|
-
volatile VALUE
|
|
456
|
+
struct _options copts = oj_default_options;
|
|
457
|
+
VALUE rargs[2];
|
|
458
|
+
volatile VALUE h;
|
|
438
459
|
|
|
439
460
|
// Some (all?) json gem to_json methods need a State instance and not just
|
|
440
461
|
// a Hash. I haven't dug deep enough to find out why but using a State
|
|
441
462
|
// instance and not a Hash gives the desired behavior.
|
|
442
463
|
*rargs = *argv;
|
|
443
|
-
if (
|
|
444
|
-
|
|
445
|
-
}
|
|
446
|
-
|
|
464
|
+
if (0 == argc) {
|
|
465
|
+
rb_raise(rb_eArgError, "wrong number of arguments (0))");
|
|
466
|
+
}
|
|
467
|
+
if (1 == argc || Qnil == argv[1]) {
|
|
468
|
+
h = rb_hash_new();
|
|
469
|
+
} else {
|
|
470
|
+
h = argv[1];
|
|
447
471
|
}
|
|
448
|
-
if (
|
|
449
|
-
|
|
472
|
+
if (!oj_hash_has_key(h, oj_indent_sym)) {
|
|
473
|
+
rb_hash_aset(h, oj_indent_sym, rb_str_new2(" "));
|
|
450
474
|
}
|
|
451
|
-
if (
|
|
452
|
-
|
|
475
|
+
if (!oj_hash_has_key(h, oj_space_before_sym)) {
|
|
476
|
+
rb_hash_aset(h, oj_space_before_sym, rb_str_new2(""));
|
|
453
477
|
}
|
|
454
|
-
if (
|
|
455
|
-
|
|
478
|
+
if (!oj_hash_has_key(h, oj_space_sym)) {
|
|
479
|
+
rb_hash_aset(h, oj_space_sym, rb_str_new2(" "));
|
|
456
480
|
}
|
|
457
|
-
if (
|
|
458
|
-
|
|
481
|
+
if (!oj_hash_has_key(h, oj_object_nl_sym)) {
|
|
482
|
+
rb_hash_aset(h, oj_object_nl_sym, rb_str_new2("\n"));
|
|
459
483
|
}
|
|
460
|
-
if (
|
|
461
|
-
|
|
484
|
+
if (!oj_hash_has_key(h, oj_array_nl_sym)) {
|
|
485
|
+
rb_hash_aset(h, oj_array_nl_sym, rb_str_new2("\n"));
|
|
486
|
+
}
|
|
487
|
+
if (Qundef == state_class) {
|
|
488
|
+
rb_warn(
|
|
489
|
+
"Oj::Rails.mimic_JSON was called implicitly. "
|
|
490
|
+
"Call it explicitly beforehand if you want to remove this warning."
|
|
491
|
+
);
|
|
492
|
+
oj_define_mimic_json(0, NULL, Qnil);
|
|
462
493
|
}
|
|
463
494
|
rargs[1] = rb_funcall(state_class, oj_new_id, 1, h);
|
|
464
|
-
|
|
495
|
+
|
|
465
496
|
copts.str_rx.head = NULL;
|
|
466
497
|
copts.str_rx.tail = NULL;
|
|
467
498
|
strcpy(copts.dump_opts.indent_str, " ");
|
|
@@ -474,98 +505,100 @@ oj_mimic_pretty_generate(int argc, VALUE *argv, VALUE self) {
|
|
|
474
505
|
copts.dump_opts.hash_size = (uint8_t)strlen(copts.dump_opts.hash_nl);
|
|
475
506
|
strcpy(copts.dump_opts.array_nl, "\n");
|
|
476
507
|
copts.dump_opts.array_size = (uint8_t)strlen(copts.dump_opts.array_nl);
|
|
477
|
-
copts.dump_opts.use
|
|
508
|
+
copts.dump_opts.use = true;
|
|
478
509
|
|
|
479
510
|
return mimic_generate_core(2, rargs, &copts);
|
|
480
511
|
}
|
|
481
512
|
|
|
482
|
-
static VALUE
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
513
|
+
static int parse_options_cb(VALUE k, VALUE v, VALUE info) {
|
|
514
|
+
struct _parseInfo *pi = (struct _parseInfo *)info;
|
|
515
|
+
|
|
516
|
+
if (oj_symbolize_names_sym == k) {
|
|
517
|
+
pi->options.sym_key = (Qtrue == v) ? Yes : No;
|
|
518
|
+
} else if (oj_quirks_mode_sym == k) {
|
|
519
|
+
pi->options.quirks_mode = (Qtrue == v) ? Yes : No;
|
|
520
|
+
} else if (oj_create_additions_sym == k) {
|
|
521
|
+
pi->options.create_ok = (Qtrue == v) ? Yes : No;
|
|
522
|
+
} else if (oj_allow_nan_sym == k) {
|
|
523
|
+
pi->options.allow_nan = (Qtrue == v) ? Yes : No;
|
|
524
|
+
} else if (oj_hash_class_sym == k) {
|
|
525
|
+
if (Qnil == v) {
|
|
526
|
+
pi->options.hash_class = Qnil;
|
|
527
|
+
} else {
|
|
528
|
+
rb_check_type(v, T_CLASS);
|
|
529
|
+
pi->options.hash_class = v;
|
|
530
|
+
}
|
|
531
|
+
} else if (oj_object_class_sym == k) {
|
|
532
|
+
if (Qnil == v) {
|
|
533
|
+
pi->options.hash_class = Qnil;
|
|
534
|
+
} else {
|
|
535
|
+
rb_check_type(v, T_CLASS);
|
|
536
|
+
pi->options.hash_class = v;
|
|
537
|
+
}
|
|
538
|
+
} else if (oj_array_class_sym == k) {
|
|
539
|
+
if (Qnil == v) {
|
|
540
|
+
pi->options.array_class = Qnil;
|
|
541
|
+
} else {
|
|
542
|
+
rb_check_type(v, T_CLASS);
|
|
543
|
+
pi->options.array_class = v;
|
|
544
|
+
}
|
|
545
|
+
} else if (oj_decimal_class_sym == k) {
|
|
546
|
+
pi->options.compat_bigdec = (oj_bigdecimal_class == v);
|
|
547
|
+
}
|
|
548
|
+
return ST_CONTINUE;
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
static VALUE mimic_parse_core(int argc, VALUE *argv, VALUE self, bool bang) {
|
|
552
|
+
struct _parseInfo pi;
|
|
553
|
+
VALUE ropts;
|
|
554
|
+
VALUE args[1];
|
|
487
555
|
|
|
488
556
|
rb_scan_args(argc, argv, "11", NULL, &ropts);
|
|
489
557
|
parse_info_init(&pi);
|
|
490
558
|
oj_set_compat_callbacks(&pi);
|
|
491
559
|
|
|
492
560
|
pi.err_class = oj_json_parser_error_class;
|
|
493
|
-
//pi.err_class = Qnil;
|
|
494
|
-
|
|
495
|
-
pi.options
|
|
496
|
-
pi.options.auto_define
|
|
497
|
-
pi.options.quirks_mode
|
|
498
|
-
pi.options.allow_invalid =
|
|
499
|
-
pi.options.empty_string
|
|
500
|
-
pi.options.create_ok
|
|
501
|
-
pi.options.allow_nan
|
|
502
|
-
pi.options.nilnil
|
|
503
|
-
pi.options.bigdec_load
|
|
504
|
-
pi.options.mode
|
|
505
|
-
pi.max_depth
|
|
561
|
+
// pi.err_class = Qnil;
|
|
562
|
+
|
|
563
|
+
pi.options = oj_default_options;
|
|
564
|
+
pi.options.auto_define = No;
|
|
565
|
+
pi.options.quirks_mode = Yes;
|
|
566
|
+
pi.options.allow_invalid = Yes;
|
|
567
|
+
pi.options.empty_string = No;
|
|
568
|
+
pi.options.create_ok = No;
|
|
569
|
+
pi.options.allow_nan = (bang ? Yes : No);
|
|
570
|
+
pi.options.nilnil = No;
|
|
571
|
+
pi.options.bigdec_load = RubyDec;
|
|
572
|
+
pi.options.mode = CompatMode;
|
|
573
|
+
pi.max_depth = 100;
|
|
506
574
|
|
|
507
575
|
if (Qnil != ropts) {
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
if (Qnil == (v = rb_hash_lookup(ropts, oj_hash_class_sym))) {
|
|
528
|
-
pi.options.hash_class = Qnil;
|
|
529
|
-
} else {
|
|
530
|
-
rb_check_type(v, T_CLASS);
|
|
531
|
-
pi.options.hash_class = v;
|
|
532
|
-
}
|
|
533
|
-
}
|
|
534
|
-
if (Qtrue == rb_funcall(ropts, oj_has_key_id, 1, oj_object_class_sym)) {
|
|
535
|
-
if (Qnil == (v = rb_hash_lookup(ropts, oj_object_class_sym))) {
|
|
536
|
-
pi.options.hash_class = Qnil;
|
|
537
|
-
} else {
|
|
538
|
-
rb_check_type(v, T_CLASS);
|
|
539
|
-
pi.options.hash_class = v;
|
|
540
|
-
}
|
|
541
|
-
}
|
|
542
|
-
if (Qtrue == rb_funcall(ropts, oj_has_key_id, 1, oj_array_class_sym)) {
|
|
543
|
-
if (Qnil == (v = rb_hash_lookup(ropts, oj_array_class_sym))) {
|
|
544
|
-
pi.options.array_class = Qnil;
|
|
545
|
-
} else {
|
|
546
|
-
rb_check_type(v, T_CLASS);
|
|
547
|
-
pi.options.array_class = v;
|
|
548
|
-
}
|
|
549
|
-
}
|
|
550
|
-
v = rb_hash_lookup(ropts, oj_max_nesting_sym);
|
|
551
|
-
if (Qtrue == v) {
|
|
552
|
-
pi.max_depth = 100;
|
|
553
|
-
} else if (Qfalse == v || Qnil == v) {
|
|
554
|
-
pi.max_depth = 0;
|
|
555
|
-
} else if (T_FIXNUM == rb_type(v)) {
|
|
556
|
-
pi.max_depth = NUM2INT(v);
|
|
557
|
-
}
|
|
558
|
-
oj_parse_opt_match_string(&pi.options.str_rx, ropts);
|
|
559
|
-
if (Yes == pi.options.create_ok && Yes == pi.options.sym_key) {
|
|
560
|
-
rb_raise(rb_eArgError, ":symbolize_names and :create_additions can not both be true.");
|
|
561
|
-
}
|
|
576
|
+
VALUE v;
|
|
577
|
+
|
|
578
|
+
if (T_HASH != rb_type(ropts)) {
|
|
579
|
+
rb_raise(rb_eArgError, "options must be a hash.");
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
rb_hash_foreach(ropts, parse_options_cb, (VALUE)&pi);
|
|
583
|
+
v = rb_hash_lookup(ropts, oj_max_nesting_sym);
|
|
584
|
+
if (Qtrue == v) {
|
|
585
|
+
pi.max_depth = 100;
|
|
586
|
+
} else if (Qfalse == v || Qnil == v) {
|
|
587
|
+
pi.max_depth = 0;
|
|
588
|
+
} else if (T_FIXNUM == rb_type(v)) {
|
|
589
|
+
pi.max_depth = NUM2INT(v);
|
|
590
|
+
}
|
|
591
|
+
oj_parse_opt_match_string(&pi.options.str_rx, ropts);
|
|
592
|
+
if (Yes == pi.options.create_ok && Yes == pi.options.sym_key) {
|
|
593
|
+
rb_raise(rb_eArgError, ":symbolize_names and :create_additions can not both be true.");
|
|
594
|
+
}
|
|
562
595
|
}
|
|
563
596
|
*args = *argv;
|
|
564
597
|
|
|
565
598
|
if (T_STRING == rb_type(*args)) {
|
|
566
|
-
|
|
599
|
+
return oj_pi_parse(1, args, &pi, 0, 0, false);
|
|
567
600
|
} else {
|
|
568
|
-
|
|
601
|
+
return oj_pi_sparse(1, args, &pi, 0);
|
|
569
602
|
}
|
|
570
603
|
}
|
|
571
604
|
|
|
@@ -578,8 +611,10 @@ mimic_parse_core(int argc, VALUE *argv, VALUE self, bool bang) {
|
|
|
578
611
|
*
|
|
579
612
|
* - *source* [_String_|IO] source to parse
|
|
580
613
|
* - *opts* [_Hash_] options
|
|
581
|
-
* - *:symbolize* [Boolean] _names flag indicating JSON object keys should be Symbols instead of
|
|
582
|
-
*
|
|
614
|
+
* - *:symbolize* [Boolean] _names flag indicating JSON object keys should be Symbols instead of
|
|
615
|
+
* Strings
|
|
616
|
+
* - *:create_additions* [Boolean] flag indicating a key matching +create_id+ in a JSON object
|
|
617
|
+
* should trigger the creation of Ruby Object
|
|
583
618
|
*
|
|
584
619
|
* Returns [Object]
|
|
585
620
|
* @see create_id=
|
|
@@ -595,21 +630,19 @@ oj_mimic_parse(int argc, VALUE *argv, VALUE self) {
|
|
|
595
630
|
* Same as parse().
|
|
596
631
|
* @see parse
|
|
597
632
|
*/
|
|
598
|
-
static VALUE
|
|
599
|
-
mimic_parse_bang(int argc, VALUE *argv, VALUE self) {
|
|
633
|
+
static VALUE mimic_parse_bang(int argc, VALUE *argv, VALUE self) {
|
|
600
634
|
return mimic_parse_core(argc, argv, self, true);
|
|
601
635
|
}
|
|
602
636
|
|
|
603
637
|
/* Document-method: recurse_proc
|
|
604
638
|
* call-seq: recurse_proc(obj, &proc)
|
|
605
|
-
*
|
|
639
|
+
*
|
|
606
640
|
* Yields to the proc for every element in the obj recursively.
|
|
607
|
-
*
|
|
641
|
+
*
|
|
608
642
|
* - *obj* [_Hash_|Array] object to walk
|
|
609
643
|
* - *proc* [_Proc_] to yield to on each element
|
|
610
644
|
*/
|
|
611
|
-
static VALUE
|
|
612
|
-
mimic_recurse_proc(VALUE self, VALUE obj) {
|
|
645
|
+
static VALUE mimic_recurse_proc(VALUE self, VALUE obj) {
|
|
613
646
|
rb_need_block();
|
|
614
647
|
mimic_walk(Qnil, obj, Qnil);
|
|
615
648
|
|
|
@@ -626,23 +659,22 @@ mimic_recurse_proc(VALUE self, VALUE obj) {
|
|
|
626
659
|
*
|
|
627
660
|
* Returns [_String_] the id.
|
|
628
661
|
*/
|
|
629
|
-
static VALUE
|
|
630
|
-
mimic_set_create_id(VALUE self, VALUE id) {
|
|
662
|
+
static VALUE mimic_set_create_id(VALUE self, VALUE id) {
|
|
631
663
|
Check_Type(id, T_STRING);
|
|
632
664
|
|
|
633
665
|
if (NULL != oj_default_options.create_id) {
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
666
|
+
if (oj_json_class != oj_default_options.create_id) {
|
|
667
|
+
xfree((char *)oj_default_options.create_id);
|
|
668
|
+
}
|
|
669
|
+
oj_default_options.create_id = NULL;
|
|
670
|
+
oj_default_options.create_id_len = 0;
|
|
639
671
|
}
|
|
640
672
|
if (Qnil != id) {
|
|
641
|
-
|
|
673
|
+
size_t len = RSTRING_LEN(id) + 1;
|
|
642
674
|
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
675
|
+
oj_default_options.create_id = ALLOC_N(char, len);
|
|
676
|
+
strcpy((char *)oj_default_options.create_id, StringValuePtr(id));
|
|
677
|
+
oj_default_options.create_id_len = len - 1;
|
|
646
678
|
}
|
|
647
679
|
return id;
|
|
648
680
|
}
|
|
@@ -652,98 +684,102 @@ mimic_set_create_id(VALUE self, VALUE id) {
|
|
|
652
684
|
*
|
|
653
685
|
* Returns [_String_] the create_id.
|
|
654
686
|
*/
|
|
655
|
-
static VALUE
|
|
656
|
-
mimic_create_id(VALUE self) {
|
|
687
|
+
static VALUE mimic_create_id(VALUE self) {
|
|
657
688
|
if (NULL != oj_default_options.create_id) {
|
|
658
|
-
|
|
689
|
+
return rb_utf8_str_new(oj_default_options.create_id, oj_default_options.create_id_len);
|
|
659
690
|
}
|
|
660
691
|
return rb_str_new_cstr(oj_json_class);
|
|
661
692
|
}
|
|
662
693
|
|
|
663
|
-
static struct
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
694
|
+
static struct _options mimic_object_to_json_options = {0, // indent
|
|
695
|
+
No, // circular
|
|
696
|
+
No, // auto_define
|
|
697
|
+
No, // sym_key
|
|
698
|
+
JXEsc, // escape_mode
|
|
699
|
+
CompatMode, // mode
|
|
700
|
+
No, // class_cache
|
|
701
|
+
RubyTime, // time_format
|
|
702
|
+
No, // bigdec_as_num
|
|
703
|
+
RubyDec, // bigdec_load
|
|
704
|
+
false, // compat_bigdec
|
|
705
|
+
No, // to_hash
|
|
706
|
+
No, // to_json
|
|
707
|
+
No, // as_json
|
|
708
|
+
No, // raw_json
|
|
709
|
+
No, // nilnil
|
|
710
|
+
No, // empty_string
|
|
711
|
+
Yes, // allow_gc
|
|
712
|
+
Yes, // quirks_mode
|
|
713
|
+
Yes, // allow_invalid
|
|
714
|
+
No, // create_ok
|
|
715
|
+
No, // allow_nan
|
|
716
|
+
No, // trace
|
|
717
|
+
No, // safe
|
|
718
|
+
false, // sec_prec_set
|
|
719
|
+
No, // ignore_under
|
|
720
|
+
Yes, // cache_keys
|
|
721
|
+
0, // cache_str
|
|
722
|
+
0, // int_range_min
|
|
723
|
+
0, // int_range_max
|
|
724
|
+
oj_json_class, // create_id
|
|
725
|
+
10, // create_id_len
|
|
726
|
+
3, // sec_prec
|
|
727
|
+
0, // float_prec
|
|
728
|
+
"%0.16g", // float_fmt
|
|
729
|
+
Qnil, // hash_class
|
|
730
|
+
Qnil, // array_class
|
|
731
|
+
{
|
|
732
|
+
// dump_opts
|
|
733
|
+
false, // use
|
|
734
|
+
"", // indent
|
|
735
|
+
"", // before_sep
|
|
736
|
+
"", // after_sep
|
|
737
|
+
"", // hash_nl
|
|
738
|
+
"", // array_nl
|
|
739
|
+
0, // indent_size
|
|
740
|
+
0, // before_size
|
|
741
|
+
0, // after_size
|
|
742
|
+
0, // hash_size
|
|
743
|
+
0, // array_size
|
|
744
|
+
RaiseNan, // nan_dump
|
|
745
|
+
false, // omit_nil
|
|
746
|
+
100, // max_depth
|
|
747
|
+
},
|
|
748
|
+
{
|
|
749
|
+
// str_rx
|
|
750
|
+
NULL, // head
|
|
751
|
+
NULL, // tail
|
|
752
|
+
{'\0'}, // err
|
|
753
|
+
}};
|
|
754
|
+
|
|
755
|
+
static VALUE mimic_object_to_json(int argc, VALUE *argv, VALUE self) {
|
|
756
|
+
struct _out out;
|
|
757
|
+
VALUE rstr;
|
|
758
|
+
struct _options copts = oj_default_options;
|
|
723
759
|
|
|
724
760
|
copts.str_rx.head = NULL;
|
|
725
761
|
copts.str_rx.tail = NULL;
|
|
726
|
-
|
|
727
|
-
out
|
|
728
|
-
|
|
729
|
-
out.omit_nil
|
|
730
|
-
copts.mode
|
|
731
|
-
copts.to_json
|
|
762
|
+
|
|
763
|
+
oj_out_init(&out);
|
|
764
|
+
|
|
765
|
+
out.omit_nil = copts.dump_opts.omit_nil;
|
|
766
|
+
copts.mode = CompatMode;
|
|
767
|
+
copts.to_json = No;
|
|
732
768
|
if (1 <= argc && Qnil != argv[0]) {
|
|
733
|
-
|
|
769
|
+
oj_parse_mimic_dump_options(argv[0], &copts);
|
|
734
770
|
}
|
|
735
771
|
// To be strict the mimic_object_to_json_options should be used but people
|
|
736
772
|
// seem to prefer the option of changing that.
|
|
737
|
-
//oj_dump_obj_to_json(self, &mimic_object_to_json_options, &out);
|
|
773
|
+
// oj_dump_obj_to_json(self, &mimic_object_to_json_options, &out);
|
|
738
774
|
oj_dump_obj_to_json_using_params(self, &copts, &out, argc, argv);
|
|
739
|
-
if (
|
|
740
|
-
|
|
775
|
+
if (NULL == out.buf) {
|
|
776
|
+
rb_raise(rb_eNoMemError, "Not enough memory.");
|
|
741
777
|
}
|
|
742
778
|
rstr = rb_str_new2(out.buf);
|
|
743
779
|
rstr = oj_encode(rstr);
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
780
|
+
|
|
781
|
+
oj_out_free(&out);
|
|
782
|
+
|
|
747
783
|
return rstr;
|
|
748
784
|
}
|
|
749
785
|
|
|
@@ -752,16 +788,14 @@ mimic_object_to_json(int argc, VALUE *argv, VALUE self) {
|
|
|
752
788
|
*
|
|
753
789
|
* Returns [_JSON::State_] the JSON::State class.
|
|
754
790
|
*/
|
|
755
|
-
static VALUE
|
|
756
|
-
mimic_state(VALUE self) {
|
|
791
|
+
static VALUE mimic_state(VALUE self) {
|
|
757
792
|
return state_class;
|
|
758
793
|
}
|
|
759
794
|
|
|
760
|
-
void
|
|
761
|
-
|
|
762
|
-
VALUE
|
|
763
|
-
VALUE
|
|
764
|
-
VALUE ext;
|
|
795
|
+
void oj_mimic_json_methods(VALUE json) {
|
|
796
|
+
VALUE json_error;
|
|
797
|
+
VALUE generator;
|
|
798
|
+
VALUE ext;
|
|
765
799
|
|
|
766
800
|
rb_define_module_function(json, "create_id=", mimic_set_create_id, 1);
|
|
767
801
|
rb_define_module_function(json, "create_id", mimic_create_id, 0);
|
|
@@ -793,36 +827,35 @@ oj_mimic_json_methods(VALUE json) {
|
|
|
793
827
|
if (rb_const_defined_at(json, rb_intern("ParserError"))) {
|
|
794
828
|
oj_json_parser_error_class = rb_const_get(json, rb_intern("ParserError"));
|
|
795
829
|
} else {
|
|
796
|
-
|
|
830
|
+
oj_json_parser_error_class = rb_define_class_under(json, "ParserError", json_error);
|
|
797
831
|
}
|
|
798
832
|
if (rb_const_defined_at(json, rb_intern("GeneratorError"))) {
|
|
799
833
|
oj_json_generator_error_class = rb_const_get(json, rb_intern("GeneratorError"));
|
|
800
834
|
} else {
|
|
801
|
-
|
|
835
|
+
oj_json_generator_error_class = rb_define_class_under(json, "GeneratorError", json_error);
|
|
802
836
|
}
|
|
803
837
|
if (rb_const_defined_at(json, rb_intern("NestingError"))) {
|
|
804
838
|
rb_const_get(json, rb_intern("NestingError"));
|
|
805
839
|
} else {
|
|
806
|
-
|
|
840
|
+
rb_define_class_under(json, "NestingError", json_error);
|
|
807
841
|
}
|
|
808
842
|
|
|
809
843
|
if (rb_const_defined_at(json, rb_intern("Ext"))) {
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
844
|
+
ext = rb_const_get_at(json, rb_intern("Ext"));
|
|
845
|
+
} else {
|
|
846
|
+
ext = rb_define_module_under(json, "Ext");
|
|
813
847
|
}
|
|
814
848
|
if (rb_const_defined_at(ext, rb_intern("Generator"))) {
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
849
|
+
generator = rb_const_get_at(ext, rb_intern("Generator"));
|
|
850
|
+
} else {
|
|
851
|
+
generator = rb_define_module_under(ext, "Generator");
|
|
818
852
|
}
|
|
819
853
|
if (!rb_const_defined_at(generator, rb_intern("State"))) {
|
|
820
|
-
|
|
854
|
+
rb_require("oj/state");
|
|
821
855
|
}
|
|
822
856
|
// Pull in the JSON::State mimic file.
|
|
823
857
|
state_class = rb_const_get_at(generator, rb_intern("State"));
|
|
824
|
-
|
|
825
|
-
symbolize_names_sym = ID2SYM(rb_intern("symbolize_names")); rb_gc_register_address(&symbolize_names_sym);
|
|
858
|
+
rb_gc_register_mark_object(state_class);
|
|
826
859
|
}
|
|
827
860
|
|
|
828
861
|
/* Document-module: JSON
|
|
@@ -831,31 +864,31 @@ oj_mimic_json_methods(VALUE json) {
|
|
|
831
864
|
*/
|
|
832
865
|
VALUE
|
|
833
866
|
oj_define_mimic_json(int argc, VALUE *argv, VALUE self) {
|
|
834
|
-
VALUE
|
|
835
|
-
VALUE
|
|
836
|
-
VALUE
|
|
837
|
-
|
|
867
|
+
VALUE dummy;
|
|
868
|
+
VALUE verbose;
|
|
869
|
+
VALUE json;
|
|
870
|
+
|
|
838
871
|
// Either set the paths to indicate JSON has been loaded or replaces the
|
|
839
872
|
// methods if it has been loaded.
|
|
840
873
|
if (rb_const_defined_at(rb_cObject, rb_intern("JSON"))) {
|
|
841
|
-
|
|
874
|
+
json = rb_const_get_at(rb_cObject, rb_intern("JSON"));
|
|
842
875
|
} else {
|
|
843
|
-
|
|
876
|
+
json = rb_define_module("JSON");
|
|
844
877
|
}
|
|
845
878
|
verbose = rb_gv_get("$VERBOSE");
|
|
846
879
|
rb_gv_set("$VERBOSE", Qfalse);
|
|
847
880
|
rb_define_module_function(rb_cObject, "JSON", mimic_dump_load, -1);
|
|
848
881
|
dummy = rb_gv_get("$LOADED_FEATURES");
|
|
849
882
|
if (rb_type(dummy) == T_ARRAY) {
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
883
|
+
rb_ary_push(dummy, rb_str_new2("json"));
|
|
884
|
+
if (0 < argc) {
|
|
885
|
+
VALUE mimic_args[1];
|
|
853
886
|
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
887
|
+
*mimic_args = *argv;
|
|
888
|
+
rb_funcall2(Oj, rb_intern("mimic_loaded"), 1, mimic_args);
|
|
889
|
+
} else {
|
|
890
|
+
rb_funcall2(Oj, rb_intern("mimic_loaded"), 0, 0);
|
|
891
|
+
}
|
|
859
892
|
}
|
|
860
893
|
oj_mimic_json_methods(json);
|
|
861
894
|
|
|
@@ -863,7 +896,7 @@ oj_define_mimic_json(int argc, VALUE *argv, VALUE self) {
|
|
|
863
896
|
|
|
864
897
|
rb_gv_set("$VERBOSE", verbose);
|
|
865
898
|
|
|
866
|
-
oj_default_options
|
|
899
|
+
oj_default_options = mimic_object_to_json_options;
|
|
867
900
|
oj_default_options.to_json = Yes;
|
|
868
901
|
|
|
869
902
|
return json;
|