2
2
// Copyright 2023-2024 liuq19, ijl
3
3
// adapted from sonic-rs' src/util/string.rs
4
4
5
+ use crate :: typeref:: PAGE_SIZE ;
5
6
use core:: simd:: cmp:: { SimdPartialEq , SimdPartialOrd } ;
6
7
7
8
macro_rules! impl_escape_unchecked {
8
9
( $src: expr, $dst: expr, $nb: expr, $omask: expr, $cn: expr) => {
9
10
$nb -= $cn;
10
11
$dst = $dst. add( $cn) ;
11
12
$src = $src. add( $cn) ;
12
- let mut mask = $omask << $cn;
13
+ $omask >>= $cn;
13
14
loop {
14
15
$nb -= 1 ;
15
- mask = mask << 1 ;
16
- let replacement = if * ( $src) == b'"' {
17
- ( * b"\\ \" \0 \0 \0 \0 \0 \0 " , 2 )
16
+ $omask = $omask >> 1 ;
17
+
18
+ if * ( $src) == b'"' {
19
+ core:: ptr:: copy_nonoverlapping( b"\\ \" " . as_ptr( ) , $dst, 2 ) ;
20
+ $dst = $dst. add( 2 ) ;
18
21
} else if * ( $src) == b'\\' {
19
- ( * b"\\ \\ \0 \0 \0 \0 \0 \0 " , 2 )
22
+ core:: ptr:: copy_nonoverlapping( b"\\ \\ " . as_ptr( ) , $dst, 2 ) ;
23
+ $dst = $dst. add( 2 ) ;
20
24
} else {
21
- match * ( $src) {
22
- 0 => ( * b"\\ u0000\0 \0 " , 6 ) ,
23
- 1 => ( * b"\\ u0001\0 \0 " , 6 ) ,
24
- 2 => ( * b"\\ u0002\0 \0 " , 6 ) ,
25
- 3 => ( * b"\\ u0003\0 \0 " , 6 ) ,
26
- 4 => ( * b"\\ u0004\0 \0 " , 6 ) ,
27
- 5 => ( * b"\\ u0005\0 \0 " , 6 ) ,
28
- 6 => ( * b"\\ u0006\0 \0 " , 6 ) ,
29
- 7 => ( * b"\\ u0007\0 \0 " , 6 ) ,
30
- 8 => ( * b"\\ b\0 \0 \0 \0 \0 \0 " , 2 ) ,
31
- 9 => ( * b"\\ t\0 \0 \0 \0 \0 \0 " , 2 ) ,
32
- 10 => ( * b"\\ n\0 \0 \0 \0 \0 \0 " , 2 ) ,
33
- 11 => ( * b"\\ u000b\0 \0 " , 6 ) ,
34
- 12 => ( * b"\\ f\0 \0 \0 \0 \0 \0 " , 2 ) ,
35
- 13 => ( * b"\\ r\0 \0 \0 \0 \0 \0 " , 2 ) ,
36
- 14 => ( * b"\\ u000e\0 \0 " , 6 ) ,
37
- 15 => ( * b"\\ u000f\0 \0 " , 6 ) ,
38
- 16 => ( * b"\\ u0010\0 \0 " , 6 ) ,
39
- 17 => ( * b"\\ u0011\0 \0 " , 6 ) ,
40
- 18 => ( * b"\\ u0012\0 \0 " , 6 ) ,
41
- 19 => ( * b"\\ u0013\0 \0 " , 6 ) ,
42
- 20 => ( * b"\\ u0014\0 \0 " , 6 ) ,
43
- 21 => ( * b"\\ u0015\0 \0 " , 6 ) ,
44
- 22 => ( * b"\\ u0016\0 \0 " , 6 ) ,
45
- 23 => ( * b"\\ u0017\0 \0 " , 6 ) ,
46
- 24 => ( * b"\\ u0018\0 \0 " , 6 ) ,
47
- 25 => ( * b"\\ u0019\0 \0 " , 6 ) ,
48
- 26 => ( * b"\\ u001a\0 \0 " , 6 ) ,
49
- 27 => ( * b"\\ u001b\0 \0 " , 6 ) ,
50
- 28 => ( * b"\\ u001c\0 \0 " , 6 ) ,
51
- 29 => ( * b"\\ u001d\0 \0 " , 6 ) ,
52
- 30 => ( * b"\\ u001e\0 \0 " , 6 ) ,
53
- 31 => ( * b"\\ u001f\0 \0 " , 6 ) ,
54
- _ => unreachable!( ) ,
55
- }
25
+ $dst = write_unusual_escape( $src, $dst) ;
56
26
} ;
57
- core:: ptr:: copy_nonoverlapping( replacement. 0 . as_ptr( ) , $dst, 8 ) ;
58
- $dst = $dst. add( replacement. 1 as usize ) ;
27
+
59
28
$src = $src. add( 1 ) ;
60
- if likely!( mask & ( 1 << ( STRIDE - 1 ) ) != 1 ) {
29
+ if likely!( $omask & 1 != 1 ) {
61
30
break ;
62
31
}
63
32
}
64
33
} ;
65
34
}
35
+
66
36
macro_rules! impl_format_simd {
67
37
( $odptr: expr, $value_ptr: expr, $value_len: expr) => {
68
38
let mut dptr = $odptr;
@@ -81,7 +51,7 @@ macro_rules! impl_format_simd {
81
51
while nb >= STRIDE {
82
52
let v = StrVector :: from_slice( core:: slice:: from_raw_parts( sptr, STRIDE ) ) ;
83
53
v. copy_to_slice( core:: slice:: from_raw_parts_mut( dptr, STRIDE ) ) ;
84
- let mask =
54
+ let mut mask =
85
55
( v. simd_eq( blash) | v. simd_eq( quote) | v. simd_lt( x20) ) . to_bitmask( ) as u32 ;
86
56
87
57
if likely!( mask == 0 ) {
@@ -95,12 +65,18 @@ macro_rules! impl_format_simd {
95
65
}
96
66
97
67
while nb > 0 {
98
- let mut v = StrVector :: default ( ) ;
99
- v. as_mut_array( ) [ ..nb] . copy_from_slice( core:: slice:: from_raw_parts( sptr, nb) ) ;
68
+ let v = if unlikely!( is_cross_page!( sptr) ) {
69
+ let mut v = StrVector :: default ( ) ;
70
+ v. as_mut_array( ) [ ..nb] . copy_from_slice( core:: slice:: from_raw_parts( sptr, nb) ) ;
71
+ v
72
+ } else {
73
+ StrVector :: from_slice( core:: slice:: from_raw_parts( sptr, STRIDE ) )
74
+ } ;
100
75
v. copy_to_slice( core:: slice:: from_raw_parts_mut( dptr, STRIDE ) ) ;
101
- let mask = ( v. simd_eq( blash) | v. simd_eq( quote) | v. simd_lt( x20) ) . to_bitmask( )
76
+ let mut mask = ( v. simd_eq( blash) | v. simd_eq( quote) | v. simd_lt( x20) ) . to_bitmask( )
102
77
as u32
103
- & ( STRIDE_SATURATION >> ( STRIDE - nb) ) ;
78
+ & ( STRIDE_SATURATION >> ( 32 - STRIDE - nb) ) ;
79
+
104
80
if likely!( mask == 0 ) {
105
81
dptr = dptr. add( nb) ;
106
82
break ;
@@ -118,6 +94,57 @@ macro_rules! impl_format_simd {
118
94
} ;
119
95
}
120
96
97
+ macro_rules! is_cross_page {
98
+ ( $src: expr) => {
99
+ unsafe { ( ( $src as usize & ( PAGE_SIZE - 1 ) ) + STRIDE ) > PAGE_SIZE }
100
+ } ;
101
+ }
102
+
103
+ #[ cold]
104
+ #[ inline( never) ]
105
+ fn write_unusual_escape ( sptr : * const u8 , dptr : * mut u8 ) -> * mut u8 {
106
+ unsafe {
107
+ debug_assert ! ( * sptr < 32 ) ;
108
+ let replacement = match * ( sptr) {
109
+ 0 => ( * b"\\ u0000\0 \0 " , 6 ) ,
110
+ 1 => ( * b"\\ u0001\0 \0 " , 6 ) ,
111
+ 2 => ( * b"\\ u0002\0 \0 " , 6 ) ,
112
+ 3 => ( * b"\\ u0003\0 \0 " , 6 ) ,
113
+ 4 => ( * b"\\ u0004\0 \0 " , 6 ) ,
114
+ 5 => ( * b"\\ u0005\0 \0 " , 6 ) ,
115
+ 6 => ( * b"\\ u0006\0 \0 " , 6 ) ,
116
+ 7 => ( * b"\\ u0007\0 \0 " , 6 ) ,
117
+ 8 => ( * b"\\ b\0 \0 \0 \0 \0 \0 " , 2 ) ,
118
+ 9 => ( * b"\\ t\0 \0 \0 \0 \0 \0 " , 2 ) ,
119
+ 10 => ( * b"\\ n\0 \0 \0 \0 \0 \0 " , 2 ) ,
120
+ 11 => ( * b"\\ u000b\0 \0 " , 6 ) ,
121
+ 12 => ( * b"\\ f\0 \0 \0 \0 \0 \0 " , 2 ) ,
122
+ 13 => ( * b"\\ r\0 \0 \0 \0 \0 \0 " , 2 ) ,
123
+ 14 => ( * b"\\ u000e\0 \0 " , 6 ) ,
124
+ 15 => ( * b"\\ u000f\0 \0 " , 6 ) ,
125
+ 16 => ( * b"\\ u0010\0 \0 " , 6 ) ,
126
+ 17 => ( * b"\\ u0011\0 \0 " , 6 ) ,
127
+ 18 => ( * b"\\ u0012\0 \0 " , 6 ) ,
128
+ 19 => ( * b"\\ u0013\0 \0 " , 6 ) ,
129
+ 20 => ( * b"\\ u0014\0 \0 " , 6 ) ,
130
+ 21 => ( * b"\\ u0015\0 \0 " , 6 ) ,
131
+ 22 => ( * b"\\ u0016\0 \0 " , 6 ) ,
132
+ 23 => ( * b"\\ u0017\0 \0 " , 6 ) ,
133
+ 24 => ( * b"\\ u0018\0 \0 " , 6 ) ,
134
+ 25 => ( * b"\\ u0019\0 \0 " , 6 ) ,
135
+ 26 => ( * b"\\ u001a\0 \0 " , 6 ) ,
136
+ 27 => ( * b"\\ u001b\0 \0 " , 6 ) ,
137
+ 28 => ( * b"\\ u001c\0 \0 " , 6 ) ,
138
+ 29 => ( * b"\\ u001d\0 \0 " , 6 ) ,
139
+ 30 => ( * b"\\ u001e\0 \0 " , 6 ) ,
140
+ 31 => ( * b"\\ u001f\0 \0 " , 6 ) ,
141
+ _ => unreachable ! ( ) ,
142
+ } ;
143
+ core:: ptr:: copy_nonoverlapping ( replacement. 0 . as_ptr ( ) , dptr, 8 ) ;
144
+ dptr. add ( replacement. 1 as usize )
145
+ }
146
+ }
147
+
121
148
#[ inline( never) ]
122
149
pub unsafe fn format_escaped_str_impl_128 (
123
150
odptr : * mut u8 ,
0 commit comments