/// Search for the first occurrence of a byte in a slice. /// /// This returns the index corresponding to the first occurrence of `needle` in /// `haystack`, or `None` if one is not found. If an index is returned, it is /// guaranteed to be less than `haystack.len()`. /// /// While this is semantically the same as something like /// `haystack.iter().position(|&b| b == needle)`, this routine will attempt to /// use highly optimized vector operations that can be an order of magnitude /// faster (or more). /// /// # Example /// /// This shows how to find the first position of a byte in a byte string. /// /// ``` /// use memchr::memchr; /// /// let haystack = b"the quick brown fox"; /// assert_eq!(memchr(b'k', haystack), Some(8)); /// ``` #[inline] pubfn memchr(needle: u8, haystack: &[u8]) -> Option<usize> { // SAFETY: memchr_raw, when a match is found, always returns a valid // pointer between start and end. unsafe {
generic::search_slice_with_raw(haystack, |start, end| {
memchr_raw(needle, start, end)
})
}
}
/// Search for the last occurrence of a byte in a slice. /// /// This returns the index corresponding to the last occurrence of `needle` in /// `haystack`, or `None` if one is not found. If an index is returned, it is /// guaranteed to be less than `haystack.len()`. /// /// While this is semantically the same as something like /// `haystack.iter().rposition(|&b| b == needle)`, this routine will attempt to /// use highly optimized vector operations that can be an order of magnitude /// faster (or more). /// /// # Example /// /// This shows how to find the last position of a byte in a byte string. /// /// ``` /// use memchr::memrchr; /// /// let haystack = b"the quick brown fox"; /// assert_eq!(memrchr(b'o', haystack), Some(17)); /// ``` #[inline] pubfn memrchr(needle: u8, haystack: &[u8]) -> Option<usize> { // SAFETY: memrchr_raw, when a match is found, always returns a valid // pointer between start and end. unsafe {
generic::search_slice_with_raw(haystack, |start, end| {
memrchr_raw(needle, start, end)
})
}
}
/// Search for the first occurrence of two possible bytes in a haystack. /// /// This returns the index corresponding to the first occurrence of one of the /// needle bytes in `haystack`, or `None` if one is not found. If an index is /// returned, it is guaranteed to be less than `haystack.len()`. /// /// While this is semantically the same as something like /// `haystack.iter().position(|&b| b == needle1 || b == needle2)`, this routine /// will attempt to use highly optimized vector operations that can be an order /// of magnitude faster (or more). /// /// # Example /// /// This shows how to find the first position of one of two possible bytes in a /// haystack. /// /// ``` /// use memchr::memchr2; /// /// let haystack = b"the quick brown fox"; /// assert_eq!(memchr2(b'k', b'q', haystack), Some(4)); /// ``` #[inline] pubfn memchr2(needle1: u8, needle2: u8, haystack: &[u8]) -> Option<usize> { // SAFETY: memchr2_raw, when a match is found, always returns a valid // pointer between start and end. unsafe {
generic::search_slice_with_raw(haystack, |start, end| {
memchr2_raw(needle1, needle2, start, end)
})
}
}
/// Search for the last occurrence of two possible bytes in a haystack. /// /// This returns the index corresponding to the last occurrence of one of the /// needle bytes in `haystack`, or `None` if one is not found. If an index is /// returned, it is guaranteed to be less than `haystack.len()`. /// /// While this is semantically the same as something like /// `haystack.iter().rposition(|&b| b == needle1 || b == needle2)`, this /// routine will attempt to use highly optimized vector operations that can be /// an order of magnitude faster (or more). /// /// # Example /// /// This shows how to find the last position of one of two possible bytes in a /// haystack. /// /// ``` /// use memchr::memrchr2; /// /// let haystack = b"the quick brown fox"; /// assert_eq!(memrchr2(b'k', b'o', haystack), Some(17)); /// ``` #[inline] pubfn memrchr2(needle1: u8, needle2: u8, haystack: &[u8]) -> Option<usize> { // SAFETY: memrchr2_raw, when a match is found, always returns a valid // pointer between start and end. unsafe {
generic::search_slice_with_raw(haystack, |start, end| {
memrchr2_raw(needle1, needle2, start, end)
})
}
}
/// Search for the first occurrence of three possible bytes in a haystack. /// /// This returns the index corresponding to the first occurrence of one of the /// needle bytes in `haystack`, or `None` if one is not found. If an index is /// returned, it is guaranteed to be less than `haystack.len()`. /// /// While this is semantically the same as something like /// `haystack.iter().position(|&b| b == needle1 || b == needle2 || b == needle3)`, /// this routine will attempt to use highly optimized vector operations that /// can be an order of magnitude faster (or more). /// /// # Example /// /// This shows how to find the first position of one of three possible bytes in /// a haystack. /// /// ``` /// use memchr::memchr3; /// /// let haystack = b"the quick brown fox"; /// assert_eq!(memchr3(b'k', b'q', b'u', haystack), Some(4)); /// ``` #[inline] pubfn memchr3(
needle1: u8,
needle2: u8,
needle3: u8,
haystack: &[u8],
) -> Option<usize> { // SAFETY: memchr3_raw, when a match is found, always returns a valid // pointer between start and end. unsafe {
generic::search_slice_with_raw(haystack, |start, end| {
memchr3_raw(needle1, needle2, needle3, start, end)
})
}
}
/// Search for the last occurrence of three possible bytes in a haystack. /// /// This returns the index corresponding to the last occurrence of one of the /// needle bytes in `haystack`, or `None` if one is not found. If an index is /// returned, it is guaranteed to be less than `haystack.len()`. /// /// While this is semantically the same as something like /// `haystack.iter().rposition(|&b| b == needle1 || b == needle2 || b == needle3)`, /// this routine will attempt to use highly optimized vector operations that /// can be an order of magnitude faster (or more). /// /// # Example /// /// This shows how to find the last position of one of three possible bytes in /// a haystack. /// /// ``` /// use memchr::memrchr3; /// /// let haystack = b"the quick brown fox"; /// assert_eq!(memrchr3(b'k', b'o', b'n', haystack), Some(17)); /// ``` #[inline] pubfn memrchr3(
needle1: u8,
needle2: u8,
needle3: u8,
haystack: &[u8],
) -> Option<usize> { // SAFETY: memrchr3_raw, when a match is found, always returns a valid // pointer between start and end. unsafe {
generic::search_slice_with_raw(haystack, |start, end| {
memrchr3_raw(needle1, needle2, needle3, start, end)
})
}
}
/// Returns an iterator over all occurrences of the needle in a haystack. /// /// The iterator returned implements `DoubleEndedIterator`. This means it /// can also be used to find occurrences in reverse order. #[inline] pubfn memchr_iter<'h>(needle: u8, haystack: &'h [u8]) -> Memchr<'h> {
Memchr::new(needle, haystack)
}
/// Returns an iterator over all occurrences of the needle in a haystack, in /// reverse. #[inline] pubfn memrchr_iter(needle: u8, haystack: &[u8]) -> Rev<Memchr<'_>> {
Memchr::new(needle, haystack).rev()
}
/// Returns an iterator over all occurrences of the needles in a haystack. /// /// The iterator returned implements `DoubleEndedIterator`. This means it /// can also be used to find occurrences in reverse order. #[inline] pubfn memchr2_iter<'h>(
needle1: u8,
needle2: u8,
haystack: &'h [u8],
) -> Memchr2<'h> {
Memchr2::new(needle1, needle2, haystack)
}
/// Returns an iterator over all occurrences of the needles in a haystack, in /// reverse. #[inline] pubfn memrchr2_iter(
needle1: u8,
needle2: u8,
haystack: &[u8],
) -> Rev<Memchr2<'_>> {
Memchr2::new(needle1, needle2, haystack).rev()
}
/// Returns an iterator over all occurrences of the needles in a haystack. /// /// The iterator returned implements `DoubleEndedIterator`. This means it /// can also be used to find occurrences in reverse order. #[inline] pubfn memchr3_iter<'h>(
needle1: u8,
needle2: u8,
needle3: u8,
haystack: &'h [u8],
) -> Memchr3<'h> {
Memchr3::new(needle1, needle2, needle3, haystack)
}
/// Returns an iterator over all occurrences of the needles in a haystack, in /// reverse. #[inline] pubfn memrchr3_iter(
needle1: u8,
needle2: u8,
needle3: u8,
haystack: &[u8],
) -> Rev<Memchr3<'_>> {
Memchr3::new(needle1, needle2, needle3, haystack).rev()
}
/// An iterator over all occurrences of a single byte in a haystack. /// /// This iterator implements `DoubleEndedIterator`, which means it can also be /// used to find occurrences in reverse order. /// /// This iterator is created by the [`memchr_iter`] or `[memrchr_iter`] /// functions. It can also be created with the [`Memchr::new`] method. /// /// The lifetime parameter `'h` refers to the lifetime of the haystack being /// searched. #[derive(Clone, Debug)] pubstruct Memchr<'h> {
needle1: u8,
it: crate::arch::generic::memchr::Iter<'h>,
}
impl<'h> Memchr<'h> { /// Returns an iterator over all occurrences of the needle byte in the /// given haystack. /// /// The iterator returned implements `DoubleEndedIterator`. This means it /// can also be used to find occurrences in reverse order. #[inline] pubfn new(needle1: u8, haystack: &'h [u8]) -> Memchr<'h> {
Memchr {
needle1,
it: crate::arch::generic::memchr::Iter::new(haystack),
}
}
}
impl<'h> Iterator for Memchr<'h> { type Item = usize;
#[inline] fn next(&mutself) -> Option<usize> { // SAFETY: All of our implementations of memchr ensure that any // pointers returns will fall within the start and end bounds, and this // upholds the safety contract of `self.it.next`. unsafe { // NOTE: I attempted to define an enum of previously created // searchers and then switch on those here instead of just // calling `memchr_raw` (or `One::new(..).find_raw(..)`). But // that turned out to have a fair bit of extra overhead when // searching very small haystacks. self.it.next(|s, e| memchr_raw(self.needle1, s, e))
}
}
#[inline] fn count(self) -> usize { self.it.count(|s, e| { // SAFETY: We rely on our generic iterator to return valid start // and end pointers. unsafe { count_raw(self.needle1, s, e) }
})
}
impl<'h> DoubleEndedIterator for Memchr<'h> { #[inline] fn next_back(&mutself) -> Option<usize> { // SAFETY: All of our implementations of memchr ensure that any // pointers returns will fall within the start and end bounds, and this // upholds the safety contract of `self.it.next_back`. unsafe { self.it.next_back(|s, e| memrchr_raw(self.needle1, s, e)) }
}
}
impl<'h> core::iter::FusedIterator for Memchr<'h> {}
/// An iterator over all occurrences of two possible bytes in a haystack. /// /// This iterator implements `DoubleEndedIterator`, which means it can also be /// used to find occurrences in reverse order. /// /// This iterator is created by the [`memchr2_iter`] or `[memrchr2_iter`] /// functions. It can also be created with the [`Memchr2::new`] method. /// /// The lifetime parameter `'h` refers to the lifetime of the haystack being /// searched. #[derive(Clone, Debug)] pubstruct Memchr2<'h> {
needle1: u8,
needle2: u8,
it: crate::arch::generic::memchr::Iter<'h>,
}
impl<'h> Memchr2<'h> { /// Returns an iterator over all occurrences of the needle bytes in the /// given haystack. /// /// The iterator returned implements `DoubleEndedIterator`. This means it /// can also be used to find occurrences in reverse order. #[inline] pubfn new(needle1: u8, needle2: u8, haystack: &'h [u8]) -> Memchr2<'h> {
Memchr2 {
needle1,
needle2,
it: crate::arch::generic::memchr::Iter::new(haystack),
}
}
}
impl<'h> Iterator for Memchr2<'h> { type Item = usize;
#[inline] fn next(&mutself) -> Option<usize> { // SAFETY: All of our implementations of memchr ensure that any // pointers returns will fall within the start and end bounds, and this // upholds the safety contract of `self.it.next`. unsafe { self.it.next(|s, e| memchr2_raw(self.needle1, self.needle2, s, e))
}
}
impl<'h> DoubleEndedIterator for Memchr2<'h> { #[inline] fn next_back(&mutself) -> Option<usize> { // SAFETY: All of our implementations of memchr ensure that any // pointers returns will fall within the start and end bounds, and this // upholds the safety contract of `self.it.next_back`. unsafe { self.it.next_back(|s, e| {
memrchr2_raw(self.needle1, self.needle2, s, e)
})
}
}
}
impl<'h> core::iter::FusedIterator for Memchr2<'h> {}
/// An iterator over all occurrences of three possible bytes in a haystack. /// /// This iterator implements `DoubleEndedIterator`, which means it can also be /// used to find occurrences in reverse order. /// /// This iterator is created by the [`memchr2_iter`] or `[memrchr2_iter`] /// functions. It can also be created with the [`Memchr3::new`] method. /// /// The lifetime parameter `'h` refers to the lifetime of the haystack being /// searched. #[derive(Clone, Debug)] pubstruct Memchr3<'h> {
needle1: u8,
needle2: u8,
needle3: u8,
it: crate::arch::generic::memchr::Iter<'h>,
}
impl<'h> Memchr3<'h> { /// Returns an iterator over all occurrences of the needle bytes in the /// given haystack. /// /// The iterator returned implements `DoubleEndedIterator`. This means it /// can also be used to find occurrences in reverse order. #[inline] pubfn new(
needle1: u8,
needle2: u8,
needle3: u8,
haystack: &'h [u8],
) -> Memchr3<'h> {
Memchr3 {
needle1,
needle2,
needle3,
it: crate::arch::generic::memchr::Iter::new(haystack),
}
}
}
impl<'h> Iterator for Memchr3<'h> { type Item = usize;
#[inline] fn next(&mutself) -> Option<usize> { // SAFETY: All of our implementations of memchr ensure that any // pointers returns will fall within the start and end bounds, and this // upholds the safety contract of `self.it.next`. unsafe { self.it.next(|s, e| {
memchr3_raw(self.needle1, self.needle2, self.needle3, s, e)
})
}
}
impl<'h> DoubleEndedIterator for Memchr3<'h> { #[inline] fn next_back(&mutself) -> Option<usize> { // SAFETY: All of our implementations of memchr ensure that any // pointers returns will fall within the start and end bounds, and this // upholds the safety contract of `self.it.next_back`. unsafe { self.it.next_back(|s, e| {
memrchr3_raw(self.needle1, self.needle2, self.needle3, s, e)
})
}
}
}
impl<'h> core::iter::FusedIterator for Memchr3<'h> {}
/// memchr, but using raw pointers to represent the haystack. /// /// # Safety /// /// Pointers must be valid. See `One::find_raw`. #[inline] unsafefn memchr_raw(
needle: u8,
start: *const u8,
end: *const u8,
) -> Option<*const u8> { #[cfg(target_arch = "x86_64")]
{ // x86_64 does CPU feature detection at runtime in order to use AVX2 // instructions even when the `avx2` feature isn't enabled at compile // time. This function also handles using a fallback if neither AVX2 // nor SSE2 (unusual) are available. crate::arch::x86_64::memchr::memchr_raw(needle, start, end)
} #[cfg(all(target_arch = "wasm32", target_feature = "simd128"))]
{ crate::arch::wasm32::memchr::memchr_raw(needle, start, end)
} #[cfg(target_arch = "aarch64")]
{ crate::arch::aarch64::memchr::memchr_raw(needle, start, end)
} #[cfg(not(any(
target_arch = "x86_64",
all(target_arch = "wasm32", target_feature = "simd128"),
target_arch = "aarch64"
)))]
{ crate::arch::all::memchr::One::new(needle).find_raw(start, end)
}
}
#[test] fn forward3_iter() { crate::tests::memchr::Runner::new(3).forward_iter(
|haystack, needles| { let n1 = needles.get(0).copied()?; let n2 = needles.get(1).copied()?; let n3 = needles.get(2).copied()?;
Some(memchr3_iter(n1, n2, n3, haystack).collect())
},
)
}
#[test] fn forward3_oneshot() { crate::tests::memchr::Runner::new(3).forward_oneshot(
|haystack, needles| { let n1 = needles.get(0).copied()?; let n2 = needles.get(1).copied()?; let n3 = needles.get(2).copied()?;
Some(memchr3(n1, n2, n3, haystack))
},
)
}
#[test] fn reverse3_iter() { crate::tests::memchr::Runner::new(3).reverse_iter(
|haystack, needles| { let n1 = needles.get(0).copied()?; let n2 = needles.get(1).copied()?; let n3 = needles.get(2).copied()?;
Some(memrchr3_iter(n1, n2, n3, haystack).collect())
},
)
}
#[test] fn reverse3_oneshot() { crate::tests::memchr::Runner::new(3).reverse_oneshot(
|haystack, needles| { let n1 = needles.get(0).copied()?; let n2 = needles.get(1).copied()?; let n3 = needles.get(2).copied()?;
Some(memrchr3(n1, n2, n3, haystack))
},
)
}
// Prior to memchr 2.6, the memchr iterators both implemented Send and // Sync. But in memchr 2.6, the iterator changed to use raw pointers // internally and I didn't add explicit Send/Sync impls. This ended up // regressing the API. This test ensures we don't do that again. // // See: https://github.com/BurntSushi/memchr/issues/133 #[test] fn sync_regression() { use core::panic::{RefUnwindSafe, UnwindSafe};
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.