oj 3.13.14 → 3.13.15
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 +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: []
|