22// Copyright 2023-2024 liuq19, ijl
33// adapted from sonic-rs' src/util/string.rs
44
5+ use crate :: typeref:: PAGE_SIZE ;
56use core:: simd:: cmp:: { SimdPartialEq , SimdPartialOrd } ;
67
78macro_rules! impl_escape_unchecked {
89 ( $src: expr, $dst: expr, $nb: expr, $omask: expr, $cn: expr) => {
910 $nb -= $cn;
1011 $dst = $dst. add( $cn) ;
1112 $src = $src. add( $cn) ;
12- let mut mask = $omask << $cn;
13+ $omask >>= $cn;
1314 loop {
1415 $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 ) ;
1821 } 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 ) ;
2024 } 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) ;
5626 } ;
57- core:: ptr:: copy_nonoverlapping( replacement. 0 . as_ptr( ) , $dst, 8 ) ;
58- $dst = $dst. add( replacement. 1 as usize ) ;
27+
5928 $src = $src. add( 1 ) ;
60- if likely!( mask & ( 1 << ( STRIDE - 1 ) ) != 1 ) {
29+ if likely!( $omask & 1 != 1 ) {
6130 break ;
6231 }
6332 }
6433 } ;
6534}
35+
6636macro_rules! impl_format_simd {
6737 ( $odptr: expr, $value_ptr: expr, $value_len: expr) => {
6838 let mut dptr = $odptr;
@@ -81,7 +51,7 @@ macro_rules! impl_format_simd {
8151 while nb >= STRIDE {
8252 let v = StrVector :: from_slice( core:: slice:: from_raw_parts( sptr, STRIDE ) ) ;
8353 v. copy_to_slice( core:: slice:: from_raw_parts_mut( dptr, STRIDE ) ) ;
84- let mask =
54+ let mut mask =
8555 ( v. simd_eq( blash) | v. simd_eq( quote) | v. simd_lt( x20) ) . to_bitmask( ) as u32 ;
8656
8757 if likely!( mask == 0 ) {
@@ -95,12 +65,18 @@ macro_rules! impl_format_simd {
9565 }
9666
9767 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+ } ;
10075 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( )
10277 as u32
103- & ( STRIDE_SATURATION >> ( STRIDE - nb) ) ;
78+ & ( STRIDE_SATURATION >> ( 32 - STRIDE - nb) ) ;
79+
10480 if likely!( mask == 0 ) {
10581 dptr = dptr. add( nb) ;
10682 break ;
@@ -118,6 +94,57 @@ macro_rules! impl_format_simd {
11894 } ;
11995}
12096
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+
121148#[ inline( never) ]
122149pub unsafe fn format_escaped_str_impl_128 (
123150 odptr : * mut u8 ,
0 commit comments