oj 3.13.13 → 3.13.16
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 +12 -0
- data/ext/oj/compat.c +10 -10
- data/ext/oj/custom.c +6 -6
- data/ext/oj/dump.c +22 -12
- 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/object.c +9 -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/parser.c +32 -4
- data/ext/oj/parser.h +1 -0
- data/ext/oj/rails.c +0 -5
- data/ext/oj/saj2.c +299 -45
- data/ext/oj/sparse.c +4 -0
- data/ext/oj/strict.c +13 -13
- data/ext/oj/wab.c +13 -18
- data/lib/oj/saj.rb +20 -6
- 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_parser_saj.rb +55 -2
- data/test/test_various.rb +6 -0
- metadata +8 -116
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/parser.c
CHANGED
@@ -533,6 +533,7 @@ static void calc_num(ojParser p) {
|
|
533
533
|
// nothing to do
|
534
534
|
break;
|
535
535
|
}
|
536
|
+
p->type = OJ_NONE;
|
536
537
|
}
|
537
538
|
|
538
539
|
static void big_change(ojParser p) {
|
@@ -598,6 +599,8 @@ static void parse(ojParser p, const byte *json) {
|
|
598
599
|
const byte *b = json;
|
599
600
|
int i;
|
600
601
|
|
602
|
+
p->line = 1;
|
603
|
+
p->col = -1;
|
601
604
|
#if DEBUG
|
602
605
|
printf("*** parse - mode: %c %s\n", p->map[256], (const char *)json);
|
603
606
|
#endif
|
@@ -652,6 +655,7 @@ static void parse(ojParser p, const byte *json) {
|
|
652
655
|
}
|
653
656
|
buf_append_string(&p->buf, (const char *)start, b - start);
|
654
657
|
if ('"' == *b) {
|
658
|
+
p->cur = b - json;
|
655
659
|
p->funcs[p->stack[p->depth]].add_str(p);
|
656
660
|
p->map = (0 == p->depth) ? value_map : after_map;
|
657
661
|
break;
|
@@ -661,12 +665,14 @@ static void parse(ojParser p, const byte *json) {
|
|
661
665
|
p->next_map = (0 == p->depth) ? value_map : after_map;
|
662
666
|
break;
|
663
667
|
case OPEN_OBJECT:
|
668
|
+
p->cur = b - json;
|
664
669
|
p->funcs[p->stack[p->depth]].open_object(p);
|
665
670
|
p->depth++;
|
666
671
|
p->stack[p->depth] = OBJECT_FUN;
|
667
672
|
p->map = key1_map;
|
668
673
|
break;
|
669
674
|
case NUM_CLOSE_OBJECT:
|
675
|
+
p->cur = b - json;
|
670
676
|
calc_num(p);
|
671
677
|
// flow through
|
672
678
|
case CLOSE_OBJECT:
|
@@ -677,15 +683,18 @@ static void parse(ojParser p, const byte *json) {
|
|
677
683
|
return;
|
678
684
|
}
|
679
685
|
p->depth--;
|
686
|
+
p->cur = b - json;
|
680
687
|
p->funcs[p->stack[p->depth]].close_object(p);
|
681
688
|
break;
|
682
689
|
case OPEN_ARRAY:
|
690
|
+
p->cur = b - json;
|
683
691
|
p->funcs[p->stack[p->depth]].open_array(p);
|
684
692
|
p->depth++;
|
685
693
|
p->stack[p->depth] = ARRAY_FUN;
|
686
694
|
p->map = value_map;
|
687
695
|
break;
|
688
696
|
case NUM_CLOSE_ARRAY:
|
697
|
+
p->cur = b - json;
|
689
698
|
calc_num(p);
|
690
699
|
// flow through
|
691
700
|
case CLOSE_ARRAY:
|
@@ -696,9 +705,11 @@ static void parse(ojParser p, const byte *json) {
|
|
696
705
|
return;
|
697
706
|
}
|
698
707
|
p->depth--;
|
708
|
+
p->cur = b - json;
|
699
709
|
p->funcs[p->stack[p->depth]].close_array(p);
|
700
710
|
break;
|
701
711
|
case NUM_COMMA:
|
712
|
+
p->cur = b - json;
|
702
713
|
calc_num(p);
|
703
714
|
if (0 < p->depth && OBJECT_FUN == p->stack[p->depth]) {
|
704
715
|
p->map = key_map;
|
@@ -860,8 +871,14 @@ static void parse(ojParser p, const byte *json) {
|
|
860
871
|
b--;
|
861
872
|
p->map = big_exp_map;
|
862
873
|
break;
|
863
|
-
case NUM_SPC:
|
864
|
-
|
874
|
+
case NUM_SPC:
|
875
|
+
p->cur = b - json;
|
876
|
+
calc_num(p);
|
877
|
+
break;
|
878
|
+
case NUM_NEWLINE:
|
879
|
+
p->cur = b - json;
|
880
|
+
calc_num(p);
|
881
|
+
b++;
|
865
882
|
#ifdef SPACE_JUMP
|
866
883
|
// for (uint32_t *sj = (uint32_t*)b; 0x20202020 == *sj; sj++) { b += 4; }
|
867
884
|
for (uint16_t *sj = (uint16_t *)b; 0x2020 == *sj; sj++) {
|
@@ -882,6 +899,7 @@ static void parse(ojParser p, const byte *json) {
|
|
882
899
|
buf_append_string(&p->buf, (const char *)start, b - start);
|
883
900
|
}
|
884
901
|
if ('"' == *b) {
|
902
|
+
p->cur = b - json;
|
885
903
|
p->funcs[p->stack[p->depth]].add_str(p);
|
886
904
|
p->map = p->next_map;
|
887
905
|
break;
|
@@ -890,6 +908,7 @@ static void parse(ojParser p, const byte *json) {
|
|
890
908
|
break;
|
891
909
|
case STR_SLASH: p->map = esc_map; break;
|
892
910
|
case STR_QUOTE:
|
911
|
+
p->cur = b - json;
|
893
912
|
p->funcs[p->stack[p->depth]].add_str(p);
|
894
913
|
p->map = p->next_map;
|
895
914
|
break;
|
@@ -967,6 +986,7 @@ static void parse(ojParser p, const byte *json) {
|
|
967
986
|
case VAL_NULL:
|
968
987
|
if ('u' == b[1] && 'l' == b[2] && 'l' == b[3]) {
|
969
988
|
b += 3;
|
989
|
+
p->cur = b - json;
|
970
990
|
p->funcs[p->stack[p->depth]].add_null(p);
|
971
991
|
p->map = (0 == p->depth) ? value_map : after_map;
|
972
992
|
break;
|
@@ -992,6 +1012,7 @@ static void parse(ojParser p, const byte *json) {
|
|
992
1012
|
case VAL_TRUE:
|
993
1013
|
if ('r' == b[1] && 'u' == b[2] && 'e' == b[3]) {
|
994
1014
|
b += 3;
|
1015
|
+
p->cur = b - json;
|
995
1016
|
p->funcs[p->stack[p->depth]].add_true(p);
|
996
1017
|
p->map = (0 == p->depth) ? value_map : after_map;
|
997
1018
|
break;
|
@@ -1017,6 +1038,7 @@ static void parse(ojParser p, const byte *json) {
|
|
1017
1038
|
case VAL_FALSE:
|
1018
1039
|
if ('a' == b[1] && 'l' == b[2] && 's' == b[3] && 'e' == b[4]) {
|
1019
1040
|
b += 4;
|
1041
|
+
p->cur = b - json;
|
1020
1042
|
p->funcs[p->stack[p->depth]].add_false(p);
|
1021
1043
|
p->map = (0 == p->depth) ? value_map : after_map;
|
1022
1044
|
break;
|
@@ -1050,6 +1072,7 @@ static void parse(ojParser p, const byte *json) {
|
|
1050
1072
|
parse_error(p, "expected null");
|
1051
1073
|
return;
|
1052
1074
|
}
|
1075
|
+
p->cur = b - json;
|
1053
1076
|
p->funcs[p->stack[p->depth]].add_null(p);
|
1054
1077
|
p->map = (0 == p->depth) ? value_map : after_map;
|
1055
1078
|
}
|
@@ -1061,6 +1084,7 @@ static void parse(ojParser p, const byte *json) {
|
|
1061
1084
|
parse_error(p, "expected false");
|
1062
1085
|
return;
|
1063
1086
|
}
|
1087
|
+
p->cur = b - json;
|
1064
1088
|
p->funcs[p->stack[p->depth]].add_false(p);
|
1065
1089
|
p->map = (0 == p->depth) ? value_map : after_map;
|
1066
1090
|
}
|
@@ -1072,6 +1096,7 @@ static void parse(ojParser p, const byte *json) {
|
|
1072
1096
|
parse_error(p, "expected true");
|
1073
1097
|
return;
|
1074
1098
|
}
|
1099
|
+
p->cur = b - json;
|
1075
1100
|
p->funcs[p->stack[p->depth]].add_true(p);
|
1076
1101
|
p->map = (0 == p->depth) ? value_map : after_map;
|
1077
1102
|
}
|
@@ -1099,7 +1124,10 @@ static void parse(ojParser p, const byte *json) {
|
|
1099
1124
|
case 'D':
|
1100
1125
|
case 'g':
|
1101
1126
|
case 'B':
|
1102
|
-
case 'Y':
|
1127
|
+
case 'Y':
|
1128
|
+
p->cur = b - json;
|
1129
|
+
calc_num(p);
|
1130
|
+
break;
|
1103
1131
|
}
|
1104
1132
|
}
|
1105
1133
|
return;
|
@@ -1456,7 +1484,7 @@ static VALUE saj_parser = Qundef;
|
|
1456
1484
|
/* Document-method: saj
|
1457
1485
|
* call-seq: saj
|
1458
1486
|
*
|
1459
|
-
* Returns the default
|
1487
|
+
* Returns the default SAJ parser. Note the default SAJ parser can not be used
|
1460
1488
|
* concurrently in more than one thread.
|
1461
1489
|
*/
|
1462
1490
|
static VALUE parser_saj(VALUE self) {
|
data/ext/oj/parser.h
CHANGED
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
|
|