diff options
| author | Manish Goregaokar <manishsmail@gmail.com> | 2017-12-13 15:26:27 -0600 |
|---|---|---|
| committer | Manish Goregaokar <manishsmail@gmail.com> | 2017-12-13 15:59:40 -0600 |
| commit | d9dc44a5e9857864905e1cdbf40ab9ac617f65e7 (patch) | |
| tree | 6826201df3c364119f5b04199c612aae8ed656dd /src/libcore | |
| parent | 585ad9ff30e579e929bca2b1221367cc440aa377 (diff) | |
| download | rust-d9dc44a5e9857864905e1cdbf40ab9ac617f65e7.tar.gz rust-d9dc44a5e9857864905e1cdbf40ab9ac617f65e7.zip | |
Fill in forward searcher impl for char
Diffstat (limited to 'src/libcore')
| -rw-r--r-- | src/libcore/str/pattern.rs | 78 |
1 files changed, 65 insertions, 13 deletions
diff --git a/src/libcore/str/pattern.rs b/src/libcore/str/pattern.rs index b1b66c9f8d8..3f24374223c 100644 --- a/src/libcore/str/pattern.rs +++ b/src/libcore/str/pattern.rs @@ -19,6 +19,7 @@ use cmp; use fmt; +use slice::memchr; use usize; // Pattern @@ -241,25 +242,66 @@ pub trait DoubleEndedSearcher<'a>: ReverseSearcher<'a> {} /// Associated type for `<char as Pattern<'a>>::Searcher`. #[derive(Clone, Debug)] -pub struct CharSearcher<'a>(&'a str); +pub struct CharSearcher<'a> { + haystack: &'a str, + // invariant: `finger` must be a valid utf8 byte index of `haystack` + finger: usize, + needle: char, + // For ascii chars + // invariant: must be an ASCII byte (no high bit) + single_byte: Option<u8>, +} unsafe impl<'a> Searcher<'a> for CharSearcher<'a> { #[inline] fn haystack(&self) -> &'a str { - unimplemented!(); + self.haystack } #[inline] fn next(&mut self) -> SearchStep { - unimplemented!(); + let old_finger = self.finger; + let slice = unsafe { self.haystack.get_unchecked(old_finger..) }; + let mut iter = slice.chars(); + let old_len = iter.iter.len(); + if let Some(ch) = iter.next() { + // add byte offset of current character + // without recalculating + self.finger += iter.iter.len() - old_len; + if ch == self.needle { + SearchStep::Match(old_finger, self.finger) + } else { + SearchStep::Reject(old_finger, self.finger) + } + } else { + SearchStep::Done + } } #[inline] fn next_match(&mut self) -> Option<(usize, usize)> { - unimplemented!(); - } - #[inline] - fn next_reject(&mut self) -> Option<(usize, usize)> { - unimplemented!(); + if let Some(byte) = self.single_byte { + let old_finger = self.finger; + let slice = unsafe { self.haystack.get_unchecked(old_finger..) }; + let bytes = slice.as_bytes(); + if let Some(index) = memchr::memchr(byte, bytes) { + // index is the index of a valid ASCII byte, + // so we can add one to it + self.finger += index + 1; + Some((index, self.finger)) + } else { + None + } + } else { + loop { + match self.next() { + SearchStep::Match(a, b) => break Some((a, b)), + SearchStep::Done => break None, + _ => continue, + } + } + } } + + // let next_reject use the default implementation from the Searcher trait } unsafe impl<'a> ReverseSearcher<'a> for CharSearcher<'a> { @@ -271,10 +313,8 @@ unsafe impl<'a> ReverseSearcher<'a> for CharSearcher<'a> { fn next_match_back(&mut self) -> Option<(usize, usize)> { unimplemented!(); } - #[inline] - fn next_reject_back(&mut self) -> Option<(usize, usize)> { - unimplemented!(); - } + + // let next_reject_back use the default implementation from the Searcher trait } impl<'a> DoubleEndedSearcher<'a> for CharSearcher<'a> {} @@ -285,7 +325,19 @@ impl<'a> Pattern<'a> for char { #[inline] fn into_searcher(self, haystack: &'a str) -> Self::Searcher { - CharSearcher(haystack) + let single_byte = if self.len_utf8() == 1 { + let mut storage = [0]; + self.encode_utf8(&mut storage); + Some(storage[0]) + } else { + None + }; + CharSearcher { + haystack, + finger: 0, + needle: self, + single_byte, + } } #[inline] |
