oj 3.13.12 → 3.13.15
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +12 -0
- data/ext/oj/dump.c +22 -13
- data/ext/oj/dump_compat.c +0 -5
- data/ext/oj/dump_object.c +2 -57
- data/ext/oj/extconf.rb +5 -4
- data/ext/oj/mimic_json.c +19 -9
- data/ext/oj/oj.c +17 -3
- data/ext/oj/oj.h +1 -1
- data/ext/oj/parse.c +50 -15
- data/ext/oj/rails.c +0 -5
- data/ext/oj/sparse.c +4 -0
- data/ext/oj/wab.c +0 -5
- data/lib/oj/version.rb +1 -1
- data/test/activesupport7/abstract_unit.rb +49 -0
- data/test/activesupport7/decoding_test.rb +125 -0
- data/test/activesupport7/encoding_test.rb +486 -0
- data/test/activesupport7/encoding_test_cases.rb +104 -0
- data/test/activesupport7/time_zone_test_helpers.rb +47 -0
- data/test/bar.rb +8 -1
- data/test/json_gem/json_generator_test.rb +2 -0
- data/test/json_gem/json_parser_test.rb +7 -0
- data/test/test_compat.rb +16 -0
- data/test/test_file.rb +18 -0
- data/test/test_various.rb +6 -0
- metadata +8 -116
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2dd6fd9c107efe5095ca235c398e2fb7cc4fb9cdd9feffb4f27fef1ed1e3faa3
|
4
|
+
data.tar.gz: 072e3744f4cbb880f1e5296ad1abba448341d9934173fa101ba1d65efe20de64
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 76fbaa3e575553ffbf37e45447429b58da392d58e59afa82491363a17ee3ab7cacf5283986db7242f1cf8b0340449d8a1d97a6f54c288076110a2fdc5ccebf30
|
7
|
+
data.tar.gz: 116f07d7db9124f62007eff33a2583f4de5a1338009fec59eca267a483be229285a7ec66c6fbb1feb92f05284afe76ae39629aca2e8f2a7ff20caa27adddc0c4
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,17 @@
|
|
1
1
|
# CHANGELOG
|
2
2
|
|
3
|
+
## 3.13.15 - 2022-07-03
|
4
|
+
|
5
|
+
- Fixed issue dumping NaN value in object mode.
|
6
|
+
|
7
|
+
## 3.13.14 - 2022-06-03
|
8
|
+
|
9
|
+
- Double fclose() due to bad merger fixed by tonobo.
|
10
|
+
|
11
|
+
## 3.13.13 - 2022-05-20
|
12
|
+
|
13
|
+
- Fixed flooding stdout with debug output when dumping.
|
14
|
+
|
3
15
|
## 3.13.12 - 2022-05-20
|
4
16
|
|
5
17
|
- Fixed crash on no arguments to pretty_generate. Now raises an exception.
|
data/ext/oj/dump.c
CHANGED
@@ -32,6 +32,7 @@ static const char nan_val[] = NAN_VAL;
|
|
32
32
|
typedef unsigned long ulong;
|
33
33
|
|
34
34
|
static size_t hibit_friendly_size(const uint8_t *str, size_t len);
|
35
|
+
static size_t slash_friendly_size(const uint8_t *str, size_t len);
|
35
36
|
static size_t xss_friendly_size(const uint8_t *str, size_t len);
|
36
37
|
static size_t ascii_friendly_size(const uint8_t *str, size_t len);
|
37
38
|
|
@@ -59,6 +60,17 @@ static char hibit_friendly_chars[256] = "\
|
|
59
60
|
11111111111111111111111111111111\
|
60
61
|
11111111111111111111111111111111";
|
61
62
|
|
63
|
+
// JSON standard but escape forward slashes `/`
|
64
|
+
static char slash_friendly_chars[256] = "\
|
65
|
+
66666666222622666666666666666666\
|
66
|
+
11211111111111121111111111111111\
|
67
|
+
11111111111111111111111111112111\
|
68
|
+
11111111111111111111111111111111\
|
69
|
+
11111111111111111111111111111111\
|
70
|
+
11111111111111111111111111111111\
|
71
|
+
11111111111111111111111111111111\
|
72
|
+
11111111111111111111111111111111";
|
73
|
+
|
62
74
|
// High bit set characters are always encoded as unicode. Worse case is 3
|
63
75
|
// bytes per character in the output. That makes this conservative.
|
64
76
|
static char ascii_friendly_chars[256] = "\
|
@@ -143,6 +155,10 @@ inline static size_t hibit_friendly_size(const uint8_t *str, size_t len) {
|
|
143
155
|
return calculate_string_size(str, len, hibit_friendly_chars);
|
144
156
|
}
|
145
157
|
|
158
|
+
inline static size_t slash_friendly_size(const uint8_t *str, size_t len) {
|
159
|
+
return calculate_string_size(str, len, slash_friendly_chars);
|
160
|
+
}
|
161
|
+
|
146
162
|
inline static size_t ascii_friendly_size(const uint8_t *str, size_t len) {
|
147
163
|
return calculate_string_size(str, len, ascii_friendly_chars);
|
148
164
|
}
|
@@ -365,7 +381,6 @@ void oj_dump_time(VALUE obj, Out out, int withZone) {
|
|
365
381
|
long long sec;
|
366
382
|
long long nsec;
|
367
383
|
|
368
|
-
#ifdef HAVE_RB_TIME_TIMESPEC
|
369
384
|
// rb_time_timespec as well as rb_time_timeeval have a bug that causes an
|
370
385
|
// exception to be raised if a time is before 1970 on 32 bit systems so
|
371
386
|
// check the timespec size and use the ruby calls if a 32 bit system.
|
@@ -378,10 +393,6 @@ void oj_dump_time(VALUE obj, Out out, int withZone) {
|
|
378
393
|
sec = NUM2LL(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
|
379
394
|
nsec = NUM2LL(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
|
380
395
|
}
|
381
|
-
#else
|
382
|
-
sec = NUM2LL(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
|
383
|
-
nsec = NUM2LL(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
|
384
|
-
#endif
|
385
396
|
|
386
397
|
*b-- = '\0';
|
387
398
|
if (withZone) {
|
@@ -467,7 +478,6 @@ void oj_dump_xml_time(VALUE obj, Out out) {
|
|
467
478
|
int tzhour, tzmin;
|
468
479
|
char tzsign = '+';
|
469
480
|
|
470
|
-
#ifdef HAVE_RB_TIME_TIMESPEC
|
471
481
|
if (16 <= sizeof(struct timespec)) {
|
472
482
|
struct timespec ts = rb_time_timespec(obj);
|
473
483
|
|
@@ -477,10 +487,6 @@ void oj_dump_xml_time(VALUE obj, Out out) {
|
|
477
487
|
sec = NUM2LL(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
|
478
488
|
nsec = NUM2LL(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
|
479
489
|
}
|
480
|
-
#else
|
481
|
-
sec = NUM2LL(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
|
482
|
-
nsec = NUM2LL(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
|
483
|
-
#endif
|
484
490
|
|
485
491
|
assure_size(out, 36);
|
486
492
|
if (9 > out->opts->sec_prec) {
|
@@ -614,7 +620,6 @@ void oj_write_obj_to_file(VALUE obj, const char *path, Options copts) {
|
|
614
620
|
|
615
621
|
oj_out_free(&out);
|
616
622
|
|
617
|
-
fclose(f);
|
618
623
|
if (!ok) {
|
619
624
|
int err = ferror(f);
|
620
625
|
fclose(f);
|
@@ -757,6 +762,11 @@ void oj_dump_cstr(const char *str, size_t cnt, bool is_sym, bool escape1, Out ou
|
|
757
762
|
cmap = ascii_friendly_chars;
|
758
763
|
size = ascii_friendly_size((uint8_t *)str, cnt);
|
759
764
|
break;
|
765
|
+
case SlashEsc:
|
766
|
+
has_hi = true;
|
767
|
+
cmap = slash_friendly_chars;
|
768
|
+
size = slash_friendly_size((uint8_t *)str, cnt);
|
769
|
+
break;
|
760
770
|
case XSSEsc:
|
761
771
|
cmap = xss_friendly_chars;
|
762
772
|
size = xss_friendly_size((uint8_t *)str, cnt);
|
@@ -951,7 +961,6 @@ void oj_grow_out(Out out, size_t len) {
|
|
951
961
|
long pos = out->cur - out->buf;
|
952
962
|
char *buf = out->buf;
|
953
963
|
|
954
|
-
printf("*** grow %ld\n", len);
|
955
964
|
size *= 2;
|
956
965
|
if (size <= len * 2 + pos) {
|
957
966
|
size += len;
|
@@ -1132,7 +1141,7 @@ void oj_dump_float(VALUE obj, int depth, Out out, bool as_ok) {
|
|
1132
1141
|
} else if (isnan(d)) {
|
1133
1142
|
if (ObjectMode == out->opts->mode) {
|
1134
1143
|
strcpy(buf, nan_val);
|
1135
|
-
cnt = sizeof(
|
1144
|
+
cnt = sizeof(nan_val) - 1;
|
1136
1145
|
} else {
|
1137
1146
|
NanDump nd = out->opts->dump_opts.nan_dump;
|
1138
1147
|
|
data/ext/oj/dump_compat.c
CHANGED
@@ -444,7 +444,6 @@ time_alt(VALUE obj, int depth, Out out) {
|
|
444
444
|
time_t sec;
|
445
445
|
long long nsec;
|
446
446
|
|
447
|
-
#ifdef HAVE_RB_TIME_TIMESPEC
|
448
447
|
if (16 <= sizeof(struct timespec)) {
|
449
448
|
struct timespec ts = rb_time_timespec(obj);
|
450
449
|
|
@@ -454,10 +453,6 @@ time_alt(VALUE obj, int depth, Out out) {
|
|
454
453
|
sec = NUM2LL(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
|
455
454
|
nsec = NUM2LL(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
|
456
455
|
}
|
457
|
-
#else
|
458
|
-
sec = NUM2LL(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
|
459
|
-
nsec = NUM2LL(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
|
460
|
-
#endif
|
461
456
|
|
462
457
|
attrs[0].num = sec;
|
463
458
|
attrs[1].num = nsec;
|
data/ext/oj/dump_object.c
CHANGED
@@ -315,7 +315,6 @@ static void dump_hash_class(VALUE obj, VALUE clas, int depth, Out out) {
|
|
315
315
|
*out->cur = '\0';
|
316
316
|
}
|
317
317
|
|
318
|
-
#ifdef HAVE_RB_IVAR_FOREACH
|
319
318
|
static int dump_attr_cb(ID key, VALUE value, VALUE ov) {
|
320
319
|
Out out = (Out)ov;
|
321
320
|
int depth = out->depth;
|
@@ -358,7 +357,6 @@ static int dump_attr_cb(ID key, VALUE value, VALUE ov) {
|
|
358
357
|
|
359
358
|
return ST_CONTINUE;
|
360
359
|
}
|
361
|
-
#endif
|
362
360
|
|
363
361
|
static void dump_hash(VALUE obj, int depth, Out out, bool as_ok) {
|
364
362
|
dump_hash_class(obj, rb_obj_class(obj), depth, out);
|
@@ -510,19 +508,8 @@ static void dump_obj_attrs(VALUE obj, VALUE clas, slot_t id, int depth, Out out)
|
|
510
508
|
default: break;
|
511
509
|
}
|
512
510
|
{
|
513
|
-
int cnt;
|
514
|
-
|
515
|
-
cnt = (int)rb_ivar_count(obj);
|
516
|
-
#else
|
517
|
-
volatile VALUE vars = rb_funcall2(obj, oj_instance_variables_id, 0, 0);
|
518
|
-
VALUE * np = RARRAY_PTR(vars);
|
519
|
-
ID vid;
|
520
|
-
const char * attr;
|
521
|
-
int i;
|
522
|
-
int first = 1;
|
523
|
-
|
524
|
-
cnt = (int)RARRAY_LEN(vars);
|
525
|
-
#endif
|
511
|
+
int cnt = (int)rb_ivar_count(obj);
|
512
|
+
|
526
513
|
if (Qundef != clas && 0 < cnt) {
|
527
514
|
*out->cur++ = ',';
|
528
515
|
}
|
@@ -535,52 +522,10 @@ static void dump_obj_attrs(VALUE obj, VALUE clas, slot_t id, int depth, Out out)
|
|
535
522
|
}
|
536
523
|
}
|
537
524
|
out->depth = depth + 1;
|
538
|
-
#ifdef HAVE_RB_IVAR_FOREACH
|
539
525
|
rb_ivar_foreach(obj, dump_attr_cb, (VALUE)out);
|
540
526
|
if (',' == *(out->cur - 1)) {
|
541
527
|
out->cur--; // backup to overwrite last comma
|
542
528
|
}
|
543
|
-
#else
|
544
|
-
size = d2 * out->indent + 1;
|
545
|
-
for (i = cnt; 0 < i; i--, np++) {
|
546
|
-
VALUE value;
|
547
|
-
|
548
|
-
vid = rb_to_id(*np);
|
549
|
-
attr = rb_id2name(vid);
|
550
|
-
if (Yes == out->opts->ignore_under && '@' == *attr && '_' == attr[1]) {
|
551
|
-
continue;
|
552
|
-
}
|
553
|
-
value = rb_ivar_get(obj, vid);
|
554
|
-
|
555
|
-
if (dump_ignore(out->opts, value)) {
|
556
|
-
continue;
|
557
|
-
}
|
558
|
-
if (out->omit_nil && Qnil == value) {
|
559
|
-
continue;
|
560
|
-
}
|
561
|
-
if (first) {
|
562
|
-
first = 0;
|
563
|
-
} else {
|
564
|
-
*out->cur++ = ',';
|
565
|
-
}
|
566
|
-
assure_size(out, size);
|
567
|
-
fill_indent(out, d2);
|
568
|
-
if ('@' == *attr) {
|
569
|
-
attr++;
|
570
|
-
oj_dump_cstr(attr, strlen(attr), 0, 0, out);
|
571
|
-
} else {
|
572
|
-
char buf[32];
|
573
|
-
|
574
|
-
*buf = '~';
|
575
|
-
strncpy(buf + 1, attr, sizeof(buf) - 2);
|
576
|
-
buf[sizeof(buf) - 1] = '\0';
|
577
|
-
oj_dump_cstr(buf, strlen(attr) + 1, 0, 0, out);
|
578
|
-
}
|
579
|
-
*out->cur++ = ':';
|
580
|
-
oj_dump_obj_val(value, d2, out);
|
581
|
-
assure_size(out, 2);
|
582
|
-
}
|
583
|
-
#endif
|
584
529
|
if (rb_obj_is_kind_of(obj, rb_eException)) {
|
585
530
|
volatile VALUE rv;
|
586
531
|
|
data/ext/oj/extconf.rb
CHANGED
@@ -23,14 +23,10 @@ dflags = {
|
|
23
23
|
'RSTRUCT_LEN_RETURNS_INTEGER_OBJECT' => ('ruby' == type && '2' == version[0] && '4' == version[1] && '1' >= version[2]) ? 1 : 0,
|
24
24
|
}
|
25
25
|
|
26
|
-
have_func('rb_time_timespec')
|
27
|
-
have_func('rb_ivar_count')
|
28
|
-
have_func('rb_ivar_foreach')
|
29
26
|
# Support for compaction.
|
30
27
|
have_func('rb_gc_mark_movable')
|
31
28
|
have_func('stpcpy')
|
32
29
|
have_func('pthread_mutex_init')
|
33
|
-
have_func('rb_enc_associate')
|
34
30
|
have_func('rb_enc_interned_str')
|
35
31
|
have_func('rb_ext_ractor_safe', 'ruby.h')
|
36
32
|
# rb_hash_bulk_insert is deep down in a header not included in normal build and that seems to fool have_func.
|
@@ -38,6 +34,11 @@ have_func('rb_hash_bulk_insert', 'ruby.h') unless '2' == version[0] && '6' == ve
|
|
38
34
|
|
39
35
|
dflags['OJ_DEBUG'] = true unless ENV['OJ_DEBUG'].nil?
|
40
36
|
|
37
|
+
if try_cflags('-msse4.2')
|
38
|
+
$CPPFLAGS += ' -msse4.2'
|
39
|
+
dflags['OJ_USE_SSE4_2'] = 1
|
40
|
+
end
|
41
|
+
|
41
42
|
dflags.each do |k,v|
|
42
43
|
if v.nil?
|
43
44
|
$CPPFLAGS += " -D#{k}"
|
data/ext/oj/mimic_json.c
CHANGED
@@ -388,6 +388,10 @@ static VALUE mimic_generate_core(int argc, VALUE *argv, Options copts) {
|
|
388
388
|
VALUE active_hack[1];
|
389
389
|
|
390
390
|
if (Qundef == state_class) {
|
391
|
+
rb_warn(
|
392
|
+
"Oj::Rails.mimic_JSON was called implicitly. "
|
393
|
+
"Call it explicitly beforehand if you want to remove this warning."
|
394
|
+
);
|
391
395
|
oj_define_mimic_json(0, NULL, Qnil);
|
392
396
|
}
|
393
397
|
active_hack[0] = rb_funcall(state_class, oj_new_id, 0);
|
@@ -460,7 +464,7 @@ oj_mimic_pretty_generate(int argc, VALUE *argv, VALUE self) {
|
|
460
464
|
if (0 == argc) {
|
461
465
|
rb_raise(rb_eArgError, "wrong number of arguments (0))");
|
462
466
|
}
|
463
|
-
if (1 == argc) {
|
467
|
+
if (1 == argc || Qnil == argv[1]) {
|
464
468
|
h = rb_hash_new();
|
465
469
|
} else {
|
466
470
|
h = argv[1];
|
@@ -481,6 +485,10 @@ oj_mimic_pretty_generate(int argc, VALUE *argv, VALUE self) {
|
|
481
485
|
rb_hash_aset(h, oj_array_nl_sym, rb_str_new2("\n"));
|
482
486
|
}
|
483
487
|
if (Qundef == state_class) {
|
488
|
+
rb_warn(
|
489
|
+
"Oj::Rails.mimic_JSON was called implicitly. "
|
490
|
+
"Call it explicitly beforehand if you want to remove this warning."
|
491
|
+
);
|
484
492
|
oj_define_mimic_json(0, NULL, Qnil);
|
485
493
|
}
|
486
494
|
rargs[1] = rb_funcall(state_class, oj_new_id, 1, h);
|
@@ -536,14 +544,6 @@ static int parse_options_cb(VALUE k, VALUE v, VALUE info) {
|
|
536
544
|
}
|
537
545
|
} else if (oj_decimal_class_sym == k) {
|
538
546
|
pi->options.compat_bigdec = (oj_bigdecimal_class == v);
|
539
|
-
} else if (oj_max_nesting_sym == k) {
|
540
|
-
if (Qtrue == v) {
|
541
|
-
pi->max_depth = 100;
|
542
|
-
} else if (Qfalse == v || Qnil == v) {
|
543
|
-
pi->max_depth = 0;
|
544
|
-
} else if (T_FIXNUM == rb_type(v)) {
|
545
|
-
pi->max_depth = NUM2INT(v);
|
546
|
-
}
|
547
547
|
}
|
548
548
|
return ST_CONTINUE;
|
549
549
|
}
|
@@ -573,11 +573,21 @@ static VALUE mimic_parse_core(int argc, VALUE *argv, VALUE self, bool bang) {
|
|
573
573
|
pi.max_depth = 100;
|
574
574
|
|
575
575
|
if (Qnil != ropts) {
|
576
|
+
VALUE v;
|
577
|
+
|
576
578
|
if (T_HASH != rb_type(ropts)) {
|
577
579
|
rb_raise(rb_eArgError, "options must be a hash.");
|
578
580
|
}
|
579
581
|
|
580
582
|
rb_hash_foreach(ropts, parse_options_cb, (VALUE)&pi);
|
583
|
+
v = rb_hash_lookup(ropts, oj_max_nesting_sym);
|
584
|
+
if (Qtrue == v) {
|
585
|
+
pi.max_depth = 100;
|
586
|
+
} else if (Qfalse == v || Qnil == v) {
|
587
|
+
pi.max_depth = 0;
|
588
|
+
} else if (T_FIXNUM == rb_type(v)) {
|
589
|
+
pi.max_depth = NUM2INT(v);
|
590
|
+
}
|
581
591
|
oj_parse_opt_match_string(&pi.options.str_rx, ropts);
|
582
592
|
if (Yes == pi.options.create_ok && Yes == pi.options.sym_key) {
|
583
593
|
rb_raise(rb_eArgError, ":symbolize_names and :create_additions can not both be true.");
|
data/ext/oj/oj.c
CHANGED
@@ -45,7 +45,6 @@ ID oj_hash_key_id;
|
|
45
45
|
ID oj_hash_set_id;
|
46
46
|
ID oj_hash_start_id;
|
47
47
|
ID oj_iconv_id;
|
48
|
-
ID oj_instance_variables_id;
|
49
48
|
ID oj_json_create_id;
|
50
49
|
ID oj_length_id;
|
51
50
|
ID oj_new_id;
|
@@ -137,6 +136,7 @@ static VALUE rails_sym;
|
|
137
136
|
static VALUE raise_sym;
|
138
137
|
static VALUE ruby_sym;
|
139
138
|
static VALUE sec_prec_sym;
|
139
|
+
static VALUE slash_sym;
|
140
140
|
static VALUE strict_sym;
|
141
141
|
static VALUE symbol_keys_sym;
|
142
142
|
static VALUE time_format_sym;
|
@@ -405,6 +405,7 @@ static VALUE get_def_opts(VALUE self) {
|
|
405
405
|
switch (oj_default_options.escape_mode) {
|
406
406
|
case NLEsc: rb_hash_aset(opts, escape_mode_sym, newline_sym); break;
|
407
407
|
case JSONEsc: rb_hash_aset(opts, escape_mode_sym, json_sym); break;
|
408
|
+
case SlashEsc: rb_hash_aset(opts, escape_mode_sym, slash_sym); break;
|
408
409
|
case XSSEsc: rb_hash_aset(opts, escape_mode_sym, xss_safe_sym); break;
|
409
410
|
case ASCIIEsc: rb_hash_aset(opts, escape_mode_sym, ascii_sym); break;
|
410
411
|
case JXEsc: rb_hash_aset(opts, escape_mode_sym, unicode_xss_sym); break;
|
@@ -734,6 +735,8 @@ static int parse_options_cb(VALUE k, VALUE v, VALUE opts) {
|
|
734
735
|
copts->escape_mode = NLEsc;
|
735
736
|
} else if (json_sym == v) {
|
736
737
|
copts->escape_mode = JSONEsc;
|
738
|
+
} else if (slash_sym == v) {
|
739
|
+
copts->escape_mode = SlashEsc;
|
737
740
|
} else if (xss_safe_sym == v) {
|
738
741
|
copts->escape_mode = XSSEsc;
|
739
742
|
} else if (ascii_sym == v) {
|
@@ -1148,7 +1151,17 @@ static VALUE load_file(int argc, VALUE *argv, VALUE self) {
|
|
1148
1151
|
}
|
1149
1152
|
}
|
1150
1153
|
path = StringValuePtr(*argv);
|
1151
|
-
|
1154
|
+
#ifdef _WIN32
|
1155
|
+
{
|
1156
|
+
WCHAR *wide_path;
|
1157
|
+
wide_path = rb_w32_mbstr_to_wstr(CP_UTF8, path, -1, NULL);
|
1158
|
+
fd = rb_w32_wopen(wide_path, O_RDONLY);
|
1159
|
+
free(wide_path);
|
1160
|
+
}
|
1161
|
+
#else
|
1162
|
+
fd = open(path, O_RDONLY);
|
1163
|
+
#endif
|
1164
|
+
if (0 == fd) {
|
1152
1165
|
rb_raise(rb_eIOError, "%s", strerror(errno));
|
1153
1166
|
}
|
1154
1167
|
switch (mode) {
|
@@ -1814,7 +1827,6 @@ void Init_oj(void) {
|
|
1814
1827
|
oj_hash_set_id = rb_intern("hash_set");
|
1815
1828
|
oj_hash_start_id = rb_intern("hash_start");
|
1816
1829
|
oj_iconv_id = rb_intern("iconv");
|
1817
|
-
oj_instance_variables_id = rb_intern("instance_variables");
|
1818
1830
|
oj_json_create_id = rb_intern("json_create");
|
1819
1831
|
oj_length_id = rb_intern("length");
|
1820
1832
|
oj_new_id = rb_intern("new");
|
@@ -1977,6 +1989,8 @@ void Init_oj(void) {
|
|
1977
1989
|
rb_gc_register_address(&ruby_sym);
|
1978
1990
|
sec_prec_sym = ID2SYM(rb_intern("second_precision"));
|
1979
1991
|
rb_gc_register_address(&sec_prec_sym);
|
1992
|
+
slash_sym = ID2SYM(rb_intern("slash"));
|
1993
|
+
rb_gc_register_address(&slash_sym);
|
1980
1994
|
strict_sym = ID2SYM(rb_intern("strict"));
|
1981
1995
|
rb_gc_register_address(&strict_sym);
|
1982
1996
|
symbol_keys_sym = ID2SYM(rb_intern("symbol_keys"));
|
data/ext/oj/oj.h
CHANGED
@@ -66,6 +66,7 @@ typedef enum { UnixTime = 'u', UnixZTime = 'z', XmlTime = 'x', RubyTime = 'r' }
|
|
66
66
|
typedef enum {
|
67
67
|
NLEsc = 'n',
|
68
68
|
JSONEsc = 'j',
|
69
|
+
SlashEsc = 's',
|
69
70
|
XSSEsc = 'x',
|
70
71
|
ASCIIEsc = 'a',
|
71
72
|
JXEsc = 'g', // json gem
|
@@ -346,7 +347,6 @@ extern ID oj_hash_key_id;
|
|
346
347
|
extern ID oj_hash_set_id;
|
347
348
|
extern ID oj_hash_start_id;
|
348
349
|
extern ID oj_iconv_id;
|
349
|
-
extern ID oj_instance_variables_id;
|
350
350
|
extern ID oj_json_create_id;
|
351
351
|
extern ID oj_length_id;
|
352
352
|
extern ID oj_new_id;
|
data/ext/oj/parse.c
CHANGED
@@ -327,26 +327,61 @@ static void read_escaped_str(ParseInfo pi, const char *start) {
|
|
327
327
|
buf_cleanup(&buf);
|
328
328
|
}
|
329
329
|
|
330
|
-
static void
|
331
|
-
const char *str = pi->cur;
|
332
|
-
Val parent = stack_peek(&pi->stack);
|
333
|
-
|
330
|
+
static inline void scan_string_noSIMD(ParseInfo pi) {
|
334
331
|
for (; '"' != *pi->cur; pi->cur++) {
|
335
|
-
if (pi->end <= pi->cur) {
|
336
|
-
oj_set_error_at(pi,
|
337
|
-
oj_parse_error_class,
|
338
|
-
__FILE__,
|
339
|
-
__LINE__,
|
340
|
-
"quoted string not terminated");
|
332
|
+
if (pi->end <= pi->cur || '\0' == *pi->cur || '\\' == *pi->cur) {
|
341
333
|
return;
|
342
|
-
}
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
334
|
+
}
|
335
|
+
}
|
336
|
+
}
|
337
|
+
|
338
|
+
#if defined(OJ_USE_SSE4_2)
|
339
|
+
#include <nmmintrin.h>
|
340
|
+
|
341
|
+
static inline void scan_string_SIMD(ParseInfo pi) {
|
342
|
+
static const char chars[16] = "\x00\\\"";
|
343
|
+
const __m128i terminate = _mm_loadu_si128((const __m128i *)&chars[0]);
|
344
|
+
const char *end = (const char *)(pi->end - 16);
|
345
|
+
|
346
|
+
for (; pi->cur <= end; pi->cur += 16) {
|
347
|
+
const __m128i string = _mm_loadu_si128((const __m128i *)pi->cur);
|
348
|
+
const int r = _mm_cmpestri(terminate, 3, string, 16, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_LEAST_SIGNIFICANT);
|
349
|
+
if (r != 16) {
|
350
|
+
pi->cur = (const char*)(pi->cur + r);
|
347
351
|
return;
|
348
352
|
}
|
349
353
|
}
|
354
|
+
|
355
|
+
scan_string_noSIMD(pi);
|
356
|
+
}
|
357
|
+
#endif
|
358
|
+
|
359
|
+
static void read_str(ParseInfo pi) {
|
360
|
+
const char *str = pi->cur;
|
361
|
+
Val parent = stack_peek(&pi->stack);
|
362
|
+
|
363
|
+
#if defined(OJ_USE_SSE4_2)
|
364
|
+
scan_string_SIMD(pi);
|
365
|
+
#else
|
366
|
+
scan_string_noSIMD(pi);
|
367
|
+
#endif
|
368
|
+
if (RB_UNLIKELY(pi->end <= pi->cur)) {
|
369
|
+
oj_set_error_at(pi,
|
370
|
+
oj_parse_error_class,
|
371
|
+
__FILE__,
|
372
|
+
__LINE__,
|
373
|
+
"quoted string not terminated");
|
374
|
+
return;
|
375
|
+
}
|
376
|
+
if (RB_UNLIKELY('\0' == *pi->cur)) {
|
377
|
+
oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "NULL byte in string");
|
378
|
+
return;
|
379
|
+
}
|
380
|
+
if ('\\' == *pi->cur) {
|
381
|
+
read_escaped_str(pi, str);
|
382
|
+
return;
|
383
|
+
}
|
384
|
+
|
350
385
|
if (0 == parent) { // simple add
|
351
386
|
pi->add_cstr(pi, str, pi->cur - str, str);
|
352
387
|
} else {
|
data/ext/oj/rails.c
CHANGED
@@ -320,7 +320,6 @@ static void dump_time(VALUE obj, int depth, Out out, bool as_ok) {
|
|
320
320
|
long long sec;
|
321
321
|
long long nsec;
|
322
322
|
|
323
|
-
#ifdef HAVE_RB_TIME_TIMESPEC
|
324
323
|
if (16 <= sizeof(struct timespec)) {
|
325
324
|
struct timespec ts = rb_time_timespec(obj);
|
326
325
|
|
@@ -330,10 +329,6 @@ static void dump_time(VALUE obj, int depth, Out out, bool as_ok) {
|
|
330
329
|
sec = NUM2LL(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
|
331
330
|
nsec = NUM2LL(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
|
332
331
|
}
|
333
|
-
#else
|
334
|
-
sec = NUM2LL(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
|
335
|
-
nsec = NUM2LL(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
|
336
|
-
#endif
|
337
332
|
dump_sec_nano(obj, sec, nsec, out);
|
338
333
|
}
|
339
334
|
|
data/ext/oj/sparse.c
CHANGED
data/ext/oj/wab.c
CHANGED
@@ -194,7 +194,6 @@ static void dump_time(VALUE obj, Out out) {
|
|
194
194
|
time_t sec;
|
195
195
|
long long nsec;
|
196
196
|
|
197
|
-
#ifdef HAVE_RB_TIME_TIMESPEC
|
198
197
|
if (16 <= sizeof(struct timespec)) {
|
199
198
|
struct timespec ts = rb_time_timespec(obj);
|
200
199
|
|
@@ -204,10 +203,6 @@ static void dump_time(VALUE obj, Out out) {
|
|
204
203
|
sec = NUM2LL(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
|
205
204
|
nsec = NUM2LL(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
|
206
205
|
}
|
207
|
-
#else
|
208
|
-
sec = NUM2LL(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
|
209
|
-
nsec = NUM2LL(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
|
210
|
-
#endif
|
211
206
|
|
212
207
|
assure_size(out, 36);
|
213
208
|
// 2012-01-05T23:58:07.123456000Z
|
data/lib/oj/version.rb
CHANGED
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
ORIG_ARGV = ARGV.dup
|
4
|
+
|
5
|
+
require "bundler/setup"
|
6
|
+
require "active_support/core_ext/kernel/reporting"
|
7
|
+
|
8
|
+
silence_warnings do
|
9
|
+
Encoding.default_internal = Encoding::UTF_8
|
10
|
+
Encoding.default_external = Encoding::UTF_8
|
11
|
+
end
|
12
|
+
|
13
|
+
require "active_support/testing/autorun"
|
14
|
+
require "active_support/testing/method_call_assertions"
|
15
|
+
|
16
|
+
ENV["NO_RELOAD"] = "1"
|
17
|
+
require "active_support"
|
18
|
+
|
19
|
+
Thread.abort_on_exception = true
|
20
|
+
|
21
|
+
# Show backtraces for deprecated behavior for quicker cleanup.
|
22
|
+
ActiveSupport::Deprecation.debug = true
|
23
|
+
|
24
|
+
# Default to old to_time behavior but allow running tests with new behavior
|
25
|
+
ActiveSupport.to_time_preserves_timezone = ENV["PRESERVE_TIMEZONES"] == "1"
|
26
|
+
|
27
|
+
# Disable available locale checks to avoid warnings running the test suite.
|
28
|
+
I18n.enforce_available_locales = false
|
29
|
+
|
30
|
+
class ActiveSupport::TestCase
|
31
|
+
if Process.respond_to?(:fork) && !Gem.win_platform?
|
32
|
+
parallelize
|
33
|
+
else
|
34
|
+
parallelize(with: :threads)
|
35
|
+
end
|
36
|
+
|
37
|
+
include ActiveSupport::Testing::MethodCallAssertions
|
38
|
+
|
39
|
+
private
|
40
|
+
# Skips the current run on Rubinius using Minitest::Assertions#skip
|
41
|
+
def rubinius_skip(message = "")
|
42
|
+
skip message if RUBY_ENGINE == "rbx"
|
43
|
+
end
|
44
|
+
|
45
|
+
# Skips the current run on JRuby using Minitest::Assertions#skip
|
46
|
+
def jruby_skip(message = "")
|
47
|
+
skip message if defined?(JRUBY_VERSION)
|
48
|
+
end
|
49
|
+
end
|