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/libcollections | |
| 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/libcollections')
| -rw-r--r-- | src/libcollections/str.rs | 320 |
1 files changed, 275 insertions, 45 deletions
diff --git a/src/libcollections/str.rs b/src/libcollections/str.rs index c22b6fb9286..08af7879688 100644 --- a/src/libcollections/str.rs +++ b/src/libcollections/str.rs @@ -69,9 +69,12 @@ use vec::Vec; use slice::SliceConcatExt; pub use core::str::{FromStr, Utf8Error, Str}; -pub use core::str::{Lines, LinesAny, MatchIndices, CharRange}; -pub use core::str::{Split, SplitTerminator, SplitN}; -pub use core::str::{RSplit, RSplitN}; +pub use core::str::{Lines, LinesAny, CharRange}; +pub use core::str::{Split, RSplit}; +pub use core::str::{SplitN, RSplitN}; +pub use core::str::{SplitTerminator, RSplitTerminator}; +pub use core::str::{Matches, RMatches}; +pub use core::str::{MatchIndices, RMatchIndices}; pub use core::str::{from_utf8, Chars, CharIndices, Bytes}; pub use core::str::{from_utf8_unchecked, ParseBoolError}; pub use unicode::str::{Words, Graphemes, GraphemeIndices}; @@ -581,12 +584,22 @@ impl str { /// An iterator over substrings of `self`, separated by characters /// matched by a pattern. /// - /// The pattern can be a simple `&str`, or a closure that determines + /// The pattern can be a simple `&str`, `char`, or a closure that determines /// the split. + /// Additional libraries might provide more complex patterns like regular expressions. + /// + /// # Iterator behavior + /// + /// The returned iterator will be double ended if the pattern allows a reverse search + /// and forward/reverse search yields the same elements. This is true for, eg, `char` but not + /// for `&str`. + /// + /// If the pattern allows a reverse search but its results might differ + /// from a forward search, `rsplit()` can be used. /// /// # Examples /// - /// Simple `&str` patterns: + /// Simple patterns: /// /// ``` /// let v: Vec<&str> = "Mary had a little lamb".split(' ').collect(); @@ -594,6 +607,12 @@ impl str { /// /// let v: Vec<&str> = "".split('X').collect(); /// assert_eq!(v, [""]); + /// + /// let v: Vec<&str> = "lionXXtigerXleopard".split('X').collect(); + /// assert_eq!(v, ["lion", "", "tiger", "leopard"]); + /// + /// let v: Vec<&str> = "lion::tiger::leopard".split("::").collect(); + /// assert_eq!(v, ["lion", "tiger", "leopard"]); /// ``` /// /// More complex patterns with a lambda: @@ -602,69 +621,92 @@ impl str { /// let v: Vec<&str> = "abc1def2ghi".split(|c: char| c.is_numeric()).collect(); /// assert_eq!(v, ["abc", "def", "ghi"]); /// - /// let v: Vec<&str> = "lionXXtigerXleopard".split('X').collect(); - /// assert_eq!(v, ["lion", "", "tiger", "leopard"]); + /// let v: Vec<&str> = "lionXtigerXleopard".split(|c: char| c.is_uppercase()).collect(); + /// assert_eq!(v, ["lion", "tiger", "leopard"]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn split<'a, P: Pattern<'a>>(&'a self, pat: P) -> Split<'a, P> { core_str::StrExt::split(&self[..], pat) } - /// An iterator over substrings of `self`, separated by characters matched - /// by a pattern, returning most `count` items. + /// An iterator over substrings of `self`, separated by characters + /// matched by a pattern and yielded in reverse order. /// - /// The pattern can be a simple `&str`, or a closure that determines + /// The pattern can be a simple `&str`, `char`, or a closure that determines /// the split. + /// Additional libraries might provide more complex patterns like regular expressions. /// - /// The last element returned, if any, will contain the remainder of the - /// string. + /// # Iterator behavior /// - /// # Examples + /// The returned iterator requires that the pattern supports a reverse search, + /// and it will be double ended if a forward/reverse search yields the same elements. /// - /// Simple `&str` patterns: + /// For iterating from the front, `split()` can be used. /// - /// ``` - /// let v: Vec<&str> = "Mary had a little lambda".splitn(2, ' ').collect(); - /// assert_eq!(v, ["Mary", "had a little lambda"]); + /// # Examples /// - /// let v: Vec<&str> = "lionXXtigerXleopard".splitn(2, 'X').collect(); - /// assert_eq!(v, ["lion", "XtigerXleopard"]); + /// Simple patterns: /// - /// let v: Vec<&str> = "abcXdef".splitn(1, 'X').collect(); - /// assert_eq!(v, ["abcXdef"]); + /// ```rust + /// let v: Vec<&str> = "Mary had a little lamb".rsplit(' ').collect(); + /// assert_eq!(v, ["lamb", "little", "a", "had", "Mary"]); /// - /// let v: Vec<&str> = "".splitn(1, 'X').collect(); + /// let v: Vec<&str> = "".rsplit('X').collect(); /// assert_eq!(v, [""]); + /// + /// let v: Vec<&str> = "lionXXtigerXleopard".rsplit('X').collect(); + /// assert_eq!(v, ["leopard", "tiger", "", "lion"]); + /// + /// let v: Vec<&str> = "lion::tiger::leopard".rsplit("::").collect(); + /// assert_eq!(v, ["leopard", "tiger", "lion"]); /// ``` /// /// More complex patterns with a lambda: /// - /// ``` - /// let v: Vec<&str> = "abc1def2ghi".splitn(2, |c: char| c.is_numeric()).collect(); - /// assert_eq!(v, ["abc", "def2ghi"]); + /// ```rust + /// let v: Vec<&str> = "abc1def2ghi".rsplit(|c: char| c.is_numeric()).collect(); + /// assert_eq!(v, ["ghi", "def", "abc"]); + /// + /// let v: Vec<&str> = "lionXtigerXleopard".rsplit(|c: char| c.is_uppercase()).collect(); + /// assert_eq!(v, ["leopard", "tiger", "lion"]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn splitn<'a, P: Pattern<'a>>(&'a self, count: usize, pat: P) -> SplitN<'a, P> { - core_str::StrExt::splitn(&self[..], count, pat) + pub fn rsplit<'a, P: Pattern<'a>>(&'a self, pat: P) -> RSplit<'a, P> + where P::Searcher: ReverseSearcher<'a> + { + core_str::StrExt::rsplit(&self[..], pat) } /// An iterator over substrings of `self`, separated by characters /// matched by a pattern. /// + /// The pattern can be a simple `&str`, `char`, or a closure that determines + /// the split. + /// Additional libraries might provide more complex patterns like regular expressions. + /// /// Equivalent to `split`, except that the trailing substring is skipped if empty. /// - /// The pattern can be a simple `&str`, or a closure that determines - /// the split. + /// This method can be used for string data that is _terminated_, rather than + /// _seperated_ by some string. + /// + /// # Iterator behavior + /// + /// The returned iterator will be double ended if the pattern allows a reverse search + /// and forward/reverse search yields the same elements. This is true for, eg, `char` but not + /// for `&str`. + /// + /// If the pattern allows a reverse search but its results might differ + /// from a forward search, `rsplit_terminator()` can be used. /// /// # Examples /// - /// Simple `&str` patterns: + /// Simple patterns: /// /// ``` /// let v: Vec<&str> = "A.B.".split_terminator('.').collect(); /// assert_eq!(v, ["A", "B"]); /// - /// let v: Vec<&str> = "A..B..".split_terminator('.').collect(); + /// let v: Vec<&str> = "A..B..".split_terminator(".").collect(); /// assert_eq!(v, ["A", "", "B", ""]); /// ``` /// @@ -679,32 +721,93 @@ impl str { core_str::StrExt::split_terminator(&self[..], pat) } - /// An iterator over substrings of `self`, separated by a pattern, - /// starting from the end of the string. + /// An iterator over substrings of `self`, separated by characters + /// matched by a pattern and yielded in reverse order. + /// + /// The pattern can be a simple `&str`, `char`, or a closure that determines + /// the split. + /// Additional libraries might provide more complex patterns like regular expressions. + /// + /// Equivalent to `split`, except that the trailing substring is skipped if empty. + /// + /// This method can be used for string data that is _terminated_, rather than + /// _seperated_ by some string. + /// + /// # Iterator behavior + /// + /// The returned iterator requires that the pattern supports a reverse search, + /// and it will be double ended if a forward/reverse search yields the same elements. + /// + /// For iterating from the front, `split_terminator()` can be used. /// /// # Examples /// /// Simple patterns: /// /// ``` - /// let v: Vec<&str> = "Mary had a little lamb".rsplit(' ').collect(); - /// assert_eq!(v, ["lamb", "little", "a", "had", "Mary"]); + /// let v: Vec<&str> = "A.B.".rsplit_terminator('.').collect(); + /// assert_eq!(v, ["B", "A"]); /// - /// let v: Vec<&str> = "lion::tiger::leopard".rsplit("::").collect(); - /// assert_eq!(v, ["leopard", "tiger", "lion"]); + /// let v: Vec<&str> = "A..B..".rsplit_terminator(".").collect(); + /// assert_eq!(v, ["", "B", "", "A"]); /// ``` /// /// More complex patterns with a lambda: /// /// ``` - /// let v: Vec<&str> = "abc1def2ghi".rsplit(|c: char| c.is_numeric()).collect(); + /// let v: Vec<&str> = "abc1def2ghi3".rsplit_terminator(|c: char| c.is_numeric()).collect(); /// assert_eq!(v, ["ghi", "def", "abc"]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn rsplit<'a, P: Pattern<'a>>(&'a self, pat: P) -> RSplit<'a, P> + pub fn rsplit_terminator<'a, P: Pattern<'a>>(&'a self, pat: P) -> RSplitTerminator<'a, P> where P::Searcher: ReverseSearcher<'a> { - core_str::StrExt::rsplit(&self[..], pat) + core_str::StrExt::rsplit_terminator(&self[..], pat) + } + + /// An iterator over substrings of `self`, separated by a pattern, + /// restricted to returning + /// at most `count` items. + /// + /// The last element returned, if any, will contain the remainder of the + /// string. + /// The pattern can be a simple `&str`, `char`, or a closure that determines + /// the split. + /// Additional libraries might provide more complex patterns like regular expressions. + /// + /// # Iterator behavior + /// + /// The returned iterator will not be double ended, because it is not efficient to support. + /// + /// If the pattern allows a reverse search, `rsplitn()` can be used. + /// + /// # Examples + /// + /// Simple patterns: + /// + /// ``` + /// let v: Vec<&str> = "Mary had a little lambda".splitn(3, ' ').collect(); + /// assert_eq!(v, ["Mary", "had", "a little lambda"]); + /// + /// let v: Vec<&str> = "lionXXtigerXleopard".splitn(3, "X").collect(); + /// assert_eq!(v, ["lion", "", "tigerXleopard"]); + /// + /// let v: Vec<&str> = "abcXdef".splitn(1, 'X').collect(); + /// assert_eq!(v, ["abcXdef"]); + /// + /// let v: Vec<&str> = "".splitn(1, 'X').collect(); + /// assert_eq!(v, [""]); + /// ``` + /// + /// More complex patterns with a lambda: + /// + /// ``` + /// let v: Vec<&str> = "abc1def2ghi".splitn(2, |c: char| c.is_numeric()).collect(); + /// assert_eq!(v, ["abc", "def2ghi"]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn splitn<'a, P: Pattern<'a>>(&'a self, count: usize, pat: P) -> SplitN<'a, P> { + core_str::StrExt::splitn(&self[..], count, pat) } /// An iterator over substrings of `self`, separated by a pattern, @@ -714,6 +817,16 @@ impl str { /// The last element returned, if any, will contain the remainder of the /// string. /// + /// The pattern can be a simple `&str`, `char`, or a closure that determines + /// the split. + /// Additional libraries might provide more complex patterns like regular expressions. + /// + /// # Iterator behavior + /// + /// The returned iterator will not be double ended, because it is not efficient to support. + /// + /// `splitn()` can be used for splitting from the front. + /// /// # Examples /// /// Simple patterns: @@ -722,6 +835,9 @@ impl str { /// let v: Vec<&str> = "Mary had a little lamb".rsplitn(3, ' ').collect(); /// assert_eq!(v, ["lamb", "little", "Mary had a"]); /// + /// let v: Vec<&str> = "lionXXtigerXleopard".rsplitn(3, 'X').collect(); + /// assert_eq!(v, ["leopard", "tiger", "lionX"]); + /// /// let v: Vec<&str> = "lion::tiger::leopard".rsplitn(2, "::").collect(); /// assert_eq!(v, ["leopard", "lion::tiger"]); /// ``` @@ -739,13 +855,87 @@ impl str { core_str::StrExt::rsplitn(&self[..], count, pat) } - /// An iterator over the start and end indices of the disjoint matches of a `&str` within + /// An iterator over the matches of a pattern within `self`. + /// + /// The pattern can be a simple `&str`, `char`, or a closure that determines + /// the split. + /// Additional libraries might provide more complex patterns like regular expressions. + /// + /// # Iterator behavior + /// + /// The returned iterator will be double ended if the pattern allows a reverse search + /// and forward/reverse search yields the same elements. This is true for, eg, `char` but not + /// for `&str`. + /// + /// If the pattern allows a reverse search but its results might differ + /// from a forward search, `rmatches()` can be used. + /// + /// # Examples + /// + /// ``` + /// # #![feature(collections)] + /// let v: Vec<&str> = "abcXXXabcYYYabc".matches("abc").collect(); + /// assert_eq!(v, ["abc", "abc", "abc"]); + /// + /// let v: Vec<&str> = "1abc2abc3".matches(|c: char| c.is_numeric()).collect(); + /// assert_eq!(v, ["1", "2", "3"]); + /// ``` + #[unstable(feature = "collections", + reason = "method got recently added")] + pub fn matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> Matches<'a, P> { + core_str::StrExt::matches(&self[..], pat) + } + + /// An iterator over the matches of a pattern within `self`, yielded in reverse order. + /// + /// The pattern can be a simple `&str`, `char`, or a closure that determines + /// the split. + /// Additional libraries might provide more complex patterns like regular expressions. + /// + /// # Iterator behavior + /// + /// The returned iterator requires that the pattern supports a reverse search, + /// and it will be double ended if a forward/reverse search yields the same elements. + /// + /// For iterating from the front, `matches()` can be used. + /// + /// # Examples + /// + /// ``` + /// # #![feature(collections)] + /// let v: Vec<&str> = "abcXXXabcYYYabc".rmatches("abc").collect(); + /// assert_eq!(v, ["abc", "abc", "abc"]); + /// + /// let v: Vec<&str> = "1abc2abc3".rmatches(|c: char| c.is_numeric()).collect(); + /// assert_eq!(v, ["3", "2", "1"]); + /// ``` + #[unstable(feature = "collections", + reason = "method got recently added")] + pub fn rmatches<'a, P: Pattern<'a>>(&'a self, pat: P) -> RMatches<'a, P> + where P::Searcher: ReverseSearcher<'a> + { + core_str::StrExt::rmatches(&self[..], pat) + } + + /// An iterator over the start and end indices of the disjoint matches of a pattern within /// `self`. /// - /// That is, each returned value `(start, end)` satisfies `self.slice(start, end) == sep`. For - /// matches of `sep` within `self` that overlap, only the indices corresponding to the first + /// For matches of `pat` within `self` that overlap, only the indices corresponding to the first /// match are returned. /// + /// The pattern can be a simple `&str`, `char`, or a closure that determines + /// the split. + /// Additional libraries might provide more complex patterns like regular expressions. + /// + /// # Iterator behavior + /// + /// The returned iterator will be double ended if the pattern allows a reverse search + /// and forward/reverse search yields the same elements. This is true for, eg, `char` but not + /// for `&str`. + /// + /// If the pattern allows a reverse search but its results might differ + /// from a forward search, `rmatch_indices()` can be used. + /// /// # Examples /// /// ``` @@ -761,12 +951,52 @@ impl str { /// ``` #[unstable(feature = "collections", reason = "might have its iterator type changed")] - // NB: Right now MatchIndices yields `(usize, usize)`, - // but it would be more consistent and useful to return `(usize, &str)` + // NB: Right now MatchIndices yields `(usize, usize)`, but it would + // be more consistent with `matches` and `char_indices` to return `(usize, &str)` pub fn match_indices<'a, P: Pattern<'a>>(&'a self, pat: P) -> MatchIndices<'a, P> { core_str::StrExt::match_indices(&self[..], pat) } + /// An iterator over the start and end indices of the disjoint matches of a pattern within + /// `self`, yielded in reverse order. + /// + /// For matches of `pat` within `self` that overlap, only the indices corresponding to the last + /// match are returned. + /// + /// The pattern can be a simple `&str`, `char`, or a closure that determines + /// the split. + /// Additional libraries might provide more complex patterns like regular expressions. + /// + /// # Iterator behavior + /// + /// The returned iterator requires that the pattern supports a reverse search, + /// and it will be double ended if a forward/reverse search yields the same elements. + /// + /// For iterating from the front, `match_indices()` can be used. + /// + /// # Examples + /// + /// ``` + /// # #![feature(collections)] + /// let v: Vec<(usize, usize)> = "abcXXXabcYYYabc".rmatch_indices("abc").collect(); + /// assert_eq!(v, [(12,15), (6,9), (0,3)]); + /// + /// let v: Vec<(usize, usize)> = "1abcabc2".rmatch_indices("abc").collect(); + /// assert_eq!(v, [(4,7), (1,4)]); + /// + /// let v: Vec<(usize, usize)> = "ababa".rmatch_indices("aba").collect(); + /// assert_eq!(v, [(2, 5)]); // only the last `aba` + /// ``` + #[unstable(feature = "collections", + reason = "might have its iterator type changed")] + // NB: Right now RMatchIndices yields `(usize, usize)`, but it would + // be more consistent with `rmatches` and `char_indices` to return `(usize, &str)` + pub fn rmatch_indices<'a, P: Pattern<'a>>(&'a self, pat: P) -> RMatchIndices<'a, P> + where P::Searcher: ReverseSearcher<'a> + { + core_str::StrExt::rmatch_indices(&self[..], pat) + } + /// An iterator over the lines of a string, separated by `\n`. /// /// This does not include the empty string after a trailing `\n`. |
