oj 3.13.14 → 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 +4 -0
- data/ext/oj/dump.c +22 -11
- 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 +18 -8
- 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/bar.rb +8 -1
- 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 +3 -107
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
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) {
|
@@ -756,6 +762,11 @@ void oj_dump_cstr(const char *str, size_t cnt, bool is_sym, bool escape1, Out ou
|
|
756
762
|
cmap = ascii_friendly_chars;
|
757
763
|
size = ascii_friendly_size((uint8_t *)str, cnt);
|
758
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;
|
759
770
|
case XSSEsc:
|
760
771
|
cmap = xss_friendly_chars;
|
761
772
|
size = xss_friendly_size((uint8_t *)str, cnt);
|
@@ -1130,7 +1141,7 @@ void oj_dump_float(VALUE obj, int depth, Out out, bool as_ok) {
|
|
1130
1141
|
} else if (isnan(d)) {
|
1131
1142
|
if (ObjectMode == out->opts->mode) {
|
1132
1143
|
strcpy(buf, nan_val);
|
1133
|
-
cnt = sizeof(
|
1144
|
+
cnt = sizeof(nan_val) - 1;
|
1134
1145
|
} else {
|
1135
1146
|
NanDump nd = out->opts->dump_opts.nan_dump;
|
1136
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);
|
@@ -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
data/test/bar.rb
CHANGED
@@ -6,4 +6,11 @@ $: << File.join(File.dirname(__FILE__), "../ext")
|
|
6
6
|
|
7
7
|
require 'oj'
|
8
8
|
|
9
|
-
Oj.
|
9
|
+
puts Oj.dump({
|
10
|
+
"float_test" => 0.25,
|
11
|
+
"nan_test" => Float::NAN,
|
12
|
+
"inf_test" => Float::INFINITY,
|
13
|
+
"minus_inf_test" => -Float::INFINITY,
|
14
|
+
"min_test" => Float::MIN,
|
15
|
+
"max_test" => Float::MAX,
|
16
|
+
}, mode: :object) # => {"float_test":0.25,"nan_test":3.3e14159265358979323846
|
@@ -269,6 +269,13 @@ EOT
|
|
269
269
|
assert_equal too_deep_ary, ok
|
270
270
|
ok = JSON.parse too_deep, :max_nesting => 0
|
271
271
|
assert_equal too_deep_ary, ok
|
272
|
+
|
273
|
+
unless ENV['REAL_JSON_GEM']
|
274
|
+
# max_nesting should be reset to 0 if not included in options
|
275
|
+
# This behavior is not compatible with Ruby standard JSON gem
|
276
|
+
ok = JSON.parse too_deep, {}
|
277
|
+
assert_equal too_deep_ary, ok
|
278
|
+
end
|
272
279
|
end
|
273
280
|
|
274
281
|
def test_backslash
|
data/test/test_compat.rb
CHANGED
@@ -488,6 +488,22 @@ class CompatJuice < Minitest::Test
|
|
488
488
|
assert_equal([1,2], Oj.load(s, :mode => :compat))
|
489
489
|
end
|
490
490
|
|
491
|
+
def test_parse_large_string
|
492
|
+
error = assert_raises() { Oj.load(%|{"a":"aaaaaaaaaa\0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}|) }
|
493
|
+
assert(error.message.include?('NULL byte in string'))
|
494
|
+
|
495
|
+
error = assert_raises() { Oj.load(%|{"a":"aaaaaaaaaaaaaaaaaaaa }|) }
|
496
|
+
assert(error.message.include?('quoted string not terminated'))
|
497
|
+
|
498
|
+
json =<<~JSON
|
499
|
+
{
|
500
|
+
"a": "\\u3074\\u30fc\\u305f\\u30fc",
|
501
|
+
"b": "aaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
502
|
+
}
|
503
|
+
JSON
|
504
|
+
assert_equal("ぴーたー", Oj.load(json)['a'])
|
505
|
+
end
|
506
|
+
|
491
507
|
def dump_and_load(obj, trace=false)
|
492
508
|
json = Oj.dump(obj)
|
493
509
|
puts json if trace
|
data/test/test_file.rb
CHANGED
@@ -212,6 +212,24 @@ class FileJuice < Minitest::Test
|
|
212
212
|
dump_and_load(DateTime.new(2012, 6, 19), false)
|
213
213
|
end
|
214
214
|
|
215
|
+
def test_load_unicode_path
|
216
|
+
json =<<~JSON
|
217
|
+
{
|
218
|
+
"x":true,
|
219
|
+
"y":58,
|
220
|
+
"z": [1,2,3]
|
221
|
+
}
|
222
|
+
JSON
|
223
|
+
|
224
|
+
Tempfile.create('file_test_conceição1.json') do |f|
|
225
|
+
f.write(json)
|
226
|
+
f.close
|
227
|
+
|
228
|
+
objects = Oj.load_file(f.path)
|
229
|
+
assert_equal(Oj.load(json), objects)
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
215
233
|
def dump_and_load(obj, trace=false)
|
216
234
|
filename = File.join(File.dirname(__FILE__), 'file_test.json')
|
217
235
|
File.open(filename, "w") { |f|
|
data/test/test_various.rb
CHANGED
@@ -345,6 +345,12 @@ class Juice < Minitest::Test
|
|
345
345
|
out = Oj.dump hash
|
346
346
|
assert_equal(%{{"key":"I \\u003c3 this"}}, out)
|
347
347
|
end
|
348
|
+
def test_escapes_slashes_by_default_when_configured_to_do_so
|
349
|
+
hash = {'key' => "I <3 this </script>"}
|
350
|
+
Oj.default_options = {:escape_mode => :slash}
|
351
|
+
out = Oj.dump hash
|
352
|
+
assert_equal(%{{"key":"I <3 this <\\/script>"}}, out)
|
353
|
+
end
|
348
354
|
def test_escapes_entities_when_asked_to
|
349
355
|
hash = {'key' => "I <3 this"}
|
350
356
|
out = Oj.dump(hash, :escape_mode => :xss_safe)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: oj
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.13.
|
4
|
+
version: 3.13.15
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Peter Ohler
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-07-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake-compiler
|
@@ -303,108 +303,4 @@ rubygems_version: 3.3.3
|
|
303
303
|
signing_key:
|
304
304
|
specification_version: 4
|
305
305
|
summary: A fast JSON parser and serializer.
|
306
|
-
test_files:
|
307
|
-
- test/_test_active.rb
|
308
|
-
- test/_test_active_mimic.rb
|
309
|
-
- test/_test_mimic_rails.rb
|
310
|
-
- test/activerecord/result_test.rb
|
311
|
-
- test/activesupport4/decoding_test.rb
|
312
|
-
- test/activesupport4/encoding_test.rb
|
313
|
-
- test/activesupport4/test_helper.rb
|
314
|
-
- test/activesupport5/abstract_unit.rb
|
315
|
-
- test/activesupport5/decoding_test.rb
|
316
|
-
- test/activesupport5/encoding_test.rb
|
317
|
-
- test/activesupport5/encoding_test_cases.rb
|
318
|
-
- test/activesupport5/test_helper.rb
|
319
|
-
- test/activesupport5/time_zone_test_helpers.rb
|
320
|
-
- test/activesupport6/abstract_unit.rb
|
321
|
-
- test/activesupport6/decoding_test.rb
|
322
|
-
- test/activesupport6/encoding_test.rb
|
323
|
-
- test/activesupport6/encoding_test_cases.rb
|
324
|
-
- test/activesupport6/test_common.rb
|
325
|
-
- test/activesupport6/test_helper.rb
|
326
|
-
- test/activesupport6/time_zone_test_helpers.rb
|
327
|
-
- test/activesupport7/abstract_unit.rb
|
328
|
-
- test/activesupport7/decoding_test.rb
|
329
|
-
- test/activesupport7/encoding_test.rb
|
330
|
-
- test/activesupport7/encoding_test_cases.rb
|
331
|
-
- test/activesupport7/time_zone_test_helpers.rb
|
332
|
-
- test/bar.rb
|
333
|
-
- test/baz.rb
|
334
|
-
- test/bug.rb
|
335
|
-
- test/files.rb
|
336
|
-
- test/foo.rb
|
337
|
-
- test/helper.rb
|
338
|
-
- test/isolated/shared.rb
|
339
|
-
- test/isolated/test_mimic_after.rb
|
340
|
-
- test/isolated/test_mimic_alone.rb
|
341
|
-
- test/isolated/test_mimic_as_json.rb
|
342
|
-
- test/isolated/test_mimic_before.rb
|
343
|
-
- test/isolated/test_mimic_define.rb
|
344
|
-
- test/isolated/test_mimic_rails_after.rb
|
345
|
-
- test/isolated/test_mimic_rails_before.rb
|
346
|
-
- test/isolated/test_mimic_redefine.rb
|
347
|
-
- test/json_gem/json_addition_test.rb
|
348
|
-
- test/json_gem/json_common_interface_test.rb
|
349
|
-
- test/json_gem/json_encoding_test.rb
|
350
|
-
- test/json_gem/json_ext_parser_test.rb
|
351
|
-
- test/json_gem/json_fixtures_test.rb
|
352
|
-
- test/json_gem/json_generator_test.rb
|
353
|
-
- test/json_gem/json_generic_object_test.rb
|
354
|
-
- test/json_gem/json_parser_test.rb
|
355
|
-
- test/json_gem/json_string_matching_test.rb
|
356
|
-
- test/json_gem/test_helper.rb
|
357
|
-
- test/mem.rb
|
358
|
-
- test/perf.rb
|
359
|
-
- test/perf_compat.rb
|
360
|
-
- test/perf_dump.rb
|
361
|
-
- test/perf_fast.rb
|
362
|
-
- test/perf_file.rb
|
363
|
-
- test/perf_object.rb
|
364
|
-
- test/perf_once.rb
|
365
|
-
- test/perf_parser.rb
|
366
|
-
- test/perf_saj.rb
|
367
|
-
- test/perf_scp.rb
|
368
|
-
- test/perf_simple.rb
|
369
|
-
- test/perf_strict.rb
|
370
|
-
- test/perf_wab.rb
|
371
|
-
- test/prec.rb
|
372
|
-
- test/sample/change.rb
|
373
|
-
- test/sample/dir.rb
|
374
|
-
- test/sample/doc.rb
|
375
|
-
- test/sample/file.rb
|
376
|
-
- test/sample/group.rb
|
377
|
-
- test/sample/hasprops.rb
|
378
|
-
- test/sample/layer.rb
|
379
|
-
- test/sample/line.rb
|
380
|
-
- test/sample/oval.rb
|
381
|
-
- test/sample/rect.rb
|
382
|
-
- test/sample/shape.rb
|
383
|
-
- test/sample/text.rb
|
384
|
-
- test/sample.rb
|
385
|
-
- test/sample_json.rb
|
386
|
-
- test/test_compat.rb
|
387
|
-
- test/test_custom.rb
|
388
|
-
- test/test_debian.rb
|
389
|
-
- test/test_fast.rb
|
390
|
-
- test/test_file.rb
|
391
|
-
- test/test_gc.rb
|
392
|
-
- test/test_generate.rb
|
393
|
-
- test/test_hash.rb
|
394
|
-
- test/test_integer_range.rb
|
395
|
-
- test/test_null.rb
|
396
|
-
- test/test_object.rb
|
397
|
-
- test/test_parser.rb
|
398
|
-
- test/test_parser_saj.rb
|
399
|
-
- test/test_parser_usual.rb
|
400
|
-
- test/test_rails.rb
|
401
|
-
- test/test_saj.rb
|
402
|
-
- test/test_scp.rb
|
403
|
-
- test/test_strict.rb
|
404
|
-
- test/test_various.rb
|
405
|
-
- test/test_wab.rb
|
406
|
-
- test/test_writer.rb
|
407
|
-
- test/tests.rb
|
408
|
-
- test/tests_mimic.rb
|
409
|
-
- test/tests_mimic_addition.rb
|
410
|
-
- test/zoo.rb
|
306
|
+
test_files: []
|