std: convert each_split_str to an iterator
This commit is contained in:
@@ -40,7 +40,7 @@ use syntax::visit::{visit_foreign_item, visit_item};
|
|||||||
use syntax::visit::{visit_mod, visit_ty, vt};
|
use syntax::visit::{visit_mod, visit_ty, vt};
|
||||||
use syntax::opt_vec::OptVec;
|
use syntax::opt_vec::OptVec;
|
||||||
|
|
||||||
use core::str::each_split_str;
|
use core::iterator::IteratorUtil;
|
||||||
use core::str;
|
use core::str;
|
||||||
use core::uint;
|
use core::uint;
|
||||||
use core::vec;
|
use core::vec;
|
||||||
@@ -1737,8 +1737,7 @@ impl Resolver {
|
|||||||
entry: %s (%?)",
|
entry: %s (%?)",
|
||||||
path_string, def_like);
|
path_string, def_like);
|
||||||
|
|
||||||
let mut pieces = ~[];
|
let mut pieces: ~[&str] = path_string.split_str_iter("::").collect();
|
||||||
for each_split_str(path_string, "::") |s| { pieces.push(s.to_owned()) }
|
|
||||||
let final_ident_str = pieces.pop();
|
let final_ident_str = pieces.pop();
|
||||||
let final_ident = self.session.ident_of(final_ident_str);
|
let final_ident = self.session.ident_of(final_ident_str);
|
||||||
|
|
||||||
|
|||||||
@@ -667,6 +667,7 @@ impl<'self> StrCharSplitSeparator for extern "Rust" fn(char) -> bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'self, Sep: StrCharSplitSeparator> Iterator<&'self str> for StrCharSplitIterator<'self, Sep> {
|
impl<'self, Sep: StrCharSplitSeparator> Iterator<&'self str> for StrCharSplitIterator<'self, Sep> {
|
||||||
|
#[inline]
|
||||||
fn next(&mut self) -> Option<&'self str> {
|
fn next(&mut self) -> Option<&'self str> {
|
||||||
if self.finished { return None }
|
if self.finished { return None }
|
||||||
|
|
||||||
@@ -709,88 +710,69 @@ impl<'self, Sep: StrCharSplitSeparator> Iterator<&'self str> for StrCharSplitIte
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// See Issue #1932 for why this is a naive search
|
/// An iterator over the start and end indicies of the matches of a
|
||||||
fn iter_matches<'a,'b>(s: &'a str, sep: &'b str,
|
/// substring within a larger string
|
||||||
f: &fn(uint, uint) -> bool) -> bool {
|
pub struct StrMatchesIndexIterator<'self> {
|
||||||
let (sep_len, l) = (sep.len(), s.len());
|
priv haystack: &'self str,
|
||||||
assert!(sep_len > 0u);
|
priv needle: &'self str,
|
||||||
let mut (i, match_start, match_i) = (0u, 0u, 0u);
|
priv position: uint,
|
||||||
|
}
|
||||||
|
|
||||||
while i < l {
|
/// An iterator over the substrings of a string separated by a given
|
||||||
if s[i] == sep[match_i] {
|
/// search string
|
||||||
if match_i == 0u { match_start = i; }
|
pub struct StrStrSplitIterator<'self> {
|
||||||
match_i += 1u;
|
priv it: StrMatchesIndexIterator<'self>,
|
||||||
// Found a match
|
priv last_end: uint,
|
||||||
if match_i == sep_len {
|
priv finished: bool
|
||||||
if !f(match_start, i + 1u) { return false; }
|
}
|
||||||
match_i = 0u;
|
|
||||||
|
impl<'self> Iterator<(uint, uint)> for StrMatchesIndexIterator<'self> {
|
||||||
|
#[inline]
|
||||||
|
fn next(&mut self) -> Option<(uint, uint)> {
|
||||||
|
// See Issue #1932 for why this is a naive search
|
||||||
|
let (h_len, n_len) = (self.haystack.len(), self.needle.len());
|
||||||
|
let mut (match_start, match_i) = (0, 0);
|
||||||
|
|
||||||
|
while self.position < h_len {
|
||||||
|
if self.haystack[self.position] == self.needle[match_i] {
|
||||||
|
if match_i == 0 { match_start = self.position; }
|
||||||
|
match_i += 1;
|
||||||
|
self.position += 1;
|
||||||
|
|
||||||
|
if match_i == n_len {
|
||||||
|
// found a match!
|
||||||
|
return Some((match_start, self.position));
|
||||||
}
|
}
|
||||||
i += 1u;
|
|
||||||
} else {
|
} else {
|
||||||
// Failed match, backtrack
|
// failed match, backtrack
|
||||||
if match_i > 0u {
|
if match_i > 0 {
|
||||||
match_i = 0u;
|
match_i = 0;
|
||||||
i = match_start + 1u;
|
self.position = match_start;
|
||||||
} else {
|
}
|
||||||
i += 1u;
|
self.position += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
None
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn iter_between_matches<'a,'b>(s: &'a str,
|
impl<'self> Iterator<&'self str> for StrStrSplitIterator<'self> {
|
||||||
sep: &'b str,
|
#[inline]
|
||||||
f: &fn(uint, uint) -> bool) -> bool {
|
fn next(&mut self) -> Option<&'self str> {
|
||||||
let mut last_end = 0u;
|
if self.finished { return None; }
|
||||||
for iter_matches(s, sep) |from, to| {
|
|
||||||
if !f(last_end, from) { return false; }
|
|
||||||
last_end = to;
|
|
||||||
}
|
|
||||||
return f(last_end, s.len());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
match self.it.next() {
|
||||||
* Splits a string into a vector of the substrings separated by a given string
|
Some((from, to)) => {
|
||||||
*
|
let ret = Some(self.it.haystack.slice(self.last_end, from));
|
||||||
* # Example
|
self.last_end = to;
|
||||||
*
|
ret
|
||||||
* ~~~ {.rust}
|
}
|
||||||
* let mut v = ~[];
|
None => {
|
||||||
* for each_split_str(".XXX.YYY.", ".") |subs| { v.push(subs); }
|
self.finished = true;
|
||||||
* assert!(v == ["", "XXX", "YYY", ""]);
|
Some(self.it.haystack.slice(self.last_end, self.it.haystack.len()))
|
||||||
* ~~~
|
|
||||||
*/
|
|
||||||
pub fn each_split_str<'a,'b>(s: &'a str,
|
|
||||||
sep: &'b str,
|
|
||||||
it: &fn(&'a str) -> bool) -> bool {
|
|
||||||
for iter_between_matches(s, sep) |from, to| {
|
|
||||||
if !it( unsafe { raw::slice_bytes(s, from, to) } ) { return false; }
|
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Splits the string `s` based on `sep`, yielding all splits to the iterator
|
|
||||||
* function provide
|
|
||||||
*
|
|
||||||
* # Example
|
|
||||||
*
|
|
||||||
* ~~~ {.rust}
|
|
||||||
* let mut v = ~[];
|
|
||||||
* for each_split_str(".XXX.YYY.", ".") |subs| { v.push(subs); }
|
|
||||||
* assert!(v == ["XXX", "YYY"]);
|
|
||||||
* ~~~
|
|
||||||
*/
|
|
||||||
pub fn each_split_str_nonempty<'a,'b>(s: &'a str,
|
|
||||||
sep: &'b str,
|
|
||||||
it: &fn(&'a str) -> bool) -> bool {
|
|
||||||
for iter_between_matches(s, sep) |from, to| {
|
|
||||||
if to > from {
|
|
||||||
if !it( unsafe { raw::slice_bytes(s, from, to) } ) { return false; }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Levenshtein Distance between two strings
|
/// Levenshtein Distance between two strings
|
||||||
@@ -929,15 +911,13 @@ pub fn each_split_within<'a>(ss: &'a str,
|
|||||||
* The original string with all occurances of `from` replaced with `to`
|
* The original string with all occurances of `from` replaced with `to`
|
||||||
*/
|
*/
|
||||||
pub fn replace(s: &str, from: &str, to: &str) -> ~str {
|
pub fn replace(s: &str, from: &str, to: &str) -> ~str {
|
||||||
let mut (result, first) = (~"", true);
|
let mut (result, last_end) = (~"", 0);
|
||||||
for iter_between_matches(s, from) |start, end| {
|
for s.matches_index_iter(from).advance |(start, end)| {
|
||||||
if first {
|
result.push_str(unsafe{raw::slice_bytes(s, last_end, start)});
|
||||||
first = false;
|
result.push_str(to);
|
||||||
} else {
|
last_end = end;
|
||||||
push_str(&mut result, to);
|
|
||||||
}
|
|
||||||
push_str(&mut result, unsafe{raw::slice_bytes(s, start, end)});
|
|
||||||
}
|
}
|
||||||
|
result.push_str(unsafe{raw::slice_bytes(s, last_end, s.len())});
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2441,6 +2421,20 @@ pub trait StrSlice<'self> {
|
|||||||
fn split_options_iter<Sep: StrCharSplitSeparator>(&self, sep: Sep,
|
fn split_options_iter<Sep: StrCharSplitSeparator>(&self, sep: Sep,
|
||||||
count: uint, allow_trailing_empty: bool)
|
count: uint, allow_trailing_empty: bool)
|
||||||
-> StrCharSplitIterator<'self, Sep>;
|
-> StrCharSplitIterator<'self, Sep>;
|
||||||
|
/// An iterator over the start and end indices of each match of
|
||||||
|
/// `sep` within `self`.
|
||||||
|
fn matches_index_iter(&self, sep: &'self str) -> StrMatchesIndexIterator<'self>;
|
||||||
|
/**
|
||||||
|
* An iterator over the substrings of `self` separated by `sep`.
|
||||||
|
*
|
||||||
|
* # Example
|
||||||
|
*
|
||||||
|
* ~~~ {.rust}
|
||||||
|
* let v: ~[&str] = ".XXX.YYY.".split_str_iter(".").collect()
|
||||||
|
* assert_eq!(v, ["", "XXX", "YYY", ""]);
|
||||||
|
* ~~~
|
||||||
|
*/
|
||||||
|
fn split_str_iter(&self, &'self str) -> StrStrSplitIterator<'self>;
|
||||||
/// An iterator over the lines of a string (subsequences separated
|
/// An iterator over the lines of a string (subsequences separated
|
||||||
/// by `\n`).
|
/// by `\n`).
|
||||||
fn line_iter(&self) -> StrCharSplitIterator<'self, char>;
|
fn line_iter(&self) -> StrCharSplitIterator<'self, char>;
|
||||||
@@ -2454,7 +2448,6 @@ pub trait StrSlice<'self> {
|
|||||||
fn len(&self) -> uint;
|
fn len(&self) -> uint;
|
||||||
fn char_len(&self) -> uint;
|
fn char_len(&self) -> uint;
|
||||||
fn slice(&self, begin: uint, end: uint) -> &'self str;
|
fn slice(&self, begin: uint, end: uint) -> &'self str;
|
||||||
fn each_split_str<'a>(&self, sep: &'a str, it: &fn(&'self str) -> bool) -> bool;
|
|
||||||
fn starts_with<'a>(&self, needle: &'a str) -> bool;
|
fn starts_with<'a>(&self, needle: &'a str) -> bool;
|
||||||
fn substr(&self, begin: uint, n: uint) -> &'self str;
|
fn substr(&self, begin: uint, n: uint) -> &'self str;
|
||||||
fn escape_default(&self) -> ~str;
|
fn escape_default(&self) -> ~str;
|
||||||
@@ -2529,6 +2522,21 @@ impl<'self> StrSlice<'self> for &'self str {
|
|||||||
only_ascii: only_ascii
|
only_ascii: only_ascii
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fn matches_index_iter(&self, sep: &'self str) -> StrMatchesIndexIterator<'self> {
|
||||||
|
assert!(!sep.is_empty())
|
||||||
|
StrMatchesIndexIterator {
|
||||||
|
haystack: *self,
|
||||||
|
needle: sep,
|
||||||
|
position: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn split_str_iter(&self, sep: &'self str) -> StrStrSplitIterator<'self> {
|
||||||
|
StrStrSplitIterator {
|
||||||
|
it: self.matches_index_iter(sep),
|
||||||
|
last_end: 0,
|
||||||
|
finished: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn line_iter(&self) -> StrCharSplitIterator<'self, char> {
|
fn line_iter(&self) -> StrCharSplitIterator<'self, char> {
|
||||||
self.split_options_iter('\n', self.len(), false)
|
self.split_options_iter('\n', self.len(), false)
|
||||||
@@ -2581,15 +2589,6 @@ impl<'self> StrSlice<'self> for &'self str {
|
|||||||
assert!(is_char_boundary(*self, end));
|
assert!(is_char_boundary(*self, end));
|
||||||
unsafe { raw::slice_bytes(*self, begin, end) }
|
unsafe { raw::slice_bytes(*self, begin, end) }
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* Splits a string into a vector of the substrings separated by a given
|
|
||||||
* string
|
|
||||||
*/
|
|
||||||
#[inline]
|
|
||||||
fn each_split_str<'a>(&self, sep: &'a str, it: &fn(&'self str) -> bool) -> bool {
|
|
||||||
each_split_str(*self, sep, it)
|
|
||||||
}
|
|
||||||
/// Returns true if one string starts with another
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn starts_with<'a>(&self, needle: &'a str) -> bool {
|
fn starts_with<'a>(&self, needle: &'a str) -> bool {
|
||||||
starts_with(*self, needle)
|
starts_with(*self, needle)
|
||||||
@@ -2836,30 +2835,6 @@ mod tests {
|
|||||||
let _cc3 = pop_char(&mut data);
|
let _cc3 = pop_char(&mut data);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_split_str() {
|
|
||||||
fn t<'a>(s: &str, sep: &'a str, u: &[~str]) {
|
|
||||||
let mut v = ~[];
|
|
||||||
for each_split_str(s, sep) |s| { v.push(s.to_owned()) }
|
|
||||||
assert!(v.iter().zip(u.iter()).all(|(a,b)| a == b));
|
|
||||||
}
|
|
||||||
t("--1233345--", "12345", [~"--1233345--"]);
|
|
||||||
t("abc::hello::there", "::", [~"abc", ~"hello", ~"there"]);
|
|
||||||
t("::hello::there", "::", [~"", ~"hello", ~"there"]);
|
|
||||||
t("hello::there::", "::", [~"hello", ~"there", ~""]);
|
|
||||||
t("::hello::there::", "::", [~"", ~"hello", ~"there", ~""]);
|
|
||||||
t("ประเทศไทย中华Việt Nam", "中华", [~"ประเทศไทย", ~"Việt Nam"]);
|
|
||||||
t("zzXXXzzYYYzz", "zz", [~"", ~"XXX", ~"YYY", ~""]);
|
|
||||||
t("zzXXXzYYYz", "XXX", [~"zz", ~"zYYYz"]);
|
|
||||||
t(".XXX.YYY.", ".", [~"", ~"XXX", ~"YYY", ~""]);
|
|
||||||
t("", ".", [~""]);
|
|
||||||
t("zz", "zz", [~"",~""]);
|
|
||||||
t("ok", "z", [~"ok"]);
|
|
||||||
t("zzz", "zz", [~"",~"z"]);
|
|
||||||
t("zzzzz", "zz", [~"",~"",~"z"]);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_split_within() {
|
fn test_split_within() {
|
||||||
fn t(s: &str, i: uint, u: &[~str]) {
|
fn t(s: &str, i: uint, u: &[~str]) {
|
||||||
@@ -3727,4 +3702,27 @@ mod tests {
|
|||||||
let lines: ~[&str] = data.line_iter().collect();
|
let lines: ~[&str] = data.line_iter().collect();
|
||||||
assert_eq!(lines, ~["", "Märy häd ä little lämb", "", "Little lämb"]);
|
assert_eq!(lines, ~["", "Märy häd ä little lämb", "", "Little lämb"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_split_str_iterator() {
|
||||||
|
fn t<'a>(s: &str, sep: &'a str, u: ~[&str]) {
|
||||||
|
let v: ~[&str] = s.split_str_iter(sep).collect();
|
||||||
|
assert_eq!(v, u);
|
||||||
|
}
|
||||||
|
t("--1233345--", "12345", ~["--1233345--"]);
|
||||||
|
t("abc::hello::there", "::", ~["abc", "hello", "there"]);
|
||||||
|
t("::hello::there", "::", ~["", "hello", "there"]);
|
||||||
|
t("hello::there::", "::", ~["hello", "there", ""]);
|
||||||
|
t("::hello::there::", "::", ~["", "hello", "there", ""]);
|
||||||
|
t("ประเทศไทย中华Việt Nam", "中华", ~["ประเทศไทย", "Việt Nam"]);
|
||||||
|
t("zzXXXzzYYYzz", "zz", ~["", "XXX", "YYY", ""]);
|
||||||
|
t("zzXXXzYYYz", "XXX", ~["zz", "zYYYz"]);
|
||||||
|
t(".XXX.YYY.", ".", ~["", "XXX", "YYY", ""]);
|
||||||
|
t("", ".", ~[""]);
|
||||||
|
t("zz", "zz", ~["",""]);
|
||||||
|
t("ok", "z", ~["ok"]);
|
||||||
|
t("zzz", "zz", ~["","z"]);
|
||||||
|
t("zzzzz", "zz", ~["","","z"]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user