nucleo/src/prefilter.rs

92 lines
2.8 KiB
Rust
Raw Normal View History

2023-07-20 00:09:51 +00:00
use ::memchr::{memchr, memchr2, memrchr, memrchr2};
use crate::chars::Char;
use crate::utf32_str::Utf32Str;
use crate::Matcher;
#[inline(always)]
fn find_ascii_ignore_case(c: u8, haystack: &[u8]) -> Option<usize> {
if c >= b'a' || c <= b'z' {
memchr2(c, c - 32, haystack)
} else {
memchr(c, haystack)
}
}
#[inline(always)]
fn find_ascii_ignore_case_rev(c: u8, haystack: &[u8]) -> Option<usize> {
if c >= b'a' || c <= b'z' {
memrchr2(c, c - 32, haystack)
} else {
memrchr(c, haystack)
}
}
impl Matcher {
pub(crate) fn prefilter_ascii(
&self,
mut haystack: &[u8],
needle: &[u8],
only_greedy: bool,
2023-07-20 00:09:51 +00:00
) -> Option<(usize, usize, usize)> {
if self.config.ignore_case {
let start = find_ascii_ignore_case(needle[0], haystack)?;
let mut greedy_end = start + 1;
haystack = &haystack[greedy_end..];
2023-07-20 00:09:51 +00:00
for &c in &needle[1..] {
let idx = find_ascii_ignore_case(c, haystack)? + 1;
greedy_end += idx;
2023-07-20 00:09:51 +00:00
haystack = &haystack[idx..];
}
if only_greedy {
Some((start, greedy_end, greedy_end))
} else {
let end = greedy_end
+ find_ascii_ignore_case_rev(*needle.last().unwrap(), haystack)
.map_or(0, |i| i + 1);
Some((start, greedy_end, end))
}
2023-07-20 00:09:51 +00:00
} else {
let start = memchr(needle[0], haystack)?;
let mut greedy_end = start + 1;
haystack = &haystack[greedy_end..];
2023-07-20 00:09:51 +00:00
for &c in &needle[1..] {
let idx = memchr(c, haystack)? + 1;
greedy_end += idx;
2023-07-20 00:09:51 +00:00
haystack = &haystack[idx..];
}
if only_greedy {
Some((start, greedy_end, greedy_end))
} else {
let end =
greedy_end + memrchr(*needle.last().unwrap(), haystack).map_or(0, |i| i + 1);
Some((start, greedy_end, end))
}
2023-07-20 00:09:51 +00:00
}
}
pub(crate) fn prefilter_non_ascii(
&self,
haystack: &[char],
needle: Utf32Str<'_>,
only_greedy: bool,
2023-07-20 00:09:51 +00:00
) -> Option<(usize, usize)> {
let needle_char = needle.get(0);
let start = haystack
.iter()
.position(|c| c.normalize(&self.config) == needle_char)?;
let needle_char = needle.last();
if only_greedy {
Some((start, start + 1))
} else {
let end = haystack.len()
- haystack[start..]
.iter()
.rev()
.position(|c| c.normalize(&self.config) == needle_char)?;
2023-07-20 00:09:51 +00:00
Some((start, end))
}
2023-07-20 00:09:51 +00:00
}
}