@@ -81,20 +81,54 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind {
81
81
}
82
82
}
83
83
84
- pub fn wmemchr ( needle : u16 , haystack : & [ u16 ] ) -> Option < usize > {
85
- extern "C" {
86
- fn wmemchr ( s : * const u16 , c : u16 , n : usize ) -> * mut u16 ;
87
- }
88
- let len = haystack. len ( ) ;
84
+ pub fn unrolled_find_u16s ( needle : u16 , haystack : & [ u16 ] ) -> Option < usize > {
89
85
let ptr = haystack. as_ptr ( ) ;
90
- let p = unsafe { wmemchr ( ptr, needle, len) } ;
91
- if p. is_null ( ) { None } else { Some ( ( p as usize - ptr as usize ) / 2 ) }
86
+ let mut len = haystack. len ( ) ;
87
+ let mut start = & haystack[ ..] ;
88
+
89
+ // For performance reasons unfold the loop eight times.
90
+ while len >= 8 {
91
+ if start[ 0 ] == needle {
92
+ return Some ( ( start. as_ptr ( ) as usize - ptr as usize ) / 2 ) ;
93
+ }
94
+ if start[ 1 ] == needle {
95
+ return Some ( ( start[ 1 ..] . as_ptr ( ) as usize - ptr as usize ) / 2 ) ;
96
+ }
97
+ if start[ 2 ] == needle {
98
+ return Some ( ( start[ 2 ..] . as_ptr ( ) as usize - ptr as usize ) / 2 ) ;
99
+ }
100
+ if start[ 3 ] == needle {
101
+ return Some ( ( start[ 3 ..] . as_ptr ( ) as usize - ptr as usize ) / 2 ) ;
102
+ }
103
+ if start[ 4 ] == needle {
104
+ return Some ( ( start[ 4 ..] . as_ptr ( ) as usize - ptr as usize ) / 2 ) ;
105
+ }
106
+ if start[ 5 ] == needle {
107
+ return Some ( ( start[ 5 ..] . as_ptr ( ) as usize - ptr as usize ) / 2 ) ;
108
+ }
109
+ if start[ 6 ] == needle {
110
+ return Some ( ( start[ 6 ..] . as_ptr ( ) as usize - ptr as usize ) / 2 ) ;
111
+ }
112
+ if start[ 7 ] == needle {
113
+ return Some ( ( start[ 7 ..] . as_ptr ( ) as usize - ptr as usize ) / 2 ) ;
114
+ }
115
+
116
+ start = & start[ 8 ..] ;
117
+ len -= 8 ;
118
+ }
119
+
120
+ for ( i, c) in start. iter ( ) . enumerate ( ) {
121
+ if * c == needle {
122
+ return Some ( ( start. as_ptr ( ) as usize - ptr as usize ) / 2 + i) ;
123
+ }
124
+ }
125
+ None
92
126
}
93
127
94
128
pub fn to_u16s < S : AsRef < OsStr > > ( s : S ) -> crate :: io:: Result < Vec < u16 > > {
95
129
fn inner ( s : & OsStr ) -> crate :: io:: Result < Vec < u16 > > {
96
130
let mut maybe_result: Vec < u16 > = s. encode_wide ( ) . collect ( ) ;
97
- if wmemchr ( 0 , & maybe_result) . is_some ( ) {
131
+ if unrolled_find_u16s ( 0 , & maybe_result) . is_some ( ) {
98
132
return Err ( crate :: io:: Error :: new (
99
133
ErrorKind :: InvalidInput ,
100
134
"strings passed to WinAPI cannot contain NULs" ,
@@ -224,7 +258,7 @@ fn wide_char_to_multi_byte(
224
258
}
225
259
226
260
pub fn truncate_utf16_at_nul ( v : & [ u16 ] ) -> & [ u16 ] {
227
- match wmemchr ( 0 , v) {
261
+ match unrolled_find_u16s ( 0 , v) {
228
262
// don't include the 0
229
263
Some ( i) => & v[ ..i] ,
230
264
None => v,
0 commit comments