oj 3.16.6 → 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 +81 -0
- data/README.md +0 -16
- data/ext/oj/compat.c +3 -3
- data/ext/oj/custom.c +17 -11
- data/ext/oj/dump.c +592 -81
- 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 +10 -7
- data/ext/oj/fast.c +40 -23
- data/ext/oj/intern.c +1 -1
- data/ext/oj/mimic_json.c +11 -7
- data/ext/oj/object.c +8 -8
- data/ext/oj/oj.c +256 -10
- data/ext/oj/oj.h +55 -52
- data/ext/oj/parse.c +243 -46
- data/ext/oj/parser.c +113 -37
- data/ext/oj/parser.h +2 -0
- data/ext/oj/rails.c +41 -36
- 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 +13 -8
- 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 +3 -13
- data/ext/oj/strict.c +2 -4
- data/ext/oj/string_writer.c +5 -7
- data/ext/oj/usual.c +20 -7
- data/ext/oj/wab.c +5 -4
- data/lib/oj/version.rb +1 -1
- data/pages/Encoding.md +1 -1
- metadata +22 -114
- 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 -542
- 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 -52
- data/test/activesupport7/decoding_test.rb +0 -125
- data/test/activesupport7/encoding_test.rb +0 -536
- 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 -26
- 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 -413
- 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 -555
- 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 -1030
- 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 -251
- 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 -441
- 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/dump.h
CHANGED
|
@@ -7,12 +7,17 @@
|
|
|
7
7
|
#include <ruby.h>
|
|
8
8
|
|
|
9
9
|
#include "oj.h"
|
|
10
|
+
#include "simd.h"
|
|
10
11
|
|
|
11
12
|
#define MAX_DEPTH 1000
|
|
12
13
|
|
|
13
14
|
// Extra padding at end of buffer.
|
|
14
15
|
#define BUFFER_EXTRA 64
|
|
15
16
|
|
|
17
|
+
#ifdef HAVE_SIMD_NEON
|
|
18
|
+
extern void initialize_neon(void);
|
|
19
|
+
#endif /* HAVE_SIMD_NEON */
|
|
20
|
+
|
|
16
21
|
extern void oj_dump_nil(VALUE obj, int depth, Out out, bool as_ok);
|
|
17
22
|
extern void oj_dump_true(VALUE obj, int depth, Out out, bool as_ok);
|
|
18
23
|
extern void oj_dump_false(VALUE obj, int depth, Out out, bool as_ok);
|
|
@@ -30,7 +35,7 @@ extern void oj_dump_xml_time(VALUE obj, Out out);
|
|
|
30
35
|
extern void oj_dump_time(VALUE obj, Out out, int withZone);
|
|
31
36
|
extern void oj_dump_obj_to_s(VALUE obj, Out out);
|
|
32
37
|
|
|
33
|
-
extern const char *oj_nan_str(VALUE obj, int opt, int mode, bool plus,
|
|
38
|
+
extern const char *oj_nan_str(VALUE obj, int opt, int mode, bool plus, size_t *lenp);
|
|
34
39
|
|
|
35
40
|
// initialize an out buffer with the provided stack allocated memory
|
|
36
41
|
extern void oj_out_init(Out out);
|
|
@@ -53,10 +58,12 @@ extern void oj_dump_raw_json(VALUE obj, int depth, Out out);
|
|
|
53
58
|
extern VALUE oj_add_to_json(int argc, VALUE *argv, VALUE self);
|
|
54
59
|
extern VALUE oj_remove_to_json(int argc, VALUE *argv, VALUE self);
|
|
55
60
|
|
|
56
|
-
extern
|
|
61
|
+
extern size_t oj_dump_float_printf(char *buf, size_t blen, VALUE obj, double d, const char *format);
|
|
57
62
|
|
|
58
63
|
extern time_t oj_sec_from_time_hard_way(VALUE obj);
|
|
59
64
|
|
|
65
|
+
extern bool oj_key_skip(VALUE key, const char *only, const char *except);
|
|
66
|
+
|
|
60
67
|
inline static void assure_size(Out out, size_t len) {
|
|
61
68
|
if (out->end - out->cur <= (long)len) {
|
|
62
69
|
oj_grow_out(out, len);
|
data/ext/oj/dump_compat.c
CHANGED
|
@@ -103,7 +103,7 @@ static void dump_values_array(VALUE *values, int depth, Out out) {
|
|
|
103
103
|
static void dump_to_json(VALUE obj, Out out) {
|
|
104
104
|
volatile VALUE rs;
|
|
105
105
|
const char *s;
|
|
106
|
-
|
|
106
|
+
size_t len;
|
|
107
107
|
|
|
108
108
|
TRACE(out->opts->trace, "to_json", obj, 0, TraceRubyIn);
|
|
109
109
|
if (0 == rb_obj_method_arity(obj, oj_to_json_id)) {
|
|
@@ -115,7 +115,7 @@ static void dump_to_json(VALUE obj, Out out) {
|
|
|
115
115
|
|
|
116
116
|
StringValue(rs);
|
|
117
117
|
s = RSTRING_PTR(rs);
|
|
118
|
-
len =
|
|
118
|
+
len = RSTRING_LEN(rs);
|
|
119
119
|
|
|
120
120
|
assure_size(out, len + 1);
|
|
121
121
|
APPEND_CHARS(out->cur, s, len);
|
|
@@ -124,7 +124,8 @@ static void dump_to_json(VALUE obj, Out out) {
|
|
|
124
124
|
|
|
125
125
|
static void dump_array(VALUE a, int depth, Out out, bool as_ok) {
|
|
126
126
|
size_t size;
|
|
127
|
-
|
|
127
|
+
size_t i;
|
|
128
|
+
size_t cnt;
|
|
128
129
|
int d2 = depth + 1;
|
|
129
130
|
long id = oj_check_circular(a, out);
|
|
130
131
|
|
|
@@ -136,7 +137,7 @@ static void dump_array(VALUE a, int depth, Out out, bool as_ok) {
|
|
|
136
137
|
dump_to_json(a, out);
|
|
137
138
|
return;
|
|
138
139
|
}
|
|
139
|
-
cnt =
|
|
140
|
+
cnt = RARRAY_LEN(a);
|
|
140
141
|
*out->cur++ = '[';
|
|
141
142
|
assure_size(out, 2);
|
|
142
143
|
if (0 == cnt) {
|
|
@@ -147,10 +148,10 @@ static void dump_array(VALUE a, int depth, Out out, bool as_ok) {
|
|
|
147
148
|
} else {
|
|
148
149
|
size = d2 * out->indent + 2;
|
|
149
150
|
}
|
|
150
|
-
assure_size(out, size * cnt);
|
|
151
151
|
cnt--;
|
|
152
152
|
for (i = 0; i <= cnt; i++) {
|
|
153
153
|
if (out->opts->dump_opts.use) {
|
|
154
|
+
assure_size(out, size);
|
|
154
155
|
if (0 < out->opts->dump_opts.array_size) {
|
|
155
156
|
APPEND_CHARS(out->cur, out->opts->dump_opts.array_nl, out->opts->dump_opts.array_size);
|
|
156
157
|
}
|
|
@@ -552,7 +553,7 @@ static void dump_float(VALUE obj, int depth, Out out, bool as_ok) {
|
|
|
552
553
|
char buf[64];
|
|
553
554
|
char *b;
|
|
554
555
|
double d = rb_num2dbl(obj);
|
|
555
|
-
|
|
556
|
+
size_t cnt = 0;
|
|
556
557
|
|
|
557
558
|
if (0.0 == d) {
|
|
558
559
|
b = buf;
|
|
@@ -590,7 +591,7 @@ static void dump_float(VALUE obj, int depth, Out out, bool as_ok) {
|
|
|
590
591
|
volatile VALUE rstr = oj_safe_string_convert(obj);
|
|
591
592
|
|
|
592
593
|
strcpy(buf, RSTRING_PTR(rstr));
|
|
593
|
-
cnt =
|
|
594
|
+
cnt = RSTRING_LEN(rstr);
|
|
594
595
|
}
|
|
595
596
|
assure_size(out, cnt);
|
|
596
597
|
APPEND_CHARS(out->cur, buf, cnt);
|
|
@@ -604,6 +605,11 @@ static int hash_cb(VALUE key, VALUE value, VALUE ov) {
|
|
|
604
605
|
if (out->omit_nil && Qnil == value) {
|
|
605
606
|
return ST_CONTINUE;
|
|
606
607
|
}
|
|
608
|
+
if (NULL != out->opts->dump_opts.only || NULL != out->opts->dump_opts.except) {
|
|
609
|
+
if (oj_key_skip(key, out->opts->dump_opts.only, out->opts->dump_opts.except)) {
|
|
610
|
+
return ST_CONTINUE;
|
|
611
|
+
}
|
|
612
|
+
}
|
|
607
613
|
if (!out->opts->dump_opts.use) {
|
|
608
614
|
assure_size(out, depth * out->indent + 1);
|
|
609
615
|
fill_indent(out, depth);
|
|
@@ -800,7 +806,7 @@ static void dump_bignum(VALUE obj, int depth, Out out, bool as_ok) {
|
|
|
800
806
|
// rb_big2str can not so unless overridden by using add_to_json(Integer)
|
|
801
807
|
// this must use to_s to pass the json gem unit tests.
|
|
802
808
|
volatile VALUE rs;
|
|
803
|
-
|
|
809
|
+
size_t cnt;
|
|
804
810
|
bool dump_as_string = false;
|
|
805
811
|
|
|
806
812
|
if (use_bignum_alt) {
|
|
@@ -809,7 +815,7 @@ static void dump_bignum(VALUE obj, int depth, Out out, bool as_ok) {
|
|
|
809
815
|
rs = oj_safe_string_convert(obj);
|
|
810
816
|
}
|
|
811
817
|
rb_check_type(rs, T_STRING);
|
|
812
|
-
cnt =
|
|
818
|
+
cnt = RSTRING_LEN(rs);
|
|
813
819
|
|
|
814
820
|
if (out->opts->int_range_min != 0 || out->opts->int_range_max != 0) {
|
|
815
821
|
dump_as_string = true; // Bignum cannot be inside of Fixnum range
|
data/ext/oj/dump_leaf.c
CHANGED
|
@@ -17,7 +17,7 @@ inline static void dump_chars(const char *s, size_t size, Out out) {
|
|
|
17
17
|
static void dump_leaf_str(Leaf leaf, Out out) {
|
|
18
18
|
switch (leaf->value_type) {
|
|
19
19
|
case STR_VAL: oj_dump_cstr(leaf->str, strlen(leaf->str), 0, 0, out); break;
|
|
20
|
-
case RUBY_VAL: oj_dump_cstr(StringValueCStr(leaf->value),
|
|
20
|
+
case RUBY_VAL: oj_dump_cstr(StringValueCStr(leaf->value), RSTRING_LEN(leaf->value), 0, 0, out); break;
|
|
21
21
|
case COL_VAL:
|
|
22
22
|
default: rb_raise(rb_eTypeError, "Unexpected value type %02x.\n", leaf->value_type); break;
|
|
23
23
|
}
|
data/ext/oj/dump_object.c
CHANGED
|
@@ -33,7 +33,7 @@ static void dump_data(VALUE obj, int depth, Out out, bool as_ok) {
|
|
|
33
33
|
if (oj_bigdecimal_class == clas) {
|
|
34
34
|
volatile VALUE rstr = oj_safe_string_convert(obj);
|
|
35
35
|
const char *str = RSTRING_PTR(rstr);
|
|
36
|
-
|
|
36
|
+
size_t len = RSTRING_LEN(rstr);
|
|
37
37
|
|
|
38
38
|
if (No != out->opts->bigdec_as_num) {
|
|
39
39
|
oj_dump_raw(str, len, out);
|
|
@@ -62,7 +62,7 @@ static void dump_obj(VALUE obj, int depth, Out out, bool as_ok) {
|
|
|
62
62
|
if (oj_bigdecimal_class == clas) {
|
|
63
63
|
volatile VALUE rstr = oj_safe_string_convert(obj);
|
|
64
64
|
const char *str = RSTRING_PTR(rstr);
|
|
65
|
-
|
|
65
|
+
size_t len = RSTRING_LEN(rstr);
|
|
66
66
|
|
|
67
67
|
if (0 == strcasecmp("Infinity", str)) {
|
|
68
68
|
str = oj_nan_str(obj, out->opts->dump_opts.nan_dump, out->opts->mode, true, &len);
|
|
@@ -95,7 +95,8 @@ static void dump_class(VALUE obj, int depth, Out out, bool as_ok) {
|
|
|
95
95
|
|
|
96
96
|
static void dump_array_class(VALUE a, VALUE clas, int depth, Out out) {
|
|
97
97
|
size_t size;
|
|
98
|
-
|
|
98
|
+
size_t i;
|
|
99
|
+
size_t cnt;
|
|
99
100
|
int d2 = depth + 1;
|
|
100
101
|
long id = oj_check_circular(a, out);
|
|
101
102
|
|
|
@@ -106,7 +107,7 @@ static void dump_array_class(VALUE a, VALUE clas, int depth, Out out) {
|
|
|
106
107
|
dump_obj_attrs(a, clas, 0, depth, out);
|
|
107
108
|
return;
|
|
108
109
|
}
|
|
109
|
-
cnt =
|
|
110
|
+
cnt = RARRAY_LEN(a);
|
|
110
111
|
*out->cur++ = '[';
|
|
111
112
|
if (0 < id) {
|
|
112
113
|
assure_size(out, d2 * out->indent + 16);
|
|
@@ -181,7 +182,7 @@ static void dump_str_class(VALUE obj, VALUE clas, int depth, Out out) {
|
|
|
181
182
|
dump_obj_attrs(obj, clas, 0, depth, out);
|
|
182
183
|
} else {
|
|
183
184
|
const char *s = RSTRING_PTR(obj);
|
|
184
|
-
size_t len =
|
|
185
|
+
size_t len = RSTRING_LEN(obj);
|
|
185
186
|
char s1 = s[1];
|
|
186
187
|
|
|
187
188
|
oj_dump_cstr(s, len, 0, (':' == *s || ('^' == *s && ('r' == s1 || 'i' == s1))), out);
|
|
@@ -195,7 +196,7 @@ static void dump_str(VALUE obj, int depth, Out out, bool as_ok) {
|
|
|
195
196
|
static void dump_sym(VALUE obj, int depth, Out out, bool as_ok) {
|
|
196
197
|
volatile VALUE s = rb_sym2str(obj);
|
|
197
198
|
|
|
198
|
-
oj_dump_cstr(RSTRING_PTR(s),
|
|
199
|
+
oj_dump_cstr(RSTRING_PTR(s), RSTRING_LEN(s), 1, 0, out);
|
|
199
200
|
}
|
|
200
201
|
|
|
201
202
|
static int hash_cb(VALUE key, VALUE value, VALUE ov) {
|
|
@@ -209,6 +210,11 @@ static int hash_cb(VALUE key, VALUE value, VALUE ov) {
|
|
|
209
210
|
if (out->omit_nil && Qnil == value) {
|
|
210
211
|
return ST_CONTINUE;
|
|
211
212
|
}
|
|
213
|
+
if (NULL != out->opts->dump_opts.only || NULL != out->opts->dump_opts.except) {
|
|
214
|
+
if (oj_key_skip(key, out->opts->dump_opts.only, out->opts->dump_opts.except)) {
|
|
215
|
+
return ST_CONTINUE;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
212
218
|
assure_size(out, size);
|
|
213
219
|
fill_indent(out, depth);
|
|
214
220
|
switch (rb_type(key)) {
|
|
@@ -389,7 +395,7 @@ static void dump_odd(VALUE obj, Odd odd, VALUE clas, int depth, Out out) {
|
|
|
389
395
|
rb_raise(rb_eEncodingError, "Invalid type for raw JSON.");
|
|
390
396
|
} else {
|
|
391
397
|
const char *s = RSTRING_PTR(v);
|
|
392
|
-
|
|
398
|
+
size_t len = RSTRING_LEN(v);
|
|
393
399
|
const char *name = rb_id2name(*odd->attrs);
|
|
394
400
|
size_t nlen = strlen(name);
|
|
395
401
|
|
|
@@ -489,7 +495,7 @@ static void dump_obj_attrs(VALUE obj, VALUE clas, slot_t id, int depth, Out out)
|
|
|
489
495
|
*out->cur++ = ',';
|
|
490
496
|
fill_indent(out, d2);
|
|
491
497
|
APPEND_CHARS(out->cur, "\"self\":", 7);
|
|
492
|
-
oj_dump_cstr(RSTRING_PTR(obj),
|
|
498
|
+
oj_dump_cstr(RSTRING_PTR(obj), RSTRING_LEN(obj), 0, 0, out);
|
|
493
499
|
break;
|
|
494
500
|
case T_ARRAY:
|
|
495
501
|
assure_size(out, d2 * out->indent + 14);
|
|
@@ -564,11 +570,12 @@ static void dump_regexp(VALUE obj, int depth, Out out, bool as_ok) {
|
|
|
564
570
|
static void dump_struct(VALUE obj, int depth, Out out, bool as_ok) {
|
|
565
571
|
VALUE clas = rb_obj_class(obj);
|
|
566
572
|
const char *class_name = rb_class2name(clas);
|
|
567
|
-
|
|
568
|
-
int d2
|
|
569
|
-
int d3
|
|
570
|
-
size_t len
|
|
571
|
-
size_t size
|
|
573
|
+
size_t i;
|
|
574
|
+
int d2 = depth + 1;
|
|
575
|
+
int d3 = d2 + 1;
|
|
576
|
+
size_t len = strlen(class_name);
|
|
577
|
+
size_t size = d2 * out->indent + d3 * out->indent + 10 + len;
|
|
578
|
+
char circular = out->opts->circular;
|
|
572
579
|
|
|
573
580
|
assure_size(out, size);
|
|
574
581
|
*out->cur++ = '{';
|
|
@@ -577,14 +584,14 @@ static void dump_struct(VALUE obj, int depth, Out out, bool as_ok) {
|
|
|
577
584
|
if ('#' == *class_name) {
|
|
578
585
|
VALUE ma = rb_struct_s_members(clas);
|
|
579
586
|
const char *name;
|
|
580
|
-
|
|
587
|
+
size_t cnt = RARRAY_LEN(ma);
|
|
581
588
|
|
|
582
589
|
*out->cur++ = '[';
|
|
583
590
|
for (i = 0; i < cnt; i++) {
|
|
584
591
|
volatile VALUE s = rb_sym2str(RARRAY_AREF(ma, i));
|
|
585
592
|
|
|
586
593
|
name = RSTRING_PTR(s);
|
|
587
|
-
len =
|
|
594
|
+
len = RSTRING_LEN(s);
|
|
588
595
|
size = len + 3;
|
|
589
596
|
assure_size(out, size);
|
|
590
597
|
if (0 < i) {
|
|
@@ -607,14 +614,18 @@ static void dump_struct(VALUE obj, int depth, Out out, bool as_ok) {
|
|
|
607
614
|
{
|
|
608
615
|
VALUE v;
|
|
609
616
|
int cnt;
|
|
617
|
+
|
|
610
618
|
#if RSTRUCT_LEN_RETURNS_INTEGER_OBJECT
|
|
611
619
|
cnt = (int)NUM2LONG(RSTRUCT_LEN(obj));
|
|
612
620
|
#else // RSTRUCT_LEN_RETURNS_INTEGER_OBJECT
|
|
613
621
|
cnt = (int)RSTRUCT_LEN(obj);
|
|
614
622
|
#endif // RSTRUCT_LEN_RETURNS_INTEGER_OBJECT
|
|
615
623
|
|
|
616
|
-
|
|
617
|
-
|
|
624
|
+
if (0 == strcmp(class_name, "Range")) {
|
|
625
|
+
out->opts->circular = 'n';
|
|
626
|
+
}
|
|
627
|
+
for (i = 0; i < (size_t)cnt; i++) {
|
|
628
|
+
v = RSTRUCT_GET(obj, (int)i);
|
|
618
629
|
if (dump_ignore(out->opts, v)) {
|
|
619
630
|
v = Qnil;
|
|
620
631
|
}
|
|
@@ -630,6 +641,9 @@ static void dump_struct(VALUE obj, int depth, Out out, bool as_ok) {
|
|
|
630
641
|
// class in interpreted Ruby so length() may not be defined.
|
|
631
642
|
int slen = FIX2INT(rb_funcall2(obj, oj_length_id, 0, 0));
|
|
632
643
|
|
|
644
|
+
if (0 == strcmp(class_name, "Range")) {
|
|
645
|
+
out->opts->circular = 'n';
|
|
646
|
+
}
|
|
633
647
|
for (i = 0; i < slen; i++) {
|
|
634
648
|
assure_size(out, size);
|
|
635
649
|
fill_indent(out, d3);
|
|
@@ -641,6 +655,7 @@ static void dump_struct(VALUE obj, int depth, Out out, bool as_ok) {
|
|
|
641
655
|
}
|
|
642
656
|
}
|
|
643
657
|
#endif
|
|
658
|
+
out->opts->circular = circular;
|
|
644
659
|
out->cur--;
|
|
645
660
|
APPEND_CHARS(out->cur, "]}", 2);
|
|
646
661
|
*out->cur = '\0';
|
data/ext/oj/dump_strict.c
CHANGED
|
@@ -30,7 +30,7 @@ static void dump_float(VALUE obj, int depth, Out out, bool as_ok) {
|
|
|
30
30
|
char buf[64];
|
|
31
31
|
char* b;
|
|
32
32
|
double d = rb_num2dbl(obj);
|
|
33
|
-
|
|
33
|
+
size_t cnt = 0;
|
|
34
34
|
|
|
35
35
|
if (0.0 == d) {
|
|
36
36
|
b = buf;
|
|
@@ -92,7 +92,7 @@ static void dump_float(VALUE obj, int depth, Out out, bool as_ok) {
|
|
|
92
92
|
} else if (0 == out->opts->float_prec) {
|
|
93
93
|
volatile VALUE rstr = oj_safe_string_convert(obj);
|
|
94
94
|
|
|
95
|
-
cnt =
|
|
95
|
+
cnt = RSTRING_LEN(rstr);
|
|
96
96
|
if ((int)sizeof(buf) <= cnt) {
|
|
97
97
|
cnt = sizeof(buf) - 1;
|
|
98
98
|
}
|
|
@@ -109,7 +109,8 @@ static void dump_float(VALUE obj, int depth, Out out, bool as_ok) {
|
|
|
109
109
|
|
|
110
110
|
static void dump_array(VALUE a, int depth, Out out, bool as_ok) {
|
|
111
111
|
size_t size;
|
|
112
|
-
|
|
112
|
+
size_t i;
|
|
113
|
+
size_t cnt;
|
|
113
114
|
int d2 = depth + 1;
|
|
114
115
|
|
|
115
116
|
if (Yes == out->opts->circular) {
|
|
@@ -118,7 +119,7 @@ static void dump_array(VALUE a, int depth, Out out, bool as_ok) {
|
|
|
118
119
|
return;
|
|
119
120
|
}
|
|
120
121
|
}
|
|
121
|
-
cnt =
|
|
122
|
+
cnt = RARRAY_LEN(a);
|
|
122
123
|
*out->cur++ = '[';
|
|
123
124
|
size = 2;
|
|
124
125
|
assure_size(out, size);
|
|
@@ -192,14 +193,19 @@ static int hash_cb(VALUE key, VALUE value, VALUE ov) {
|
|
|
192
193
|
if (out->omit_nil && Qnil == value) {
|
|
193
194
|
return ST_CONTINUE;
|
|
194
195
|
}
|
|
196
|
+
if (NULL != out->opts->dump_opts.only || NULL != out->opts->dump_opts.except) {
|
|
197
|
+
if (oj_key_skip(key, out->opts->dump_opts.only, out->opts->dump_opts.except)) {
|
|
198
|
+
return ST_CONTINUE;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
195
201
|
if (!out->opts->dump_opts.use) {
|
|
196
202
|
size = depth * out->indent + 1;
|
|
197
203
|
assure_size(out, size);
|
|
198
204
|
fill_indent(out, depth);
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
205
|
+
switch (rtype) {
|
|
206
|
+
case T_STRING: oj_dump_str(key, 0, out, false); break;
|
|
207
|
+
case T_SYMBOL: oj_dump_sym(key, 0, out, false); break;
|
|
208
|
+
default: oj_dump_str(oj_safe_string_convert(key), 0, out, false); break;
|
|
203
209
|
}
|
|
204
210
|
*out->cur++ = ':';
|
|
205
211
|
} else {
|
|
@@ -214,10 +220,10 @@ static int hash_cb(VALUE key, VALUE value, VALUE ov) {
|
|
|
214
220
|
APPEND_CHARS(out->cur, out->opts->dump_opts.indent_str, out->opts->dump_opts.indent_size);
|
|
215
221
|
}
|
|
216
222
|
}
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
223
|
+
switch (rtype) {
|
|
224
|
+
case T_STRING: oj_dump_str(key, 0, out, false); break;
|
|
225
|
+
case T_SYMBOL: oj_dump_sym(key, 0, out, false); break;
|
|
226
|
+
default: oj_dump_str(oj_safe_string_convert(key), 0, out, false); break;
|
|
221
227
|
}
|
|
222
228
|
size = out->opts->dump_opts.before_size + out->opts->dump_opts.after_size + 2;
|
|
223
229
|
assure_size(out, size);
|
|
@@ -290,7 +296,7 @@ static void dump_data_strict(VALUE obj, int depth, Out out, bool as_ok) {
|
|
|
290
296
|
if (oj_bigdecimal_class == clas) {
|
|
291
297
|
volatile VALUE rstr = oj_safe_string_convert(obj);
|
|
292
298
|
|
|
293
|
-
oj_dump_raw(RSTRING_PTR(rstr),
|
|
299
|
+
oj_dump_raw(RSTRING_PTR(rstr), RSTRING_LEN(rstr), out);
|
|
294
300
|
} else {
|
|
295
301
|
raise_strict(obj);
|
|
296
302
|
}
|
|
@@ -302,7 +308,7 @@ static void dump_data_null(VALUE obj, int depth, Out out, bool as_ok) {
|
|
|
302
308
|
if (oj_bigdecimal_class == clas) {
|
|
303
309
|
volatile VALUE rstr = oj_safe_string_convert(obj);
|
|
304
310
|
|
|
305
|
-
oj_dump_raw(RSTRING_PTR(rstr),
|
|
311
|
+
oj_dump_raw(RSTRING_PTR(rstr), RSTRING_LEN(rstr), out);
|
|
306
312
|
} else {
|
|
307
313
|
oj_dump_nil(Qnil, depth, out, false);
|
|
308
314
|
}
|
data/ext/oj/extconf.rb
CHANGED
|
@@ -35,13 +35,16 @@ have_func('rb_ext_ractor_safe', 'ruby.h')
|
|
|
35
35
|
|
|
36
36
|
dflags['OJ_DEBUG'] = true unless ENV['OJ_DEBUG'].nil?
|
|
37
37
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
38
|
+
# SIMD optimizations use runtime CPU detection and function-level target attributes
|
|
39
|
+
# We do NOT add global -msse4.2/-msse2 flags here because:
|
|
40
|
+
# 1. It would cause illegal instruction errors on CPUs without SSE4.2
|
|
41
|
+
# 2. The code uses __attribute__((target("sse4.2"))) for SSE4.2 functions
|
|
42
|
+
# 3. Runtime detection in oj_get_simd_implementation() selects the right path
|
|
43
|
+
#
|
|
44
|
+
# We only add -msse2 if available, since SSE2 is baseline for all x86_64 CPUs
|
|
45
|
+
# and needed for compiling the SSE2 fallback code on 32-bit x86
|
|
46
|
+
if try_cflags('-msse2')
|
|
47
|
+
$CPPFLAGS += ' -msse2'
|
|
45
48
|
end
|
|
46
49
|
|
|
47
50
|
if enable_config('trace-log', false)
|
data/ext/oj/fast.c
CHANGED
|
@@ -80,21 +80,10 @@ static void each_leaf(Doc doc, VALUE self);
|
|
|
80
80
|
static int move_step(Doc doc, const char *path, int loc);
|
|
81
81
|
static Leaf get_doc_leaf(Doc doc, const char *path);
|
|
82
82
|
static Leaf get_leaf(Leaf *stack, Leaf *lp, const char *path);
|
|
83
|
-
static void each_value(Doc doc, Leaf leaf);
|
|
83
|
+
static void each_value(Doc doc, Leaf leaf, VALUE self);
|
|
84
84
|
|
|
85
85
|
VALUE oj_doc_class = Qundef;
|
|
86
86
|
|
|
87
|
-
// This is only for CentOS 5.4 with Ruby 1.9.3-p0.
|
|
88
|
-
#ifndef HAVE_STPCPY
|
|
89
|
-
char *stpcpy(char *dest, const char *src) {
|
|
90
|
-
size_t cnt = strlen(src);
|
|
91
|
-
|
|
92
|
-
strcpy(dest, src);
|
|
93
|
-
|
|
94
|
-
return dest + cnt;
|
|
95
|
-
}
|
|
96
|
-
#endif
|
|
97
|
-
|
|
98
87
|
inline static void next_non_white(ParseInfo pi) {
|
|
99
88
|
for (; 1; pi->s++) {
|
|
100
89
|
switch (*pi->s) {
|
|
@@ -193,8 +182,7 @@ static VALUE leaf_value(Doc doc, Leaf leaf) {
|
|
|
193
182
|
case T_FIXNUM: leaf_fixnum_value(leaf); break;
|
|
194
183
|
case T_FLOAT: leaf_float_value(leaf); break;
|
|
195
184
|
case T_STRING:
|
|
196
|
-
leaf->value =
|
|
197
|
-
leaf->value = oj_encode(leaf->value);
|
|
185
|
+
leaf->value = rb_utf8_str_new_cstr(leaf->str);
|
|
198
186
|
leaf->value_type = RUBY_VAL;
|
|
199
187
|
break;
|
|
200
188
|
case T_ARRAY: return leaf_array_value(doc, leaf); break;
|
|
@@ -247,6 +235,19 @@ static void skip_comment(ParseInfo pi) {
|
|
|
247
235
|
#define NUM_MAX (FIXNUM_MAX >> 8)
|
|
248
236
|
#endif
|
|
249
237
|
|
|
238
|
+
static void validate_integer_size(size_t limit, char *head, char *tail) {
|
|
239
|
+
size_t total = (size_t)(tail - head);
|
|
240
|
+
bool has_sign = (head[0] == '-' || head[0] == '+');
|
|
241
|
+
size_t digit_count = total - (has_sign ? 1 : 0);
|
|
242
|
+
|
|
243
|
+
if (digit_count > limit) {
|
|
244
|
+
rb_raise(oj_parse_error_class,
|
|
245
|
+
"integer exceeds :max_integer_digits (%lu > %lu)",
|
|
246
|
+
(unsigned long)digit_count,
|
|
247
|
+
(unsigned long)limit);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
250
251
|
static void leaf_fixnum_value(Leaf leaf) {
|
|
251
252
|
char *s = leaf->str;
|
|
252
253
|
int64_t n = 0;
|
|
@@ -266,7 +267,12 @@ static void leaf_fixnum_value(Leaf leaf) {
|
|
|
266
267
|
}
|
|
267
268
|
}
|
|
268
269
|
if (big) {
|
|
269
|
-
|
|
270
|
+
size_t limit = oj_default_options.max_integer_digits;
|
|
271
|
+
char c = *s;
|
|
272
|
+
|
|
273
|
+
if (0 < limit) {
|
|
274
|
+
validate_integer_size(limit, leaf->str, s);
|
|
275
|
+
}
|
|
270
276
|
|
|
271
277
|
*s = '\0';
|
|
272
278
|
leaf->value = rb_cstr_to_inum(leaf->str, 10, 0);
|
|
@@ -309,8 +315,7 @@ static VALUE leaf_hash_value(Doc doc, Leaf leaf) {
|
|
|
309
315
|
volatile VALUE key;
|
|
310
316
|
|
|
311
317
|
do {
|
|
312
|
-
key =
|
|
313
|
-
key = oj_encode(key);
|
|
318
|
+
key = rb_utf8_str_new_cstr(e->key);
|
|
314
319
|
rb_hash_aset(h, key, leaf_value(doc, e));
|
|
315
320
|
e = e->next;
|
|
316
321
|
} while (e != first);
|
|
@@ -952,6 +957,9 @@ static void each_leaf(Doc doc, VALUE self) {
|
|
|
952
957
|
}
|
|
953
958
|
} else {
|
|
954
959
|
rb_yield(self);
|
|
960
|
+
if (NULL == DATA_PTR(self)) {
|
|
961
|
+
rb_raise(rb_eIOError, "Document closed.");
|
|
962
|
+
}
|
|
955
963
|
}
|
|
956
964
|
}
|
|
957
965
|
|
|
@@ -1045,19 +1053,22 @@ static int move_step(Doc doc, const char *path, int loc) {
|
|
|
1045
1053
|
return loc;
|
|
1046
1054
|
}
|
|
1047
1055
|
|
|
1048
|
-
static void each_value(Doc doc, Leaf leaf) {
|
|
1056
|
+
static void each_value(Doc doc, Leaf leaf, VALUE self) {
|
|
1049
1057
|
if (COL_VAL == leaf->value_type) {
|
|
1050
1058
|
if (0 != leaf->elements) {
|
|
1051
1059
|
Leaf first = leaf->elements->next;
|
|
1052
1060
|
Leaf e = first;
|
|
1053
1061
|
|
|
1054
1062
|
do {
|
|
1055
|
-
each_value(doc, e);
|
|
1063
|
+
each_value(doc, e, self);
|
|
1056
1064
|
e = e->next;
|
|
1057
1065
|
} while (e != first);
|
|
1058
1066
|
}
|
|
1059
1067
|
} else {
|
|
1060
1068
|
rb_yield(leaf_value(doc, leaf));
|
|
1069
|
+
if (NULL == DATA_PTR(self)) {
|
|
1070
|
+
rb_raise(rb_eIOError, "Document closed.");
|
|
1071
|
+
}
|
|
1061
1072
|
}
|
|
1062
1073
|
}
|
|
1063
1074
|
|
|
@@ -1088,7 +1099,7 @@ static VALUE doc_open(VALUE clas, VALUE str) {
|
|
|
1088
1099
|
int given = rb_block_given_p();
|
|
1089
1100
|
|
|
1090
1101
|
Check_Type(str, T_STRING);
|
|
1091
|
-
len =
|
|
1102
|
+
len = RSTRING_LEN(str) + 1;
|
|
1092
1103
|
json = OJ_R_ALLOC_N(char, len);
|
|
1093
1104
|
|
|
1094
1105
|
memcpy(json, StringValuePtr(str), len);
|
|
@@ -1257,8 +1268,7 @@ static VALUE doc_local_key(VALUE self) {
|
|
|
1257
1268
|
volatile VALUE key = Qnil;
|
|
1258
1269
|
|
|
1259
1270
|
if (T_HASH == leaf->parent_type) {
|
|
1260
|
-
key =
|
|
1261
|
-
key = oj_encode(key);
|
|
1271
|
+
key = rb_utf8_str_new_cstr(leaf->key);
|
|
1262
1272
|
} else if (T_ARRAY == leaf->parent_type) {
|
|
1263
1273
|
key = LONG2NUM(leaf->index);
|
|
1264
1274
|
}
|
|
@@ -1494,12 +1504,19 @@ static VALUE doc_each_child(int argc, VALUE *argv, VALUE self) {
|
|
|
1494
1504
|
Leaf first = (*doc->where)->elements->next;
|
|
1495
1505
|
Leaf e = first;
|
|
1496
1506
|
|
|
1507
|
+
if (MAX_STACK <= (doc->where + 1) - doc->where_path) {
|
|
1508
|
+
rb_raise(rb_const_get_at(Oj, rb_intern("DepthError")), "Path too deep. Limit is %d levels.", MAX_STACK);
|
|
1509
|
+
}
|
|
1497
1510
|
doc->where++;
|
|
1498
1511
|
do {
|
|
1499
1512
|
*doc->where = e;
|
|
1500
1513
|
rb_yield(self);
|
|
1514
|
+
if (NULL == DATA_PTR(self)) {
|
|
1515
|
+
rb_raise(rb_eIOError, "Document closed.");
|
|
1516
|
+
}
|
|
1501
1517
|
e = e->next;
|
|
1502
1518
|
} while (e != first);
|
|
1519
|
+
doc->where--;
|
|
1503
1520
|
}
|
|
1504
1521
|
if (0 < wlen) {
|
|
1505
1522
|
memcpy(doc->where_path, save_path, sizeof(Leaf) * (wlen + 1));
|
|
@@ -1543,7 +1560,7 @@ static VALUE doc_each_value(int argc, VALUE *argv, VALUE self) {
|
|
|
1543
1560
|
path = StringValuePtr(*argv);
|
|
1544
1561
|
}
|
|
1545
1562
|
if (0 != (leaf = get_doc_leaf(doc, path))) {
|
|
1546
|
-
each_value(doc, leaf);
|
|
1563
|
+
each_value(doc, leaf, self);
|
|
1547
1564
|
}
|
|
1548
1565
|
}
|
|
1549
1566
|
return Qnil;
|
data/ext/oj/intern.c
CHANGED
data/ext/oj/mimic_json.c
CHANGED
|
@@ -246,8 +246,7 @@ static VALUE mimic_dump(int argc, VALUE *argv, VALUE self) {
|
|
|
246
246
|
if (0 == out.buf) {
|
|
247
247
|
rb_raise(rb_eNoMemError, "Not enough memory.");
|
|
248
248
|
}
|
|
249
|
-
rstr =
|
|
250
|
-
rstr = oj_encode(rstr);
|
|
249
|
+
rstr = rb_utf8_str_new_cstr(out.buf);
|
|
251
250
|
if (2 <= argc && Qnil != argv[1] && rb_respond_to(argv[1], oj_write_id)) {
|
|
252
251
|
VALUE io = argv[1];
|
|
253
252
|
VALUE args[1];
|
|
@@ -396,8 +395,7 @@ static VALUE mimic_generate_core(int argc, VALUE *argv, Options copts) {
|
|
|
396
395
|
if (0 == out.buf) {
|
|
397
396
|
rb_raise(rb_eNoMemError, "Not enough memory.");
|
|
398
397
|
}
|
|
399
|
-
rstr =
|
|
400
|
-
rstr = oj_encode(rstr);
|
|
398
|
+
rstr = rb_utf8_str_new_cstr(out.buf);
|
|
401
399
|
|
|
402
400
|
oj_out_free(&out);
|
|
403
401
|
|
|
@@ -713,6 +711,7 @@ static struct _options mimic_object_to_json_options = {0, // indent
|
|
|
713
711
|
0, // cache_str
|
|
714
712
|
0, // int_range_min
|
|
715
713
|
0, // int_range_max
|
|
714
|
+
0, // max_integer_digits
|
|
716
715
|
oj_json_class, // create_id
|
|
717
716
|
10, // create_id_len
|
|
718
717
|
3, // sec_prec
|
|
@@ -737,6 +736,8 @@ static struct _options mimic_object_to_json_options = {0, // indent
|
|
|
737
736
|
false, // omit_nil
|
|
738
737
|
false, // omit_null_byte
|
|
739
738
|
100, // max_depth
|
|
739
|
+
NULL, // only
|
|
740
|
+
NULL, // except
|
|
740
741
|
},
|
|
741
742
|
{
|
|
742
743
|
// str_rx
|
|
@@ -768,8 +769,7 @@ static VALUE mimic_object_to_json(int argc, VALUE *argv, VALUE self) {
|
|
|
768
769
|
if (NULL == out.buf) {
|
|
769
770
|
rb_raise(rb_eNoMemError, "Not enough memory.");
|
|
770
771
|
}
|
|
771
|
-
rstr =
|
|
772
|
-
rstr = oj_encode(rstr);
|
|
772
|
+
rstr = rb_utf8_str_new_cstr(out.buf);
|
|
773
773
|
|
|
774
774
|
oj_out_free(&out);
|
|
775
775
|
|
|
@@ -837,11 +837,15 @@ void oj_mimic_json_methods(VALUE json) {
|
|
|
837
837
|
} else {
|
|
838
838
|
json_error = rb_define_class_under(json, "JSONError", rb_eStandardError);
|
|
839
839
|
}
|
|
840
|
+
|
|
841
|
+
rb_global_variable(&oj_json_parser_error_class);
|
|
840
842
|
if (rb_const_defined_at(json, rb_intern("ParserError"))) {
|
|
841
843
|
oj_json_parser_error_class = rb_const_get(json, rb_intern("ParserError"));
|
|
842
844
|
} else {
|
|
843
845
|
oj_json_parser_error_class = rb_define_class_under(json, "ParserError", json_error);
|
|
844
846
|
}
|
|
847
|
+
|
|
848
|
+
rb_global_variable(&oj_json_generator_error_class);
|
|
845
849
|
if (rb_const_defined_at(json, rb_intern("GeneratorError"))) {
|
|
846
850
|
oj_json_generator_error_class = rb_const_get(json, rb_intern("GeneratorError"));
|
|
847
851
|
} else {
|
|
@@ -867,8 +871,8 @@ void oj_mimic_json_methods(VALUE json) {
|
|
|
867
871
|
rb_require("oj/state");
|
|
868
872
|
}
|
|
869
873
|
// Pull in the JSON::State mimic file.
|
|
874
|
+
rb_global_variable(&state_class);
|
|
870
875
|
state_class = rb_const_get_at(generator, rb_intern("State"));
|
|
871
|
-
rb_gc_register_mark_object(state_class);
|
|
872
876
|
}
|
|
873
877
|
|
|
874
878
|
/* Document-module: JSON
|