diff options
| author | Marvin Löbel <loebel.marvin@gmail.com> | 2015-03-15 01:48:34 +0100 |
|---|---|---|
| committer | Marvin Löbel <loebel.marvin@gmail.com> | 2015-04-05 18:52:57 +0200 |
| commit | 1b4cddcbfd61d05d42995cd38387e2faabe6156a (patch) | |
| tree | 3408c21657729fdd36fb706a12257fd62a897bc1 /src/libcore/str/pattern.rs | |
| parent | cf00fc4da984481a75229ce1e40f339f292d2166 (diff) | |
| download | rust-1b4cddcbfd61d05d42995cd38387e2faabe6156a.tar.gz rust-1b4cddcbfd61d05d42995cd38387e2faabe6156a.zip | |
Implemented remaining string pattern iterators.
- Added missing reverse versions of methods - Added [r]matches() - Generated the string pattern iterators with a macro - Added where bounds to the methods returning reverse iterators for better error messages.
Diffstat (limited to 'src/libcore/str/pattern.rs')
| -rw-r--r-- | src/libcore/str/pattern.rs | 183 |
1 files changed, 113 insertions, 70 deletions
diff --git a/src/libcore/str/pattern.rs b/src/libcore/str/pattern.rs index 922ab2c14a6..0c2a58f3ca7 100644 --- a/src/libcore/str/pattern.rs +++ b/src/libcore/str/pattern.rs @@ -8,6 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +//! The string Pattern API. +//! +//! For more details, see the traits `Pattern`, `Searcher`, +//! `ReverseSearcher` and `DoubleEndedSearcher`. + use prelude::*; // Pattern @@ -223,7 +228,9 @@ pub unsafe trait ReverseSearcher<'a>: Searcher<'a> { /// `"[aa]a"` or `"a[aa]"`, depending from which side it is searched. pub trait DoubleEndedSearcher<'a>: ReverseSearcher<'a> {} +///////////////////////////////////////////////////////////////////////////// // Impl for a CharEq wrapper +///////////////////////////////////////////////////////////////////////////// #[doc(hidden)] trait CharEq { @@ -261,6 +268,7 @@ impl<'a> CharEq for &'a [char] { struct CharEqPattern<C: CharEq>(C); +#[derive(Clone)] struct CharEqSearcher<'a, C: CharEq> { char_eq: C, haystack: &'a str, @@ -330,12 +338,15 @@ unsafe impl<'a, C: CharEq> ReverseSearcher<'a> for CharEqSearcher<'a, C> { impl<'a, C: CharEq> DoubleEndedSearcher<'a> for CharEqSearcher<'a, C> {} +///////////////////////////////////////////////////////////////////////////// // Impl for &str +///////////////////////////////////////////////////////////////////////////// // Todo: Optimize the naive implementation here +/// Associated type for `<&str as Pattern<'a>>::Searcher`. #[derive(Clone)] -struct StrSearcher<'a, 'b> { +pub struct StrSearcher<'a, 'b> { haystack: &'a str, needle: &'b str, start: usize, @@ -456,116 +467,148 @@ fn str_search_step<F, G>(mut m: &mut StrSearcher, } } -macro_rules! char_eq_pattern_impl { - ($wrapper:ty, $wrapper_ident:ident) => { - fn into_searcher(self, haystack: &'a str) -> $wrapper { - $wrapper_ident(CharEqPattern(self).into_searcher(haystack)) +///////////////////////////////////////////////////////////////////////////// + +macro_rules! pattern_methods { + ($t:ty, $pmap:expr, $smap:expr) => { + // FIXME: #22463 + //type Searcher = $t; + + #[inline] + fn into_searcher(self, haystack: &'a str) -> $t { + $smap($pmap(self).into_searcher(haystack)) } + #[inline] fn is_contained_in(self, haystack: &'a str) -> bool { - CharEqPattern(self).is_contained_in(haystack) + $pmap(self).is_contained_in(haystack) } + #[inline] fn is_prefix_of(self, haystack: &'a str) -> bool { - CharEqPattern(self).is_prefix_of(haystack) + $pmap(self).is_prefix_of(haystack) } + #[inline] fn is_suffix_of(self, haystack: &'a str) -> bool - where $wrapper: ReverseSearcher<'a> + where $t: ReverseSearcher<'a> { - CharEqPattern(self).is_suffix_of(haystack) + $pmap(self).is_suffix_of(haystack) } } } -// Pattern for char - -impl<'a> Pattern<'a> for char { - type Searcher = CharSearcher<'a>; - char_eq_pattern_impl!(CharSearcher<'a>, CharSearcher); +macro_rules! searcher_methods { + (forward) => { + #[inline] + fn haystack(&self) -> &'a str { + self.0.haystack() + } + #[inline] + fn next(&mut self) -> SearchStep { + self.0.next() + } + #[inline] + fn next_match(&mut self) -> Option<(usize, usize)> { + self.0.next_match() + } + #[inline] + fn next_reject(&mut self) -> Option<(usize, usize)> { + self.0.next_reject() + } + }; + (reverse) => { + #[inline] + fn next_back(&mut self) -> SearchStep { + self.0.next_back() + } + #[inline] + fn next_match_back(&mut self) -> Option<(usize, usize)> { + self.0.next_match_back() + } + #[inline] + fn next_reject_back(&mut self) -> Option<(usize, usize)> { + self.0.next_reject_back() + } + } } -pub struct CharSearcher<'a>(CharEqSearcher<'a, char>); +///////////////////////////////////////////////////////////////////////////// +// Impl for char +///////////////////////////////////////////////////////////////////////////// + +/// Associated type for `<char as Pattern<'a>>::Searcher`. +#[derive(Clone)] +pub struct CharSearcher<'a>(<CharEqPattern<char> as Pattern<'a>>::Searcher); unsafe impl<'a> Searcher<'a> for CharSearcher<'a> { - #[inline] - fn haystack(&self) -> &'a str { self.0.haystack() } - #[inline] - fn next(&mut self) -> SearchStep { self.0.next() } + searcher_methods!(forward); } + unsafe impl<'a> ReverseSearcher<'a> for CharSearcher<'a> { - #[inline] - fn next_back(&mut self) -> SearchStep { self.0.next_back() } + searcher_methods!(reverse); } -impl<'a> DoubleEndedSearcher<'a> for CharSearcher<'a> {} -// Pattern for &[char] +impl<'a> DoubleEndedSearcher<'a> for CharSearcher<'a> {} -impl<'a, 'b> Pattern<'a> for &'b [char] { - type Searcher = CharSliceSearcher<'a, 'b>; - char_eq_pattern_impl!(CharSliceSearcher<'a, 'b>, CharSliceSearcher); +/// Searches for chars that are equal to a given char +impl<'a> Pattern<'a> for char { + type Searcher = CharSearcher<'a>; + pattern_methods!(CharSearcher<'a>, CharEqPattern, CharSearcher); } -pub struct CharSliceSearcher<'a, 'b>(CharEqSearcher<'a, &'b [char]>); +///////////////////////////////////////////////////////////////////////////// +// Impl for &[char] +///////////////////////////////////////////////////////////////////////////// + +// Todo: Change / Remove due to ambiguity in meaning. + +/// Associated type for `<&[char] as Pattern<'a>>::Searcher`. +#[derive(Clone)] +pub struct CharSliceSearcher<'a, 'b>(<CharEqPattern<&'b [char]> as Pattern<'a>>::Searcher); unsafe impl<'a, 'b> Searcher<'a> for CharSliceSearcher<'a, 'b> { - #[inline] - fn haystack(&self) -> &'a str { self.0.haystack() } - #[inline] - fn next(&mut self) -> SearchStep { self.0.next() } + searcher_methods!(forward); } + unsafe impl<'a, 'b> ReverseSearcher<'a> for CharSliceSearcher<'a, 'b> { - #[inline] - fn next_back(&mut self) -> SearchStep { self.0.next_back() } + searcher_methods!(reverse); } -impl<'a, 'b> DoubleEndedSearcher<'a> for CharSliceSearcher<'a, 'b> {} -// Pattern for predicates +impl<'a, 'b> DoubleEndedSearcher<'a> for CharSliceSearcher<'a, 'b> {} -impl<'a, F: FnMut(char) -> bool> Pattern<'a> for F { - type Searcher = CharPredSearcher<'a, F>; - char_eq_pattern_impl!(CharPredSearcher<'a, F>, CharPredSearcher); +/// Searches for chars that are equal to any of the chars in the array +impl<'a, 'b> Pattern<'a> for &'b [char] { + type Searcher = CharSliceSearcher<'a, 'b>; + pattern_methods!(CharSliceSearcher<'a, 'b>, CharEqPattern, CharSliceSearcher); } -pub struct CharPredSearcher<'a, F: FnMut(char) -> bool>(CharEqSearcher<'a, F>); +///////////////////////////////////////////////////////////////////////////// +// Impl for F: FnMut(char) -> bool +///////////////////////////////////////////////////////////////////////////// + +/// Associated type for `<F as Pattern<'a>>::Searcher`. +#[derive(Clone)] +pub struct CharPredicateSearcher<'a, F>(<CharEqPattern<F> as Pattern<'a>>::Searcher) + where F: FnMut(char) -> bool; -unsafe impl<'a, F> Searcher<'a> for CharPredSearcher<'a, F> +unsafe impl<'a, F> Searcher<'a> for CharPredicateSearcher<'a, F> where F: FnMut(char) -> bool { - #[inline] - fn haystack(&self) -> &'a str { self.0.haystack() } - #[inline] - fn next(&mut self) -> SearchStep { self.0.next() } + searcher_methods!(forward); } -unsafe impl<'a, F> ReverseSearcher<'a> for CharPredSearcher<'a, F> + +unsafe impl<'a, F> ReverseSearcher<'a> for CharPredicateSearcher<'a, F> where F: FnMut(char) -> bool { - #[inline] - fn next_back(&mut self) -> SearchStep { self.0.next_back() } + searcher_methods!(reverse); } -impl<'a, F> DoubleEndedSearcher<'a> for CharPredSearcher<'a, F> - where F: FnMut(char) -> bool -{} -// Pattern for &&str +impl<'a, F> DoubleEndedSearcher<'a> for CharPredicateSearcher<'a, F> + where F: FnMut(char) -> bool {} -impl<'a, 'b> Pattern<'a> for &'b &'b str { - type Searcher = <&'b str as Pattern<'a>>::Searcher; - #[inline] - fn into_searcher(self, haystack: &'a str) - -> <&'b str as Pattern<'a>>::Searcher { - (*self).into_searcher(haystack) - } - #[inline] - fn is_contained_in(self, haystack: &'a str) -> bool { - (*self).is_contained_in(haystack) - } - #[inline] - fn is_prefix_of(self, haystack: &'a str) -> bool { - (*self).is_prefix_of(haystack) - } - #[inline] - fn is_suffix_of(self, haystack: &'a str) -> bool { - (*self).is_suffix_of(haystack) - } +/// Searches for chars that match the given predicate +impl<'a, F> Pattern<'a> for F where F: FnMut(char) -> bool { + type Searcher = CharPredicateSearcher<'a, F>; + pattern_methods!(CharPredicateSearcher<'a, F>, CharEqPattern, CharPredicateSearcher); } |
