diff --git a/src/string/src/lib.rs b/src/string/src/lib.rs index cd57b63fbed23fce3f3a589b8c8e7aa0cc03ed2e..dafdceaa70eb073b51e3261b08341bae28395e24 100644 --- a/src/string/src/lib.rs +++ b/src/string/src/lib.rs @@ -11,6 +11,7 @@ use errno::*; use core::cmp; use core::usize; use core::ptr; +use core::mem; #[no_mangle] pub unsafe extern "C" fn memccpy( @@ -32,12 +33,42 @@ pub unsafe extern "C" fn memccpy( #[no_mangle] pub unsafe extern "C" fn memchr(s: *const c_void, c: c_int, n: usize) -> *mut c_void { - let s = s as *mut u8; + let mut s = s as *const u8; let c = c as u8; - for i in 0..n { - if *s.offset(i as isize) == c { - return s.offset(i as isize) as *mut c_void; + let mut n = n; + // read one byte at a time until s is aligned + while s as usize % mem::size_of::<usize>() != 0 { + if n == 0 { + return ptr::null_mut(); + } + if *s == c { + return s as *mut c_void; + } + n -= 1; + s = s.offset(1); + } + let mut s = s as *const usize; + let lowbits = !0 as usize / 255; + let highbits = lowbits * 0x80; + let repeated_c = lowbits * c as usize; + while n >= mem::size_of::<usize>() { + // read multiple bytes at a time + // turn the requested byte into 8 zero bits + let m = *s ^ repeated_c; + // subtracting one from zero flips high bit from 0 to 1 + if (m.wrapping_sub(lowbits) & !m & highbits) != 0 { + break; } + n -= mem::size_of::<usize>(); + s = s.offset(1); + } + let mut s = s as *const u8; + while n > 0 { + if *s == c { + return s as *mut c_void; + } + n -= 1; + s = s.offset(1); } ptr::null_mut() } @@ -131,8 +162,6 @@ pub unsafe extern "C" fn strcpy(s1: *mut c_char, s2: *const c_char) -> *mut c_ch #[no_mangle] pub unsafe extern "C" fn strcspn(s1: *const c_char, s2: *const c_char) -> size_t { - use core::mem; - let s1 = s1 as *const u8; let s2 = s2 as *const u8; @@ -288,8 +317,6 @@ pub unsafe extern "C" fn strrchr(s: *const c_char, c: c_int) -> *mut c_char { #[no_mangle] pub unsafe extern "C" fn strspn(s1: *const c_char, s2: *const c_char) -> size_t { - use core::mem; - let s1 = s1 as *const u8; let s2 = s2 as *const u8;