Skip to content

Commit 442ae6b

Browse files
committed
Fix a bug in memrnchr
The bytes check was incorrect, leading to bugs in some cases.
1 parent a004e24 commit 442ae6b

File tree

1 file changed

+2
-23
lines changed

1 file changed

+2
-23
lines changed

src/memrnchr.rs

Lines changed: 2 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,6 @@
33
// We use this mainly to skip repeated `/`. If there is only one slash, `memrnchr` performs the same
44
// as a naive version (e.g. `rposition`). However, it is much faster in pathological cases.
55

6-
const LO_U64: u64 = 0x0101010101010101;
7-
const HI_U64: u64 = 0x8080808080808080;
8-
9-
// use truncation
10-
const LO_USIZE: usize = LO_U64 as usize;
11-
const HI_USIZE: usize = HI_U64 as usize;
12-
136
#[cfg(target_pointer_width = "32")]
147
const USIZE_BYTES: usize = 4;
158
#[cfg(target_pointer_width = "64")]
@@ -49,10 +42,8 @@ pub fn memrnchr(x: u8, text: &[u8]) -> Option<usize> {
4942
let u = *(ptr.offset(offset as isize - 2 * USIZE_BYTES as isize) as *const usize);
5043
let v = *(ptr.offset(offset as isize - USIZE_BYTES as isize) as *const usize);
5144

52-
// break if there is a matching byte
53-
let zu = contains_zero_byte(u ^ repeated_x);
54-
let zv = contains_zero_byte(v ^ repeated_x);
55-
if !zu || !zv {
45+
// break if there is no matching byte
46+
if u & repeated_x != usize::max_value() || v & repeated_x != usize::max_value() {
5647
break;
5748
}
5849
}
@@ -63,18 +54,6 @@ pub fn memrnchr(x: u8, text: &[u8]) -> Option<usize> {
6354
text[..offset].iter().rposition(|elt| *elt != x)
6455
}
6556

66-
/// Return `true` if `x` contains any zero byte.
67-
///
68-
/// From *Matters Computational*, J. Arndt
69-
///
70-
/// "The idea is to subtract one from each of the bytes and then look for
71-
/// bytes where the borrow propagated all the way to the most significant
72-
/// bit."
73-
#[inline]
74-
fn contains_zero_byte(x: usize) -> bool {
75-
x.wrapping_sub(LO_USIZE) & !x & HI_USIZE != 0
76-
}
77-
7857
#[cfg(target_pointer_width = "32")]
7958
#[inline]
8059
fn repeat_byte(b: u8) -> usize {

0 commit comments

Comments
 (0)