oj 3.16.0 → 3.17.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +107 -0
- data/README.md +0 -16
- data/ext/oj/cache.c +4 -2
- data/ext/oj/cache.h +3 -2
- data/ext/oj/compat.c +3 -3
- data/ext/oj/custom.c +17 -11
- data/ext/oj/dump.c +624 -90
- data/ext/oj/dump.h +9 -2
- data/ext/oj/dump_compat.c +15 -9
- data/ext/oj/dump_leaf.c +1 -1
- data/ext/oj/dump_object.c +32 -17
- data/ext/oj/dump_strict.c +20 -14
- data/ext/oj/extconf.rb +11 -9
- data/ext/oj/fast.c +50 -32
- data/ext/oj/intern.c +24 -7
- data/ext/oj/mimic_json.c +17 -11
- data/ext/oj/object.c +21 -13
- data/ext/oj/oj.c +387 -140
- data/ext/oj/oj.h +59 -55
- data/ext/oj/parse.c +248 -47
- data/ext/oj/parser.c +179 -89
- data/ext/oj/parser.h +4 -2
- data/ext/oj/rails.c +64 -42
- data/ext/oj/reader.c +1 -1
- data/ext/oj/rxclass.c +1 -1
- data/ext/oj/rxclass.h +1 -1
- data/ext/oj/safe.c +230 -0
- data/ext/oj/safe.h +79 -0
- data/ext/oj/saj.c +15 -10
- data/ext/oj/scp.c +3 -6
- data/ext/oj/simd.h +219 -0
- data/ext/oj/sparse.c +6 -3
- data/ext/oj/stream_writer.c +38 -28
- data/ext/oj/strict.c +2 -4
- data/ext/oj/string_writer.c +54 -22
- data/ext/oj/usual.c +57 -35
- data/ext/oj/usual.h +1 -0
- data/ext/oj/val_stack.c +13 -2
- data/ext/oj/wab.c +5 -4
- data/lib/oj/mimic.rb +1 -5
- data/lib/oj/schandler.rb +5 -4
- data/lib/oj/version.rb +1 -1
- data/pages/Encoding.md +1 -1
- metadata +36 -100
- data/test/_test_active.rb +0 -75
- data/test/_test_active_mimic.rb +0 -95
- data/test/_test_mimic_rails.rb +0 -123
- data/test/activerecord/result_test.rb +0 -31
- data/test/activesupport6/abstract_unit.rb +0 -44
- data/test/activesupport6/decoding_test.rb +0 -133
- data/test/activesupport6/encoding_test.rb +0 -507
- data/test/activesupport6/encoding_test_cases.rb +0 -98
- data/test/activesupport6/test_common.rb +0 -17
- data/test/activesupport6/test_helper.rb +0 -163
- data/test/activesupport6/time_zone_test_helpers.rb +0 -39
- data/test/activesupport7/abstract_unit.rb +0 -49
- data/test/activesupport7/decoding_test.rb +0 -125
- data/test/activesupport7/encoding_test.rb +0 -486
- data/test/activesupport7/encoding_test_cases.rb +0 -104
- data/test/activesupport7/time_zone_test_helpers.rb +0 -47
- data/test/files.rb +0 -29
- data/test/foo.rb +0 -14
- data/test/helper.rb +0 -39
- data/test/isolated/shared.rb +0 -309
- data/test/isolated/test_mimic_after.rb +0 -13
- data/test/isolated/test_mimic_alone.rb +0 -12
- data/test/isolated/test_mimic_as_json.rb +0 -45
- data/test/isolated/test_mimic_before.rb +0 -13
- data/test/isolated/test_mimic_define.rb +0 -28
- data/test/isolated/test_mimic_rails_after.rb +0 -22
- data/test/isolated/test_mimic_rails_before.rb +0 -21
- data/test/isolated/test_mimic_redefine.rb +0 -15
- data/test/json_gem/json_addition_test.rb +0 -216
- data/test/json_gem/json_common_interface_test.rb +0 -155
- data/test/json_gem/json_encoding_test.rb +0 -107
- data/test/json_gem/json_ext_parser_test.rb +0 -21
- data/test/json_gem/json_fixtures_test.rb +0 -36
- data/test/json_gem/json_generator_test.rb +0 -407
- data/test/json_gem/json_generic_object_test.rb +0 -90
- data/test/json_gem/json_parser_test.rb +0 -477
- data/test/json_gem/json_string_matching_test.rb +0 -42
- data/test/json_gem/test_helper.rb +0 -30
- data/test/mem.rb +0 -34
- data/test/perf.rb +0 -102
- data/test/perf_compat.rb +0 -128
- data/test/perf_dump.rb +0 -50
- data/test/perf_fast.rb +0 -162
- data/test/perf_file.rb +0 -62
- data/test/perf_object.rb +0 -134
- data/test/perf_once.rb +0 -59
- data/test/perf_parser.rb +0 -183
- data/test/perf_saj.rb +0 -101
- data/test/perf_scp.rb +0 -140
- data/test/perf_simple.rb +0 -289
- data/test/perf_strict.rb +0 -137
- data/test/perf_wab.rb +0 -129
- data/test/prec.rb +0 -23
- data/test/sample/change.rb +0 -13
- data/test/sample/dir.rb +0 -18
- data/test/sample/doc.rb +0 -35
- data/test/sample/file.rb +0 -47
- data/test/sample/group.rb +0 -15
- data/test/sample/hasprops.rb +0 -15
- data/test/sample/layer.rb +0 -11
- data/test/sample/line.rb +0 -20
- data/test/sample/oval.rb +0 -10
- data/test/sample/rect.rb +0 -9
- data/test/sample/shape.rb +0 -34
- data/test/sample/text.rb +0 -19
- data/test/sample.rb +0 -54
- data/test/sample_json.rb +0 -37
- data/test/test_compat.rb +0 -567
- data/test/test_custom.rb +0 -554
- data/test/test_debian.rb +0 -50
- data/test/test_fast.rb +0 -526
- data/test/test_file.rb +0 -250
- data/test/test_gc.rb +0 -60
- data/test/test_generate.rb +0 -21
- data/test/test_hash.rb +0 -39
- data/test/test_integer_range.rb +0 -72
- data/test/test_null.rb +0 -376
- data/test/test_object.rb +0 -1016
- data/test/test_parser.rb +0 -11
- data/test/test_parser_debug.rb +0 -27
- data/test/test_parser_saj.rb +0 -337
- data/test/test_parser_usual.rb +0 -217
- data/test/test_rails.rb +0 -35
- data/test/test_saj.rb +0 -188
- data/test/test_scp.rb +0 -431
- data/test/test_strict.rb +0 -431
- data/test/test_various.rb +0 -801
- data/test/test_wab.rb +0 -311
- data/test/test_writer.rb +0 -380
- data/test/tests.rb +0 -33
- data/test/tests_mimic.rb +0 -23
- data/test/tests_mimic_addition.rb +0 -16
data/ext/oj/oj.c
CHANGED
|
@@ -18,6 +18,9 @@
|
|
|
18
18
|
#include "odd.h"
|
|
19
19
|
#include "parse.h"
|
|
20
20
|
#include "rails.h"
|
|
21
|
+
#include "simd.h"
|
|
22
|
+
|
|
23
|
+
#define MAX_INDENT 16
|
|
21
24
|
|
|
22
25
|
typedef struct _yesNoOpt {
|
|
23
26
|
VALUE sym;
|
|
@@ -33,10 +36,10 @@ ID oj_array_append_id;
|
|
|
33
36
|
ID oj_array_end_id;
|
|
34
37
|
ID oj_array_start_id;
|
|
35
38
|
ID oj_as_json_id;
|
|
36
|
-
ID oj_at_id;
|
|
37
39
|
ID oj_begin_id;
|
|
38
40
|
ID oj_bigdecimal_id;
|
|
39
41
|
ID oj_end_id;
|
|
42
|
+
ID oj_eofq_id;
|
|
40
43
|
ID oj_exclude_end_id;
|
|
41
44
|
ID oj_error_id;
|
|
42
45
|
ID oj_file_id;
|
|
@@ -51,6 +54,7 @@ ID oj_json_create_id;
|
|
|
51
54
|
ID oj_length_id;
|
|
52
55
|
ID oj_new_id;
|
|
53
56
|
ID oj_parse_id;
|
|
57
|
+
ID oj_plus_id;
|
|
54
58
|
ID oj_pos_id;
|
|
55
59
|
ID oj_raw_json_id;
|
|
56
60
|
ID oj_read_id;
|
|
@@ -91,9 +95,7 @@ VALUE oj_array_class_sym;
|
|
|
91
95
|
VALUE oj_create_additions_sym;
|
|
92
96
|
VALUE oj_decimal_class_sym;
|
|
93
97
|
VALUE oj_hash_class_sym;
|
|
94
|
-
VALUE oj_in_sym;
|
|
95
98
|
VALUE oj_indent_sym;
|
|
96
|
-
VALUE oj_nanosecond_sym;
|
|
97
99
|
VALUE oj_object_class_sym;
|
|
98
100
|
VALUE oj_quirks_mode_sym;
|
|
99
101
|
VALUE oj_safe_sym;
|
|
@@ -120,7 +122,9 @@ static VALUE create_id_sym;
|
|
|
120
122
|
static VALUE custom_sym;
|
|
121
123
|
static VALUE empty_string_sym;
|
|
122
124
|
static VALUE escape_mode_sym;
|
|
125
|
+
static VALUE except_sym;
|
|
123
126
|
static VALUE integer_range_sym;
|
|
127
|
+
static VALUE max_integer_digits_sym;
|
|
124
128
|
static VALUE fast_sym;
|
|
125
129
|
static VALUE float_prec_sym;
|
|
126
130
|
static VALUE float_format_sym;
|
|
@@ -138,6 +142,7 @@ static VALUE null_sym;
|
|
|
138
142
|
static VALUE object_sym;
|
|
139
143
|
static VALUE omit_null_byte_sym;
|
|
140
144
|
static VALUE omit_nil_sym;
|
|
145
|
+
static VALUE only_sym;
|
|
141
146
|
static VALUE rails_sym;
|
|
142
147
|
static VALUE raise_sym;
|
|
143
148
|
static VALUE ruby_sym;
|
|
@@ -167,6 +172,8 @@ pthread_mutex_t oj_cache_mutex;
|
|
|
167
172
|
VALUE oj_cache_mutex = Qnil;
|
|
168
173
|
#endif
|
|
169
174
|
|
|
175
|
+
SIMD_Implementation SIMD_Impl = SIMD_NONE;
|
|
176
|
+
|
|
170
177
|
extern void oj_parser_init();
|
|
171
178
|
|
|
172
179
|
const char oj_json_class[] = "json_class";
|
|
@@ -202,6 +209,7 @@ struct _options oj_default_options = {
|
|
|
202
209
|
0, // cache_str
|
|
203
210
|
0, // int_range_min
|
|
204
211
|
0, // int_range_max
|
|
212
|
+
0, // max_integer_digits
|
|
205
213
|
oj_json_class, // create_id
|
|
206
214
|
10, // create_id_len
|
|
207
215
|
9, // sec_prec
|
|
@@ -226,6 +234,8 @@ struct _options oj_default_options = {
|
|
|
226
234
|
false, // omit_nil
|
|
227
235
|
false, // omit_null_byte
|
|
228
236
|
MAX_DEPTH, // max_depth
|
|
237
|
+
NULL, // only
|
|
238
|
+
NULL, // except
|
|
229
239
|
},
|
|
230
240
|
{
|
|
231
241
|
// str_rx
|
|
@@ -236,76 +246,109 @@ struct _options oj_default_options = {
|
|
|
236
246
|
NULL,
|
|
237
247
|
};
|
|
238
248
|
|
|
249
|
+
static VALUE only_array_from_string(const char *str) {
|
|
250
|
+
volatile VALUE a = Qnil;
|
|
251
|
+
|
|
252
|
+
if (NULL != str && 2 < strlen(str)) {
|
|
253
|
+
str++;
|
|
254
|
+
char *cp;
|
|
255
|
+
|
|
256
|
+
a = rb_ary_new();
|
|
257
|
+
while (NULL != (cp = strchr(str, ':'))) {
|
|
258
|
+
rb_ary_push(a, rb_id2sym(rb_intern2(str, cp - str)));
|
|
259
|
+
str = cp + 1;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
return a;
|
|
263
|
+
}
|
|
264
|
+
|
|
239
265
|
/* Document-method: default_options()
|
|
240
266
|
* call-seq: default_options()
|
|
241
267
|
*
|
|
242
268
|
* Returns the default load and dump options as a Hash. The options are
|
|
243
|
-
* - *:indent* [_Fixnum_|_String_|_nil_] number of spaces to indent each element
|
|
244
|
-
*document, zero or nil is no newline between JSON elements,
|
|
245
|
-
*top level JSON elements in a stream,
|
|
246
|
-
*
|
|
247
|
-
*references
|
|
269
|
+
* - *:indent* [_Fixnum_|_String_|_nil_] number of spaces to indent each element
|
|
270
|
+
* in an JSON document, zero or nil is no newline between JSON elements,
|
|
271
|
+
* negative indicates no newline between top level JSON elements in a stream,
|
|
272
|
+
* a String indicates the string should be used for indentation
|
|
273
|
+
* - *:circular* [_Boolean_|_nil_] support circular references while dumping as
|
|
274
|
+
* well as shared references
|
|
248
275
|
* - *:auto_define* [_Boolean_|_nil_] automatically define classes if they do not exist
|
|
249
276
|
* - *:symbol_keys* [_Boolean_|_nil_] use symbols instead of strings for hash keys
|
|
250
|
-
* - *:escape_mode* [_:newline_|_:json_|_:slash_|_:xss_safe_|_:ascii_|_:unicode_xss_|_nil_]
|
|
251
|
-
*characters to escape
|
|
252
|
-
* - *:class_cache* [_Boolean_|_nil_] cache classes for faster parsing (if dynamically
|
|
253
|
-
*classes or reloading classes then don't use this)
|
|
254
|
-
* - *:mode* [_:object_|_:strict_|_:compat_|_:null_|_:custom_|_:rails_|_:wab_] load and
|
|
255
|
-
*to use for JSON
|
|
277
|
+
* - *:escape_mode* [_:newline_|_:json_|_:slash_|_:xss_safe_|_:ascii_|_:unicode_xss_|_nil_]
|
|
278
|
+
* determines the characters to escape
|
|
279
|
+
* - *:class_cache* [_Boolean_|_nil_] cache classes for faster parsing (if dynamically
|
|
280
|
+
* modifying classes or reloading classes then don't use this)
|
|
281
|
+
* - *:mode* [_:object_|_:strict_|_:compat_|_:null_|_:custom_|_:rails_|_:wab_] load and
|
|
282
|
+
* dump modes to use for JSON
|
|
256
283
|
* - *:time_format* [_:unix_|_:unix_zone_|_:xmlschema_|_:ruby_] time format when dumping
|
|
257
|
-
* - *:bigdecimal_as_decimal* [_Boolean_|_nil_] dump BigDecimal as a decimal number or
|
|
258
|
-
*
|
|
259
|
-
*
|
|
260
|
-
*
|
|
261
|
-
*
|
|
262
|
-
*
|
|
263
|
-
* - *:
|
|
264
|
-
*
|
|
265
|
-
* - *:
|
|
266
|
-
*
|
|
267
|
-
* - *:
|
|
268
|
-
*
|
|
269
|
-
* - *:
|
|
270
|
-
*
|
|
271
|
-
* - *:
|
|
272
|
-
*
|
|
284
|
+
* - *:bigdecimal_as_decimal* [_Boolean_|_nil_] dump BigDecimal as a decimal number or
|
|
285
|
+
* as a String
|
|
286
|
+
* - *:bigdecimal_load* [_:bigdecimal_|_:float_|_:auto_|_:fast_|_:ruby_] load decimals
|
|
287
|
+
* as BigDecimal instead of as a Float. :auto pick the most precise for the number
|
|
288
|
+
* of digits. :float should be the same as ruby. :fast may require rounding but is
|
|
289
|
+
* must faster.
|
|
290
|
+
* - *:compat_bigdecimal* [_true_|_false_] load decimals as BigDecimal instead of as
|
|
291
|
+
* a Float when in compat or rails mode.
|
|
292
|
+
* - *:create_id* [_String_|_nil_] create id for json compatible object encoding,
|
|
293
|
+
* default is 'json_class'
|
|
294
|
+
* - *:create_additions* [_Boolean_|_nil_] if true allow creation of instances using
|
|
295
|
+
* create_id on load.
|
|
296
|
+
* - *:second_precision* [_Fixnum_|_nil_] number of digits after the decimal when
|
|
297
|
+
* dumping the seconds portion of time
|
|
298
|
+
* - *:float_precision* [_Fixnum_|_nil_] number of digits of precision when dumping
|
|
299
|
+
* floats, 0 indicates use Ruby
|
|
300
|
+
* - *:float_format* [_String_] the C printf format string for printing floats.
|
|
301
|
+
* Default follows the float_precision and will be changed if float_precision is
|
|
302
|
+
* changed. The string can be no more than 6 bytes.
|
|
273
303
|
* - *:use_to_json* [_Boolean_|_nil_] call to_json() methods on dump, default is false
|
|
274
304
|
* - *:use_as_json* [_Boolean_|_nil_] call as_json() methods on dump, default is false
|
|
275
305
|
* - *:use_raw_json* [_Boolean_|_nil_] call raw_json() methods on dump, default is false
|
|
276
|
-
* - *:nilnil* [_Boolean_|_nil_] if true a nil input to load will return nil and
|
|
277
|
-
*Exception
|
|
306
|
+
* - *:nilnil* [_Boolean_|_nil_] if true a nil input to load will return nil and
|
|
307
|
+
* not raise an Exception
|
|
278
308
|
* - *:empty_string* [_Boolean_|_nil_] if true an empty input will not raise an Exception
|
|
279
309
|
* - *:allow_gc* [_Boolean_|_nil_] allow or prohibit GC during parsing, default is true (allow)
|
|
280
|
-
* - *:quirks_mode* [_true,_|_false_|_nil_] Allow single JSON values instead of
|
|
281
|
-
*is true (allow)
|
|
282
|
-
* - *:allow_invalid_unicode* [_true,_|_false_|_nil_] Allow invalid unicode,
|
|
283
|
-
*allow)
|
|
284
|
-
* - *:allow_nan* [_true,_|_false_|_nil_] Allow Nan, Infinity, and -Infinity to
|
|
285
|
-
*is true (allow)
|
|
286
|
-
* - *:indent_str* [_String_|_nil_] String to use for indentation, overriding the
|
|
287
|
-
*not nil
|
|
288
|
-
* - *:space* [_String_|_nil_] String to use for the space after the colon in JSON
|
|
289
|
-
*
|
|
310
|
+
* - *:quirks_mode* [_true,_|_false_|_nil_] Allow single JSON values instead of
|
|
311
|
+
* documents, default is true (allow)
|
|
312
|
+
* - *:allow_invalid_unicode* [_true,_|_false_|_nil_] Allow invalid unicode,
|
|
313
|
+
* default is false (don't allow)
|
|
314
|
+
* - *:allow_nan* [_true,_|_false_|_nil_] Allow Nan, Infinity, and -Infinity to
|
|
315
|
+
* be parsed, default is true (allow)
|
|
316
|
+
* - *:indent_str* [_String_|_nil_] String to use for indentation, overriding the
|
|
317
|
+
* indent option is not nil
|
|
318
|
+
* - *:space* [_String_|_nil_] String to use for the space after the colon in JSON
|
|
319
|
+
* object fields
|
|
320
|
+
* - *:space_before* [_String_|_nil_] String to use before the colon separator in
|
|
321
|
+
* JSON object fields
|
|
290
322
|
* - *:object_nl* [_String_|_nil_] String to use after a JSON object field value
|
|
291
323
|
* - *:array_nl* [_String_|_nil_] String to use after a JSON array value
|
|
292
|
-
* - *:nan* [_:null_|_:huge_|_:word_|_:raise_|_:auto_] how to dump Infinity and
|
|
293
|
-
*null, :huge places a huge number, :word places Infinity
|
|
294
|
-
*uses default for each mode.
|
|
295
|
-
* - *:hash_class* [_Class_|_nil_] Class to use instead of Hash on load,
|
|
296
|
-
*used
|
|
324
|
+
* - *:nan* [_:null_|_:huge_|_:word_|_:raise_|_:auto_] how to dump Infinity and
|
|
325
|
+
* NaN. :null places a null, :huge places a huge number, :word places Infinity
|
|
326
|
+
* or NaN, :raise raises and exception, :auto uses default for each mode.
|
|
327
|
+
* - *:hash_class* [_Class_|_nil_] Class to use instead of Hash on load,
|
|
328
|
+
* :object_class can also be used
|
|
297
329
|
* - *:array_class* [_Class_|_nil_] Class to use instead of Array on load
|
|
298
|
-
* - *:omit_nil* [_true_|_false_] if true Hash and Object attributes with nil
|
|
299
|
-
*
|
|
330
|
+
* - *:omit_nil* [_true_|_false_] if true Hash and Object attributes with nil
|
|
331
|
+
* values are omitted
|
|
332
|
+
* - *:omit_null_byte* [_true_|_false_] if true null bytes in strings will be
|
|
333
|
+
* omitted when dumping
|
|
300
334
|
* - *:ignore* [_nil_|_Array_] either nil or an Array of classes to ignore when dumping
|
|
301
|
-
* - *:ignore_under* [_Boolean_] if true then attributes that start with _ are
|
|
302
|
-
*object or custom mode.
|
|
335
|
+
* - *:ignore_under* [_Boolean_] if true then attributes that start with _ are
|
|
336
|
+
* ignored when dumping in object or custom mode.
|
|
303
337
|
* - *:cache_keys* [_Boolean_] if true then hash keys are cached if less than 35 bytes.
|
|
304
|
-
* - *:cache_str* [_Fixnum_] maximum string value length to cache (strings less
|
|
338
|
+
* - *:cache_str* [_Fixnum_] maximum string value length to cache (strings less
|
|
339
|
+
* than this are cached)
|
|
305
340
|
* - *:integer_range* [_Range_] Dump integers outside range as strings.
|
|
306
|
-
* - *:
|
|
307
|
-
*
|
|
308
|
-
*
|
|
341
|
+
* - *:max_integer_digits* [_Fixnum_] Maximum number of decimal digits allowed in a
|
|
342
|
+
* parsed integer. When the limit is exceeded a parse error is raised. 0 (the
|
|
343
|
+
* default) disables the limit. Setting a reasonable limit is recommended when
|
|
344
|
+
* parsing untrusted input to mitigate CPU-DoS attacks. Only applies to the
|
|
345
|
+
* legacy parsers (Oj.load, Oj::Doc, JSON.parse mimic); Oj::Parser is unaffected.
|
|
346
|
+
* - *:trace* [_true,_|_false_] Trace all load and dump calls, default is false
|
|
347
|
+
* (trace is off)
|
|
348
|
+
* - *:safe* [_true,_|_false_] Safe mimic breaks JSON mimic to be safer, default
|
|
349
|
+
* is false (safe is off)
|
|
350
|
+
* - *:only* [_nil,_|_Array_] A list of the fields to encode. All others are skipped.
|
|
351
|
+
* - *:except* [_nil,_|_Array_] A list of the fields to not encode. All others are encoded.
|
|
309
352
|
*
|
|
310
353
|
* Return [_Hash_] all current option settings.
|
|
311
354
|
*/
|
|
@@ -414,6 +457,7 @@ static VALUE get_def_opts(VALUE self) {
|
|
|
414
457
|
} else {
|
|
415
458
|
rb_hash_aset(opts, integer_range_sym, Qnil);
|
|
416
459
|
}
|
|
460
|
+
rb_hash_aset(opts, max_integer_digits_sym, LONG2NUM((long)oj_default_options.max_integer_digits));
|
|
417
461
|
switch (oj_default_options.escape_mode) {
|
|
418
462
|
case NLEsc: rb_hash_aset(opts, escape_mode_sym, newline_sym); break;
|
|
419
463
|
case JSONEsc: rb_hash_aset(opts, escape_mode_sym, json_sym); break;
|
|
@@ -471,6 +515,9 @@ static VALUE get_def_opts(VALUE self) {
|
|
|
471
515
|
rb_hash_aset(opts, oj_hash_class_sym, oj_default_options.hash_class);
|
|
472
516
|
rb_hash_aset(opts, oj_array_class_sym, oj_default_options.array_class);
|
|
473
517
|
|
|
518
|
+
rb_hash_aset(opts, only_sym, only_array_from_string(oj_default_options.dump_opts.only));
|
|
519
|
+
rb_hash_aset(opts, except_sym, only_array_from_string(oj_default_options.dump_opts.except));
|
|
520
|
+
|
|
474
521
|
if (NULL == oj_default_options.ignore) {
|
|
475
522
|
rb_hash_aset(opts, ignore_sym, Qnil);
|
|
476
523
|
} else {
|
|
@@ -490,73 +537,72 @@ static VALUE get_def_opts(VALUE self) {
|
|
|
490
537
|
*
|
|
491
538
|
* Sets the default options for load and dump.
|
|
492
539
|
* - *opts* [_Hash_] options to change
|
|
493
|
-
* - *:indent* [_Fixnum_|_String_|_nil_] number of spaces to indent each element
|
|
494
|
-
*document or the String to use for indentation.
|
|
540
|
+
* - *:indent* [_Fixnum_|_String_|_nil_] number of spaces to indent each element
|
|
541
|
+
* in a JSON document or the String to use for indentation.
|
|
495
542
|
* - :circular [_Boolean_|_nil_] support circular references while dumping.
|
|
496
543
|
* - *:auto_define* [_Boolean_|_nil_] automatically define classes if they do not exist.
|
|
497
544
|
* - *:symbol_keys* [_Boolean_|_nil_] convert hash keys to symbols.
|
|
498
545
|
* - *:class_cache* [_Boolean_|_nil_] cache classes for faster parsing.
|
|
499
|
-
* - *:escape* [_:newline_|_:json_|_:xss_safe_|_:ascii_|_unicode_xss_|_nil_]
|
|
500
|
-
*high-bit characters as escaped sequences if :ascii, :json
|
|
501
|
-
|
|
502
|
-
*
|
|
503
|
-
*
|
|
504
|
-
*
|
|
505
|
-
*
|
|
506
|
-
*
|
|
507
|
-
*
|
|
508
|
-
*
|
|
509
|
-
*
|
|
510
|
-
*
|
|
511
|
-
*
|
|
512
|
-
*
|
|
513
|
-
*Object
|
|
514
|
-
*
|
|
515
|
-
*
|
|
516
|
-
*
|
|
517
|
-
*
|
|
518
|
-
*
|
|
519
|
-
*
|
|
520
|
-
*
|
|
546
|
+
* - *:escape* [_:newline_|_:json_|_:xss_safe_|_:ascii_|_unicode_xss_|_nil_]
|
|
547
|
+
* mode encodes all high-bit characters as escaped sequences if :ascii, :json
|
|
548
|
+
* is standand UTF-8 JSON encoding, :newline is the same as :json but newlines
|
|
549
|
+
* are not escaped, :unicode_xss allows unicode but escapes &, <, and >, and
|
|
550
|
+
* any \u20xx characters along with some others, and :xss_safe escapes &, <,
|
|
551
|
+
* and >, and some others.
|
|
552
|
+
* - *:bigdecimal_as_decimal* [_Boolean_|_nil_] dump BigDecimal as a decimal
|
|
553
|
+
* number or as a String.
|
|
554
|
+
* - *:bigdecimal_load* [_:bigdecimal_|_:float_|_:auto_|_nil_] load decimals as
|
|
555
|
+
* BigDecimal instead of as a Float. :auto pick the most precise for the number of digits.
|
|
556
|
+
* - *:compat_bigdecimal* [_true_|_false_] load decimals as BigDecimal instead
|
|
557
|
+
* of as a Float in compat mode.
|
|
558
|
+
* - *:mode* [_:object_|_:strict_|_:compat_|_:null_|_:custom_|_:rails_|_:wab_] load
|
|
559
|
+
* and dump mode to use for JSON :strict raises an exception when a non-supported
|
|
560
|
+
* Object is encountered. :compat attempts to extract variable values from an
|
|
561
|
+
* Object using to_json() or to_hash() then it walks the Object's variables if
|
|
562
|
+
* neither is found. The :object mode ignores to_hash() and to_json() methods
|
|
563
|
+
* and encodes variables using code internal to the Oj gem. The :null mode
|
|
564
|
+
* ignores non-supported Objects and replaces them with a null. The :custom
|
|
565
|
+
* mode honors all dump options. The :rails more mimics rails and Active behavior.
|
|
566
|
+
* - *:time_format* [_:unix_|_:xmlschema_|_:ruby_] time format when dumping in :compat
|
|
567
|
+
* mode :unix decimal number denoting the number of seconds since 1/1/1970,
|
|
568
|
+
* :unix_zone decimal number denoting the number of seconds since 1/1/1970
|
|
569
|
+
* plus the utc_offset in the exponent, :xmlschema date-time format taken
|
|
570
|
+
* from XML Schema as a String, :ruby Time.to_s formatted String.
|
|
521
571
|
* - *:create_id* [_String_|_nil_] create id for json compatible object encoding
|
|
522
|
-
* - *:create_additions* [_Boolean_|_nil_] if true allow creation of instances using create_id on
|
|
523
|
-
*
|
|
524
|
-
*
|
|
525
|
-
*
|
|
526
|
-
*
|
|
527
|
-
*
|
|
528
|
-
* - *:float_precision* [_Fixnum_|_nil_] number of digits of precision when dumping floats, 0
|
|
529
|
-
*indicates use Ruby.
|
|
572
|
+
* - *:create_additions* [_Boolean_|_nil_] if true allow creation of instances using create_id on load.
|
|
573
|
+
* - *:second_precision* [_Fixnum_|_nil_] number of digits after the decimal
|
|
574
|
+
* when dumping the seconds portion of time.
|
|
575
|
+
* - *:float_format* [_String_] the C printf format string for printing floats.
|
|
576
|
+
* Default follows the float_precision and will be changed if float_precision
|
|
577
|
+
* is changed. The string can be no more than 6 bytes.
|
|
578
|
+
* - *:float_precision* [_Fixnum_|_nil_] number of digits of precision when dumping floats, 0 indicates use Ruby.
|
|
530
579
|
* - *:use_to_json* [_Boolean_|_nil_] call to_json() methods on dump, default is false.
|
|
531
580
|
* - *:use_as_json* [_Boolean_|_nil_] call as_json() methods on dump, default is false.
|
|
532
581
|
* - *:use_to_hash* [_Boolean_|_nil_] call to_hash() methods on dump, default is false.
|
|
533
582
|
* - *:use_raw_json* [_Boolean_|_nil_] call raw_json() methods on dump, default is false.
|
|
534
|
-
* - *:nilnil* [_Boolean_|_nil_] if true a nil input to load will return nil and not raise an
|
|
535
|
-
*Exception.
|
|
583
|
+
* - *:nilnil* [_Boolean_|_nil_] if true a nil input to load will return nil and not raise an Exception.
|
|
536
584
|
* - *:allow_gc* [_Boolean_|_nil_] allow or prohibit GC during parsing, default is true (allow).
|
|
537
|
-
* - *:quirks_mode* [_Boolean_|_nil_] allow single JSON values instead of documents, default is
|
|
538
|
-
*
|
|
539
|
-
* - *:allow_invalid_unicode* [_Boolean_|_nil_] allow invalid unicode, default is false (don't
|
|
540
|
-
*allow).
|
|
585
|
+
* - *:quirks_mode* [_Boolean_|_nil_] allow single JSON values instead of documents, default is true (allow).
|
|
586
|
+
* - *:allow_invalid_unicode* [_Boolean_|_nil_] allow invalid unicode, default is false (don't allow).
|
|
541
587
|
* - *:allow_nan* [_Boolean_|_nil_] allow Nan, Infinity, and -Infinity, default is true (allow).
|
|
542
588
|
* - *:space* [_String_|_nil_] String to use for the space after the colon in JSON object fields.
|
|
543
|
-
* - *:space_before* [_String_|_nil_] String to use before the colon separator in JSON object
|
|
544
|
-
*fields.
|
|
589
|
+
* - *:space_before* [_String_|_nil_] String to use before the colon separator in JSON object fields.
|
|
545
590
|
* - *:object_nl* [_String_|_nil_] String to use after a JSON object field value.
|
|
546
591
|
* - *:array_nl* [_String_|_nil_] String to use after a JSON array value
|
|
547
|
-
* - *:nan* [_:null_|_:huge_|_:word_|_:raise_] how to dump Infinity and NaN in null,
|
|
548
|
-
*compat mode. :null places a null, :huge places a huge number, :word
|
|
549
|
-
*raises and exception, :auto uses default for each mode.
|
|
550
|
-
* - *:hash_class* [_Class_|_nil_] Class to use instead of Hash on load, :object_class can also be
|
|
551
|
-
*used.
|
|
592
|
+
* - *:nan* [_:null_|_:huge_|_:word_|_:raise_] how to dump Infinity and NaN in null,
|
|
593
|
+
* strict, and compat mode. :null places a null, :huge places a huge number, :word
|
|
594
|
+
* places Infinity or NaN, :raise raises and exception, :auto uses default for each mode.
|
|
595
|
+
* - *:hash_class* [_Class_|_nil_] Class to use instead of Hash on load, :object_class can also be used.
|
|
552
596
|
* - *:array_class* [_Class_|_nil_] Class to use instead of Array on load.
|
|
553
597
|
* - *:omit_nil* [_true_|_false_] if true Hash and Object attributes with nil values are omitted.
|
|
554
598
|
* - *:ignore* [_nil_|Array] either nil or an Array of classes to ignore when dumping
|
|
555
|
-
* - *:ignore_under* [_Boolean_] if true then attributes that start with _ are
|
|
556
|
-
*dumping in object or custom mode.
|
|
599
|
+
* - *:ignore_under* [_Boolean_] if true then attributes that start with _ are
|
|
600
|
+
* ignored when dumping in object or custom mode.
|
|
557
601
|
* - *:cache_keys* [_Boolean_] if true then hash keys are cached
|
|
558
602
|
* - *:cache_str* [_Fixnum_] maximum string value length to cache (strings less than this are cached)
|
|
559
603
|
* - *:integer_range* [_Range_] Dump integers outside range as strings.
|
|
604
|
+
* - *:max_integer_digits* [_Fixnum_] Maximum decimal digits in a parsed integer
|
|
605
|
+
* (0 = unlimited). Use to mitigate CPU-DoS via huge integer values in JSON.
|
|
560
606
|
* - *:trace* [_Boolean_] turn trace on or off.
|
|
561
607
|
* - *:safe* [_Boolean_] turn safe mimic on or off.
|
|
562
608
|
*/
|
|
@@ -616,6 +662,95 @@ bool set_yesno_options(VALUE key, VALUE value, Options copts) {
|
|
|
616
662
|
return false;
|
|
617
663
|
}
|
|
618
664
|
|
|
665
|
+
static const char *make_only_value(VALUE v) {
|
|
666
|
+
switch (rb_type(v)) {
|
|
667
|
+
case RUBY_T_NIL:
|
|
668
|
+
case RUBY_T_NONE: return NULL;
|
|
669
|
+
case RUBY_T_ARRAY: {
|
|
670
|
+
long len = rb_array_len(v);
|
|
671
|
+
long i;
|
|
672
|
+
long size = 0;
|
|
673
|
+
char *buf;
|
|
674
|
+
char *bp;
|
|
675
|
+
|
|
676
|
+
for (i = 0; i < len; i++) {
|
|
677
|
+
VALUE x = rb_ary_entry(v, i);
|
|
678
|
+
|
|
679
|
+
switch (rb_type(x)) {
|
|
680
|
+
case RUBY_T_SYMBOL:
|
|
681
|
+
size += strlen(rb_id2name(rb_sym2id(x)));
|
|
682
|
+
size++;
|
|
683
|
+
break;
|
|
684
|
+
case RUBY_T_STRING:
|
|
685
|
+
size += strlen(StringValueCStr(x));
|
|
686
|
+
size++;
|
|
687
|
+
break;
|
|
688
|
+
default: rb_raise(rb_eArgError, ":only and :except must be nil, symbol, string, or array."); break;
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
if (0 == size) {
|
|
692
|
+
return NULL;
|
|
693
|
+
}
|
|
694
|
+
buf = OJ_R_ALLOC_N(char, size + 2);
|
|
695
|
+
bp = buf;
|
|
696
|
+
*bp++ = ':';
|
|
697
|
+
for (i = 0; i < len; i++) {
|
|
698
|
+
VALUE x = rb_ary_entry(v, i);
|
|
699
|
+
const char *str;
|
|
700
|
+
|
|
701
|
+
switch (rb_type(x)) {
|
|
702
|
+
case RUBY_T_SYMBOL:
|
|
703
|
+
str = rb_id2name(rb_sym2id(x));
|
|
704
|
+
size = strlen(str);
|
|
705
|
+
memcpy(bp, str, size);
|
|
706
|
+
bp += size;
|
|
707
|
+
*bp++ = ':';
|
|
708
|
+
break;
|
|
709
|
+
case RUBY_T_STRING:
|
|
710
|
+
str = StringValueCStr(x);
|
|
711
|
+
size = strlen(str);
|
|
712
|
+
memcpy(bp, str, size);
|
|
713
|
+
bp += size;
|
|
714
|
+
*bp++ = ':';
|
|
715
|
+
break;
|
|
716
|
+
default:
|
|
717
|
+
// ignore
|
|
718
|
+
break;
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
*bp = '\0';
|
|
722
|
+
|
|
723
|
+
return buf;
|
|
724
|
+
}
|
|
725
|
+
case RUBY_T_STRING: {
|
|
726
|
+
const char *str = StringValueCStr(v);
|
|
727
|
+
size_t size = strlen(str);
|
|
728
|
+
char *buf = OJ_R_ALLOC_N(char, size + 3);
|
|
729
|
+
|
|
730
|
+
buf[0] = ':';
|
|
731
|
+
strcpy(buf + 1, str);
|
|
732
|
+
buf[size + 1] = ':';
|
|
733
|
+
buf[size + 2] = '\0';
|
|
734
|
+
|
|
735
|
+
return buf;
|
|
736
|
+
}
|
|
737
|
+
case RUBY_T_SYMBOL: {
|
|
738
|
+
const char *str = rb_id2name(rb_sym2id(v));
|
|
739
|
+
size_t size = strlen(str);
|
|
740
|
+
char *buf = OJ_R_ALLOC_N(char, size + 3);
|
|
741
|
+
|
|
742
|
+
buf[0] = ':';
|
|
743
|
+
strcpy(buf + 1, str);
|
|
744
|
+
buf[size + 1] = ':';
|
|
745
|
+
buf[size + 2] = '\0';
|
|
746
|
+
|
|
747
|
+
return buf;
|
|
748
|
+
}
|
|
749
|
+
default: rb_raise(rb_eArgError, ":only and zzz :except must be nil, symbol, string, or array."); break;
|
|
750
|
+
}
|
|
751
|
+
return NULL;
|
|
752
|
+
}
|
|
753
|
+
|
|
619
754
|
static int parse_options_cb(VALUE k, VALUE v, VALUE opts) {
|
|
620
755
|
Options copts = (Options)opts;
|
|
621
756
|
size_t len;
|
|
@@ -633,7 +768,10 @@ static int parse_options_cb(VALUE k, VALUE v, VALUE opts) {
|
|
|
633
768
|
case T_FIXNUM:
|
|
634
769
|
copts->dump_opts.indent_size = 0;
|
|
635
770
|
*copts->dump_opts.indent_str = '\0';
|
|
636
|
-
|
|
771
|
+
if (MAX_INDENT < FIX2INT(v)) {
|
|
772
|
+
rb_raise(rb_eArgError, "indent is limited to %d characters.", MAX_INDENT);
|
|
773
|
+
}
|
|
774
|
+
copts->indent = FIX2INT(v);
|
|
637
775
|
break;
|
|
638
776
|
case T_STRING:
|
|
639
777
|
if (sizeof(copts->dump_opts.indent_str) <= (len = RSTRING_LEN(v))) {
|
|
@@ -917,12 +1055,12 @@ static int parse_options_cb(VALUE k, VALUE v, VALUE opts) {
|
|
|
917
1055
|
OJ_R_FREE(copts->ignore);
|
|
918
1056
|
copts->ignore = NULL;
|
|
919
1057
|
if (Qnil != v) {
|
|
920
|
-
|
|
1058
|
+
size_t cnt;
|
|
921
1059
|
|
|
922
1060
|
rb_check_type(v, T_ARRAY);
|
|
923
|
-
cnt =
|
|
1061
|
+
cnt = RARRAY_LEN(v);
|
|
924
1062
|
if (0 < cnt) {
|
|
925
|
-
|
|
1063
|
+
size_t i;
|
|
926
1064
|
|
|
927
1065
|
copts->ignore = OJ_R_ALLOC_N(VALUE, cnt + 1);
|
|
928
1066
|
for (i = 0; i < cnt; i++) {
|
|
@@ -948,6 +1086,20 @@ static int parse_options_cb(VALUE k, VALUE v, VALUE opts) {
|
|
|
948
1086
|
} else if (Qfalse != v) {
|
|
949
1087
|
rb_raise(rb_eArgError, ":integer_range must be a range of Fixnum.");
|
|
950
1088
|
}
|
|
1089
|
+
} else if (max_integer_digits_sym == k) {
|
|
1090
|
+
if (Qnil == v || Qfalse == v) {
|
|
1091
|
+
copts->max_integer_digits = 0;
|
|
1092
|
+
} else if (T_FIXNUM == rb_type(v)) {
|
|
1093
|
+
long n = FIX2LONG(v);
|
|
1094
|
+
|
|
1095
|
+
if (n < 0) {
|
|
1096
|
+
rb_raise(rb_eArgError, ":max_integer_digits must be >= 0.");
|
|
1097
|
+
}
|
|
1098
|
+
|
|
1099
|
+
copts->max_integer_digits = (size_t)n;
|
|
1100
|
+
} else {
|
|
1101
|
+
rb_raise(rb_eArgError, ":max_integer_digits must be a non-negative Integer.");
|
|
1102
|
+
}
|
|
951
1103
|
} else if (symbol_keys_sym == k || oj_symbolize_names_sym == k) {
|
|
952
1104
|
if (Qnil == v) {
|
|
953
1105
|
return ST_CONTINUE;
|
|
@@ -967,11 +1119,23 @@ static int parse_options_cb(VALUE k, VALUE v, VALUE opts) {
|
|
|
967
1119
|
}
|
|
968
1120
|
} else if (float_format_sym == k) {
|
|
969
1121
|
rb_check_type(v, T_STRING);
|
|
970
|
-
if (6 <
|
|
1122
|
+
if (6 < RSTRING_LEN(v)) {
|
|
971
1123
|
rb_raise(rb_eArgError, ":float_format must be 6 bytes or less.");
|
|
972
1124
|
}
|
|
973
1125
|
strncpy(copts->float_fmt, RSTRING_PTR(v), (size_t)RSTRING_LEN(v));
|
|
974
1126
|
copts->float_fmt[RSTRING_LEN(v)] = '\0';
|
|
1127
|
+
} else if (only_sym == k) {
|
|
1128
|
+
if (NULL != copts->dump_opts.only) {
|
|
1129
|
+
OJ_R_FREE((void *)copts->dump_opts.only);
|
|
1130
|
+
copts->dump_opts.only = NULL;
|
|
1131
|
+
}
|
|
1132
|
+
copts->dump_opts.only = make_only_value(v);
|
|
1133
|
+
} else if (except_sym == k) {
|
|
1134
|
+
if (NULL != copts->dump_opts.except) {
|
|
1135
|
+
OJ_R_FREE((void *)copts->dump_opts.except);
|
|
1136
|
+
copts->dump_opts.except = NULL;
|
|
1137
|
+
}
|
|
1138
|
+
copts->dump_opts.except = make_only_value(v);
|
|
975
1139
|
}
|
|
976
1140
|
return ST_CONTINUE;
|
|
977
1141
|
}
|
|
@@ -1182,7 +1346,7 @@ static VALUE load_file(int argc, VALUE *argv, VALUE self) {
|
|
|
1182
1346
|
OJ_FREE(wide_path);
|
|
1183
1347
|
}
|
|
1184
1348
|
#else
|
|
1185
|
-
fd
|
|
1349
|
+
fd = open(path, O_RDONLY);
|
|
1186
1350
|
#endif
|
|
1187
1351
|
if (0 == fd) {
|
|
1188
1352
|
rb_raise(rb_eIOError, "%s", strerror(errno));
|
|
@@ -1271,8 +1435,7 @@ static VALUE dump_body(VALUE a) {
|
|
|
1271
1435
|
if (0 == arg->out->buf) {
|
|
1272
1436
|
rb_raise(rb_eNoMemError, "Not enough memory.");
|
|
1273
1437
|
}
|
|
1274
|
-
rstr =
|
|
1275
|
-
rstr = oj_encode(rstr);
|
|
1438
|
+
rstr = rb_utf8_str_new_cstr(arg->out->buf);
|
|
1276
1439
|
|
|
1277
1440
|
return rstr;
|
|
1278
1441
|
}
|
|
@@ -1329,18 +1492,16 @@ static VALUE dump(int argc, VALUE *argv, VALUE self) {
|
|
|
1329
1492
|
* will be called. The mode is set to :compat.
|
|
1330
1493
|
* - *obj* [_Object_] Object to serialize as an JSON document String
|
|
1331
1494
|
* - *options* [_Hash_]
|
|
1332
|
-
* - *:max_nesting* [_Fixnum_|_boolean_] It true nesting is limited to 100.
|
|
1333
|
-
* is set to the provided value. The option to detect
|
|
1334
|
-
* compatible with the json gem.,
|
|
1335
|
-
*
|
|
1336
|
-
*
|
|
1337
|
-
*
|
|
1338
|
-
* (allow).
|
|
1339
|
-
* - *:indent* [_String_|_nil_] String to use for indentation, overriding the indent option if not
|
|
1340
|
-
* nil.
|
|
1495
|
+
* - *:max_nesting* [_Fixnum_|_boolean_] It true nesting is limited to 100.
|
|
1496
|
+
* If a Fixnum nesting is set to the provided value. The option to detect
|
|
1497
|
+
* circular references is available but is not compatible with the json gem.,
|
|
1498
|
+
* default is false or unlimited.
|
|
1499
|
+
* - *:allow_nan* [_boolean_] If true non JSON compliant words such as Nan and
|
|
1500
|
+
* Infinity will be used as appropriate, default is true.
|
|
1501
|
+
* - *:quirks_mode* [_boolean_] Allow single JSON values instead of documents, default is true (allow).
|
|
1502
|
+
* - *:indent* [_String_|_nil_] String to use for indentation, overriding the indent option if not nil.
|
|
1341
1503
|
* - *:space* [_String_|_nil_] String to use for the space after the colon in JSON object fields.
|
|
1342
|
-
* - *:space_before* [_String_|_nil_] String to use before the colon separator in JSON object
|
|
1343
|
-
* fields.
|
|
1504
|
+
* - *:space_before* [_String_|_nil_] String to use before the colon separator in JSON object fields.
|
|
1344
1505
|
* - *:object_nl* [_String_|_nil_] String to use after a JSON object field value.
|
|
1345
1506
|
* - *:array_nl* [_String_|_nil_] String to use after a JSON array value.
|
|
1346
1507
|
* - *:trace* [_Boolean_] If true trace is turned on.
|
|
@@ -1374,8 +1535,7 @@ static VALUE to_json(int argc, VALUE *argv, VALUE self) {
|
|
|
1374
1535
|
if (0 == out.buf) {
|
|
1375
1536
|
rb_raise(rb_eNoMemError, "Not enough memory.");
|
|
1376
1537
|
}
|
|
1377
|
-
rstr =
|
|
1378
|
-
rstr = oj_encode(rstr);
|
|
1538
|
+
rstr = rb_utf8_str_new_cstr(out.buf);
|
|
1379
1539
|
|
|
1380
1540
|
oj_out_free(&out);
|
|
1381
1541
|
|
|
@@ -1435,10 +1595,10 @@ static VALUE to_stream(int argc, VALUE *argv, VALUE self) {
|
|
|
1435
1595
|
*
|
|
1436
1596
|
* - *clas* [_Class__|_Module_] Class or Module to be made special
|
|
1437
1597
|
* - *create_object* [_Object_] object to call the create method on
|
|
1438
|
-
* - *create_method* [_Symbol_] method on the clas that will create a new instance
|
|
1439
|
-
* given all the member values in the order specified.
|
|
1440
|
-
* - *members* [_Symbol__|_String_] methods used to get the member values from
|
|
1441
|
-
* clas.
|
|
1598
|
+
* - *create_method* [_Symbol_] method on the clas that will create a new instance
|
|
1599
|
+
* of the clas when given all the member values in the order specified.
|
|
1600
|
+
* - *members* [_Symbol__|_String_] methods used to get the member values from
|
|
1601
|
+
* instances of the clas.
|
|
1442
1602
|
*/
|
|
1443
1603
|
static VALUE register_odd(int argc, VALUE *argv, VALUE self) {
|
|
1444
1604
|
if (3 > argc) {
|
|
@@ -1471,10 +1631,10 @@ static VALUE register_odd(int argc, VALUE *argv, VALUE self) {
|
|
|
1471
1631
|
*
|
|
1472
1632
|
* - *clas* [_Class_|_Module_] Class or Module to be made special
|
|
1473
1633
|
* - *create_object* [_Object_] object to call the create method on
|
|
1474
|
-
* - *create_method* [_Symbol_] method on the clas that will create a new instance
|
|
1475
|
-
*given all the member values in the order specified.
|
|
1476
|
-
* - *dump_method* [_Symbol_|_String_] method to call on the object being
|
|
1477
|
-
*raw JSON.
|
|
1634
|
+
* - *create_method* [_Symbol_] method on the clas that will create a new instance
|
|
1635
|
+
* of the clas when given all the member values in the order specified.
|
|
1636
|
+
* - *dump_method* [_Symbol_|_String_] method to call on the object being
|
|
1637
|
+
* serialized to generate the raw JSON.
|
|
1478
1638
|
*/
|
|
1479
1639
|
static VALUE register_odd_raw(int argc, VALUE *argv, VALUE self) {
|
|
1480
1640
|
if (3 > argc) {
|
|
@@ -1700,8 +1860,8 @@ extern VALUE oj_define_mimic_json(int argc, VALUE *argv, VALUE self);
|
|
|
1700
1860
|
* - *:space_before* [_String_] String placed before a : delimiter
|
|
1701
1861
|
* - *:object_nl* [_String_] String placed after a JSON object
|
|
1702
1862
|
* - *:array_nl* [_String_] String placed after a JSON array
|
|
1703
|
-
* - *:ascii_only* [_Boolean_] if not nil or false then use only ascii characters
|
|
1704
|
-
* Note JSON.generate does support this even if it is not documented.
|
|
1863
|
+
* - *:ascii_only* [_Boolean_] if not nil or false then use only ascii characters
|
|
1864
|
+
* in the output. Note JSON.generate does support this even if it is not documented.
|
|
1705
1865
|
*
|
|
1706
1866
|
* Returns [_String_]generated JSON.
|
|
1707
1867
|
*/
|
|
@@ -1758,8 +1918,8 @@ static VALUE mem_report(VALUE self) {
|
|
|
1758
1918
|
* global and options to methods allow additional behavior modifications. The
|
|
1759
1919
|
* modes are:
|
|
1760
1920
|
*
|
|
1761
|
-
* - *:strict* mode will only allow the 7 basic JSON types to be serialized.
|
|
1762
|
-
* will raise an Exception.
|
|
1921
|
+
* - *:strict* mode will only allow the 7 basic JSON types to be serialized.
|
|
1922
|
+
* Any other Object will raise an Exception.
|
|
1763
1923
|
*
|
|
1764
1924
|
* - *:null* mode is similar to the :strict mode except any Object that is not
|
|
1765
1925
|
* one of the JSON base types is replaced by a JSON null.
|
|
@@ -1777,6 +1937,78 @@ static VALUE mem_report(VALUE self) {
|
|
|
1777
1937
|
*
|
|
1778
1938
|
* - *:wab* specifically for WAB data exchange.
|
|
1779
1939
|
*/
|
|
1940
|
+
|
|
1941
|
+
// =============================================================================
|
|
1942
|
+
// Runtime SIMD CPU detection
|
|
1943
|
+
// Cross-platform support for Windows (MSVC), Linux, and macOS (GCC/Clang)
|
|
1944
|
+
// =============================================================================
|
|
1945
|
+
SIMD_Implementation oj_get_simd_implementation(void) {
|
|
1946
|
+
#ifdef HAVE_SIMD_X86
|
|
1947
|
+
// x86/x86_64 runtime detection
|
|
1948
|
+
|
|
1949
|
+
#if defined(_MSC_VER)
|
|
1950
|
+
// MSVC: Use __cpuid intrinsic
|
|
1951
|
+
int cpu_info[4];
|
|
1952
|
+
__cpuid(cpu_info, 1);
|
|
1953
|
+
|
|
1954
|
+
// Check for SSE4.2 (bit 20 of ECX)
|
|
1955
|
+
if (cpu_info[2] & (1 << 20)) {
|
|
1956
|
+
return SIMD_SSE42;
|
|
1957
|
+
}
|
|
1958
|
+
// Check for SSE2 (bit 26 of EDX)
|
|
1959
|
+
if (cpu_info[3] & (1 << 26)) {
|
|
1960
|
+
return SIMD_SSE2;
|
|
1961
|
+
}
|
|
1962
|
+
|
|
1963
|
+
#elif defined(__GNUC__) || defined(__clang__)
|
|
1964
|
+
// GCC/Clang: Use __builtin_cpu_supports if available
|
|
1965
|
+
#if defined(__has_builtin)
|
|
1966
|
+
#if __has_builtin(__builtin_cpu_supports)
|
|
1967
|
+
#define OJ_HAS_BUILTIN_CPU_SUPPORTS 1
|
|
1968
|
+
#endif
|
|
1969
|
+
#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))
|
|
1970
|
+
// GCC 4.8+ has __builtin_cpu_supports
|
|
1971
|
+
#define OJ_HAS_BUILTIN_CPU_SUPPORTS 1
|
|
1972
|
+
#endif
|
|
1973
|
+
|
|
1974
|
+
#ifdef OJ_HAS_BUILTIN_CPU_SUPPORTS
|
|
1975
|
+
#ifdef HAVE_SIMD_SSE4_2
|
|
1976
|
+
if (__builtin_cpu_supports("sse4.2")) {
|
|
1977
|
+
return SIMD_SSE42;
|
|
1978
|
+
}
|
|
1979
|
+
#endif
|
|
1980
|
+
#ifdef HAVE_SIMD_SSE2
|
|
1981
|
+
if (__builtin_cpu_supports("sse2")) {
|
|
1982
|
+
return SIMD_SSE2;
|
|
1983
|
+
}
|
|
1984
|
+
#endif
|
|
1985
|
+
#else
|
|
1986
|
+
// Fallback: Use CPUID instruction directly
|
|
1987
|
+
unsigned int eax, ebx, ecx, edx;
|
|
1988
|
+
if (__get_cpuid(1, &eax, &ebx, &ecx, &edx)) {
|
|
1989
|
+
// Check for SSE4.2 (bit 20 of ECX)
|
|
1990
|
+
if (ecx & (1 << 20)) {
|
|
1991
|
+
return SIMD_SSE42;
|
|
1992
|
+
}
|
|
1993
|
+
// Check for SSE2 (bit 26 of EDX)
|
|
1994
|
+
if (edx & (1 << 26)) {
|
|
1995
|
+
return SIMD_SSE2;
|
|
1996
|
+
}
|
|
1997
|
+
}
|
|
1998
|
+
#endif // OJ_HAS_BUILTIN_CPU_SUPPORTS
|
|
1999
|
+
|
|
2000
|
+
#endif // _MSC_VER vs GCC/Clang
|
|
2001
|
+
|
|
2002
|
+
#endif // HAVE_SIMD_X86
|
|
2003
|
+
|
|
2004
|
+
#ifdef HAVE_SIMD_NEON
|
|
2005
|
+
// ARM NEON is always available on ARM64 and detected at compile time
|
|
2006
|
+
return SIMD_NEON;
|
|
2007
|
+
#endif
|
|
2008
|
+
|
|
2009
|
+
return SIMD_NONE;
|
|
2010
|
+
}
|
|
2011
|
+
|
|
1780
2012
|
void Init_oj(void) {
|
|
1781
2013
|
int err = 0;
|
|
1782
2014
|
|
|
@@ -1843,10 +2075,10 @@ void Init_oj(void) {
|
|
|
1843
2075
|
oj_array_end_id = rb_intern("array_end");
|
|
1844
2076
|
oj_array_start_id = rb_intern("array_start");
|
|
1845
2077
|
oj_as_json_id = rb_intern("as_json");
|
|
1846
|
-
oj_at_id = rb_intern("at");
|
|
1847
2078
|
oj_begin_id = rb_intern("begin");
|
|
1848
2079
|
oj_bigdecimal_id = rb_intern("BigDecimal");
|
|
1849
2080
|
oj_end_id = rb_intern("end");
|
|
2081
|
+
oj_eofq_id = rb_intern("eof?");
|
|
1850
2082
|
oj_error_id = rb_intern("error");
|
|
1851
2083
|
oj_exclude_end_id = rb_intern("exclude_end?");
|
|
1852
2084
|
oj_file_id = rb_intern("file?");
|
|
@@ -1861,6 +2093,7 @@ void Init_oj(void) {
|
|
|
1861
2093
|
oj_length_id = rb_intern("length");
|
|
1862
2094
|
oj_new_id = rb_intern("new");
|
|
1863
2095
|
oj_parse_id = rb_intern("parse");
|
|
2096
|
+
oj_plus_id = rb_intern("+");
|
|
1864
2097
|
oj_pos_id = rb_intern("pos");
|
|
1865
2098
|
oj_raw_json_id = rb_intern("raw_json");
|
|
1866
2099
|
oj_read_id = rb_intern("read");
|
|
@@ -1949,6 +2182,8 @@ void Init_oj(void) {
|
|
|
1949
2182
|
rb_gc_register_address(&escape_mode_sym);
|
|
1950
2183
|
integer_range_sym = ID2SYM(rb_intern("integer_range"));
|
|
1951
2184
|
rb_gc_register_address(&integer_range_sym);
|
|
2185
|
+
max_integer_digits_sym = ID2SYM(rb_intern("max_integer_digits"));
|
|
2186
|
+
rb_gc_register_address(&max_integer_digits_sym);
|
|
1952
2187
|
fast_sym = ID2SYM(rb_intern("fast"));
|
|
1953
2188
|
rb_gc_register_address(&fast_sym);
|
|
1954
2189
|
float_format_sym = ID2SYM(rb_intern("float_format"));
|
|
@@ -1993,14 +2228,10 @@ void Init_oj(void) {
|
|
|
1993
2228
|
rb_gc_register_address(&oj_decimal_class_sym);
|
|
1994
2229
|
oj_hash_class_sym = ID2SYM(rb_intern("hash_class"));
|
|
1995
2230
|
rb_gc_register_address(&oj_hash_class_sym);
|
|
1996
|
-
oj_in_sym = ID2SYM(rb_intern("in"));
|
|
1997
|
-
rb_gc_register_address(&oj_in_sym);
|
|
1998
2231
|
oj_indent_sym = ID2SYM(rb_intern("indent"));
|
|
1999
2232
|
rb_gc_register_address(&oj_indent_sym);
|
|
2000
2233
|
oj_max_nesting_sym = ID2SYM(rb_intern("max_nesting"));
|
|
2001
2234
|
rb_gc_register_address(&oj_max_nesting_sym);
|
|
2002
|
-
oj_nanosecond_sym = ID2SYM(rb_intern("nanosecond"));
|
|
2003
|
-
rb_gc_register_address(&oj_nanosecond_sym);
|
|
2004
2235
|
oj_object_class_sym = ID2SYM(rb_intern("object_class"));
|
|
2005
2236
|
rb_gc_register_address(&oj_object_class_sym);
|
|
2006
2237
|
oj_object_nl_sym = ID2SYM(rb_intern("object_nl"));
|
|
@@ -2059,6 +2290,10 @@ void Init_oj(void) {
|
|
|
2059
2290
|
rb_gc_register_address(&xmlschema_sym);
|
|
2060
2291
|
xss_safe_sym = ID2SYM(rb_intern("xss_safe"));
|
|
2061
2292
|
rb_gc_register_address(&xss_safe_sym);
|
|
2293
|
+
only_sym = ID2SYM(rb_intern("only"));
|
|
2294
|
+
rb_gc_register_address(&only_sym);
|
|
2295
|
+
except_sym = ID2SYM(rb_intern("except"));
|
|
2296
|
+
rb_gc_register_address(&except_sym);
|
|
2062
2297
|
|
|
2063
2298
|
oj_slash_string = rb_str_new2("/");
|
|
2064
2299
|
rb_gc_register_address(&oj_slash_string);
|
|
@@ -2080,6 +2315,18 @@ void Init_oj(void) {
|
|
|
2080
2315
|
#endif
|
|
2081
2316
|
oj_init_doc();
|
|
2082
2317
|
|
|
2318
|
+
SIMD_Impl = oj_get_simd_implementation();
|
|
2319
|
+
|
|
2083
2320
|
oj_parser_init();
|
|
2084
2321
|
oj_scanner_init();
|
|
2322
|
+
|
|
2323
|
+
#ifdef HAVE_SIMD_NEON
|
|
2324
|
+
initialize_neon();
|
|
2325
|
+
#endif /* HAVE_SIMD_NEON */
|
|
2326
|
+
|
|
2327
|
+
#ifdef HAVE_SIMD_SSE4_2
|
|
2328
|
+
if (SIMD_Impl == SIMD_SSE42) {
|
|
2329
|
+
initialize_sse42();
|
|
2330
|
+
}
|
|
2331
|
+
#endif /* HAVE_SIMD_SSE4_2 */
|
|
2085
2332
|
}
|