oj 2.0.0 → 3.0.0
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 +7 -0
- data/LICENSE +17 -23
- data/README.md +74 -425
- data/ext/oj/buf.h +103 -0
- data/ext/oj/cache8.c +4 -0
- data/ext/oj/circarray.c +68 -0
- data/ext/oj/circarray.h +23 -0
- data/ext/oj/code.c +227 -0
- data/ext/oj/code.h +40 -0
- data/ext/oj/compat.c +243 -0
- data/ext/oj/custom.c +1097 -0
- data/ext/oj/dump.c +766 -1534
- data/ext/oj/dump.h +92 -0
- data/ext/oj/dump_compat.c +937 -0
- data/ext/oj/dump_leaf.c +254 -0
- data/ext/oj/dump_object.c +810 -0
- data/ext/oj/dump_rails.c +329 -0
- data/ext/oj/dump_strict.c +416 -0
- data/ext/oj/encode.h +51 -0
- data/ext/oj/err.c +57 -0
- data/ext/oj/err.h +70 -0
- data/ext/oj/extconf.rb +17 -7
- data/ext/oj/fast.c +213 -180
- data/ext/oj/hash.c +163 -0
- data/ext/oj/hash.h +46 -0
- data/ext/oj/hash_test.c +512 -0
- data/ext/oj/mimic_json.c +817 -0
- data/ext/oj/mimic_rails.c +806 -0
- data/ext/oj/mimic_rails.h +17 -0
- data/ext/oj/object.c +752 -0
- data/ext/oj/odd.c +230 -0
- data/ext/oj/odd.h +44 -0
- data/ext/oj/oj.c +1288 -929
- data/ext/oj/oj.h +240 -69
- data/ext/oj/parse.c +1014 -0
- data/ext/oj/parse.h +92 -0
- data/ext/oj/reader.c +223 -0
- data/ext/oj/reader.h +151 -0
- data/ext/oj/resolve.c +127 -0
- data/ext/oj/{cache.h → resolve.h} +6 -13
- data/ext/oj/rxclass.c +133 -0
- data/ext/oj/rxclass.h +27 -0
- data/ext/oj/saj.c +77 -175
- data/ext/oj/scp.c +224 -0
- data/ext/oj/sparse.c +911 -0
- data/ext/oj/stream_writer.c +301 -0
- data/ext/oj/strict.c +162 -0
- data/ext/oj/string_writer.c +480 -0
- data/ext/oj/val_stack.c +98 -0
- data/ext/oj/val_stack.h +188 -0
- data/lib/oj/active_support_helper.rb +41 -0
- data/lib/oj/bag.rb +6 -10
- data/lib/oj/easy_hash.rb +52 -0
- data/lib/oj/json.rb +172 -0
- data/lib/oj/mimic.rb +260 -5
- data/lib/oj/saj.rb +13 -10
- data/lib/oj/schandler.rb +142 -0
- data/lib/oj/state.rb +131 -0
- data/lib/oj/version.rb +1 -1
- data/lib/oj.rb +11 -23
- data/pages/Advanced.md +22 -0
- data/pages/Compatibility.md +25 -0
- data/pages/Custom.md +23 -0
- data/pages/Encoding.md +65 -0
- data/pages/JsonGem.md +79 -0
- data/pages/Modes.md +140 -0
- data/pages/Options.md +250 -0
- data/pages/Rails.md +60 -0
- data/pages/Security.md +20 -0
- data/test/_test_active.rb +76 -0
- data/test/_test_active_mimic.rb +96 -0
- data/test/_test_mimic_rails.rb +126 -0
- data/test/activesupport4/decoding_test.rb +105 -0
- data/test/activesupport4/encoding_test.rb +531 -0
- data/test/activesupport4/test_helper.rb +41 -0
- data/test/activesupport5/decoding_test.rb +125 -0
- data/test/activesupport5/encoding_test.rb +483 -0
- data/test/activesupport5/encoding_test_cases.rb +90 -0
- data/test/activesupport5/test_helper.rb +50 -0
- data/test/activesupport5/time_zone_test_helpers.rb +24 -0
- data/test/helper.rb +27 -0
- data/test/isolated/shared.rb +310 -0
- data/test/isolated/test_mimic_after.rb +13 -0
- data/test/isolated/test_mimic_alone.rb +12 -0
- data/test/isolated/test_mimic_as_json.rb +45 -0
- data/test/isolated/test_mimic_before.rb +13 -0
- data/test/isolated/test_mimic_define.rb +28 -0
- data/test/isolated/test_mimic_rails_after.rb +22 -0
- data/test/isolated/test_mimic_rails_before.rb +21 -0
- data/test/isolated/test_mimic_redefine.rb +15 -0
- data/test/json_gem/json_addition_test.rb +216 -0
- data/test/json_gem/json_common_interface_test.rb +143 -0
- data/test/json_gem/json_encoding_test.rb +109 -0
- data/test/json_gem/json_ext_parser_test.rb +20 -0
- data/test/json_gem/json_fixtures_test.rb +35 -0
- data/test/json_gem/json_generator_test.rb +383 -0
- data/test/json_gem/json_generic_object_test.rb +90 -0
- data/test/json_gem/json_parser_test.rb +470 -0
- data/test/json_gem/json_string_matching_test.rb +42 -0
- data/test/json_gem/test_helper.rb +18 -0
- data/test/perf_compat.rb +130 -0
- data/test/perf_fast.rb +9 -9
- data/test/perf_file.rb +64 -0
- data/test/{perf_obj.rb → perf_object.rb} +24 -10
- data/test/perf_scp.rb +151 -0
- data/test/perf_strict.rb +32 -113
- data/test/sample.rb +2 -3
- data/test/test_compat.rb +474 -0
- data/test/test_custom.rb +355 -0
- data/test/test_debian.rb +53 -0
- data/test/test_fast.rb +66 -16
- data/test/test_file.rb +237 -0
- data/test/test_gc.rb +49 -0
- data/test/test_hash.rb +29 -0
- data/test/test_null.rb +376 -0
- data/test/test_object.rb +1010 -0
- data/test/test_saj.rb +16 -16
- data/test/test_scp.rb +417 -0
- data/test/test_strict.rb +410 -0
- data/test/test_various.rb +815 -0
- data/test/test_writer.rb +308 -0
- data/test/tests.rb +9 -902
- data/test/tests_mimic.rb +14 -0
- data/test/tests_mimic_addition.rb +7 -0
- metadata +253 -38
- data/ext/oj/cache.c +0 -148
- data/ext/oj/foo.rb +0 -6
- data/ext/oj/load.c +0 -1049
- data/test/a.rb +0 -38
- data/test/perf1.rb +0 -64
- data/test/perf2.rb +0 -76
- data/test/perf_obj_old.rb +0 -213
- data/test/test_mimic.rb +0 -208
data/ext/oj/oj.c
CHANGED
|
@@ -1,32 +1,6 @@
|
|
|
1
1
|
/* oj.c
|
|
2
2
|
* Copyright (c) 2012, Peter Ohler
|
|
3
|
-
*
|
|
4
3
|
* All rights reserved.
|
|
5
|
-
*
|
|
6
|
-
* Redistribution and use in source and binary forms, with or without
|
|
7
|
-
* modification, are permitted provided that the following conditions are met:
|
|
8
|
-
*
|
|
9
|
-
* - Redistributions of source code must retain the above copyright notice, this
|
|
10
|
-
* list of conditions and the following disclaimer.
|
|
11
|
-
*
|
|
12
|
-
* - Redistributions in binary form must reproduce the above copyright notice,
|
|
13
|
-
* this list of conditions and the following disclaimer in the documentation
|
|
14
|
-
* and/or other materials provided with the distribution.
|
|
15
|
-
*
|
|
16
|
-
* - Neither the name of Peter Ohler nor the names of its contributors may be
|
|
17
|
-
* used to endorse or promote products derived from this software without
|
|
18
|
-
* specific prior written permission.
|
|
19
|
-
*
|
|
20
|
-
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
21
|
-
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
22
|
-
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
23
|
-
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
24
|
-
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
25
|
-
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
26
|
-
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
27
|
-
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
28
|
-
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
29
|
-
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
30
4
|
*/
|
|
31
5
|
|
|
32
6
|
#include <stdlib.h>
|
|
@@ -35,8 +9,19 @@
|
|
|
35
9
|
#include <string.h>
|
|
36
10
|
#include <sys/types.h>
|
|
37
11
|
#include <unistd.h>
|
|
12
|
+
#include <fcntl.h>
|
|
38
13
|
|
|
39
14
|
#include "oj.h"
|
|
15
|
+
#include "parse.h"
|
|
16
|
+
#include "hash.h"
|
|
17
|
+
#include "odd.h"
|
|
18
|
+
#include "dump.h"
|
|
19
|
+
#include "mimic_rails.h"
|
|
20
|
+
#include "encode.h"
|
|
21
|
+
|
|
22
|
+
#if !HAS_ENCODING_SUPPORT || defined(RUBINIUS_RUBY)
|
|
23
|
+
#define rb_eEncodingError rb_eException
|
|
24
|
+
#endif
|
|
40
25
|
|
|
41
26
|
typedef struct _YesNoOpt {
|
|
42
27
|
VALUE sym;
|
|
@@ -48,18 +33,35 @@ void Init_oj();
|
|
|
48
33
|
VALUE Oj = Qnil;
|
|
49
34
|
|
|
50
35
|
ID oj_add_value_id;
|
|
36
|
+
ID oj_array_append_id;
|
|
51
37
|
ID oj_array_end_id;
|
|
52
38
|
ID oj_array_start_id;
|
|
53
39
|
ID oj_as_json_id;
|
|
40
|
+
ID oj_begin_id;
|
|
41
|
+
ID oj_end_id;
|
|
42
|
+
ID oj_exclude_end_id;
|
|
54
43
|
ID oj_error_id;
|
|
44
|
+
ID oj_file_id;
|
|
55
45
|
ID oj_fileno_id;
|
|
46
|
+
ID oj_ftype_id;
|
|
47
|
+
ID oj_has_key_id;
|
|
56
48
|
ID oj_hash_end_id;
|
|
49
|
+
ID oj_hash_key_id;
|
|
50
|
+
ID oj_hash_set_id;
|
|
57
51
|
ID oj_hash_start_id;
|
|
52
|
+
ID oj_iconv_id;
|
|
58
53
|
ID oj_instance_variables_id;
|
|
59
54
|
ID oj_json_create_id;
|
|
55
|
+
ID oj_length_id;
|
|
60
56
|
ID oj_new_id;
|
|
57
|
+
ID oj_parse_id;
|
|
58
|
+
ID oj_pos_id;
|
|
61
59
|
ID oj_read_id;
|
|
60
|
+
ID oj_readpartial_id;
|
|
61
|
+
ID oj_replace_id;
|
|
62
|
+
ID oj_stat_id;
|
|
62
63
|
ID oj_string_id;
|
|
64
|
+
ID oj_to_h_id;
|
|
63
65
|
ID oj_to_hash_id;
|
|
64
66
|
ID oj_to_json_id;
|
|
65
67
|
ID oj_to_s_id;
|
|
@@ -68,480 +70,978 @@ ID oj_to_time_id;
|
|
|
68
70
|
ID oj_tv_nsec_id;
|
|
69
71
|
ID oj_tv_sec_id;
|
|
70
72
|
ID oj_tv_usec_id;
|
|
73
|
+
ID oj_utc_id;
|
|
71
74
|
ID oj_utc_offset_id;
|
|
75
|
+
ID oj_utcq_id;
|
|
72
76
|
ID oj_write_id;
|
|
73
77
|
|
|
78
|
+
|
|
74
79
|
VALUE oj_bag_class;
|
|
75
|
-
VALUE oj_parse_error_class;
|
|
76
80
|
VALUE oj_bigdecimal_class;
|
|
81
|
+
VALUE oj_cstack_class;
|
|
82
|
+
VALUE oj_date_class;
|
|
83
|
+
VALUE oj_datetime_class;
|
|
84
|
+
VALUE oj_enumerable_class;
|
|
85
|
+
VALUE oj_parse_error_class;
|
|
86
|
+
VALUE oj_stream_writer_class;
|
|
87
|
+
VALUE oj_string_writer_class;
|
|
77
88
|
VALUE oj_stringio_class;
|
|
78
89
|
VALUE oj_struct_class;
|
|
79
|
-
VALUE oj_time_class;
|
|
80
90
|
|
|
81
91
|
VALUE oj_slash_string;
|
|
82
92
|
|
|
83
|
-
|
|
93
|
+
VALUE oj_allow_nan_sym;
|
|
94
|
+
VALUE oj_array_class_sym;
|
|
95
|
+
VALUE oj_create_additions_sym;
|
|
96
|
+
VALUE oj_hash_class_sym;
|
|
97
|
+
VALUE oj_indent_sym;
|
|
98
|
+
VALUE oj_object_class_sym;
|
|
99
|
+
VALUE oj_quirks_mode_sym;
|
|
100
|
+
|
|
101
|
+
static VALUE allow_blank_sym;
|
|
102
|
+
static VALUE allow_gc_sym;
|
|
103
|
+
static VALUE allow_invalid_unicode_sym;
|
|
104
|
+
static VALUE ascii_sym;
|
|
84
105
|
static VALUE auto_define_sym;
|
|
106
|
+
static VALUE auto_sym;
|
|
107
|
+
static VALUE bigdecimal_as_decimal_sym;
|
|
108
|
+
static VALUE bigdecimal_load_sym;
|
|
109
|
+
static VALUE bigdecimal_sym;
|
|
85
110
|
static VALUE circular_sym;
|
|
111
|
+
static VALUE class_cache_sym;
|
|
86
112
|
static VALUE compat_sym;
|
|
87
113
|
static VALUE create_id_sym;
|
|
88
|
-
static VALUE
|
|
89
|
-
static VALUE
|
|
114
|
+
static VALUE custom_sym;
|
|
115
|
+
static VALUE empty_string_sym;
|
|
116
|
+
static VALUE escape_mode_sym;
|
|
117
|
+
static VALUE float_prec_sym;
|
|
118
|
+
static VALUE float_sym;
|
|
119
|
+
static VALUE huge_sym;
|
|
120
|
+
static VALUE json_sym;
|
|
121
|
+
static VALUE match_string_sym;
|
|
90
122
|
static VALUE mode_sym;
|
|
123
|
+
static VALUE nan_sym;
|
|
124
|
+
static VALUE newline_sym;
|
|
125
|
+
static VALUE nilnil_sym;
|
|
91
126
|
static VALUE null_sym;
|
|
92
127
|
static VALUE object_sym;
|
|
128
|
+
static VALUE omit_nil_sym;
|
|
129
|
+
static VALUE rails_sym;
|
|
130
|
+
static VALUE raise_sym;
|
|
93
131
|
static VALUE ruby_sym;
|
|
132
|
+
static VALUE sec_prec_sym;
|
|
94
133
|
static VALUE strict_sym;
|
|
95
134
|
static VALUE symbol_keys_sym;
|
|
96
135
|
static VALUE time_format_sym;
|
|
136
|
+
static VALUE unicode_xss_sym;
|
|
97
137
|
static VALUE unix_sym;
|
|
138
|
+
static VALUE unix_zone_sym;
|
|
139
|
+
static VALUE use_as_json_sym;
|
|
140
|
+
static VALUE use_to_hash_sym;
|
|
141
|
+
static VALUE use_to_json_sym;
|
|
142
|
+
static VALUE word_sym;
|
|
98
143
|
static VALUE xmlschema_sym;
|
|
99
|
-
|
|
100
|
-
static VALUE array_nl_sym;
|
|
101
|
-
static VALUE create_additions_sym;
|
|
102
|
-
static VALUE object_nl_sym;
|
|
103
|
-
static VALUE space_before_sym;
|
|
104
|
-
static VALUE space_sym;
|
|
105
|
-
static VALUE symbolize_names_sym;
|
|
106
|
-
|
|
107
|
-
static VALUE mimic = Qnil;
|
|
108
|
-
|
|
109
|
-
Cache oj_class_cache = 0;
|
|
110
|
-
Cache oj_attr_cache = 0;
|
|
144
|
+
static VALUE xss_safe_sym;
|
|
111
145
|
|
|
112
146
|
#if HAS_ENCODING_SUPPORT
|
|
113
147
|
rb_encoding *oj_utf8_encoding = 0;
|
|
148
|
+
#else
|
|
149
|
+
VALUE oj_utf8_encoding = Qnil;
|
|
114
150
|
#endif
|
|
115
151
|
|
|
116
|
-
#if
|
|
117
|
-
pthread_mutex_t oj_cache_mutex;
|
|
152
|
+
#if USE_PTHREAD_MUTEX
|
|
153
|
+
pthread_mutex_t oj_cache_mutex;
|
|
154
|
+
#elif USE_RB_MUTEX
|
|
155
|
+
VALUE oj_cache_mutex = Qnil;
|
|
118
156
|
#endif
|
|
157
|
+
|
|
119
158
|
static const char json_class[] = "json_class";
|
|
120
159
|
|
|
121
160
|
struct _Options oj_default_options = {
|
|
122
|
-
0,
|
|
123
|
-
No,
|
|
124
|
-
|
|
125
|
-
No,
|
|
126
|
-
|
|
127
|
-
ObjectMode,
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
161
|
+
0, // indent
|
|
162
|
+
No, // circular
|
|
163
|
+
No, // auto_define
|
|
164
|
+
No, // sym_key
|
|
165
|
+
JSONEsc, // escape_mode
|
|
166
|
+
ObjectMode, // mode
|
|
167
|
+
Yes, // class_cache
|
|
168
|
+
UnixTime, // time_format
|
|
169
|
+
Yes, // bigdec_as_num
|
|
170
|
+
AutoDec, // bigdec_load
|
|
171
|
+
No, // to_hash
|
|
172
|
+
No, // to_json
|
|
173
|
+
No, // as_json
|
|
174
|
+
No, // nilnil
|
|
175
|
+
Yes, // empty_string
|
|
176
|
+
Yes, // allow_gc
|
|
177
|
+
Yes, // quirks_mode
|
|
178
|
+
No, // allow_invalid
|
|
179
|
+
No, // create_ok
|
|
180
|
+
Yes, // allow_nan
|
|
181
|
+
json_class, // create_id
|
|
182
|
+
10, // create_id_len
|
|
183
|
+
9, // sec_prec
|
|
184
|
+
16, // float_prec
|
|
185
|
+
"%0.15g", // float_fmt
|
|
186
|
+
Qnil, // hash_class
|
|
187
|
+
Qnil, // array_class
|
|
188
|
+
{ // dump_opts
|
|
189
|
+
false, //use
|
|
190
|
+
"", // indent
|
|
191
|
+
"", // before_sep
|
|
192
|
+
"", // after_sep
|
|
193
|
+
"", // hash_nl
|
|
194
|
+
"", // array_nl
|
|
195
|
+
0, // indent_size
|
|
196
|
+
0, // before_size
|
|
197
|
+
0, // after_size
|
|
198
|
+
0, // hash_size
|
|
199
|
+
0, // array_size
|
|
200
|
+
AutoNan,// nan_dump
|
|
201
|
+
false, // omit_nil
|
|
202
|
+
MAX_DEPTH, // max_depth
|
|
203
|
+
},
|
|
204
|
+
{ // str_rx
|
|
205
|
+
NULL, // head
|
|
206
|
+
NULL, // tail
|
|
207
|
+
{ '\0' }, // err
|
|
145
208
|
}
|
|
146
|
-
|
|
147
|
-
}
|
|
209
|
+
};
|
|
148
210
|
|
|
149
|
-
/*
|
|
211
|
+
/* Document-method: default_options()
|
|
212
|
+
* call-seq: default_options()
|
|
150
213
|
*
|
|
151
214
|
* Returns the default load and dump options as a Hash. The options are
|
|
152
|
-
* - indent
|
|
153
|
-
* - circular
|
|
154
|
-
* - auto_define
|
|
155
|
-
* - symbol_keys
|
|
156
|
-
* -
|
|
157
|
-
* -
|
|
158
|
-
* -
|
|
159
|
-
* -
|
|
160
|
-
*
|
|
215
|
+
* - *:indent* [_Fixnum_|_String_|_nil_] number of spaces to indent each element in an JSON document, zero or nil is no newline between JSON elements, negative indicates no newline between top level JSON elements in a stream, a String indicates the string should be used for indentation
|
|
216
|
+
* - *:circular* [_Boolean_|_nil_] support circular references while dumping
|
|
217
|
+
* - *:auto_define* [_Boolean_|_nil_] automatically define classes if they do not exist
|
|
218
|
+
* - *:symbol_keys* [_Boolean_|_nil_] use symbols instead of strings for hash keys
|
|
219
|
+
* - *:escape_mode* [_:newline_|_:json_|_:xss_safe_|_:ascii_|_unicode_xss_|_nil_] determines the characters to escape
|
|
220
|
+
* - *:class_cache* [_Boolean_|_nil_] cache classes for faster parsing (if dynamically modifying classes or reloading classes then don't use this)
|
|
221
|
+
* - *:mode* [_:object_|_:strict_|_:compat_|_:null_|_:custom_|_:rails_] load and dump modes to use for JSON
|
|
222
|
+
* - *:time_format* [_:unix_|_:unix_zone_|_:xmlschema_|_:ruby_] time format when dumping in :compat and :object mode
|
|
223
|
+
* - *:bigdecimal_as_decimal* [_Boolean_|_nil_] dump BigDecimal as a decimal number or as a String
|
|
224
|
+
* - *:bigdecimal_load* [_:bigdecimal_|_:float_|_:auto_] load decimals as BigDecimal instead of as a Float. :auto pick the most precise for the number of digits.
|
|
225
|
+
* - *:create_id* [_String_|_nil_] create id for json compatible object encoding, default is 'json_create'
|
|
226
|
+
* - *:second_precision* [_Fixnum_|_nil_] number of digits after the decimal when dumping the seconds portion of time
|
|
227
|
+
* - *:float_precision* [_Fixnum_|_nil_] number of digits of precision when dumping floats, 0 indicates use Ruby
|
|
228
|
+
* - *:use_to_json* [_Boolean_|_nil_] call to_json() methods on dump, default is false
|
|
229
|
+
* - *:use_as_json* [_Boolean_|_nil_] call as_json() methods on dump, default is false
|
|
230
|
+
* - *:nilnil* [_Boolean_|_nil_] if true a nil input to load will return nil and not raise an Exception
|
|
231
|
+
* - *:empty_string* [_Boolean_|_nil_] if true an empty input will not raise an Exception
|
|
232
|
+
* - *:allow_gc* [_Boolean_|_nil_] allow or prohibit GC during parsing, default is true (allow)
|
|
233
|
+
* - *:quirks_mode* [_true,_|_false_|_nil_] Allow single JSON values instead of documents, default is true (allow)
|
|
234
|
+
* - *:allow_invalid_unicode* [_true,_|_false_|_nil_] Allow invalid unicode, default is false (don't allow)
|
|
235
|
+
* - *:allow_nan* [_true,_|_false_|_nil_] Allow Nan, Infinity, and -Infinity to be parsed, default is true (allow)
|
|
236
|
+
* - *:indent_str* [_String_|_nil_] String to use for indentation, overriding the indent option is not nil
|
|
237
|
+
* - *:space* [_String_|_nil_] String to use for the space after the colon in JSON object fields
|
|
238
|
+
* - *:space_before* [_String_|_nil_] String to use before the colon separator in JSON object fields
|
|
239
|
+
* - *:object_nl* [_String_|_nil_] String to use after a JSON object field value
|
|
240
|
+
* - *:array_nl* [_String_|_nil_] String to use after a JSON array value
|
|
241
|
+
* - *:nan* [_:null_|_:huge_|_:word_|_:raise_|_:auto_] how to dump Infinity and NaN in null, strict, and compat mode. :null places a null, :huge places a huge number, :word places Infinity or NaN, :raise raises and exception, :auto uses default for each mode.
|
|
242
|
+
* - *:hash_class* [_Class_|_nil_] Class to use instead of Hash on load, :object_class can also be used
|
|
243
|
+
* - *:array_class* [_Class_|_nil_] Class to use instead of Array on load
|
|
244
|
+
* - *:omit_nil* [_true_|_false_] if true Hash and Object attributes with nil values are omitted
|
|
245
|
+
*
|
|
246
|
+
* Return [_Hash_] all current option settings.
|
|
161
247
|
*/
|
|
162
248
|
static VALUE
|
|
163
249
|
get_def_opts(VALUE self) {
|
|
164
250
|
VALUE opts = rb_hash_new();
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
251
|
+
|
|
252
|
+
if (0 == oj_default_options.dump_opts.indent_size) {
|
|
253
|
+
rb_hash_aset(opts, oj_indent_sym, INT2FIX(oj_default_options.indent));
|
|
254
|
+
} else {
|
|
255
|
+
rb_hash_aset(opts, oj_indent_sym, rb_str_new2(oj_default_options.dump_opts.indent_str));
|
|
256
|
+
}
|
|
257
|
+
rb_hash_aset(opts, sec_prec_sym, INT2FIX(oj_default_options.sec_prec));
|
|
168
258
|
rb_hash_aset(opts, circular_sym, (Yes == oj_default_options.circular) ? Qtrue : ((No == oj_default_options.circular) ? Qfalse : Qnil));
|
|
259
|
+
rb_hash_aset(opts, class_cache_sym, (Yes == oj_default_options.class_cache) ? Qtrue : ((No == oj_default_options.class_cache) ? Qfalse : Qnil));
|
|
169
260
|
rb_hash_aset(opts, auto_define_sym, (Yes == oj_default_options.auto_define) ? Qtrue : ((No == oj_default_options.auto_define) ? Qfalse : Qnil));
|
|
170
|
-
rb_hash_aset(opts, ascii_only_sym, (Yes == oj_default_options.ascii_only) ? Qtrue : ((No == oj_default_options.ascii_only) ? Qfalse : Qnil));
|
|
171
261
|
rb_hash_aset(opts, symbol_keys_sym, (Yes == oj_default_options.sym_key) ? Qtrue : ((No == oj_default_options.sym_key) ? Qfalse : Qnil));
|
|
262
|
+
rb_hash_aset(opts, bigdecimal_as_decimal_sym, (Yes == oj_default_options.bigdec_as_num) ? Qtrue : ((No == oj_default_options.bigdec_as_num) ? Qfalse : Qnil));
|
|
263
|
+
rb_hash_aset(opts, use_to_json_sym, (Yes == oj_default_options.to_json) ? Qtrue : ((No == oj_default_options.to_json) ? Qfalse : Qnil));
|
|
264
|
+
rb_hash_aset(opts, use_to_hash_sym, (Yes == oj_default_options.to_hash) ? Qtrue : ((No == oj_default_options.to_hash) ? Qfalse : Qnil));
|
|
265
|
+
rb_hash_aset(opts, use_as_json_sym, (Yes == oj_default_options.as_json) ? Qtrue : ((No == oj_default_options.as_json) ? Qfalse : Qnil));
|
|
266
|
+
rb_hash_aset(opts, nilnil_sym, (Yes == oj_default_options.nilnil) ? Qtrue : ((No == oj_default_options.nilnil) ? Qfalse : Qnil));
|
|
267
|
+
rb_hash_aset(opts, empty_string_sym, (Yes == oj_default_options.empty_string) ? Qtrue : ((No == oj_default_options.empty_string) ? Qfalse : Qnil));
|
|
268
|
+
rb_hash_aset(opts, allow_gc_sym, (Yes == oj_default_options.allow_gc) ? Qtrue : ((No == oj_default_options.allow_gc) ? Qfalse : Qnil));
|
|
269
|
+
rb_hash_aset(opts, oj_quirks_mode_sym, (Yes == oj_default_options.quirks_mode) ? Qtrue : ((No == oj_default_options.quirks_mode) ? Qfalse : Qnil));
|
|
270
|
+
rb_hash_aset(opts, allow_invalid_unicode_sym, (Yes == oj_default_options.allow_invalid) ? Qtrue : ((No == oj_default_options.allow_invalid) ? Qfalse : Qnil));
|
|
271
|
+
rb_hash_aset(opts, oj_allow_nan_sym, (Yes == oj_default_options.allow_nan) ? Qtrue : ((No == oj_default_options.allow_nan) ? Qfalse : Qnil));
|
|
272
|
+
rb_hash_aset(opts, float_prec_sym, INT2FIX(oj_default_options.float_prec));
|
|
172
273
|
switch (oj_default_options.mode) {
|
|
173
274
|
case StrictMode: rb_hash_aset(opts, mode_sym, strict_sym); break;
|
|
174
275
|
case CompatMode: rb_hash_aset(opts, mode_sym, compat_sym); break;
|
|
175
276
|
case NullMode: rb_hash_aset(opts, mode_sym, null_sym); break;
|
|
176
277
|
case ObjectMode:
|
|
278
|
+
case CustomMode: rb_hash_aset(opts, mode_sym, custom_sym); break;
|
|
279
|
+
case RailsMode: rb_hash_aset(opts, mode_sym, rails_sym); break;
|
|
177
280
|
default: rb_hash_aset(opts, mode_sym, object_sym); break;
|
|
178
281
|
}
|
|
282
|
+
switch (oj_default_options.escape_mode) {
|
|
283
|
+
case NLEsc: rb_hash_aset(opts, escape_mode_sym, newline_sym); break;
|
|
284
|
+
case JSONEsc: rb_hash_aset(opts, escape_mode_sym, json_sym); break;
|
|
285
|
+
case XSSEsc: rb_hash_aset(opts, escape_mode_sym, xss_safe_sym); break;
|
|
286
|
+
case ASCIIEsc: rb_hash_aset(opts, escape_mode_sym, ascii_sym); break;
|
|
287
|
+
case JXEsc: rb_hash_aset(opts, escape_mode_sym, unicode_xss_sym); break;
|
|
288
|
+
default: rb_hash_aset(opts, escape_mode_sym, json_sym); break;
|
|
289
|
+
}
|
|
179
290
|
switch (oj_default_options.time_format) {
|
|
180
291
|
case XmlTime: rb_hash_aset(opts, time_format_sym, xmlschema_sym); break;
|
|
181
292
|
case RubyTime: rb_hash_aset(opts, time_format_sym, ruby_sym); break;
|
|
293
|
+
case UnixZTime: rb_hash_aset(opts, time_format_sym, unix_zone_sym); break;
|
|
182
294
|
case UnixTime:
|
|
183
295
|
default: rb_hash_aset(opts, time_format_sym, unix_sym); break;
|
|
184
296
|
}
|
|
297
|
+
switch (oj_default_options.bigdec_load) {
|
|
298
|
+
case BigDec: rb_hash_aset(opts, bigdecimal_load_sym, bigdecimal_sym);break;
|
|
299
|
+
case FloatDec: rb_hash_aset(opts, bigdecimal_load_sym, float_sym); break;
|
|
300
|
+
case AutoDec:
|
|
301
|
+
default: rb_hash_aset(opts, bigdecimal_load_sym, auto_sym); break;
|
|
302
|
+
}
|
|
185
303
|
rb_hash_aset(opts, create_id_sym, (0 == oj_default_options.create_id) ? Qnil : rb_str_new2(oj_default_options.create_id));
|
|
186
|
-
|
|
304
|
+
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));
|
|
305
|
+
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));
|
|
306
|
+
rb_hash_aset(opts, oj_object_nl_sym, (0 == oj_default_options.dump_opts.hash_size) ? Qnil : rb_str_new2(oj_default_options.dump_opts.hash_nl));
|
|
307
|
+
rb_hash_aset(opts, oj_array_nl_sym, (0 == oj_default_options.dump_opts.array_size) ? Qnil : rb_str_new2(oj_default_options.dump_opts.array_nl));
|
|
308
|
+
|
|
309
|
+
switch (oj_default_options.dump_opts.nan_dump) {
|
|
310
|
+
case NullNan: rb_hash_aset(opts, nan_sym, null_sym); break;
|
|
311
|
+
case RaiseNan: rb_hash_aset(opts, nan_sym, raise_sym); break;
|
|
312
|
+
case WordNan: rb_hash_aset(opts, nan_sym, word_sym); break;
|
|
313
|
+
case HugeNan: rb_hash_aset(opts, nan_sym, huge_sym); break;
|
|
314
|
+
case AutoNan:
|
|
315
|
+
default: rb_hash_aset(opts, nan_sym, auto_sym); break;
|
|
316
|
+
}
|
|
317
|
+
rb_hash_aset(opts, omit_nil_sym, oj_default_options.dump_opts.omit_nil ? Qtrue : Qfalse);
|
|
318
|
+
rb_hash_aset(opts, oj_hash_class_sym, oj_default_options.hash_class);
|
|
319
|
+
rb_hash_aset(opts, oj_array_class_sym, oj_default_options.array_class);
|
|
320
|
+
|
|
187
321
|
return opts;
|
|
188
322
|
}
|
|
189
323
|
|
|
190
|
-
/*
|
|
324
|
+
/* Document-method: default_options=
|
|
325
|
+
* call-seq: default_options=(opts)
|
|
191
326
|
*
|
|
192
327
|
* Sets the default options for load and dump.
|
|
193
|
-
*
|
|
194
|
-
*
|
|
195
|
-
*
|
|
196
|
-
*
|
|
197
|
-
*
|
|
198
|
-
*
|
|
199
|
-
*
|
|
200
|
-
*
|
|
201
|
-
*
|
|
202
|
-
*
|
|
203
|
-
*
|
|
204
|
-
*
|
|
205
|
-
*
|
|
206
|
-
*
|
|
207
|
-
*
|
|
208
|
-
*
|
|
209
|
-
*
|
|
210
|
-
*
|
|
211
|
-
*
|
|
212
|
-
*
|
|
213
|
-
*
|
|
328
|
+
* - *opts* [_Hash_] options to change
|
|
329
|
+
* - *:indent* [_Fixnum_|_String_|_nil_] number of spaces to indent each element in a JSON document or the String to use for identation.
|
|
330
|
+
* - :circular [_Boolean_|_nil_] support circular references while dumping.
|
|
331
|
+
* - *:auto_define* [_Boolean_|_nil_] automatically define classes if they do not exist.
|
|
332
|
+
* - *:symbol_keys* [_Boolean_|_nil_] convert hash keys to symbols.
|
|
333
|
+
* - *:class_cache* [_Boolean_|_nil_] cache classes for faster parsing.
|
|
334
|
+
* - *: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.
|
|
335
|
+
* - *:bigdecimal_as_decimal* [_Boolean_|_nil_] dump BigDecimal as a decimal number or as a String.
|
|
336
|
+
* - *: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.
|
|
337
|
+
* - *:mode* [_:object_|_:strict_|_:compat_|_:null_|_:custom_|_:rails_] 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.
|
|
338
|
+
* - *: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.
|
|
339
|
+
* - *:create_id* [_String_|_nil_] create id for json compatible object encoding
|
|
340
|
+
* - *:second_precision* [_Fixnum_|_nil_] number of digits after the decimal when dumping the seconds portion of time.
|
|
341
|
+
* - *:float_precision* [_Fixnum_|_nil_] number of digits of precision when dumping floats, 0 indicates use Ruby.
|
|
342
|
+
* - *:use_to_json* [_Boolean_|_nil_] call to_json() methods on dump, default is false.
|
|
343
|
+
* - *:use_as_json* [_Boolean_|_nil_] call as_json() methods on dump, default is false.
|
|
344
|
+
* - *:use_to_hash* [_Boolean_|_nil_] call to_hash() methods on dump, default is false.
|
|
345
|
+
* - *:nilnil* [_Boolean_|_nil_] if true a nil input to load will return nil and not raise an Exception.
|
|
346
|
+
* - *:allow_gc* [_Boolean_|_nil_] allow or prohibit GC during parsing, default is true (allow).
|
|
347
|
+
* - *:quirks_mode* [_Boolean_|_nil_] allow single JSON values instead of documents, default is true (allow).
|
|
348
|
+
* - *:allow_invalid_unicode* [_Boolean_|_nil_] allow invalid unicode, default is false (don't allow).
|
|
349
|
+
* - *:allow_nan* [_Boolean_|_nil_] allow Nan, Infinity, and -Infinity, default is true (allow).
|
|
350
|
+
* - *:space* [_String_|_nil_] String to use for the space after the colon in JSON object fields.
|
|
351
|
+
* - *:space_before* [_String_|_nil_] String to use before the colon separator in JSON object fields.
|
|
352
|
+
* - *:object_nl* [_String_|_nil_] String to use after a JSON object field value.
|
|
353
|
+
* - *:array_nl* [_String_|_nil_] String to use after a JSON array value
|
|
354
|
+
* - *:nan* [_:null_|_:huge_|_:word_|_:raise_] how to dump Infinity and NaN in null, strict, and compat mode. :null places a null, :huge places a huge number, :word places Infinity or NaN, :raise raises and exception, :auto uses default for each mode.
|
|
355
|
+
* - *:hash_class* [_Class_|_nil_] Class to use instead of Hash on load, :object_class can also be used.
|
|
356
|
+
* - *:array_class* [_Class_|_nil_] Class to use instead of Array on load.
|
|
357
|
+
* - *:omit_nil* [_true_|_false_] if true Hash and Object attributes with nil values are omitted.
|
|
214
358
|
*/
|
|
215
359
|
static VALUE
|
|
216
360
|
set_def_opts(VALUE self, VALUE opts) {
|
|
361
|
+
Check_Type(opts, T_HASH);
|
|
362
|
+
oj_parse_options(opts, &oj_default_options);
|
|
363
|
+
|
|
364
|
+
return Qnil;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
void
|
|
368
|
+
oj_parse_options(VALUE ropts, Options copts) {
|
|
217
369
|
struct _YesNoOpt ynos[] = {
|
|
218
|
-
{ circular_sym, &
|
|
219
|
-
{ auto_define_sym, &
|
|
220
|
-
{ symbol_keys_sym, &
|
|
221
|
-
{
|
|
370
|
+
{ circular_sym, &copts->circular },
|
|
371
|
+
{ auto_define_sym, &copts->auto_define },
|
|
372
|
+
{ symbol_keys_sym, &copts->sym_key },
|
|
373
|
+
{ class_cache_sym, &copts->class_cache },
|
|
374
|
+
{ bigdecimal_as_decimal_sym, &copts->bigdec_as_num },
|
|
375
|
+
{ use_to_hash_sym, &copts->to_hash },
|
|
376
|
+
{ use_to_json_sym, &copts->to_json },
|
|
377
|
+
{ use_as_json_sym, &copts->as_json },
|
|
378
|
+
{ nilnil_sym, &copts->nilnil },
|
|
379
|
+
{ allow_blank_sym, &copts->nilnil }, // same as nilnil
|
|
380
|
+
{ empty_string_sym, &copts->empty_string },
|
|
381
|
+
{ allow_gc_sym, &copts->allow_gc },
|
|
382
|
+
{ oj_quirks_mode_sym, &copts->quirks_mode },
|
|
383
|
+
{ allow_invalid_unicode_sym, &copts->allow_invalid },
|
|
384
|
+
{ oj_allow_nan_sym, &copts->allow_nan },
|
|
385
|
+
{ oj_create_additions_sym, &copts->create_ok },
|
|
222
386
|
{ Qnil, 0 }
|
|
223
387
|
};
|
|
224
|
-
YesNoOpt
|
|
225
|
-
VALUE v;
|
|
388
|
+
YesNoOpt o;
|
|
389
|
+
volatile VALUE v;
|
|
390
|
+
size_t len;
|
|
226
391
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
if (Qnil != v) {
|
|
230
|
-
Check_Type(v, T_FIXNUM);
|
|
231
|
-
oj_default_options.indent = FIX2INT(v);
|
|
392
|
+
if (T_HASH != rb_type(ropts)) {
|
|
393
|
+
return;
|
|
232
394
|
}
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
395
|
+
if (Qtrue == rb_funcall(ropts, oj_has_key_id, 1, oj_indent_sym)) {
|
|
396
|
+
v = rb_hash_lookup(ropts, oj_indent_sym);
|
|
397
|
+
switch (rb_type(v)) {
|
|
398
|
+
case T_NIL:
|
|
399
|
+
copts->dump_opts.indent_size = 0;
|
|
400
|
+
*copts->dump_opts.indent_str = '\0';
|
|
401
|
+
copts->indent = 0;
|
|
402
|
+
break;
|
|
403
|
+
case T_FIXNUM:
|
|
404
|
+
copts->dump_opts.indent_size = 0;
|
|
405
|
+
*copts->dump_opts.indent_str = '\0';
|
|
406
|
+
copts->indent = FIX2INT(v);
|
|
407
|
+
break;
|
|
408
|
+
case T_STRING:
|
|
409
|
+
if (sizeof(copts->dump_opts.indent_str) <= (len = RSTRING_LEN(v))) {
|
|
410
|
+
rb_raise(rb_eArgError, "indent string is limited to %lu characters.", sizeof(copts->dump_opts.indent_str));
|
|
411
|
+
}
|
|
412
|
+
strcpy(copts->dump_opts.indent_str, StringValuePtr(v));
|
|
413
|
+
copts->dump_opts.indent_size = (uint8_t)len;
|
|
414
|
+
copts->indent = 0;
|
|
415
|
+
break;
|
|
416
|
+
default:
|
|
417
|
+
rb_raise(rb_eTypeError, "indent must be a Fixnum, String, or nil.");
|
|
418
|
+
break;
|
|
241
419
|
}
|
|
242
|
-
oj_default_options.max_stack = (size_t)i;
|
|
243
420
|
}
|
|
421
|
+
if (Qnil != (v = rb_hash_lookup(ropts, float_prec_sym))) {
|
|
422
|
+
int n;
|
|
244
423
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
424
|
+
#ifdef RUBY_INTEGER_UNIFICATION
|
|
425
|
+
if (rb_cInteger != rb_obj_class(v)) {
|
|
426
|
+
rb_raise(rb_eArgError, ":float_precision must be a Integer.");
|
|
427
|
+
}
|
|
428
|
+
#else
|
|
429
|
+
if (T_FIXNUM != rb_type(v)) {
|
|
430
|
+
rb_raise(rb_eArgError, ":float_precision must be a Fixnum.");
|
|
431
|
+
}
|
|
432
|
+
#endif
|
|
433
|
+
n = FIX2INT(v);
|
|
434
|
+
if (0 >= n) {
|
|
435
|
+
*copts->float_fmt = '\0';
|
|
436
|
+
copts->float_prec = 0;
|
|
437
|
+
} else {
|
|
438
|
+
if (20 < n) {
|
|
439
|
+
n = 20;
|
|
440
|
+
}
|
|
441
|
+
sprintf(copts->float_fmt, "%%0.%dg", n);
|
|
442
|
+
copts->float_prec = n;
|
|
443
|
+
}
|
|
258
444
|
}
|
|
445
|
+
if (Qnil != (v = rb_hash_lookup(ropts, sec_prec_sym))) {
|
|
446
|
+
int n;
|
|
259
447
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
448
|
+
#ifdef RUBY_INTEGER_UNIFICATION
|
|
449
|
+
if (rb_cInteger != rb_obj_class(v)) {
|
|
450
|
+
rb_raise(rb_eArgError, ":second_precision must be a Integer.");
|
|
451
|
+
}
|
|
452
|
+
#else
|
|
453
|
+
if (T_FIXNUM != rb_type(v)) {
|
|
454
|
+
rb_raise(rb_eArgError, ":second_precision must be a Fixnum.");
|
|
455
|
+
}
|
|
456
|
+
#endif
|
|
457
|
+
n = NUM2INT(v);
|
|
458
|
+
if (0 > n) {
|
|
459
|
+
n = 0;
|
|
460
|
+
} else if (9 < n) {
|
|
461
|
+
n = 9;
|
|
462
|
+
}
|
|
463
|
+
copts->sec_prec = n;
|
|
271
464
|
}
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
465
|
+
if (Qnil != (v = rb_hash_lookup(ropts, mode_sym))) {
|
|
466
|
+
if (object_sym == v) {
|
|
467
|
+
copts->mode = ObjectMode;
|
|
468
|
+
} else if (strict_sym == v) {
|
|
469
|
+
copts->mode = StrictMode;
|
|
470
|
+
} else if (compat_sym == v || json_sym == v) {
|
|
471
|
+
copts->mode = CompatMode;
|
|
472
|
+
} else if (null_sym == v) {
|
|
473
|
+
copts->mode = NullMode;
|
|
474
|
+
} else if (custom_sym == v) {
|
|
475
|
+
copts->mode = CustomMode;
|
|
476
|
+
} else if (rails_sym == v) {
|
|
477
|
+
copts->mode = RailsMode;
|
|
478
|
+
} else {
|
|
479
|
+
rb_raise(rb_eArgError, ":mode must be :object, :strict, :compat, :null, :custom, or :rails.");
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
if (Qnil != (v = rb_hash_lookup(ropts, time_format_sym))) {
|
|
483
|
+
if (unix_sym == v) {
|
|
484
|
+
copts->time_format = UnixTime;
|
|
485
|
+
} else if (unix_zone_sym == v) {
|
|
486
|
+
copts->time_format = UnixZTime;
|
|
487
|
+
} else if (xmlschema_sym == v) {
|
|
488
|
+
copts->time_format = XmlTime;
|
|
489
|
+
} else if (ruby_sym == v) {
|
|
490
|
+
copts->time_format = RubyTime;
|
|
491
|
+
} else {
|
|
492
|
+
rb_raise(rb_eArgError, ":time_format must be :unix, :unix_zone, :xmlschema, or :ruby.");
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
if (Qnil != (v = rb_hash_lookup(ropts, escape_mode_sym))) {
|
|
496
|
+
if (newline_sym == v) {
|
|
497
|
+
copts->escape_mode = NLEsc;
|
|
498
|
+
} else if (json_sym == v) {
|
|
499
|
+
copts->escape_mode = JSONEsc;
|
|
500
|
+
} else if (xss_safe_sym == v) {
|
|
501
|
+
copts->escape_mode = XSSEsc;
|
|
502
|
+
} else if (ascii_sym == v) {
|
|
503
|
+
copts->escape_mode = ASCIIEsc;
|
|
504
|
+
} else if (unicode_xss_sym == v) {
|
|
505
|
+
copts->escape_mode = JXEsc;
|
|
506
|
+
} else {
|
|
507
|
+
rb_raise(rb_eArgError, ":encoding must be :newline, :json, :xss_safe, :unicode_xss, or :ascii.");
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
if (Qnil != (v = rb_hash_lookup(ropts, bigdecimal_load_sym))) {
|
|
511
|
+
if (bigdecimal_sym == v || Qtrue == v) {
|
|
512
|
+
copts->bigdec_load = BigDec;
|
|
513
|
+
} else if (float_sym == v) {
|
|
514
|
+
copts->bigdec_load = FloatDec;
|
|
515
|
+
} else if (auto_sym == v || Qfalse == v) {
|
|
516
|
+
copts->bigdec_load = AutoDec;
|
|
517
|
+
} else {
|
|
518
|
+
rb_raise(rb_eArgError, ":bigdecimal_load must be :bigdecimal, :float, or :auto.");
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
if (Qtrue == rb_funcall(ropts, oj_has_key_id, 1, create_id_sym)) {
|
|
522
|
+
v = rb_hash_lookup(ropts, create_id_sym);
|
|
523
|
+
if (Qnil == v) {
|
|
275
524
|
if (json_class != oj_default_options.create_id) {
|
|
276
525
|
xfree((char*)oj_default_options.create_id);
|
|
277
526
|
}
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
527
|
+
copts->create_id = NULL;
|
|
528
|
+
copts->create_id_len = 0;
|
|
529
|
+
} else if (T_STRING == rb_type(v)) {
|
|
530
|
+
const char *str = StringValuePtr(v);
|
|
531
|
+
|
|
532
|
+
len = RSTRING_LEN(v);
|
|
533
|
+
if (len != copts->create_id_len ||
|
|
534
|
+
0 != strcmp(copts->create_id, str)) {
|
|
535
|
+
copts->create_id = ALLOC_N(char, len + 1);
|
|
536
|
+
strcpy((char*)copts->create_id, str);
|
|
537
|
+
copts->create_id_len = len;
|
|
538
|
+
}
|
|
539
|
+
} else {
|
|
540
|
+
rb_raise(rb_eArgError, ":create_id must be string.");
|
|
286
541
|
}
|
|
287
542
|
}
|
|
288
|
-
|
|
289
543
|
for (o = ynos; 0 != o->attr; o++) {
|
|
290
|
-
if (
|
|
291
|
-
continue;
|
|
292
|
-
}
|
|
293
|
-
if (Qnil != (v = rb_hash_lookup(opts, o->sym))) {
|
|
544
|
+
if (Qnil != (v = rb_hash_lookup(ropts, o->sym))) {
|
|
294
545
|
if (Qtrue == v) {
|
|
295
546
|
*o->attr = Yes;
|
|
296
547
|
} else if (Qfalse == v) {
|
|
297
548
|
*o->attr = No;
|
|
298
549
|
} else {
|
|
299
|
-
rb_raise(rb_eArgError, "%s must be true
|
|
550
|
+
rb_raise(rb_eArgError, "%s must be true or false.", rb_id2name(SYM2ID(o->sym)));
|
|
300
551
|
}
|
|
301
552
|
}
|
|
302
553
|
}
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
{ symbol_keys_sym, &copts->sym_key },
|
|
312
|
-
{ ascii_only_sym, &copts->ascii_only },
|
|
313
|
-
{ Qnil, 0 }
|
|
314
|
-
};
|
|
315
|
-
YesNoOpt o;
|
|
316
|
-
|
|
317
|
-
if (rb_cHash == rb_obj_class(ropts)) {
|
|
318
|
-
VALUE v;
|
|
319
|
-
|
|
320
|
-
if (Qnil != (v = rb_hash_lookup(ropts, indent_sym))) {
|
|
321
|
-
if (rb_cFixnum != rb_obj_class(v)) {
|
|
322
|
-
rb_raise(rb_eArgError, ":indent must be a Fixnum.");
|
|
554
|
+
if (Qtrue == rb_funcall(ropts, oj_has_key_id, 1, oj_space_sym)) {
|
|
555
|
+
if (Qnil == (v = rb_hash_lookup(ropts, oj_space_sym))) {
|
|
556
|
+
copts->dump_opts.after_size = 0;
|
|
557
|
+
*copts->dump_opts.after_sep = '\0';
|
|
558
|
+
} else {
|
|
559
|
+
rb_check_type(v, T_STRING);
|
|
560
|
+
if (sizeof(copts->dump_opts.after_sep) <= (len = RSTRING_LEN(v))) {
|
|
561
|
+
rb_raise(rb_eArgError, "space string is limited to %lu characters.", sizeof(copts->dump_opts.after_sep));
|
|
323
562
|
}
|
|
324
|
-
copts->
|
|
563
|
+
strcpy(copts->dump_opts.after_sep, StringValuePtr(v));
|
|
564
|
+
copts->dump_opts.after_size = (uint8_t)len;
|
|
325
565
|
}
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
copts->
|
|
335
|
-
} else {
|
|
336
|
-
rb_raise(rb_eArgError, ":mode must be :object, :strict, :compat, or :null.");
|
|
566
|
+
}
|
|
567
|
+
if (Qtrue == rb_funcall(ropts, oj_has_key_id, 1, oj_space_before_sym)) {
|
|
568
|
+
if (Qnil == (v = rb_hash_lookup(ropts, oj_space_before_sym))) {
|
|
569
|
+
copts->dump_opts.before_size = 0;
|
|
570
|
+
*copts->dump_opts.before_sep = '\0';
|
|
571
|
+
} else {
|
|
572
|
+
rb_check_type(v, T_STRING);
|
|
573
|
+
if (sizeof(copts->dump_opts.before_sep) <= (len = RSTRING_LEN(v))) {
|
|
574
|
+
rb_raise(rb_eArgError, "sapce_before string is limited to %lu characters.", sizeof(copts->dump_opts.before_sep));
|
|
337
575
|
}
|
|
576
|
+
strcpy(copts->dump_opts.before_sep, StringValuePtr(v));
|
|
577
|
+
copts->dump_opts.before_size = (uint8_t)len;
|
|
338
578
|
}
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
rb_raise(rb_eArgError, "
|
|
579
|
+
}
|
|
580
|
+
if (Qtrue == rb_funcall(ropts, oj_has_key_id, 1, oj_object_nl_sym)) {
|
|
581
|
+
if (Qnil == (v = rb_hash_lookup(ropts, oj_object_nl_sym))) {
|
|
582
|
+
copts->dump_opts.hash_size = 0;
|
|
583
|
+
*copts->dump_opts.hash_nl = '\0';
|
|
584
|
+
} else {
|
|
585
|
+
rb_check_type(v, T_STRING);
|
|
586
|
+
if (sizeof(copts->dump_opts.hash_nl) <= (len = RSTRING_LEN(v))) {
|
|
587
|
+
rb_raise(rb_eArgError, "object_nl string is limited to %lu characters.", sizeof(copts->dump_opts.hash_nl));
|
|
348
588
|
}
|
|
589
|
+
strcpy(copts->dump_opts.hash_nl, StringValuePtr(v));
|
|
590
|
+
copts->dump_opts.hash_size = (uint8_t)len;
|
|
349
591
|
}
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
592
|
+
}
|
|
593
|
+
if (Qtrue == rb_funcall(ropts, oj_has_key_id, 1, oj_array_nl_sym)) {
|
|
594
|
+
if (Qnil == (v = rb_hash_lookup(ropts, oj_array_nl_sym))) {
|
|
595
|
+
copts->dump_opts.array_size = 0;
|
|
596
|
+
*copts->dump_opts.array_nl = '\0';
|
|
597
|
+
} else {
|
|
598
|
+
rb_check_type(v, T_STRING);
|
|
599
|
+
if (sizeof(copts->dump_opts.array_nl) <= (len = RSTRING_LEN(v))) {
|
|
600
|
+
rb_raise(rb_eArgError, "array_nl string is limited to %lu characters.", sizeof(copts->dump_opts.array_nl));
|
|
359
601
|
}
|
|
602
|
+
strcpy(copts->dump_opts.array_nl, StringValuePtr(v));
|
|
603
|
+
copts->dump_opts.array_size = (uint8_t)len;
|
|
360
604
|
}
|
|
361
605
|
}
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
if (copts->max_stack < len) {
|
|
374
|
-
json = ALLOC_N(char, len);
|
|
606
|
+
if (Qnil != (v = rb_hash_lookup(ropts, nan_sym))) {
|
|
607
|
+
if (null_sym == v) {
|
|
608
|
+
copts->dump_opts.nan_dump = NullNan;
|
|
609
|
+
} else if (huge_sym == v) {
|
|
610
|
+
copts->dump_opts.nan_dump = HugeNan;
|
|
611
|
+
} else if (word_sym == v) {
|
|
612
|
+
copts->dump_opts.nan_dump = WordNan;
|
|
613
|
+
} else if (raise_sym == v) {
|
|
614
|
+
copts->dump_opts.nan_dump = RaiseNan;
|
|
615
|
+
} else if (auto_sym == v) {
|
|
616
|
+
copts->dump_opts.nan_dump = AutoNan;
|
|
375
617
|
} else {
|
|
376
|
-
|
|
618
|
+
rb_raise(rb_eArgError, ":nan must be :null, :huge, :word, :raise, or :auto.");
|
|
377
619
|
}
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
json = ALLOCA_N(char, len);
|
|
390
|
-
}
|
|
391
|
-
strcpy(json, StringValuePtr(s));
|
|
392
|
-
#ifndef JRUBY_RUBY
|
|
393
|
-
#if !IS_WINDOWS
|
|
394
|
-
// JRuby gets confused with what is the real fileno.
|
|
395
|
-
} else if (rb_respond_to(input, oj_fileno_id) && Qnil != (s = rb_funcall(input, oj_fileno_id, 0))) {
|
|
396
|
-
int fd = FIX2INT(s);
|
|
397
|
-
ssize_t cnt;
|
|
398
|
-
|
|
399
|
-
len = lseek(fd, 0, SEEK_END);
|
|
400
|
-
lseek(fd, 0, SEEK_SET);
|
|
401
|
-
if (copts->max_stack < len) {
|
|
402
|
-
json = ALLOC_N(char, len + 1);
|
|
403
|
-
} else {
|
|
404
|
-
json = ALLOCA_N(char, len + 1);
|
|
405
|
-
}
|
|
406
|
-
if (0 >= (cnt = read(fd, json, len)) || cnt != (ssize_t)len) {
|
|
407
|
-
rb_raise(rb_eIOError, "failed to read from IO Object.");
|
|
408
|
-
}
|
|
409
|
-
json[len] = '\0';
|
|
410
|
-
#endif
|
|
411
|
-
#endif
|
|
412
|
-
} else if (rb_respond_to(input, oj_read_id)) {
|
|
413
|
-
s = rb_funcall2(input, oj_read_id, 0, 0);
|
|
414
|
-
len = RSTRING_LEN(s) + 1;
|
|
415
|
-
if (copts->max_stack < len) {
|
|
416
|
-
json = ALLOC_N(char, len);
|
|
417
|
-
} else {
|
|
418
|
-
json = ALLOCA_N(char, len);
|
|
419
|
-
}
|
|
420
|
-
strcpy(json, StringValuePtr(s));
|
|
620
|
+
}
|
|
621
|
+
copts->dump_opts.use = (0 < copts->dump_opts.indent_size ||
|
|
622
|
+
0 < copts->dump_opts.after_size ||
|
|
623
|
+
0 < copts->dump_opts.before_size ||
|
|
624
|
+
0 < copts->dump_opts.hash_size ||
|
|
625
|
+
0 < copts->dump_opts.array_size);
|
|
626
|
+
if (Qnil != (v = rb_hash_lookup(ropts, omit_nil_sym))) {
|
|
627
|
+
if (Qtrue == v) {
|
|
628
|
+
copts->dump_opts.omit_nil = true;
|
|
629
|
+
} else if (Qfalse == v) {
|
|
630
|
+
copts->dump_opts.omit_nil = false;
|
|
421
631
|
} else {
|
|
422
|
-
rb_raise(rb_eArgError, "
|
|
632
|
+
rb_raise(rb_eArgError, ":omit_nil must be true or false.");
|
|
423
633
|
}
|
|
424
634
|
}
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
635
|
+
// This is here only for backwards compatibility with the original Oj.
|
|
636
|
+
v = rb_hash_lookup(ropts, oj_ascii_only_sym);
|
|
637
|
+
if (Qtrue == v) {
|
|
638
|
+
copts->escape_mode = ASCIIEsc;
|
|
639
|
+
} else if (Qfalse == v) {
|
|
640
|
+
copts->escape_mode = JSONEsc;
|
|
428
641
|
}
|
|
429
|
-
|
|
642
|
+
if (Qtrue == rb_funcall(ropts, oj_has_key_id, 1, oj_hash_class_sym)) {
|
|
643
|
+
if (Qnil == (v = rb_hash_lookup(ropts, oj_hash_class_sym))) {
|
|
644
|
+
copts->hash_class = Qnil;
|
|
645
|
+
} else {
|
|
646
|
+
rb_check_type(v, T_CLASS);
|
|
647
|
+
copts->hash_class = v;
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
if (Qtrue == rb_funcall(ropts, oj_has_key_id, 1, oj_object_class_sym)) {
|
|
651
|
+
if (Qnil == (v = rb_hash_lookup(ropts, oj_object_class_sym))) {
|
|
652
|
+
copts->hash_class = Qnil;
|
|
653
|
+
} else {
|
|
654
|
+
rb_check_type(v, T_CLASS);
|
|
655
|
+
copts->hash_class = v;
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
if (Qtrue == rb_funcall(ropts, oj_has_key_id, 1, oj_array_class_sym)) {
|
|
659
|
+
if (Qnil == (v = rb_hash_lookup(ropts, oj_array_class_sym))) {
|
|
660
|
+
copts->array_class = Qnil;
|
|
661
|
+
} else {
|
|
662
|
+
rb_check_type(v, T_CLASS);
|
|
663
|
+
copts->array_class = v;
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
oj_parse_opt_match_string(&copts->str_rx, ropts);
|
|
430
667
|
}
|
|
431
668
|
|
|
432
|
-
|
|
669
|
+
static int
|
|
670
|
+
match_string_cb(VALUE key, VALUE value, RxClass rc) {
|
|
671
|
+
if (T_CLASS != rb_type(value)) {
|
|
672
|
+
rb_raise(rb_eArgError, "for :match_string, the hash values must be a Class.");
|
|
673
|
+
}
|
|
674
|
+
switch (rb_type(key)) {
|
|
675
|
+
case T_REGEXP:
|
|
676
|
+
oj_rxclass_rappend(rc, key, value);
|
|
677
|
+
break;
|
|
678
|
+
case T_STRING:
|
|
679
|
+
if (0 != oj_rxclass_append(rc, StringValuePtr(key), value)) {
|
|
680
|
+
rb_raise(rb_eArgError, "%s", rc->err);
|
|
681
|
+
}
|
|
682
|
+
break;
|
|
683
|
+
default:
|
|
684
|
+
rb_raise(rb_eArgError, "for :match_string, keys must either a String or RegExp.");
|
|
685
|
+
break;
|
|
686
|
+
}
|
|
687
|
+
return ST_CONTINUE;
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
void
|
|
691
|
+
oj_parse_opt_match_string(RxClass rc, VALUE ropts) {
|
|
692
|
+
VALUE v;
|
|
693
|
+
|
|
694
|
+
if (Qnil != (v = rb_hash_lookup(ropts, match_string_sym))) {
|
|
695
|
+
rb_check_type(v, T_HASH);
|
|
696
|
+
// Zero out rc. Pattern are not appended but override.
|
|
697
|
+
rc->head = NULL;
|
|
698
|
+
rc->tail = NULL;
|
|
699
|
+
*rc->err = '\0';
|
|
700
|
+
rb_hash_foreach(v, match_string_cb, (VALUE)rc);
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
/* Document-method: load
|
|
705
|
+
* call-seq: load(json, options) { _|_obj, start, len_|_ }
|
|
706
|
+
*
|
|
707
|
+
* Parses a JSON document String into a Object, Hash, Array, String, Fixnum,
|
|
708
|
+
* Float, true, false, or nil according to the default mode or the mode
|
|
709
|
+
* specified. Raises an exception if the JSON is malformed or the classes
|
|
710
|
+
* specified are not valid. If the string input is not a valid JSON document (an
|
|
711
|
+
* empty string is not a valid JSON document) an exception is raised.
|
|
712
|
+
*
|
|
713
|
+
* When used with a document that has multiple JSON elements the block, if
|
|
714
|
+
* any, will be yielded to. If no block then the last element read will be
|
|
715
|
+
* returned.
|
|
716
|
+
*
|
|
717
|
+
* This parser operates on string and will attempt to load files into memory if
|
|
718
|
+
* a file object is passed as the first argument. A stream input will be parsed
|
|
719
|
+
* using a stream parser but others use the slightly faster string parser.
|
|
720
|
+
*
|
|
721
|
+
* A block can be provided with a single argument. That argument will be the
|
|
722
|
+
* parsed JSON document. This is useful when parsing a string that includes
|
|
723
|
+
* multiple JSON documents. The block can take up to 3 arguments, the parsed
|
|
724
|
+
* object, the position in the string or stream of the start of the JSON for
|
|
725
|
+
* that object, and the length of the JSON for that object plus trailing
|
|
726
|
+
* whitespace.
|
|
433
727
|
*
|
|
434
|
-
*
|
|
435
|
-
*
|
|
436
|
-
*
|
|
437
|
-
*
|
|
438
|
-
*
|
|
728
|
+
* - *json* [_String_|_IO_] JSON String or an Object that responds to read()
|
|
729
|
+
* - *options* [_Hash_] load options (same as default_options)
|
|
730
|
+
* - -
|
|
731
|
+
* - *obj* [_Hash_|_Array_|_String_|_Fixnum_|_Float_|_Boolean_|_nil_] parsed object.
|
|
732
|
+
* - *start* [_optional, _Integer_] start position of parsed JSON for obj.
|
|
733
|
+
* - *len* [_optional, _Integer_] length of parsed JSON for obj.
|
|
734
|
+
*
|
|
735
|
+
* Returns [_Hash_|_Array_|_String_|_Fixnum_|_Float_|_Boolean_|_nil_]
|
|
439
736
|
*/
|
|
440
737
|
static VALUE
|
|
441
738
|
load(int argc, VALUE *argv, VALUE self) {
|
|
442
|
-
|
|
739
|
+
Mode mode = oj_default_options.mode;
|
|
443
740
|
|
|
444
741
|
if (1 > argc) {
|
|
445
742
|
rb_raise(rb_eArgError, "Wrong number of arguments to load().");
|
|
446
743
|
}
|
|
447
744
|
if (2 <= argc) {
|
|
448
|
-
|
|
745
|
+
VALUE ropts = argv[1];
|
|
746
|
+
VALUE v;
|
|
747
|
+
|
|
748
|
+
Check_Type(ropts, T_HASH);
|
|
749
|
+
if (Qnil != (v = rb_hash_lookup(ropts, mode_sym))) {
|
|
750
|
+
if (object_sym == v) {
|
|
751
|
+
mode = ObjectMode;
|
|
752
|
+
} else if (strict_sym == v) {
|
|
753
|
+
mode = StrictMode;
|
|
754
|
+
} else if (compat_sym == v || json_sym == v) {
|
|
755
|
+
mode = CompatMode;
|
|
756
|
+
} else if (null_sym == v) {
|
|
757
|
+
mode = NullMode;
|
|
758
|
+
} else if (custom_sym == v) {
|
|
759
|
+
mode = CustomMode;
|
|
760
|
+
} else if (rails_sym == v) {
|
|
761
|
+
mode = RailsMode;
|
|
762
|
+
} else {
|
|
763
|
+
rb_raise(rb_eArgError, ":mode must be :object, :strict, :compat, :null, :custom, or :rails.");
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
}
|
|
767
|
+
switch (mode) {
|
|
768
|
+
case StrictMode:
|
|
769
|
+
case NullMode:
|
|
770
|
+
return oj_strict_parse(argc, argv, self);
|
|
771
|
+
case CompatMode:
|
|
772
|
+
case RailsMode:
|
|
773
|
+
return oj_compat_parse(argc, argv, self);
|
|
774
|
+
case CustomMode:
|
|
775
|
+
return oj_custom_parse(argc, argv, self);
|
|
776
|
+
case ObjectMode:
|
|
777
|
+
default:
|
|
778
|
+
break;
|
|
449
779
|
}
|
|
450
|
-
return
|
|
780
|
+
return oj_object_parse(argc, argv, self);
|
|
451
781
|
}
|
|
452
782
|
|
|
453
783
|
/* Document-method: load_file
|
|
454
|
-
*
|
|
784
|
+
* call-seq: load_file(path, options) { _|_obj, start, len_|_ }
|
|
785
|
+
*
|
|
786
|
+
* Parses a JSON document String into a Object, Hash, Array, String, Fixnum,
|
|
787
|
+
* Float, true, false, or nil according to the default mode or the mode
|
|
788
|
+
* specified. Raises an exception if the JSON is malformed or the classes
|
|
789
|
+
* specified are not valid. If the string input is not a valid JSON document (an
|
|
790
|
+
* empty string is not a valid JSON document) an exception is raised.
|
|
455
791
|
*
|
|
456
|
-
*
|
|
457
|
-
*
|
|
458
|
-
*
|
|
792
|
+
* When used with a document that has multiple JSON elements the block, if
|
|
793
|
+
* any, will be yielded to. If no block then the last element read will be
|
|
794
|
+
* returned.
|
|
459
795
|
*
|
|
460
|
-
*
|
|
461
|
-
*
|
|
796
|
+
* If the input file is not a valid JSON document (an empty file is not a valid
|
|
797
|
+
* JSON document) an exception is raised.
|
|
798
|
+
*
|
|
799
|
+
* This is a stream based parser which allows a large or huge file to be loaded
|
|
800
|
+
* without pulling the whole file into memory.
|
|
801
|
+
*
|
|
802
|
+
* A block can be provided with a single argument. That argument will be the
|
|
803
|
+
* parsed JSON document. This is useful when parsing a string that includes
|
|
804
|
+
* multiple JSON documents. The block can take up to 3 arguments, the parsed
|
|
805
|
+
* object, the position in the string or stream of the start of the JSON for
|
|
806
|
+
* that object, and the length of the JSON for that object plus trailing
|
|
807
|
+
* whitespace.
|
|
808
|
+
*
|
|
809
|
+
* - *path* [_String_] to a file containing a JSON document
|
|
810
|
+
* - *options* [_Hash_] load options (same as default_options)
|
|
811
|
+
* - -
|
|
812
|
+
* - *obj* [_Hash_|_Array_|_String_|_Fixnum_|_Float_|_Boolean_|_nil_] parsed object.
|
|
813
|
+
* - *start* [_optional, _Integer_] start position of parsed JSON for obj.
|
|
814
|
+
* - *len* [_optional, _Integer_] length of parsed JSON for obj.
|
|
815
|
+
*
|
|
816
|
+
* Returns [_Object_|_Hash_|_Array_|_String_|_Fixnum_|_Float_|_Boolean_|_nil_]
|
|
462
817
|
*/
|
|
463
818
|
static VALUE
|
|
464
819
|
load_file(int argc, VALUE *argv, VALUE self) {
|
|
465
820
|
char *path;
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
VALUE obj;
|
|
470
|
-
struct _Options options = oj_default_options;
|
|
471
|
-
size_t max_stack = oj_default_options.max_stack;
|
|
821
|
+
int fd;
|
|
822
|
+
Mode mode = oj_default_options.mode;
|
|
823
|
+
struct _ParseInfo pi;
|
|
472
824
|
|
|
825
|
+
if (1 > argc) {
|
|
826
|
+
rb_raise(rb_eArgError, "Wrong number of arguments to load().");
|
|
827
|
+
}
|
|
473
828
|
Check_Type(*argv, T_STRING);
|
|
829
|
+
parse_info_init(&pi);
|
|
830
|
+
pi.options = oj_default_options;
|
|
831
|
+
pi.handler = Qnil;
|
|
832
|
+
pi.err_class = Qnil;
|
|
833
|
+
pi.max_depth = 0;
|
|
834
|
+
if (2 <= argc) {
|
|
835
|
+
VALUE ropts = argv[1];
|
|
836
|
+
VALUE v;
|
|
837
|
+
|
|
838
|
+
Check_Type(ropts, T_HASH);
|
|
839
|
+
if (Qnil != (v = rb_hash_lookup(ropts, mode_sym))) {
|
|
840
|
+
if (object_sym == v) {
|
|
841
|
+
mode = ObjectMode;
|
|
842
|
+
} else if (strict_sym == v) {
|
|
843
|
+
mode = StrictMode;
|
|
844
|
+
} else if (compat_sym == v || json_sym == v) {
|
|
845
|
+
mode = CompatMode;
|
|
846
|
+
} else if (null_sym == v) {
|
|
847
|
+
mode = NullMode;
|
|
848
|
+
} else if (custom_sym == v) {
|
|
849
|
+
mode = CustomMode;
|
|
850
|
+
} else if (rails_sym == v) {
|
|
851
|
+
mode = RailsMode;
|
|
852
|
+
} else {
|
|
853
|
+
rb_raise(rb_eArgError, ":mode must be :object, :strict, :compat, :null, :custom, :rails.");
|
|
854
|
+
}
|
|
855
|
+
}
|
|
856
|
+
}
|
|
474
857
|
path = StringValuePtr(*argv);
|
|
475
|
-
if (0 == (
|
|
858
|
+
if (0 == (fd = open(path, O_RDONLY))) {
|
|
476
859
|
rb_raise(rb_eIOError, "%s", strerror(errno));
|
|
477
860
|
}
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
json[len] = '\0';
|
|
492
|
-
if (2 <= argc) {
|
|
493
|
-
parse_options(argv[1], &options);
|
|
494
|
-
}
|
|
495
|
-
obj = oj_parse(json, &options);
|
|
496
|
-
if (max_stack < len) {
|
|
497
|
-
xfree(json);
|
|
861
|
+
switch (mode) {
|
|
862
|
+
case StrictMode:
|
|
863
|
+
oj_set_strict_callbacks(&pi);
|
|
864
|
+
return oj_pi_sparse(argc, argv, &pi, fd);
|
|
865
|
+
case NullMode:
|
|
866
|
+
case CompatMode:
|
|
867
|
+
case CustomMode:
|
|
868
|
+
case RailsMode:
|
|
869
|
+
oj_set_compat_callbacks(&pi);
|
|
870
|
+
return oj_pi_sparse(argc, argv, &pi, fd);
|
|
871
|
+
case ObjectMode:
|
|
872
|
+
default:
|
|
873
|
+
break;
|
|
498
874
|
}
|
|
499
|
-
|
|
875
|
+
oj_set_object_callbacks(&pi);
|
|
876
|
+
|
|
877
|
+
return oj_pi_sparse(argc, argv, &pi, fd);
|
|
500
878
|
}
|
|
501
879
|
|
|
502
|
-
/*
|
|
880
|
+
/* Document-method: safe_load
|
|
881
|
+
* call-seq: safe_load(doc)
|
|
882
|
+
*
|
|
883
|
+
* Loads a JSON document in strict mode with :auto_define and :symbol_keys
|
|
884
|
+
* turned off. This function should be safe to use with JSON received on an
|
|
885
|
+
* unprotected public interface.
|
|
886
|
+
*
|
|
887
|
+
* - *doc* [_String__|_IO_] JSON String or IO to load.
|
|
888
|
+
*
|
|
889
|
+
* Returns [_Hash_|_Array_|_String_|_Fixnum_|_Bignum_|_BigDecimal_|_nil_|_True_|_False_]
|
|
890
|
+
*/
|
|
891
|
+
static VALUE
|
|
892
|
+
safe_load(VALUE self, VALUE doc) {
|
|
893
|
+
struct _ParseInfo pi;
|
|
894
|
+
VALUE args[1];
|
|
895
|
+
|
|
896
|
+
parse_info_init(&pi);
|
|
897
|
+
pi.err_class = Qnil;
|
|
898
|
+
pi.max_depth = 0;
|
|
899
|
+
pi.options = oj_default_options;
|
|
900
|
+
pi.options.auto_define = No;
|
|
901
|
+
pi.options.sym_key = No;
|
|
902
|
+
pi.options.mode = StrictMode;
|
|
903
|
+
oj_set_strict_callbacks(&pi);
|
|
904
|
+
*args = doc;
|
|
905
|
+
|
|
906
|
+
return oj_pi_parse(1, args, &pi, 0, 0, 1);
|
|
907
|
+
}
|
|
908
|
+
|
|
909
|
+
/* Document-method: saj_parse
|
|
910
|
+
* call-seq: saj_parse(handler, io)
|
|
911
|
+
*
|
|
912
|
+
* Parses an IO stream or file containing a JSON document. Raises an exception
|
|
913
|
+
* if the JSON is malformed. This is a callback parser that calls the methods in
|
|
914
|
+
* the handler if they exist. A sample is the Oj::Saj class which can be used as
|
|
915
|
+
* a base class for the handler.
|
|
916
|
+
*
|
|
917
|
+
* - *handler* [_Oj::Saj_] responds to Oj::Saj methods
|
|
918
|
+
* - *io* [_IO_|_String_] IO Object to read from
|
|
919
|
+
*/
|
|
920
|
+
|
|
921
|
+
/* Document-method: sc_parse
|
|
922
|
+
* call-seq: sc_parse(handler, io)
|
|
923
|
+
*
|
|
924
|
+
* Parses an IO stream or file containing a JSON document. Raises an exception
|
|
925
|
+
* if the JSON is malformed. This is a callback parser (Simple Callback Parser)
|
|
926
|
+
* that calls the methods in the handler if they exist. A sample is the
|
|
927
|
+
* Oj::ScHandler class which can be used as a base class for the handler. This
|
|
928
|
+
* callback parser is slightly more efficient than the Saj callback parser and
|
|
929
|
+
* requires less argument checking.
|
|
930
|
+
*
|
|
931
|
+
* - *handler* [_Oj_::ScHandler_] responds to Oj::ScHandler methods
|
|
932
|
+
* - *io* [_IO__|_String_] IO Object to read from
|
|
933
|
+
*/
|
|
934
|
+
|
|
935
|
+
/* Document-method: dump
|
|
936
|
+
* call-seq: dump(obj, options)
|
|
503
937
|
*
|
|
504
938
|
* Dumps an Object (obj) to a string.
|
|
505
|
-
*
|
|
506
|
-
*
|
|
939
|
+
* - *obj* [_Object_] Object to serialize as an JSON document String
|
|
940
|
+
* - *options* [_Hash_] same as default_options
|
|
507
941
|
*/
|
|
508
942
|
static VALUE
|
|
509
943
|
dump(int argc, VALUE *argv, VALUE self) {
|
|
510
|
-
char
|
|
944
|
+
char buf[4096];
|
|
945
|
+
struct _Out out;
|
|
511
946
|
struct _Options copts = oj_default_options;
|
|
512
947
|
VALUE rstr;
|
|
513
|
-
|
|
948
|
+
|
|
949
|
+
if (1 > argc) {
|
|
950
|
+
rb_raise(rb_eArgError, "wrong number of arguments (0 for 1).");
|
|
951
|
+
}
|
|
514
952
|
if (2 == argc) {
|
|
515
|
-
|
|
953
|
+
oj_parse_options(argv[1], &copts);
|
|
516
954
|
}
|
|
517
|
-
if (
|
|
955
|
+
if (CompatMode == copts.mode) {
|
|
956
|
+
copts.to_json = No;
|
|
957
|
+
copts.dump_opts.nan_dump = true;
|
|
958
|
+
}
|
|
959
|
+
out.buf = buf;
|
|
960
|
+
out.end = buf + sizeof(buf) - 10;
|
|
961
|
+
out.allocated = 0;
|
|
962
|
+
out.omit_nil = copts.dump_opts.omit_nil;
|
|
963
|
+
out.caller = CALLER_DUMP;
|
|
964
|
+
oj_dump_obj_to_json(*argv, &copts, &out);
|
|
965
|
+
if (0 == out.buf) {
|
|
518
966
|
rb_raise(rb_eNoMemError, "Not enough memory.");
|
|
519
967
|
}
|
|
520
|
-
rstr = rb_str_new2(
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
968
|
+
rstr = rb_str_new2(out.buf);
|
|
969
|
+
rstr = oj_encode(rstr);
|
|
970
|
+
if (out.allocated) {
|
|
971
|
+
xfree(out.buf);
|
|
972
|
+
}
|
|
526
973
|
return rstr;
|
|
527
974
|
}
|
|
528
975
|
|
|
976
|
+
/* Document-method: to_json
|
|
977
|
+
* call-seq: to_json(obj, options)
|
|
978
|
+
*
|
|
979
|
+
* Dumps an Object (obj) to a string. If the object has a to_json method that
|
|
980
|
+
* will be called. The mode is set to :compat.
|
|
981
|
+
* - *obj* [_Object_] Object to serialize as an JSON document String
|
|
982
|
+
* - *options* [_Hash_]
|
|
983
|
+
* - *:max_nesting* [_boolean_] It true nesting is limited to 100. The option to detect circular references is available but is not compatible with the json gem., default is false
|
|
984
|
+
* - *:allow_nan* [_boolean_] If true non JSON compliant words such as Nan and Infinity will be used as appropriate, default is true.
|
|
985
|
+
* - *:quirks_mode* [_boolean_] Allow single JSON values instead of documents, default is true (allow).
|
|
986
|
+
* - *:indent_str* [_String_|_nil_] String to use for indentation, overriding the indent option if not nil.
|
|
987
|
+
* - *:space* [_String_|_nil_] String to use for the space after the colon in JSON object fields.
|
|
988
|
+
* - *:space_before* [_String_|_nil_] String to use before the colon separator in JSON object fields.
|
|
989
|
+
* - *:object_nl* [_String_|_nil_] String to use after a JSON object field value.
|
|
990
|
+
* - *:array_nl* [_String_|_nil_] String to use after a JSON array value.
|
|
991
|
+
*
|
|
992
|
+
* Returns [_String_] the encoded JSON.
|
|
993
|
+
*/
|
|
994
|
+
static VALUE
|
|
995
|
+
to_json(int argc, VALUE *argv, VALUE self) {
|
|
996
|
+
char buf[4096];
|
|
997
|
+
struct _Out out;
|
|
998
|
+
struct _Options copts = oj_default_options;
|
|
999
|
+
VALUE rstr;
|
|
1000
|
+
|
|
1001
|
+
if (1 > argc) {
|
|
1002
|
+
rb_raise(rb_eArgError, "wrong number of arguments (0 for 1).");
|
|
1003
|
+
}
|
|
1004
|
+
copts.dump_opts.nan_dump = false;
|
|
1005
|
+
if (2 == argc) {
|
|
1006
|
+
oj_parse_mimic_dump_options(argv[1], &copts);
|
|
1007
|
+
}
|
|
1008
|
+
copts.mode = CompatMode;
|
|
1009
|
+
copts.to_json = Yes;
|
|
1010
|
+
out.buf = buf;
|
|
1011
|
+
out.end = buf + sizeof(buf) - 10;
|
|
1012
|
+
out.allocated = 0;
|
|
1013
|
+
out.omit_nil = copts.dump_opts.omit_nil;
|
|
1014
|
+
// For obj.to_json or generate nan is not allowed but if called from dump
|
|
1015
|
+
// it is.
|
|
1016
|
+
copts.dump_opts.nan_dump = false;
|
|
1017
|
+
oj_dump_obj_to_json(*argv, &copts, &out);
|
|
1018
|
+
if (0 == out.buf) {
|
|
1019
|
+
rb_raise(rb_eNoMemError, "Not enough memory.");
|
|
1020
|
+
}
|
|
1021
|
+
rstr = rb_str_new2(out.buf);
|
|
1022
|
+
rstr = oj_encode(rstr);
|
|
1023
|
+
if (out.allocated) {
|
|
1024
|
+
xfree(out.buf);
|
|
1025
|
+
}
|
|
1026
|
+
return rstr;
|
|
1027
|
+
}
|
|
529
1028
|
|
|
530
|
-
/*
|
|
1029
|
+
/* Document-method: to_file
|
|
1030
|
+
* call-seq: to_file(file_path, obj, options)
|
|
531
1031
|
*
|
|
532
1032
|
* Dumps an Object to the specified file.
|
|
533
|
-
*
|
|
534
|
-
*
|
|
535
|
-
*
|
|
536
|
-
*
|
|
537
|
-
*
|
|
1033
|
+
* - *file* [_String_] _path file path to write the JSON document to
|
|
1034
|
+
* - *obj* [_Object_] Object to serialize as an JSON document String
|
|
1035
|
+
* - *options* [_Hash_] formating options
|
|
1036
|
+
* - *:indent* [_Fixnum_] format expected
|
|
1037
|
+
* - *:circular* [_Boolean_] allow circular references, default: false
|
|
538
1038
|
*/
|
|
539
1039
|
static VALUE
|
|
540
1040
|
to_file(int argc, VALUE *argv, VALUE self) {
|
|
541
1041
|
struct _Options copts = oj_default_options;
|
|
542
1042
|
|
|
543
1043
|
if (3 == argc) {
|
|
544
|
-
|
|
1044
|
+
oj_parse_options(argv[2], &copts);
|
|
545
1045
|
}
|
|
546
1046
|
Check_Type(*argv, T_STRING);
|
|
547
1047
|
oj_write_obj_to_file(argv[1], StringValuePtr(*argv), &copts);
|
|
@@ -549,438 +1049,444 @@ to_file(int argc, VALUE *argv, VALUE self) {
|
|
|
549
1049
|
return Qnil;
|
|
550
1050
|
}
|
|
551
1051
|
|
|
552
|
-
/*
|
|
1052
|
+
/* Document-method: to_stream
|
|
1053
|
+
* call-seq: to_stream(io, obj, options)
|
|
553
1054
|
*
|
|
554
|
-
*
|
|
555
|
-
*
|
|
556
|
-
*
|
|
557
|
-
*
|
|
1055
|
+
* Dumps an Object to the specified IO stream.
|
|
1056
|
+
* - *io* [_IO_] IO stream to write the JSON document to
|
|
1057
|
+
* - *obj* [_Object_] Object to serialize as an JSON document String
|
|
1058
|
+
* - *options* [_Hash_] formating options
|
|
1059
|
+
* - *:indent* [_Fixnum_] format expected
|
|
1060
|
+
* - *:circular* [_Boolean_] allow circular references, default: false
|
|
558
1061
|
*/
|
|
559
1062
|
static VALUE
|
|
560
|
-
|
|
1063
|
+
to_stream(int argc, VALUE *argv, VALUE self) {
|
|
561
1064
|
struct _Options copts = oj_default_options;
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
if (argc < 2) {
|
|
567
|
-
rb_raise(rb_eArgError, "Wrong number of arguments to saj_parse.\n");
|
|
568
|
-
}
|
|
569
|
-
if (rb_type(input) == T_STRING) {
|
|
570
|
-
// the json string gets modified so make a copy of it
|
|
571
|
-
len = RSTRING_LEN(input) + 1;
|
|
572
|
-
if (copts.max_stack < len) {
|
|
573
|
-
json = ALLOC_N(char, len);
|
|
574
|
-
} else {
|
|
575
|
-
json = ALLOCA_N(char, len);
|
|
576
|
-
}
|
|
577
|
-
strcpy(json, StringValuePtr(input));
|
|
578
|
-
} else {
|
|
579
|
-
VALUE clas = rb_obj_class(input);
|
|
580
|
-
VALUE s;
|
|
581
|
-
|
|
582
|
-
if (oj_stringio_class == clas) {
|
|
583
|
-
s = rb_funcall2(input, oj_string_id, 0, 0);
|
|
584
|
-
len = RSTRING_LEN(s) + 1;
|
|
585
|
-
if (copts.max_stack < len) {
|
|
586
|
-
json = ALLOC_N(char, len);
|
|
587
|
-
} else {
|
|
588
|
-
json = ALLOCA_N(char, len);
|
|
589
|
-
}
|
|
590
|
-
strcpy(json, StringValuePtr(s));
|
|
591
|
-
#ifndef JRUBY_RUBY
|
|
592
|
-
#if !IS_WINDOWS
|
|
593
|
-
// JRuby gets confused with what is the real fileno.
|
|
594
|
-
} else if (rb_respond_to(input, oj_fileno_id) && Qnil != (s = rb_funcall(input, oj_fileno_id, 0))) {
|
|
595
|
-
int fd = FIX2INT(s);
|
|
596
|
-
ssize_t cnt;
|
|
597
|
-
|
|
598
|
-
len = lseek(fd, 0, SEEK_END);
|
|
599
|
-
lseek(fd, 0, SEEK_SET);
|
|
600
|
-
if (copts.max_stack < len) {
|
|
601
|
-
json = ALLOC_N(char, len + 1);
|
|
602
|
-
} else {
|
|
603
|
-
json = ALLOCA_N(char, len + 1);
|
|
604
|
-
}
|
|
605
|
-
if (0 >= (cnt = read(fd, json, len)) || cnt != (ssize_t)len) {
|
|
606
|
-
rb_raise(rb_eIOError, "failed to read from IO Object.");
|
|
607
|
-
}
|
|
608
|
-
json[len] = '\0';
|
|
609
|
-
#endif
|
|
610
|
-
#endif
|
|
611
|
-
} else if (rb_respond_to(input, oj_read_id)) {
|
|
612
|
-
s = rb_funcall2(input, oj_read_id, 0, 0);
|
|
613
|
-
len = RSTRING_LEN(s) + 1;
|
|
614
|
-
if (copts.max_stack < len) {
|
|
615
|
-
json = ALLOC_N(char, len);
|
|
616
|
-
} else {
|
|
617
|
-
json = ALLOCA_N(char, len);
|
|
618
|
-
}
|
|
619
|
-
strcpy(json, StringValuePtr(s));
|
|
620
|
-
} else {
|
|
621
|
-
rb_raise(rb_eArgError, "saj_parse() expected a String or IO Object.");
|
|
622
|
-
}
|
|
623
|
-
}
|
|
624
|
-
oj_saj_parse(*argv, json);
|
|
625
|
-
if (copts.max_stack < len) {
|
|
626
|
-
xfree(json);
|
|
1065
|
+
|
|
1066
|
+
if (3 == argc) {
|
|
1067
|
+
oj_parse_options(argv[2], &copts);
|
|
627
1068
|
}
|
|
1069
|
+
oj_write_obj_to_stream(argv[1], *argv, &copts);
|
|
1070
|
+
|
|
628
1071
|
return Qnil;
|
|
629
1072
|
}
|
|
630
1073
|
|
|
631
|
-
|
|
632
|
-
|
|
1074
|
+
/* Document-method: register_odd
|
|
1075
|
+
* call-seq: register_odd(clas, create_object, create_method, *members)
|
|
1076
|
+
*
|
|
1077
|
+
* Registers a class as special. This is useful for working around subclasses of
|
|
1078
|
+
* primitive types as is done with ActiveSupport classes. The use of this
|
|
1079
|
+
* function should be limited to just classes that can not be handled in the
|
|
1080
|
+
* normal way. It is not intended as a hook for changing the output of all
|
|
1081
|
+
* classes as it is not optimized for large numbers of classes.
|
|
1082
|
+
*
|
|
1083
|
+
* - *clas* [_Class__|_Module_] Class or Module to be made special
|
|
1084
|
+
* - *create_object* [_Object_] object to call the create method on
|
|
1085
|
+
* - *create_method* [_Symbol_] method on the clas that will create a new instance of the clas when given all the member values in the order specified.
|
|
1086
|
+
* - *members* [_Symbol__|_String_] methods used to get the member values from instances of the clas.
|
|
1087
|
+
*/
|
|
633
1088
|
static VALUE
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
VALUE rstr;
|
|
638
|
-
|
|
639
|
-
if (0 == (json = oj_write_obj_to_str(*argv, &copts))) {
|
|
640
|
-
rb_raise(rb_eNoMemError, "Not enough memory.");
|
|
1089
|
+
register_odd(int argc, VALUE *argv, VALUE self) {
|
|
1090
|
+
if (3 > argc) {
|
|
1091
|
+
rb_raise(rb_eArgError, "incorrect number of arguments.");
|
|
641
1092
|
}
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
*args = rstr;
|
|
651
|
-
rb_funcall2(io, oj_write_id, 1, args);
|
|
652
|
-
rstr = io;
|
|
1093
|
+
switch (rb_type(*argv)) {
|
|
1094
|
+
case T_CLASS:
|
|
1095
|
+
case T_MODULE:
|
|
1096
|
+
break;
|
|
1097
|
+
default:
|
|
1098
|
+
rb_raise(rb_eTypeError, "expected a class or module.");
|
|
1099
|
+
break;
|
|
653
1100
|
}
|
|
654
|
-
|
|
1101
|
+
Check_Type(argv[2], T_SYMBOL);
|
|
1102
|
+
if (MAX_ODD_ARGS < argc - 2) {
|
|
1103
|
+
rb_raise(rb_eArgError, "too many members.");
|
|
1104
|
+
}
|
|
1105
|
+
oj_reg_odd(argv[0], argv[1], argv[2], argc - 3, argv + 3, false);
|
|
655
1106
|
|
|
656
|
-
return
|
|
1107
|
+
return Qnil;
|
|
657
1108
|
}
|
|
658
1109
|
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
1110
|
+
/* Document-method: register_odd_raw
|
|
1111
|
+
* call-seq: register_odd_raw(clas, create_object, create_method, dump_method)
|
|
1112
|
+
*
|
|
1113
|
+
* Registers a class as special and expect the output to be a string that can be
|
|
1114
|
+
* included in the dumped JSON directly. This is useful for working around
|
|
1115
|
+
* subclasses of primitive types as is done with ActiveSupport classes. The use
|
|
1116
|
+
* of this function should be limited to just classes that can not be handled in
|
|
1117
|
+
* the normal way. It is not intended as a hook for changing the output of all
|
|
1118
|
+
* classes as it is not optimized for large numbers of classes. Be careful with
|
|
1119
|
+
* this option as the JSON may be incorrect if invalid JSON is returned.
|
|
1120
|
+
*
|
|
1121
|
+
* - *clas* [_Class_|_Module_] Class or Module to be made special
|
|
1122
|
+
* - *create_object* [_Object_] object to call the create method on
|
|
1123
|
+
* - *create_method* [_Symbol_] method on the clas that will create a new instance of the clas when given all the member values in the order specified.
|
|
1124
|
+
* - *dump_method* [_Symbol_|_String_] method to call on the object being serialized to generate the raw JSON.
|
|
1125
|
+
*/
|
|
1126
|
+
static VALUE
|
|
1127
|
+
register_odd_raw(int argc, VALUE *argv, VALUE self) {
|
|
1128
|
+
if (3 > argc) {
|
|
1129
|
+
rb_raise(rb_eArgError, "incorrect number of arguments.");
|
|
1130
|
+
}
|
|
1131
|
+
switch (rb_type(*argv)) {
|
|
1132
|
+
case T_CLASS:
|
|
1133
|
+
case T_MODULE:
|
|
665
1134
|
break;
|
|
666
|
-
case T_ARRAY:
|
|
667
|
-
{
|
|
668
|
-
VALUE *np = RARRAY_PTR(obj);
|
|
669
|
-
size_t cnt = RARRAY_LEN(obj);
|
|
670
|
-
|
|
671
|
-
for (; 0 < cnt; cnt--, np++) {
|
|
672
|
-
mimic_walk(Qnil, *np, proc);
|
|
673
|
-
}
|
|
674
|
-
break;
|
|
675
|
-
}
|
|
676
1135
|
default:
|
|
1136
|
+
rb_raise(rb_eTypeError, "expected a class or module.");
|
|
677
1137
|
break;
|
|
678
1138
|
}
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
}
|
|
683
|
-
} else {
|
|
684
|
-
#if HAS_PROC_WITH_BLOCK
|
|
685
|
-
VALUE args[1];
|
|
686
|
-
|
|
687
|
-
*args = obj;
|
|
688
|
-
rb_proc_call_with_block(proc, 1, args, Qnil);
|
|
689
|
-
#else
|
|
690
|
-
rb_raise(rb_eNotImpError, "Calling a Proc with a block not supported in this version. Use func() {|x| } syntax instead.");
|
|
691
|
-
#endif
|
|
1139
|
+
Check_Type(argv[2], T_SYMBOL);
|
|
1140
|
+
if (MAX_ODD_ARGS < argc - 2) {
|
|
1141
|
+
rb_raise(rb_eArgError, "too many members.");
|
|
692
1142
|
}
|
|
693
|
-
|
|
1143
|
+
oj_reg_odd(argv[0], argv[1], argv[2], 1, argv + 3, true);
|
|
1144
|
+
|
|
1145
|
+
return Qnil;
|
|
694
1146
|
}
|
|
695
1147
|
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
1148
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
1149
|
+
// RDoc entries must be in the same file as the rb_define_method and must be
|
|
1150
|
+
// directly above the C method function. The extern declaration is enough to
|
|
1151
|
+
// get it to work.
|
|
1152
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
700
1153
|
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
1154
|
+
/* Document-method: strict_load
|
|
1155
|
+
* call-seq: strict_load(json, options) { _|_obj, start, len_|_ }
|
|
1156
|
+
*
|
|
1157
|
+
* Parses a JSON document String into an Hash, Array, String, Fixnum, Float,
|
|
1158
|
+
* true, false, or nil. It parses using a mode that is strict in that it maps
|
|
1159
|
+
* each primitive JSON type to a similar Ruby type. The :create_id is not
|
|
1160
|
+
* honored in this mode. Note that a Ruby Hash is used to represent the JSON
|
|
1161
|
+
* Object type. These two are not the same since the JSON Object type can have
|
|
1162
|
+
* repeating entries with the same key and Ruby Hash can not.
|
|
1163
|
+
*
|
|
1164
|
+
* When used with a document that has multiple JSON elements the block, if
|
|
1165
|
+
* any, will be yielded to. If no block then the last element read will be
|
|
1166
|
+
* returned.
|
|
1167
|
+
*
|
|
1168
|
+
* Raises an exception if the JSON is malformed or the classes specified are not
|
|
1169
|
+
* valid. If the input is not a valid JSON document (an empty string is not a
|
|
1170
|
+
* valid JSON document) an exception is raised.
|
|
1171
|
+
*
|
|
1172
|
+
* A block can be provided with a single argument. That argument will be the
|
|
1173
|
+
* parsed JSON document. This is useful when parsing a string that includes
|
|
1174
|
+
* multiple JSON documents. The block can take up to 3 arguments, the parsed
|
|
1175
|
+
* object, the position in the string or stream of the start of the JSON for
|
|
1176
|
+
* that object, and the length of the JSON for that object plus trailing
|
|
1177
|
+
* whitespace.
|
|
1178
|
+
*
|
|
1179
|
+
* - *json* [_String_|_IO_] JSON String or an Object that responds to read().
|
|
1180
|
+
* - *options* [_Hash_] load options (same as default_options).
|
|
1181
|
+
* - -
|
|
1182
|
+
* - *obj* [_Hash_|_Array_|_String_|_Fixnum_|_Float_|_Boolean_|_nil_] parsed object.
|
|
1183
|
+
* - *start* [_optional, _Integer_] start position of parsed JSON for obj.
|
|
1184
|
+
* - *len* [_optional, _Integer_] length of parsed JSON for obj.
|
|
1185
|
+
*
|
|
1186
|
+
* Returns [_Hash_|_Array_|_String_|_Fixnum_|_Float_|_Boolean_|_nil_]
|
|
1187
|
+
*/
|
|
1188
|
+
extern VALUE oj_strict_parse(int argc, VALUE *argv, VALUE self);
|
|
705
1189
|
|
|
706
|
-
|
|
707
|
-
}
|
|
1190
|
+
/* Document-method: compat_load
|
|
1191
|
+
* call-seq: compat_load(json, options) { _|_obj, start, len_|_ }
|
|
1192
|
+
*
|
|
1193
|
+
* Parses a JSON document String into an Object, Hash, Array, String, Fixnum,
|
|
1194
|
+
* Float, true, false, or nil. It parses using a mode that is generally
|
|
1195
|
+
* compatible with other Ruby JSON parsers in that it will create objects based
|
|
1196
|
+
* on the :create_id value. It is not compatible in every way to every other
|
|
1197
|
+
* parser though as each parser has it's own variations.
|
|
1198
|
+
*
|
|
1199
|
+
* When used with a document that has multiple JSON elements the block, if
|
|
1200
|
+
* any, will be yielded to. If no block then the last element read will be
|
|
1201
|
+
* returned.
|
|
1202
|
+
*
|
|
1203
|
+
* Raises an exception if the JSON is malformed or the classes specified are not
|
|
1204
|
+
* valid. If the input is not a valid JSON document (an empty string is not a
|
|
1205
|
+
* valid JSON document) an exception is raised.
|
|
1206
|
+
*
|
|
1207
|
+
* A block can be provided with a single argument. That argument will be the
|
|
1208
|
+
* parsed JSON document. This is useful when parsing a string that includes
|
|
1209
|
+
* multiple JSON documents. The block can take up to 3 arguments, the parsed
|
|
1210
|
+
* object, the position in the string or stream of the start of the JSON for
|
|
1211
|
+
* that object, and the length of the JSON for that object plus trailing
|
|
1212
|
+
* whitespace.
|
|
1213
|
+
*
|
|
1214
|
+
* - *json* [_String_|_IO_] JSON String or an Object that responds to read().
|
|
1215
|
+
* - *options* [_Hash_] load options (same as default_options).
|
|
1216
|
+
* - -
|
|
1217
|
+
* - *obj* [_Hash_|_Array_|_String_|_Fixnum_|_Float_|_Boolean_|_nil_] parsed object.
|
|
1218
|
+
* - *start* [_optional, _Integer_] start position of parsed JSON for obj.
|
|
1219
|
+
* - *len* [_optional, _Integer_] length of parsed JSON for obj.
|
|
1220
|
+
*
|
|
1221
|
+
* Returns [_Hash_|_Array_|_String_|_Fixnum_|_Float_|_Boolean_|_nil_]
|
|
1222
|
+
*/
|
|
1223
|
+
extern VALUE oj_compat_parse(int argc, VALUE *argv, VALUE self);
|
|
708
1224
|
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
1225
|
+
/* Document-method: object_load
|
|
1226
|
+
* call-seq: object_load(json, options) { _|_obj, start, len_|_ }
|
|
1227
|
+
*
|
|
1228
|
+
* Parses a JSON document String into an Object, Hash, Array, String, Fixnum,
|
|
1229
|
+
* Float, true, false, or nil. In the :object mode the JSON should have been
|
|
1230
|
+
* generated by Oj.dump(). The parser will reconstitute the original marshalled
|
|
1231
|
+
* or dumped Object. The :auto_define and :circular options have meaning with
|
|
1232
|
+
* this parsing mode.
|
|
1233
|
+
*
|
|
1234
|
+
* Raises an exception if the JSON is malformed or the classes specified are not
|
|
1235
|
+
* valid. If the input is not a valid JSON document (an empty string is not a
|
|
1236
|
+
* valid JSON document) an exception is raised.
|
|
1237
|
+
*
|
|
1238
|
+
* Note: Oj is not able to automatically deserialize all classes that are a
|
|
1239
|
+
* subclass of a Ruby Exception. Only exception that take one required string
|
|
1240
|
+
* argument in the initialize() method are supported. This is an example of how
|
|
1241
|
+
* to write an Exception subclass that supports both a single string intializer
|
|
1242
|
+
* and an Exception as an argument. Additional optional arguments can be added
|
|
1243
|
+
* as well.
|
|
1244
|
+
*
|
|
1245
|
+
* The reason for this restriction has to do with a design decision on the part
|
|
1246
|
+
* of the Ruby developers. Exceptions are special Objects. They do not follow the
|
|
1247
|
+
* rules of other Objects. Exceptions have 'mesg' and a 'bt' attribute. Note that
|
|
1248
|
+
* these are not '@mesg' and '@bt'. They can not be set using the normal C or
|
|
1249
|
+
* Ruby calls. The only way I have found to set the 'mesg' attribute is through
|
|
1250
|
+
* the initializer. Unfortunately that means any subclass that provides a
|
|
1251
|
+
* different initializer can not be automatically decoded. A way around this is
|
|
1252
|
+
* to use a create function but this example shows an alternative.
|
|
1253
|
+
*
|
|
1254
|
+
* A block can be provided with a single argument. That argument will be the
|
|
1255
|
+
* parsed JSON document. This is useful when parsing a string that includes
|
|
1256
|
+
* multiple JSON documents. The block can take up to 3 arguments, the parsed
|
|
1257
|
+
* object, the position in the string or stream of the start of the JSON for
|
|
1258
|
+
* that object, and the length of the JSON for that object plus trailing
|
|
1259
|
+
* whitespace.
|
|
1260
|
+
*
|
|
1261
|
+
* - *json* [_String_|_IO_] JSON String or an Object that responds to read().
|
|
1262
|
+
* - *options* [_Hash_] load options (same as default_options).
|
|
1263
|
+
* - -
|
|
1264
|
+
* - *obj* [_Hash_|_Array_|_String_|_Fixnum_|_Float_|_Boolean_|_nil_] parsed object.
|
|
1265
|
+
* - *start* [_optional, _Integer_] start position of parsed JSON for obj.
|
|
1266
|
+
* - *len* [_optional, _Integer_] length of parsed JSON for obj.
|
|
1267
|
+
*
|
|
1268
|
+
* Returns [_Hash_|_Array_|_String_|_Fixnum_|_Float_|_Boolean_|_nil_]
|
|
1269
|
+
*/
|
|
1270
|
+
extern VALUE oj_object_parse(int argc, VALUE *argv, VALUE self);
|
|
720
1271
|
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
if (0 == copts->dump_opts) {
|
|
738
|
-
copts->dump_opts = &dump_opts;
|
|
739
|
-
}
|
|
740
|
-
copts->dump_opts->indent = StringValuePtr(v);
|
|
741
|
-
copts->dump_opts->indent_size = (uint8_t)strlen(copts->dump_opts->indent);
|
|
742
|
-
}
|
|
743
|
-
if (Qnil != (v = rb_hash_lookup(ropts, space_sym))) {
|
|
744
|
-
rb_check_type(v, T_STRING);
|
|
745
|
-
if (0 == copts->dump_opts) {
|
|
746
|
-
copts->dump_opts = &dump_opts;
|
|
747
|
-
}
|
|
748
|
-
copts->dump_opts->after_sep = StringValuePtr(v);
|
|
749
|
-
copts->dump_opts->after_size = (uint8_t)strlen(copts->dump_opts->after_sep);
|
|
750
|
-
}
|
|
751
|
-
if (Qnil != (v = rb_hash_lookup(ropts, space_before_sym))) {
|
|
752
|
-
rb_check_type(v, T_STRING);
|
|
753
|
-
if (0 == copts->dump_opts) {
|
|
754
|
-
copts->dump_opts = &dump_opts;
|
|
755
|
-
}
|
|
756
|
-
copts->dump_opts->before_sep = StringValuePtr(v);
|
|
757
|
-
copts->dump_opts->before_size = (uint8_t)strlen(copts->dump_opts->before_sep);
|
|
758
|
-
}
|
|
759
|
-
if (Qnil != (v = rb_hash_lookup(ropts, object_nl_sym))) {
|
|
760
|
-
rb_check_type(v, T_STRING);
|
|
761
|
-
if (0 == copts->dump_opts) {
|
|
762
|
-
copts->dump_opts = &dump_opts;
|
|
763
|
-
}
|
|
764
|
-
copts->dump_opts->hash_nl = StringValuePtr(v);
|
|
765
|
-
copts->dump_opts->hash_size = (uint8_t)strlen(copts->dump_opts->hash_nl);
|
|
766
|
-
}
|
|
767
|
-
if (Qnil != (v = rb_hash_lookup(ropts, array_nl_sym))) {
|
|
768
|
-
rb_check_type(v, T_STRING);
|
|
769
|
-
if (0 == copts->dump_opts) {
|
|
770
|
-
copts->dump_opts = &dump_opts;
|
|
771
|
-
}
|
|
772
|
-
copts->dump_opts->array_nl = StringValuePtr(v);
|
|
773
|
-
copts->dump_opts->array_size = (uint8_t)strlen(copts->dump_opts->array_nl);
|
|
774
|
-
}
|
|
775
|
-
// :allow_nan is not supported as Oj always allows_nan
|
|
776
|
-
// :max_nesting is always set to 100
|
|
777
|
-
}
|
|
778
|
-
if (0 == (json = oj_write_obj_to_str(*argv, copts))) {
|
|
779
|
-
rb_raise(rb_eNoMemError, "Not enough memory.");
|
|
780
|
-
}
|
|
781
|
-
rstr = rb_str_new2(json);
|
|
782
|
-
#if HAS_ENCODING_SUPPORT
|
|
783
|
-
rb_enc_associate(rstr, oj_utf8_encoding);
|
|
784
|
-
#endif
|
|
785
|
-
xfree(json);
|
|
1272
|
+
/* Document-method: add_to_json
|
|
1273
|
+
* call-seq: add_to_json(*args)
|
|
1274
|
+
*
|
|
1275
|
+
* Override simple to_s dump behavior in :compat mode to instead use an
|
|
1276
|
+
* optimized dump that includes the classname and attributes so that the
|
|
1277
|
+
* object can be re-created on load. The format is the same as the json gem
|
|
1278
|
+
* but does not use the ruby methods for encoding.
|
|
1279
|
+
*
|
|
1280
|
+
* The classes supported for optimization are: Array, BigDecimal, Complex,
|
|
1281
|
+
* Date, DateTime, Exception, Hash, Integer, OpenStruct, Range, Rational,
|
|
1282
|
+
* Regexp, Struct, and Time. Providing no classes will result in all those
|
|
1283
|
+
* classes being optimized.q
|
|
1284
|
+
*
|
|
1285
|
+
* - *args( [_Class_] zero or more classes to optimize.
|
|
1286
|
+
*/
|
|
1287
|
+
extern VALUE oj_add_to_json(int argc, VALUE *argv, VALUE self);
|
|
786
1288
|
|
|
787
|
-
|
|
788
|
-
|
|
1289
|
+
/* @!method remove_to_json(*args)
|
|
1290
|
+
*
|
|
1291
|
+
* Reverts back to the to_s dump behavior in :compat mode to instead use an
|
|
1292
|
+
* optimized dump that includes the classname and attributes so that the
|
|
1293
|
+
* object can be re-created on load. The format is the same as the json gem
|
|
1294
|
+
* but does not use the ruby methods for encoding.
|
|
1295
|
+
*
|
|
1296
|
+
* The classes supported for optimization are: Array, BigDecimal, Complex,
|
|
1297
|
+
* Date, DateTime, Exception, Hash, Integer, OpenStruct, Range, Rational,
|
|
1298
|
+
* Regexp, Struct, and Time. Providing no classes will result in all those
|
|
1299
|
+
* classes being reverted from the optimized mode.
|
|
1300
|
+
*
|
|
1301
|
+
* - *args* [_Class_] zero or more classes to optimize.
|
|
1302
|
+
*/
|
|
1303
|
+
extern VALUE oj_remove_to_json(int argc, VALUE *argv, VALUE self);
|
|
789
1304
|
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
1305
|
+
/* Document-method: mimic_JSON
|
|
1306
|
+
* call-seq: mimic_JSON()
|
|
1307
|
+
*
|
|
1308
|
+
* Creates the JSON module with methods and classes to mimic the JSON gem. After
|
|
1309
|
+
* this method is invoked calls that expect the JSON module will use Oj instead
|
|
1310
|
+
* and be faster than the original JSON. Most options that could be passed to
|
|
1311
|
+
* the JSON methods are supported. The calls to set parser or generator will not
|
|
1312
|
+
* raise an Exception but will not have any effect. The method can also be
|
|
1313
|
+
* called after the json gem is loaded. The necessary methods on the json gem
|
|
1314
|
+
* will be replaced with Oj methods.
|
|
1315
|
+
*
|
|
1316
|
+
* Note that this also sets the default options of :mode to :compat and
|
|
1317
|
+
* :encoding to :ascii.
|
|
1318
|
+
*
|
|
1319
|
+
* Returns [_Module_] the JSON module.
|
|
1320
|
+
*/
|
|
1321
|
+
extern VALUE oj_define_mimic_json(int argc, VALUE *argv, VALUE self);
|
|
793
1322
|
|
|
794
|
-
|
|
795
|
-
|
|
1323
|
+
/* Document-method: generate
|
|
1324
|
+
* call-seq: generate(obj, opts=nil)
|
|
1325
|
+
*
|
|
1326
|
+
* Encode obj as a JSON String. The obj argument must be a Hash, Array, or
|
|
1327
|
+
* respond to to_h or to_json. Options other than those listed such as
|
|
1328
|
+
* +:allow_nan+ or +:max_nesting+ are ignored.
|
|
1329
|
+
*
|
|
1330
|
+
* - *obj* [_Object__|_Hash_|_Array_] object to convert to a JSON String
|
|
1331
|
+
* - *opts* [_Hash_] options
|
|
1332
|
+
* - - *:indent* [_String_] String to use for indentation.
|
|
1333
|
+
* - *:space* [_String_] String placed after a , or : delimiter
|
|
1334
|
+
* - *:space * _before [_String_] String placed before a : delimiter
|
|
1335
|
+
* - *:object_nl* [_String_] String placed after a JSON object
|
|
1336
|
+
* - *:array_nl* [_String_] String placed after a JSON array
|
|
1337
|
+
* - *:ascii_only* [_Boolean_] if not nil or false then use only ascii characters in the output. Note JSON.generate does support this even if it is not documented.
|
|
1338
|
+
*
|
|
1339
|
+
* Returns [_String_]generated JSON.
|
|
1340
|
+
*/
|
|
1341
|
+
extern VALUE oj_mimic_generate(int argc, VALUE *argv, VALUE self);
|
|
1342
|
+
|
|
1343
|
+
/*
|
|
1344
|
+
extern void oj_hash_test();
|
|
796
1345
|
|
|
797
1346
|
static VALUE
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
dump_opts.indent = " ";
|
|
803
|
-
dump_opts.indent_size = (uint8_t)strlen(dump_opts.indent);
|
|
804
|
-
dump_opts.before_sep = " ";
|
|
805
|
-
dump_opts.before_size = (uint8_t)strlen(dump_opts.before_sep);
|
|
806
|
-
dump_opts.after_sep = " ";
|
|
807
|
-
dump_opts.after_size = (uint8_t)strlen(dump_opts.after_sep);
|
|
808
|
-
dump_opts.hash_nl = "\n";
|
|
809
|
-
dump_opts.hash_size = (uint8_t)strlen(dump_opts.hash_nl);
|
|
810
|
-
dump_opts.array_nl = "\n";
|
|
811
|
-
dump_opts.array_size = (uint8_t)strlen(dump_opts.array_nl);
|
|
812
|
-
copts.dump_opts = &dump_opts;
|
|
813
|
-
|
|
814
|
-
return mimic_generate_core(argc, argv, &copts);
|
|
1347
|
+
hash_test(VALUE self) {
|
|
1348
|
+
oj_hash_test();
|
|
1349
|
+
return Qnil;
|
|
815
1350
|
}
|
|
1351
|
+
*/
|
|
816
1352
|
|
|
1353
|
+
#if !HAS_ENCODING_SUPPORT
|
|
817
1354
|
static VALUE
|
|
818
|
-
|
|
819
|
-
|
|
1355
|
+
iconv_encoder(VALUE x) {
|
|
1356
|
+
VALUE iconv;
|
|
820
1357
|
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
}
|
|
824
|
-
if (2 <= argc && Qnil != argv[1]) {
|
|
825
|
-
VALUE ropts = argv[1];
|
|
826
|
-
VALUE v;
|
|
1358
|
+
rb_require("iconv");
|
|
1359
|
+
iconv = rb_const_get(rb_cObject, rb_intern("Iconv"));
|
|
827
1360
|
|
|
828
|
-
|
|
829
|
-
rb_raise(rb_eArgError, "options must be a hash.");
|
|
830
|
-
}
|
|
831
|
-
if (Qnil != (v = rb_hash_lookup(ropts, symbolize_names_sym))) {
|
|
832
|
-
options.sym_key = (Qtrue == v) ? Yes : No;
|
|
833
|
-
}
|
|
834
|
-
if (Qnil != (v = rb_hash_lookup(ropts, create_additions_sym))) {
|
|
835
|
-
options.mode = (Qtrue == v) ? CompatMode : StrictMode;
|
|
836
|
-
}
|
|
837
|
-
// :allow_nan is not supported as Oj always allows nan
|
|
838
|
-
// :max_nesting is always set to 100
|
|
839
|
-
// :object_class is always Hash
|
|
840
|
-
// :array_class is always Array
|
|
841
|
-
}
|
|
842
|
-
return load_with_opts(*argv, &options);
|
|
1361
|
+
return rb_funcall(iconv, rb_intern("new"), 2, rb_str_new2("ASCII//TRANSLIT"), rb_str_new2("UTF-8"));
|
|
843
1362
|
}
|
|
844
1363
|
|
|
845
1364
|
static VALUE
|
|
846
|
-
|
|
847
|
-
rb_need_block();
|
|
848
|
-
mimic_walk(Qnil, obj, Qnil);
|
|
849
|
-
|
|
1365
|
+
iconv_rescue(VALUE x) {
|
|
850
1366
|
return Qnil;
|
|
851
1367
|
}
|
|
1368
|
+
#endif
|
|
852
1369
|
|
|
853
1370
|
static VALUE
|
|
854
|
-
|
|
1371
|
+
protect_require(VALUE x) {
|
|
1372
|
+
rb_require("time");
|
|
1373
|
+
rb_require("bigdecimal");
|
|
855
1374
|
return Qnil;
|
|
856
1375
|
}
|
|
857
1376
|
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
*
|
|
1377
|
+
/* Document-module: Oj
|
|
1378
|
+
*
|
|
1379
|
+
* Optimized JSON (Oj), as the name implies was written to provide speed
|
|
1380
|
+
* optimized JSON handling.
|
|
1381
|
+
*
|
|
1382
|
+
* Oj uses modes to control how object are encoded and decoded. In addition
|
|
1383
|
+
* global and options to methods allow additional behavior modifications. The
|
|
1384
|
+
* modes are:
|
|
1385
|
+
*
|
|
1386
|
+
* - *:strict* mode will only allow the 7 basic JSON types to be serialized. Any other Object
|
|
1387
|
+
* will raise an Exception.
|
|
1388
|
+
*
|
|
1389
|
+
* - *:null* mode is similar to the :strict mode except any Object that is not
|
|
1390
|
+
* one of the JSON base types is replaced by a JSON null.
|
|
1391
|
+
*
|
|
1392
|
+
* - *:object* mode will dump any Object as a JSON Object with keys that match
|
|
1393
|
+
* the Ruby Object's variable names without the '@' character. This is the
|
|
1394
|
+
* highest performance mode.
|
|
1395
|
+
*
|
|
1396
|
+
* - *:compat* or *:json* mode is the compatible mode for the json gem. It mimics
|
|
1397
|
+
* the json gem including the options, defaults, and restrictions.
|
|
1398
|
+
*
|
|
1399
|
+
* - *:rails* is the compatibility mode for Rails or Active support.
|
|
879
1400
|
*
|
|
880
|
-
*
|
|
881
|
-
* gem. After this method is invoked calls that expect the JSON module will
|
|
882
|
-
* use Oj instead and be faster than the original JSON. Most options that
|
|
883
|
-
* could be passed to the JSON methods are supported. The calls to set parser
|
|
884
|
-
* or generator will not raise an Exception but will not have any effect.
|
|
1401
|
+
* - *:custom* is the most configurable mode.
|
|
885
1402
|
*/
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
VALUE ext;
|
|
890
|
-
VALUE dummy;
|
|
891
|
-
|
|
892
|
-
if (rb_const_defined_at(rb_cObject, rb_intern("JSON"))) {
|
|
893
|
-
rb_raise(rb_const_get_at(Oj, rb_intern("MimicError")),
|
|
894
|
-
"JSON module already exists. Can not mimic. Do not require 'json' before calling mimic_JSON.");
|
|
895
|
-
}
|
|
896
|
-
mimic = rb_define_module("JSON");
|
|
897
|
-
ext = rb_define_module_under(mimic, "Ext");
|
|
898
|
-
dummy = rb_define_class_under(ext, "Parser", rb_cObject);
|
|
899
|
-
dummy = rb_define_class_under(ext, "Generator", rb_cObject);
|
|
900
|
-
// convince Ruby that the json gem has already been loaded
|
|
901
|
-
dummy = rb_gv_get("$LOADED_FEATURES");
|
|
902
|
-
if (rb_type(dummy) == T_ARRAY) {
|
|
903
|
-
rb_ary_push(dummy, rb_str_new2("json"));
|
|
904
|
-
if (0 < argc) {
|
|
905
|
-
VALUE mimic_args[1];
|
|
906
|
-
|
|
907
|
-
*mimic_args = *argv;
|
|
908
|
-
rb_funcall2(Oj, rb_intern("mimic_loaded"), 1, mimic_args);
|
|
909
|
-
} else {
|
|
910
|
-
rb_funcall2(Oj, rb_intern("mimic_loaded"), 0, 0);
|
|
911
|
-
}
|
|
912
|
-
}
|
|
1403
|
+
void
|
|
1404
|
+
Init_oj() {
|
|
1405
|
+
int err = 0;
|
|
913
1406
|
|
|
914
|
-
|
|
915
|
-
rb_define_module_function(mimic, "generator=", no_op1, 1);
|
|
916
|
-
rb_define_module_function(mimic, "create_id=", mimic_create_id, 1);
|
|
917
|
-
|
|
918
|
-
rb_define_module_function(mimic, "dump", mimic_dump, -1);
|
|
919
|
-
rb_define_module_function(mimic, "load", mimic_load, -1);
|
|
920
|
-
rb_define_module_function(mimic, "restore", mimic_load, -1);
|
|
921
|
-
rb_define_module_function(mimic, "recurse_proc", mimic_recurse_proc, 1);
|
|
922
|
-
rb_define_module_function(mimic, "[]", mimic_dump_load, -1);
|
|
923
|
-
|
|
924
|
-
rb_define_module_function(mimic, "generate", mimic_generate, -1);
|
|
925
|
-
rb_define_module_function(mimic, "fast_generate", mimic_generate, -1);
|
|
926
|
-
rb_define_module_function(mimic, "pretty_generate", mimic_pretty_generate, -1);
|
|
927
|
-
/* for older versions of JSON, the deprecated unparse methods */
|
|
928
|
-
rb_define_module_function(mimic, "unparse", mimic_generate, -1);
|
|
929
|
-
rb_define_module_function(mimic, "fast_unparse", mimic_generate, -1);
|
|
930
|
-
rb_define_module_function(mimic, "pretty_unparse", mimic_pretty_generate, -1);
|
|
931
|
-
|
|
932
|
-
rb_define_module_function(mimic, "parse", mimic_parse, -1);
|
|
933
|
-
rb_define_module_function(mimic, "parse!", mimic_parse, -1);
|
|
934
|
-
|
|
935
|
-
array_nl_sym = ID2SYM(rb_intern("array_nl")); rb_gc_register_address(&array_nl_sym);
|
|
936
|
-
create_additions_sym = ID2SYM(rb_intern("create_additions")); rb_gc_register_address(&create_additions_sym);
|
|
937
|
-
object_nl_sym = ID2SYM(rb_intern("object_nl")); rb_gc_register_address(&object_nl_sym);
|
|
938
|
-
space_before_sym = ID2SYM(rb_intern("space_before")); rb_gc_register_address(&space_before_sym);
|
|
939
|
-
space_sym = ID2SYM(rb_intern("space")); rb_gc_register_address(&space_sym);
|
|
940
|
-
symbolize_names_sym = ID2SYM(rb_intern("symbolize_names")); rb_gc_register_address(&symbolize_names_sym);
|
|
941
|
-
|
|
942
|
-
oj_default_options.mode = CompatMode;
|
|
943
|
-
oj_default_options.ascii_only = Yes;
|
|
944
|
-
}
|
|
945
|
-
return mimic;
|
|
946
|
-
}
|
|
1407
|
+
Oj = rb_define_module("Oj");
|
|
947
1408
|
|
|
948
|
-
|
|
949
|
-
Odd odd;
|
|
950
|
-
ID *idp;
|
|
1409
|
+
oj_cstack_class = rb_define_class_under(Oj, "CStack", rb_cObject);
|
|
951
1410
|
|
|
952
|
-
|
|
1411
|
+
oj_string_writer_init();
|
|
1412
|
+
oj_stream_writer_init();
|
|
953
1413
|
|
|
954
|
-
rb_require("time");
|
|
955
1414
|
rb_require("date");
|
|
956
|
-
|
|
1415
|
+
// On Rubinius the require fails but can be done from a ruby file.
|
|
1416
|
+
rb_protect(protect_require, Qnil, &err);
|
|
1417
|
+
#if NEEDS_RATIONAL
|
|
1418
|
+
rb_require("rational");
|
|
1419
|
+
#endif
|
|
957
1420
|
rb_require("stringio");
|
|
1421
|
+
#if HAS_ENCODING_SUPPORT
|
|
1422
|
+
oj_utf8_encoding = rb_enc_find("UTF-8");
|
|
1423
|
+
#else
|
|
1424
|
+
// need an option to turn this on
|
|
1425
|
+
oj_utf8_encoding = rb_rescue(iconv_encoder, Qnil, iconv_rescue, Qnil);
|
|
1426
|
+
oj_utf8_encoding = Qnil;
|
|
1427
|
+
#endif
|
|
1428
|
+
|
|
1429
|
+
//rb_define_module_function(Oj, "hash_test", hash_test, 0);
|
|
958
1430
|
|
|
959
1431
|
rb_define_module_function(Oj, "default_options", get_def_opts, 0);
|
|
960
1432
|
rb_define_module_function(Oj, "default_options=", set_def_opts, 1);
|
|
961
1433
|
|
|
962
|
-
rb_define_module_function(Oj, "mimic_JSON",
|
|
1434
|
+
rb_define_module_function(Oj, "mimic_JSON", oj_define_mimic_json, -1);
|
|
963
1435
|
rb_define_module_function(Oj, "load", load, -1);
|
|
964
1436
|
rb_define_module_function(Oj, "load_file", load_file, -1);
|
|
1437
|
+
rb_define_module_function(Oj, "safe_load", safe_load, 1);
|
|
1438
|
+
rb_define_module_function(Oj, "strict_load", oj_strict_parse, -1);
|
|
1439
|
+
rb_define_module_function(Oj, "compat_load", oj_compat_parse, -1);
|
|
1440
|
+
rb_define_module_function(Oj, "object_load", oj_object_parse, -1);
|
|
1441
|
+
|
|
965
1442
|
rb_define_module_function(Oj, "dump", dump, -1);
|
|
1443
|
+
|
|
966
1444
|
rb_define_module_function(Oj, "to_file", to_file, -1);
|
|
1445
|
+
rb_define_module_function(Oj, "to_stream", to_stream, -1);
|
|
1446
|
+
// JSON gem compatibility
|
|
1447
|
+
rb_define_module_function(Oj, "to_json", to_json, -1);
|
|
1448
|
+
rb_define_module_function(Oj, "generate", oj_mimic_generate, -1);
|
|
1449
|
+
rb_define_module_function(Oj, "fast_generate", oj_mimic_generate, -1);
|
|
967
1450
|
|
|
968
|
-
rb_define_module_function(Oj, "
|
|
1451
|
+
rb_define_module_function(Oj, "add_to_json", oj_add_to_json, -1);
|
|
1452
|
+
rb_define_module_function(Oj, "remove_to_json", oj_remove_to_json, -1);
|
|
1453
|
+
|
|
1454
|
+
rb_define_module_function(Oj, "register_odd", register_odd, -1);
|
|
1455
|
+
rb_define_module_function(Oj, "register_odd_raw", register_odd_raw, -1);
|
|
1456
|
+
|
|
1457
|
+
rb_define_module_function(Oj, "saj_parse", oj_saj_parse, -1);
|
|
1458
|
+
rb_define_module_function(Oj, "sc_parse", oj_sc_parse, -1);
|
|
969
1459
|
|
|
970
1460
|
oj_add_value_id = rb_intern("add_value");
|
|
1461
|
+
oj_array_append_id = rb_intern("array_append");
|
|
971
1462
|
oj_array_end_id = rb_intern("array_end");
|
|
972
1463
|
oj_array_start_id = rb_intern("array_start");
|
|
973
1464
|
oj_as_json_id = rb_intern("as_json");
|
|
974
1465
|
oj_error_id = rb_intern("error");
|
|
1466
|
+
oj_begin_id = rb_intern("begin");
|
|
1467
|
+
oj_end_id = rb_intern("end");
|
|
1468
|
+
oj_exclude_end_id = rb_intern("exclude_end?");
|
|
1469
|
+
oj_file_id = rb_intern("file?");
|
|
975
1470
|
oj_fileno_id = rb_intern("fileno");
|
|
1471
|
+
oj_ftype_id = rb_intern("ftype");
|
|
976
1472
|
oj_hash_end_id = rb_intern("hash_end");
|
|
1473
|
+
oj_hash_key_id = rb_intern("hash_key");
|
|
1474
|
+
oj_hash_set_id = rb_intern("hash_set");
|
|
977
1475
|
oj_hash_start_id = rb_intern("hash_start");
|
|
1476
|
+
oj_iconv_id = rb_intern("iconv");
|
|
978
1477
|
oj_instance_variables_id = rb_intern("instance_variables");
|
|
979
1478
|
oj_json_create_id = rb_intern("json_create");
|
|
1479
|
+
oj_length_id = rb_intern("length");
|
|
980
1480
|
oj_new_id = rb_intern("new");
|
|
1481
|
+
oj_parse_id = rb_intern("parse");
|
|
1482
|
+
oj_pos_id = rb_intern("pos");
|
|
981
1483
|
oj_read_id = rb_intern("read");
|
|
1484
|
+
oj_readpartial_id = rb_intern("readpartial");
|
|
1485
|
+
oj_replace_id = rb_intern("replace");
|
|
1486
|
+
oj_stat_id = rb_intern("stat");
|
|
982
1487
|
oj_string_id = rb_intern("string");
|
|
983
1488
|
oj_to_hash_id = rb_intern("to_hash");
|
|
1489
|
+
oj_to_h_id = rb_intern("to_h");
|
|
984
1490
|
oj_to_json_id = rb_intern("to_json");
|
|
985
1491
|
oj_to_s_id = rb_intern("to_s");
|
|
986
1492
|
oj_to_sym_id = rb_intern("to_sym");
|
|
@@ -988,248 +1494,101 @@ void Init_oj() {
|
|
|
988
1494
|
oj_tv_nsec_id = rb_intern("tv_nsec");
|
|
989
1495
|
oj_tv_sec_id = rb_intern("tv_sec");
|
|
990
1496
|
oj_tv_usec_id = rb_intern("tv_usec");
|
|
1497
|
+
oj_utc_id = rb_intern("utc");
|
|
991
1498
|
oj_utc_offset_id = rb_intern("utc_offset");
|
|
1499
|
+
oj_utcq_id = rb_intern("utc?");
|
|
992
1500
|
oj_write_id = rb_intern("write");
|
|
1501
|
+
oj_has_key_id = rb_intern("has_key?");
|
|
1502
|
+
|
|
1503
|
+
rb_require("oj/bag");
|
|
1504
|
+
rb_require("oj/error");
|
|
1505
|
+
rb_require("oj/mimic");
|
|
1506
|
+
rb_require("oj/saj");
|
|
1507
|
+
rb_require("oj/schandler");
|
|
993
1508
|
|
|
994
1509
|
oj_bag_class = rb_const_get_at(Oj, rb_intern("Bag"));
|
|
995
|
-
oj_parse_error_class = rb_const_get_at(Oj, rb_intern("ParseError"));
|
|
996
|
-
oj_struct_class = rb_const_get(rb_cObject, rb_intern("Struct"));
|
|
997
|
-
oj_time_class = rb_const_get(rb_cObject, rb_intern("Time"));
|
|
998
1510
|
oj_bigdecimal_class = rb_const_get(rb_cObject, rb_intern("BigDecimal"));
|
|
1511
|
+
oj_date_class = rb_const_get(rb_cObject, rb_intern("Date"));
|
|
1512
|
+
oj_datetime_class = rb_const_get(rb_cObject, rb_intern("DateTime"));
|
|
1513
|
+
oj_enumerable_class = rb_const_get(rb_cObject, rb_intern("Enumerable"));
|
|
1514
|
+
oj_parse_error_class = rb_const_get_at(Oj, rb_intern("ParseError"));
|
|
999
1515
|
oj_stringio_class = rb_const_get(rb_cObject, rb_intern("StringIO"));
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1516
|
+
oj_struct_class = rb_const_get(rb_cObject, rb_intern("Struct"));
|
|
1517
|
+
oj_json_parser_error_class = rb_eEncodingError; // replaced if mimic is called
|
|
1518
|
+
oj_json_generator_error_class = rb_eEncodingError; // replaced if mimic is called
|
|
1519
|
+
|
|
1520
|
+
allow_blank_sym = ID2SYM(rb_intern("allow_blank")); rb_gc_register_address(&allow_blank_sym);
|
|
1521
|
+
allow_gc_sym = ID2SYM(rb_intern("allow_gc")); rb_gc_register_address(&allow_gc_sym);
|
|
1522
|
+
allow_invalid_unicode_sym = ID2SYM(rb_intern("allow_invalid_unicode"));rb_gc_register_address(&allow_invalid_unicode_sym);
|
|
1523
|
+
ascii_sym = ID2SYM(rb_intern("ascii")); rb_gc_register_address(&ascii_sym);
|
|
1524
|
+
auto_define_sym = ID2SYM(rb_intern("auto_define")); rb_gc_register_address(&auto_define_sym);
|
|
1525
|
+
auto_sym = ID2SYM(rb_intern("auto")); rb_gc_register_address(&auto_sym);
|
|
1526
|
+
bigdecimal_as_decimal_sym = ID2SYM(rb_intern("bigdecimal_as_decimal"));rb_gc_register_address(&bigdecimal_as_decimal_sym);
|
|
1527
|
+
bigdecimal_load_sym = ID2SYM(rb_intern("bigdecimal_load")); rb_gc_register_address(&bigdecimal_load_sym);
|
|
1528
|
+
bigdecimal_sym = ID2SYM(rb_intern("bigdecimal")); rb_gc_register_address(&bigdecimal_sym);
|
|
1529
|
+
circular_sym = ID2SYM(rb_intern("circular")); rb_gc_register_address(&circular_sym);
|
|
1530
|
+
class_cache_sym = ID2SYM(rb_intern("class_cache")); rb_gc_register_address(&class_cache_sym);
|
|
1531
|
+
compat_sym = ID2SYM(rb_intern("compat")); rb_gc_register_address(&compat_sym);
|
|
1532
|
+
create_id_sym = ID2SYM(rb_intern("create_id")); rb_gc_register_address(&create_id_sym);
|
|
1533
|
+
custom_sym = ID2SYM(rb_intern("custom")); rb_gc_register_address(&custom_sym);
|
|
1534
|
+
empty_string_sym = ID2SYM(rb_intern("empty_string")); rb_gc_register_address(&empty_string_sym);
|
|
1535
|
+
escape_mode_sym = ID2SYM(rb_intern("escape_mode")); rb_gc_register_address(&escape_mode_sym);
|
|
1536
|
+
float_prec_sym = ID2SYM(rb_intern("float_precision")); rb_gc_register_address(&float_prec_sym);
|
|
1537
|
+
float_sym = ID2SYM(rb_intern("float")); rb_gc_register_address(&float_sym);
|
|
1538
|
+
huge_sym = ID2SYM(rb_intern("huge")); rb_gc_register_address(&huge_sym);
|
|
1539
|
+
json_sym = ID2SYM(rb_intern("json")); rb_gc_register_address(&json_sym);
|
|
1540
|
+
match_string_sym = ID2SYM(rb_intern("match_string")); rb_gc_register_address(&match_string_sym);
|
|
1541
|
+
mode_sym = ID2SYM(rb_intern("mode")); rb_gc_register_address(&mode_sym);
|
|
1542
|
+
nan_sym = ID2SYM(rb_intern("nan")); rb_gc_register_address(&nan_sym);
|
|
1543
|
+
newline_sym = ID2SYM(rb_intern("newline")); rb_gc_register_address(&newline_sym);
|
|
1544
|
+
nilnil_sym = ID2SYM(rb_intern("nilnil")); rb_gc_register_address(&nilnil_sym);
|
|
1545
|
+
null_sym = ID2SYM(rb_intern("null")); rb_gc_register_address(&null_sym);
|
|
1546
|
+
object_sym = ID2SYM(rb_intern("object")); rb_gc_register_address(&object_sym);
|
|
1547
|
+
oj_allow_nan_sym = ID2SYM(rb_intern("allow_nan")); rb_gc_register_address(&oj_allow_nan_sym);
|
|
1548
|
+
oj_array_class_sym = ID2SYM(rb_intern("array_class")); rb_gc_register_address(&oj_array_class_sym);
|
|
1549
|
+
oj_array_nl_sym = ID2SYM(rb_intern("array_nl")); rb_gc_register_address(&oj_array_nl_sym);
|
|
1550
|
+
oj_ascii_only_sym = ID2SYM(rb_intern("ascii_only")); rb_gc_register_address(&oj_ascii_only_sym);
|
|
1551
|
+
oj_create_additions_sym = ID2SYM(rb_intern("create_additions"));rb_gc_register_address(&oj_create_additions_sym);
|
|
1552
|
+
oj_hash_class_sym = ID2SYM(rb_intern("hash_class")); rb_gc_register_address(&oj_hash_class_sym);
|
|
1553
|
+
oj_indent_sym = ID2SYM(rb_intern("indent")); rb_gc_register_address(&oj_indent_sym);
|
|
1554
|
+
oj_max_nesting_sym = ID2SYM(rb_intern("max_nesting")); rb_gc_register_address(&oj_max_nesting_sym);
|
|
1555
|
+
oj_object_class_sym = ID2SYM(rb_intern("object_class")); rb_gc_register_address(&oj_object_class_sym);
|
|
1556
|
+
oj_object_nl_sym = ID2SYM(rb_intern("object_nl")); rb_gc_register_address(&oj_object_nl_sym);
|
|
1557
|
+
oj_quirks_mode_sym = ID2SYM(rb_intern("quirks_mode")); rb_gc_register_address(&oj_quirks_mode_sym);
|
|
1558
|
+
oj_space_before_sym = ID2SYM(rb_intern("space_before")); rb_gc_register_address(&oj_space_before_sym);
|
|
1559
|
+
oj_space_sym = ID2SYM(rb_intern("space")); rb_gc_register_address(&oj_space_sym);
|
|
1560
|
+
omit_nil_sym = ID2SYM(rb_intern("omit_nil")); rb_gc_register_address(&omit_nil_sym);
|
|
1561
|
+
rails_sym = ID2SYM(rb_intern("rails")); rb_gc_register_address(&rails_sym);
|
|
1562
|
+
raise_sym = ID2SYM(rb_intern("raise")); rb_gc_register_address(&raise_sym);
|
|
1563
|
+
ruby_sym = ID2SYM(rb_intern("ruby")); rb_gc_register_address(&ruby_sym);
|
|
1564
|
+
sec_prec_sym = ID2SYM(rb_intern("second_precision")); rb_gc_register_address(&sec_prec_sym);
|
|
1565
|
+
strict_sym = ID2SYM(rb_intern("strict")); rb_gc_register_address(&strict_sym);
|
|
1566
|
+
symbol_keys_sym = ID2SYM(rb_intern("symbol_keys")); rb_gc_register_address(&symbol_keys_sym);
|
|
1567
|
+
time_format_sym = ID2SYM(rb_intern("time_format")); rb_gc_register_address(&time_format_sym);
|
|
1568
|
+
unicode_xss_sym = ID2SYM(rb_intern("unicode_xss")); rb_gc_register_address(&unicode_xss_sym);
|
|
1569
|
+
unix_sym = ID2SYM(rb_intern("unix")); rb_gc_register_address(&unix_sym);
|
|
1570
|
+
unix_zone_sym = ID2SYM(rb_intern("unix_zone")); rb_gc_register_address(&unix_zone_sym);
|
|
1571
|
+
use_as_json_sym = ID2SYM(rb_intern("use_as_json")); rb_gc_register_address(&use_as_json_sym);
|
|
1572
|
+
use_to_hash_sym = ID2SYM(rb_intern("use_to_hash")); rb_gc_register_address(&use_to_hash_sym);
|
|
1573
|
+
use_to_json_sym = ID2SYM(rb_intern("use_to_json")); rb_gc_register_address(&use_to_json_sym);
|
|
1574
|
+
word_sym = ID2SYM(rb_intern("word")); rb_gc_register_address(&word_sym);
|
|
1575
|
+
xmlschema_sym = ID2SYM(rb_intern("xmlschema")); rb_gc_register_address(&xmlschema_sym);
|
|
1576
|
+
xss_safe_sym = ID2SYM(rb_intern("xss_safe")); rb_gc_register_address(&xss_safe_sym);
|
|
1577
|
+
|
|
1578
|
+
oj_slash_string = rb_str_new2("/"); rb_gc_register_address(&oj_slash_string);
|
|
1019
1579
|
|
|
1020
1580
|
oj_default_options.mode = ObjectMode;
|
|
1021
|
-
#if HAS_ENCODING_SUPPORT
|
|
1022
|
-
oj_utf8_encoding = rb_enc_find("UTF-8");
|
|
1023
|
-
#endif
|
|
1024
1581
|
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
idp = odd->attrs;
|
|
1031
|
-
odd->clas = rb_const_get(rb_cObject, rb_intern("Rational"));
|
|
1032
|
-
odd->create_obj = rb_cObject;
|
|
1033
|
-
odd->create_op = rb_intern("Rational");
|
|
1034
|
-
odd->attr_cnt = 2;
|
|
1035
|
-
*idp++ = rb_intern("numerator");
|
|
1036
|
-
*idp++ = rb_intern("denominator");
|
|
1037
|
-
*idp++ = 0;
|
|
1038
|
-
// Date
|
|
1039
|
-
odd++;
|
|
1040
|
-
idp = odd->attrs;
|
|
1041
|
-
odd->clas = rb_const_get(rb_cObject, rb_intern("Date"));
|
|
1042
|
-
odd->create_obj = odd->clas;
|
|
1043
|
-
odd->create_op = oj_new_id;
|
|
1044
|
-
odd->attr_cnt = 4;
|
|
1045
|
-
*idp++ = rb_intern("year");
|
|
1046
|
-
*idp++ = rb_intern("month");
|
|
1047
|
-
*idp++ = rb_intern("day");
|
|
1048
|
-
*idp++ = rb_intern("start");
|
|
1049
|
-
*idp++ = 0;
|
|
1050
|
-
// DateTime
|
|
1051
|
-
odd++;
|
|
1052
|
-
idp = odd->attrs;
|
|
1053
|
-
odd->clas = rb_const_get(rb_cObject, rb_intern("DateTime"));
|
|
1054
|
-
odd->create_obj = odd->clas;
|
|
1055
|
-
odd->create_op = oj_new_id;
|
|
1056
|
-
odd->attr_cnt = 8;
|
|
1057
|
-
*idp++ = rb_intern("year");
|
|
1058
|
-
*idp++ = rb_intern("month");
|
|
1059
|
-
*idp++ = rb_intern("day");
|
|
1060
|
-
*idp++ = rb_intern("hour");
|
|
1061
|
-
*idp++ = rb_intern("min");
|
|
1062
|
-
*idp++ = rb_intern("sec");
|
|
1063
|
-
*idp++ = rb_intern("offset");
|
|
1064
|
-
*idp++ = rb_intern("start");
|
|
1065
|
-
*idp++ = 0;
|
|
1066
|
-
// Range
|
|
1067
|
-
odd++;
|
|
1068
|
-
idp = odd->attrs;
|
|
1069
|
-
odd->clas = rb_const_get(rb_cObject, rb_intern("Range"));
|
|
1070
|
-
odd->create_obj = odd->clas;
|
|
1071
|
-
odd->create_op = oj_new_id;
|
|
1072
|
-
odd->attr_cnt = 3;
|
|
1073
|
-
*idp++ = rb_intern("begin");
|
|
1074
|
-
*idp++ = rb_intern("end");
|
|
1075
|
-
*idp++ = rb_intern("exclude_end?");
|
|
1076
|
-
*idp++ = 0;
|
|
1077
|
-
// The end. bump up the size of odds if a new class is added.
|
|
1078
|
-
odd++;
|
|
1079
|
-
odd->clas = Qundef;
|
|
1080
|
-
|
|
1081
|
-
#if SAFE_CACHE
|
|
1582
|
+
oj_hash_init();
|
|
1583
|
+
oj_odd_init();
|
|
1584
|
+
oj_mimic_rails_init();
|
|
1585
|
+
|
|
1586
|
+
#if USE_PTHREAD_MUTEX
|
|
1082
1587
|
pthread_mutex_init(&oj_cache_mutex, 0);
|
|
1588
|
+
#elif USE_RB_MUTEX
|
|
1589
|
+
oj_cache_mutex = rb_mutex_new();
|
|
1590
|
+
rb_gc_register_address(&oj_cache_mutex);
|
|
1083
1591
|
#endif
|
|
1084
1592
|
oj_init_doc();
|
|
1085
1593
|
}
|
|
1086
1594
|
|
|
1087
|
-
void
|
|
1088
|
-
_oj_raise_error(const char *msg, const char *json, const char *current, const char* file, int line) {
|
|
1089
|
-
int jline = 1;
|
|
1090
|
-
int col = 1;
|
|
1091
|
-
|
|
1092
|
-
for (; json < current && '\n' != *current; current--) {
|
|
1093
|
-
col++;
|
|
1094
|
-
}
|
|
1095
|
-
for (; json < current; current--) {
|
|
1096
|
-
if ('\n' == *current) {
|
|
1097
|
-
jline++;
|
|
1098
|
-
}
|
|
1099
|
-
}
|
|
1100
|
-
rb_raise(oj_parse_error_class, "%s at line %d, column %d [%s:%d]", msg, jline, col, file, line);
|
|
1101
|
-
}
|
|
1102
|
-
|
|
1103
|
-
// mimic JSON documentation
|
|
1104
|
-
|
|
1105
|
-
/* Document-module: JSON
|
|
1106
|
-
*
|
|
1107
|
-
* JSON is a JSON parser. This module when defined by the Oj module is a
|
|
1108
|
-
* faster replacement for the original.
|
|
1109
|
-
*/
|
|
1110
|
-
/* Document-module: JSON::Ext
|
|
1111
|
-
*
|
|
1112
|
-
* The Ext module is a placeholder in the mimic JSON module used for
|
|
1113
|
-
* compatibility only.
|
|
1114
|
-
*/
|
|
1115
|
-
/* Document-class: JSON::Ext::Parser
|
|
1116
|
-
*
|
|
1117
|
-
* The JSON::Ext::Parser is a placeholder in the mimic JSON module used for
|
|
1118
|
-
* compatibility only.
|
|
1119
|
-
*/
|
|
1120
|
-
/* Document-class: JSON::Ext::Generator
|
|
1121
|
-
*
|
|
1122
|
-
* The JSON::Ext::Generator is a placeholder in the mimic JSON module used for
|
|
1123
|
-
* compatibility only.
|
|
1124
|
-
*/
|
|
1125
|
-
|
|
1126
|
-
/* Document-method: create_id=
|
|
1127
|
-
* call-seq: create_id=(id) -> String
|
|
1128
|
-
*
|
|
1129
|
-
* Sets the create_id tag to look for in JSON document. That key triggers the
|
|
1130
|
-
* creation of a class with the same name.
|
|
1131
|
-
*
|
|
1132
|
-
* @param [nil|String] id new create_id
|
|
1133
|
-
* @return the id
|
|
1134
|
-
*/
|
|
1135
|
-
/* Document-method: parser=
|
|
1136
|
-
* call-seq: parser=(parser) -> nil
|
|
1137
|
-
*
|
|
1138
|
-
* Does nothing other than provide compatibiltiy.
|
|
1139
|
-
* @param [Object] parser ignored
|
|
1140
|
-
*/
|
|
1141
|
-
/* Document-method: generator=
|
|
1142
|
-
* call-seq: generator=(generator) -> nil
|
|
1143
|
-
*
|
|
1144
|
-
* Does nothing other than provide compatibiltiy.
|
|
1145
|
-
* @param [Object] generator ignored
|
|
1146
|
-
*/
|
|
1147
|
-
/* Document-method: dump
|
|
1148
|
-
* call-seq: dump(obj, anIO=nil, limit = nil) -> String
|
|
1149
|
-
*
|
|
1150
|
-
* Encodes an object as a JSON String.
|
|
1151
|
-
*
|
|
1152
|
-
* @param [Object] obj object to convert to encode as JSON
|
|
1153
|
-
* @param [IO] anIO an IO that allows writing
|
|
1154
|
-
* @param [Fixnum] limit ignored
|
|
1155
|
-
*/
|
|
1156
|
-
/* Document-method: load
|
|
1157
|
-
* call-seq: load(source, proc=nil) -> Object
|
|
1158
|
-
*
|
|
1159
|
-
* Loads a Ruby Object from a JSON source that can be either a String or an
|
|
1160
|
-
* IO. If Proc is given or a block is providedit is called with each nested
|
|
1161
|
-
* element of the loaded Object.
|
|
1162
|
-
*
|
|
1163
|
-
* @param [String|IO] source JSON source
|
|
1164
|
-
* @param [Proc] proc to yield to on each element or nil
|
|
1165
|
-
*/
|
|
1166
|
-
/* Document-method: restore
|
|
1167
|
-
* call-seq: restore(source, proc=nil) -> Object
|
|
1168
|
-
*
|
|
1169
|
-
* Loads a Ruby Object from a JSON source that can be either a String or an
|
|
1170
|
-
* IO. If Proc is given or a block is providedit is called with each nested
|
|
1171
|
-
* element of the loaded Object.
|
|
1172
|
-
*
|
|
1173
|
-
* @param [String|IO] source JSON source
|
|
1174
|
-
* @param [Proc] proc to yield to on each element or nil
|
|
1175
|
-
*/
|
|
1176
|
-
/* Document-method: recurse_proc
|
|
1177
|
-
* call-seq: recurse_proc(obj, &proc) -> nil
|
|
1178
|
-
*
|
|
1179
|
-
* Yields to the proc for every element in the obj recursivly.
|
|
1180
|
-
*
|
|
1181
|
-
* @param [Hash|Array] obj object to walk
|
|
1182
|
-
* @param [Proc] proc to yield to on each element
|
|
1183
|
-
*/
|
|
1184
|
-
/* Document-method: []
|
|
1185
|
-
* call-seq: [](obj, opts={}) -> Object
|
|
1186
|
-
*
|
|
1187
|
-
* If the obj argument is a String then it is assumed to be a JSON String and
|
|
1188
|
-
* parsed otherwise the obj is encoded as a JSON String.
|
|
1189
|
-
*
|
|
1190
|
-
* @param [String|Hash|Array] obj object to convert
|
|
1191
|
-
* @param [Hash] opts same options as either generate or parse
|
|
1192
|
-
*/
|
|
1193
|
-
/* Document-method: generate
|
|
1194
|
-
* call-seq: generate(obj, opts=nil) -> String
|
|
1195
|
-
*
|
|
1196
|
-
* Encode obj as a JSON String. The obj argument must be a Hash, Array, or
|
|
1197
|
-
* respond to to_h or to_json. Options other than those listed such as
|
|
1198
|
-
* +:allow_nan+ or +:max_nesting+ are ignored.
|
|
1199
|
-
*
|
|
1200
|
-
* @param [Object|Hash|Array] obj object to convert to a JSON String
|
|
1201
|
-
* @param [Hash] opts options
|
|
1202
|
-
* @param [String] :indent String to use for indentation
|
|
1203
|
-
* @param [String] :space String placed after a , or : delimiter
|
|
1204
|
-
* @param [String] :space_before String placed before a : delimiter
|
|
1205
|
-
* @param [String] :object_nl String placed after a JSON object
|
|
1206
|
-
* @param [String] :array_nl String placed after a JSON array
|
|
1207
|
-
*/
|
|
1208
|
-
/* Document-method: fast_generate
|
|
1209
|
-
* call-seq: fast_generate(obj, opts=nil) -> String
|
|
1210
|
-
* Same as generate().
|
|
1211
|
-
* @see generate
|
|
1212
|
-
*/
|
|
1213
|
-
/* Document-method: pretty_generate
|
|
1214
|
-
* call-seq: pretty_generate(obj, opts=nil) -> String
|
|
1215
|
-
* Same as generate() but with different defaults for the spacing options.
|
|
1216
|
-
* @see generate
|
|
1217
|
-
*/
|
|
1218
|
-
/* Document-method: parse
|
|
1219
|
-
* call-seq: parse(source, opts=nil) -> Object
|
|
1220
|
-
*
|
|
1221
|
-
* Parses a JSON String or IO into a Ruby Object. Options other than those
|
|
1222
|
-
* listed such as +:allow_nan+ or +:max_nesting+ are ignored. +:object_class+ and
|
|
1223
|
-
* +:array_object+ are not supported.
|
|
1224
|
-
*
|
|
1225
|
-
* @param [String|IO] source source to parse
|
|
1226
|
-
* @param [Hash] opts options
|
|
1227
|
-
* @param [true|false] :symbolize_names flag indicating JSON object keys should be Symbols instead of Strings
|
|
1228
|
-
* @param [true|false] :create_additions flag indicating a key matching +create_id+ in a JSON object should trigger the creation of Ruby Object
|
|
1229
|
-
* @see create_id=
|
|
1230
|
-
*/
|
|
1231
|
-
/* Document-method: parse!
|
|
1232
|
-
* call-seq: parse!(source, opts=nil) -> Object
|
|
1233
|
-
* Same as parse().
|
|
1234
|
-
* @see parse
|
|
1235
|
-
*/
|