std: convert character-based str::find_* to methods. Add .slice_{to,from} methods.
This commit is contained in:
parent
76fc9be5a1
commit
0cfc08d81e
9 changed files with 158 additions and 405 deletions
|
@ -417,7 +417,7 @@ fn scan_until_char(haystack: &str, needle: char, idx: &mut uint) -> bool {
|
||||||
if *idx >= haystack.len() {
|
if *idx >= haystack.len() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
let opt = str::find_char_from(haystack, needle, *idx);
|
let opt = haystack.slice_from(*idx).find(needle);
|
||||||
if opt.is_none() {
|
if opt.is_none() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -375,7 +375,7 @@ pub fn check_variants_T<T:Copy>(crate: @ast::crate,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn last_part(filename: ~str) -> ~str {
|
pub fn last_part(filename: ~str) -> ~str {
|
||||||
let ix = str::rfind_char(filename, '/').get();
|
let ix = filename.rfind('/').get();
|
||||||
filename.slice(ix + 1u, filename.len() - 3u).to_owned()
|
filename.slice(ix + 1u, filename.len() - 3u).to_owned()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -841,26 +841,11 @@ fn check_item_non_camel_case_types(cx: &Context, it: @ast::item) {
|
||||||
fn is_camel_case(cx: ty::ctxt, ident: ast::ident) -> bool {
|
fn is_camel_case(cx: ty::ctxt, ident: ast::ident) -> bool {
|
||||||
let ident = cx.sess.str_of(ident);
|
let ident = cx.sess.str_of(ident);
|
||||||
assert!(!ident.is_empty());
|
assert!(!ident.is_empty());
|
||||||
let ident = ident_without_trailing_underscores(*ident);
|
let ident = ident.trim_chars(&['_']);
|
||||||
let ident = ident_without_leading_underscores(ident);
|
|
||||||
char::is_uppercase(str::char_at(ident, 0)) &&
|
char::is_uppercase(str::char_at(ident, 0)) &&
|
||||||
!ident.contains_char('_')
|
!ident.contains_char('_')
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ident_without_trailing_underscores<'r>(ident: &'r str) -> &'r str {
|
|
||||||
match str::rfind(ident, |c| c != '_') {
|
|
||||||
Some(idx) => ident.slice(0, idx + 1),
|
|
||||||
None => ident, // all underscores
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn ident_without_leading_underscores<'r>(ident: &'r str) -> &'r str {
|
|
||||||
match str::find(ident, |c| c != '_') {
|
|
||||||
Some(idx) => ident.slice(idx, ident.len()),
|
|
||||||
None => ident // all underscores
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn check_case(cx: &Context, ident: ast::ident, span: span) {
|
fn check_case(cx: &Context, ident: ast::ident, span: span) {
|
||||||
if !is_camel_case(cx.tcx, ident) {
|
if !is_camel_case(cx.tcx, ident) {
|
||||||
cx.span_lint(non_camel_case_types, span,
|
cx.span_lint(non_camel_case_types, span,
|
||||||
|
|
|
@ -2681,7 +2681,7 @@ impl Resolver {
|
||||||
match module_prefix_result {
|
match module_prefix_result {
|
||||||
Failed => {
|
Failed => {
|
||||||
let mpath = self.idents_to_str(module_path);
|
let mpath = self.idents_to_str(module_path);
|
||||||
match str::rfind(self.idents_to_str(module_path), |c| { c == ':' }) {
|
match self.idents_to_str(module_path).rfind(':') {
|
||||||
Some(idx) => {
|
Some(idx) => {
|
||||||
self.session.span_err(span, fmt!("unresolved import: could not find `%s` \
|
self.session.span_err(span, fmt!("unresolved import: could not find `%s` \
|
||||||
in `%s`", str::substr(mpath, idx,
|
in `%s`", str::substr(mpath, idx,
|
||||||
|
|
|
@ -118,19 +118,17 @@ fn first_sentence_(s: &str) -> ~str {
|
||||||
let mut dotcount = 0;
|
let mut dotcount = 0;
|
||||||
// The index of the character following a single dot. This allows
|
// The index of the character following a single dot. This allows
|
||||||
// Things like [0..1) to appear in the brief description
|
// Things like [0..1) to appear in the brief description
|
||||||
let idx = do str::find(s) |ch| {
|
let idx = s.find(|ch: char| {
|
||||||
if ch == '.' {
|
if ch == '.' {
|
||||||
dotcount += 1;
|
dotcount += 1;
|
||||||
false
|
false
|
||||||
|
} else if dotcount == 1 {
|
||||||
|
true
|
||||||
} else {
|
} else {
|
||||||
if dotcount == 1 {
|
dotcount = 0;
|
||||||
true
|
false
|
||||||
} else {
|
|
||||||
dotcount = 0;
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
});
|
||||||
match idx {
|
match idx {
|
||||||
Some(idx) if idx > 2u => {
|
Some(idx) if idx > 2u => {
|
||||||
str::to_owned(s.slice(0, idx - 1))
|
str::to_owned(s.slice(0, idx - 1))
|
||||||
|
|
|
@ -175,7 +175,7 @@ pub fn split_version<'a>(s: &'a str) -> Option<(&'a str, Version)> {
|
||||||
if { let mut i: uint = 0; for str::to_chars(s).each |&c| { if c == '#' { i += 1; } }; i > 1 } {
|
if { let mut i: uint = 0; for str::to_chars(s).each |&c| { if c == '#' { i += 1; } }; i > 1 } {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
match str::rfind_char(s, '#') {
|
match s.rfind('#') {
|
||||||
Some(i) => {
|
Some(i) => {
|
||||||
debug!("in %s, i = %?", s, i);
|
debug!("in %s, i = %?", s, i);
|
||||||
let path = s.slice(0, i);
|
let path = s.slice(0, i);
|
||||||
|
|
|
@ -479,8 +479,8 @@ impl GenericPath for PosixPath {
|
||||||
match self.filename() {
|
match self.filename() {
|
||||||
None => None,
|
None => None,
|
||||||
Some(ref f) => {
|
Some(ref f) => {
|
||||||
match str::rfind_char(*f, '.') {
|
match f.rfind('.') {
|
||||||
Some(p) => Some(f.slice(0, p).to_owned()),
|
Some(p) => Some(f.slice_to(p).to_owned()),
|
||||||
None => Some(copy *f),
|
None => Some(copy *f),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -491,8 +491,8 @@ impl GenericPath for PosixPath {
|
||||||
match self.filename() {
|
match self.filename() {
|
||||||
None => None,
|
None => None,
|
||||||
Some(ref f) => {
|
Some(ref f) => {
|
||||||
match str::rfind_char(*f, '.') {
|
match f.rfind('.') {
|
||||||
Some(p) if p < f.len() => Some(f.slice(p, f.len()).to_owned()),
|
Some(p) if p < f.len() => Some(f.slice_from(p).to_owned()),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -693,8 +693,8 @@ impl GenericPath for WindowsPath {
|
||||||
match self.filename() {
|
match self.filename() {
|
||||||
None => None,
|
None => None,
|
||||||
Some(ref f) => {
|
Some(ref f) => {
|
||||||
match str::rfind_char(*f, '.') {
|
match f.rfind('.') {
|
||||||
Some(p) => Some(f.slice(0, p).to_owned()),
|
Some(p) => Some(f.slice_to(p).to_owned()),
|
||||||
None => Some(copy *f),
|
None => Some(copy *f),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -705,8 +705,8 @@ impl GenericPath for WindowsPath {
|
||||||
match self.filename() {
|
match self.filename() {
|
||||||
None => None,
|
None => None,
|
||||||
Some(ref f) => {
|
Some(ref f) => {
|
||||||
match str::rfind_char(*f, '.') {
|
match f.rfind('.') {
|
||||||
Some(p) if p < f.len() => Some(f.slice(p, f.len()).to_owned()),
|
Some(p) if p < f.len() => Some(f.slice_from(p).to_owned()),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@ use at_vec;
|
||||||
use cast::transmute;
|
use cast::transmute;
|
||||||
use cast;
|
use cast;
|
||||||
use char;
|
use char;
|
||||||
|
use char::Char;
|
||||||
use clone::Clone;
|
use clone::Clone;
|
||||||
use cmp::{TotalOrd, Ordering, Less, Equal, Greater};
|
use cmp::{TotalOrd, Ordering, Less, Equal, Greater};
|
||||||
use container::Container;
|
use container::Container;
|
||||||
|
@ -510,7 +511,7 @@ pub fn unshift_char(s: &mut ~str, ch: char) {
|
||||||
pub fn trim_left_chars<'a>(s: &'a str, chars_to_trim: &[char]) -> &'a str {
|
pub fn trim_left_chars<'a>(s: &'a str, chars_to_trim: &[char]) -> &'a str {
|
||||||
if chars_to_trim.is_empty() { return s; }
|
if chars_to_trim.is_empty() { return s; }
|
||||||
|
|
||||||
match find(s, |c| !chars_to_trim.contains(&c)) {
|
match s.find(|c| !chars_to_trim.contains(&c)) {
|
||||||
None => "",
|
None => "",
|
||||||
Some(first) => unsafe { raw::slice_bytes(s, first, s.len()) }
|
Some(first) => unsafe { raw::slice_bytes(s, first, s.len()) }
|
||||||
}
|
}
|
||||||
|
@ -528,7 +529,7 @@ pub fn trim_left_chars<'a>(s: &'a str, chars_to_trim: &[char]) -> &'a str {
|
||||||
pub fn trim_right_chars<'a>(s: &'a str, chars_to_trim: &[char]) -> &'a str {
|
pub fn trim_right_chars<'a>(s: &'a str, chars_to_trim: &[char]) -> &'a str {
|
||||||
if chars_to_trim.is_empty() { return s; }
|
if chars_to_trim.is_empty() { return s; }
|
||||||
|
|
||||||
match rfind(s, |c| !chars_to_trim.contains(&c)) {
|
match s.rfind(|c| !chars_to_trim.contains(&c)) {
|
||||||
None => "",
|
None => "",
|
||||||
Some(last) => {
|
Some(last) => {
|
||||||
let next = char_range_at(s, last).next;
|
let next = char_range_at(s, last).next;
|
||||||
|
@ -552,7 +553,7 @@ pub fn trim_chars<'a>(s: &'a str, chars_to_trim: &[char]) -> &'a str {
|
||||||
|
|
||||||
/// Returns a string with leading whitespace removed
|
/// Returns a string with leading whitespace removed
|
||||||
pub fn trim_left<'a>(s: &'a str) -> &'a str {
|
pub fn trim_left<'a>(s: &'a str) -> &'a str {
|
||||||
match find(s, |c| !char::is_whitespace(c)) {
|
match s.find(|c| !char::is_whitespace(c)) {
|
||||||
None => "",
|
None => "",
|
||||||
Some(first) => unsafe { raw::slice_bytes(s, first, s.len()) }
|
Some(first) => unsafe { raw::slice_bytes(s, first, s.len()) }
|
||||||
}
|
}
|
||||||
|
@ -560,7 +561,7 @@ pub fn trim_left<'a>(s: &'a str) -> &'a str {
|
||||||
|
|
||||||
/// Returns a string with trailing whitespace removed
|
/// Returns a string with trailing whitespace removed
|
||||||
pub fn trim_right<'a>(s: &'a str) -> &'a str {
|
pub fn trim_right<'a>(s: &'a str) -> &'a str {
|
||||||
match rfind(s, |c| !char::is_whitespace(c)) {
|
match s.rfind(|c| !char::is_whitespace(c)) {
|
||||||
None => "",
|
None => "",
|
||||||
Some(last) => {
|
Some(last) => {
|
||||||
let next = char_range_at(s, last).next;
|
let next = char_range_at(s, last).next;
|
||||||
|
@ -621,6 +622,34 @@ pub fn substr<'a>(s: &'a str, begin: uint, n: uint) -> &'a str {
|
||||||
s.slice(begin, begin + count_bytes(s, begin, n))
|
s.slice(begin, begin + count_bytes(s, begin, n))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Something that can be used to compare against a character
|
||||||
|
pub trait CharEq {
|
||||||
|
/// Determine if the splitter should split at the given character
|
||||||
|
fn matches(&self, char) -> bool;
|
||||||
|
/// Indicate if this is only concerned about ASCII characters,
|
||||||
|
/// which can allow for a faster implementation.
|
||||||
|
fn only_ascii(&self) -> bool;
|
||||||
|
}
|
||||||
|
impl CharEq for char {
|
||||||
|
#[inline(always)]
|
||||||
|
fn matches(&self, c: char) -> bool { *self == c }
|
||||||
|
|
||||||
|
fn only_ascii(&self) -> bool { (*self as uint) < 128 }
|
||||||
|
}
|
||||||
|
impl<'self> CharEq for &'self fn(char) -> bool {
|
||||||
|
#[inline(always)]
|
||||||
|
fn matches(&self, c: char) -> bool { (*self)(c) }
|
||||||
|
|
||||||
|
fn only_ascii(&self) -> bool { false }
|
||||||
|
}
|
||||||
|
impl CharEq for extern "Rust" fn(char) -> bool {
|
||||||
|
#[inline(always)]
|
||||||
|
fn matches(&self, c: char) -> bool { (*self)(c) }
|
||||||
|
|
||||||
|
fn only_ascii(&self) -> bool { false }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// An iterator over the substrings of a string, separated by `sep`.
|
/// An iterator over the substrings of a string, separated by `sep`.
|
||||||
pub struct StrCharSplitIterator<'self,Sep> {
|
pub struct StrCharSplitIterator<'self,Sep> {
|
||||||
priv string: &'self str,
|
priv string: &'self str,
|
||||||
|
@ -639,34 +668,7 @@ pub type WordIterator<'self> =
|
||||||
FilterIterator<'self, &'self str,
|
FilterIterator<'self, &'self str,
|
||||||
StrCharSplitIterator<'self, extern "Rust" fn(char) -> bool>>;
|
StrCharSplitIterator<'self, extern "Rust" fn(char) -> bool>>;
|
||||||
|
|
||||||
/// A separator for splitting a string character-wise
|
impl<'self, Sep: CharEq> Iterator<&'self str> for StrCharSplitIterator<'self, Sep> {
|
||||||
pub trait StrCharSplitSeparator {
|
|
||||||
/// Determine if the splitter should split at the given character
|
|
||||||
fn should_split(&self, char) -> bool;
|
|
||||||
/// Indicate if the splitter only uses ASCII characters, which
|
|
||||||
/// allows for a faster implementation.
|
|
||||||
fn only_ascii(&self) -> bool;
|
|
||||||
}
|
|
||||||
impl StrCharSplitSeparator for char {
|
|
||||||
#[inline(always)]
|
|
||||||
fn should_split(&self, c: char) -> bool { *self == c }
|
|
||||||
|
|
||||||
fn only_ascii(&self) -> bool { (*self as uint) < 128 }
|
|
||||||
}
|
|
||||||
impl<'self> StrCharSplitSeparator for &'self fn(char) -> bool {
|
|
||||||
#[inline(always)]
|
|
||||||
fn should_split(&self, c: char) -> bool { (*self)(c) }
|
|
||||||
|
|
||||||
fn only_ascii(&self) -> bool { false }
|
|
||||||
}
|
|
||||||
impl<'self> StrCharSplitSeparator for extern "Rust" fn(char) -> bool {
|
|
||||||
#[inline(always)]
|
|
||||||
fn should_split(&self, c: char) -> bool { (*self)(c) }
|
|
||||||
|
|
||||||
fn only_ascii(&self) -> bool { false }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'self, Sep: StrCharSplitSeparator> Iterator<&'self str> for StrCharSplitIterator<'self, Sep> {
|
|
||||||
#[inline]
|
#[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 }
|
||||||
|
@ -680,7 +682,7 @@ impl<'self, Sep: StrCharSplitSeparator> Iterator<&'self str> for StrCharSplitIte
|
||||||
while self.position < l && self.count > 0 {
|
while self.position < l && self.count > 0 {
|
||||||
let byte = self.string[self.position];
|
let byte = self.string[self.position];
|
||||||
|
|
||||||
if self.sep.should_split(byte as char) {
|
if self.sep.matches(byte as char) {
|
||||||
let slice = unsafe { raw::slice_bytes(self.string, start, self.position) };
|
let slice = unsafe { raw::slice_bytes(self.string, start, self.position) };
|
||||||
self.position += 1;
|
self.position += 1;
|
||||||
self.count -= 1;
|
self.count -= 1;
|
||||||
|
@ -692,7 +694,7 @@ impl<'self, Sep: StrCharSplitSeparator> Iterator<&'self str> for StrCharSplitIte
|
||||||
while self.position < l && self.count > 0 {
|
while self.position < l && self.count > 0 {
|
||||||
let CharRange {ch, next} = char_range_at(self.string, self.position);
|
let CharRange {ch, next} = char_range_at(self.string, self.position);
|
||||||
|
|
||||||
if self.sep.should_split(ch) {
|
if self.sep.matches(ch) {
|
||||||
let slice = unsafe { raw::slice_bytes(self.string, start, self.position) };
|
let slice = unsafe { raw::slice_bytes(self.string, start, self.position) };
|
||||||
self.position = next;
|
self.position = next;
|
||||||
self.count -= 1;
|
self.count -= 1;
|
||||||
|
@ -1157,318 +1159,6 @@ pub fn map(ss: &str, ff: &fn(char) -> char) -> ~str {
|
||||||
Section: Searching
|
Section: Searching
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the byte index of the first matching character
|
|
||||||
*
|
|
||||||
* # Arguments
|
|
||||||
*
|
|
||||||
* * `s` - The string to search
|
|
||||||
* * `c` - The character to search for
|
|
||||||
*
|
|
||||||
* # Return value
|
|
||||||
*
|
|
||||||
* An `option` containing the byte index of the first matching character
|
|
||||||
* or `none` if there is no match
|
|
||||||
*/
|
|
||||||
pub fn find_char(s: &str, c: char) -> Option<uint> {
|
|
||||||
find_char_between(s, c, 0u, s.len())
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the byte index of the first matching character beginning
|
|
||||||
* from a given byte offset
|
|
||||||
*
|
|
||||||
* # Arguments
|
|
||||||
*
|
|
||||||
* * `s` - The string to search
|
|
||||||
* * `c` - The character to search for
|
|
||||||
* * `start` - The byte index to begin searching at, inclusive
|
|
||||||
*
|
|
||||||
* # Return value
|
|
||||||
*
|
|
||||||
* An `option` containing the byte index of the first matching character
|
|
||||||
* or `none` if there is no match
|
|
||||||
*
|
|
||||||
* # Failure
|
|
||||||
*
|
|
||||||
* `start` must be less than or equal to `s.len()`. `start` must be the
|
|
||||||
* index of a character boundary, as defined by `is_char_boundary`.
|
|
||||||
*/
|
|
||||||
pub fn find_char_from(s: &str, c: char, start: uint) -> Option<uint> {
|
|
||||||
find_char_between(s, c, start, s.len())
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the byte index of the first matching character within a given range
|
|
||||||
*
|
|
||||||
* # Arguments
|
|
||||||
*
|
|
||||||
* * `s` - The string to search
|
|
||||||
* * `c` - The character to search for
|
|
||||||
* * `start` - The byte index to begin searching at, inclusive
|
|
||||||
* * `end` - The byte index to end searching at, exclusive
|
|
||||||
*
|
|
||||||
* # Return value
|
|
||||||
*
|
|
||||||
* An `option` containing the byte index of the first matching character
|
|
||||||
* or `none` if there is no match
|
|
||||||
*
|
|
||||||
* # Failure
|
|
||||||
*
|
|
||||||
* `start` must be less than or equal to `end` and `end` must be less than
|
|
||||||
* or equal to `s.len()`. `start` must be the index of a character boundary,
|
|
||||||
* as defined by `is_char_boundary`.
|
|
||||||
*/
|
|
||||||
pub fn find_char_between(s: &str, c: char, start: uint, end: uint)
|
|
||||||
-> Option<uint> {
|
|
||||||
if c < 128u as char {
|
|
||||||
assert!(start <= end);
|
|
||||||
assert!(end <= s.len());
|
|
||||||
let mut i = start;
|
|
||||||
let b = c as u8;
|
|
||||||
while i < end {
|
|
||||||
if s[i] == b { return Some(i); }
|
|
||||||
i += 1u;
|
|
||||||
}
|
|
||||||
return None;
|
|
||||||
} else {
|
|
||||||
find_between(s, start, end, |x| x == c)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the byte index of the last matching character
|
|
||||||
*
|
|
||||||
* # Arguments
|
|
||||||
*
|
|
||||||
* * `s` - The string to search
|
|
||||||
* * `c` - The character to search for
|
|
||||||
*
|
|
||||||
* # Return value
|
|
||||||
*
|
|
||||||
* An `option` containing the byte index of the last matching character
|
|
||||||
* or `none` if there is no match
|
|
||||||
*/
|
|
||||||
pub fn rfind_char(s: &str, c: char) -> Option<uint> {
|
|
||||||
rfind_char_between(s, c, s.len(), 0u)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the byte index of the last matching character beginning
|
|
||||||
* from a given byte offset
|
|
||||||
*
|
|
||||||
* # Arguments
|
|
||||||
*
|
|
||||||
* * `s` - The string to search
|
|
||||||
* * `c` - The character to search for
|
|
||||||
* * `start` - The byte index to begin searching at, exclusive
|
|
||||||
*
|
|
||||||
* # Return value
|
|
||||||
*
|
|
||||||
* An `option` containing the byte index of the last matching character
|
|
||||||
* or `none` if there is no match
|
|
||||||
*
|
|
||||||
* # Failure
|
|
||||||
*
|
|
||||||
* `start` must be less than or equal to `s.len()`. `start` must be
|
|
||||||
* the index of a character boundary, as defined by `is_char_boundary`.
|
|
||||||
*/
|
|
||||||
pub fn rfind_char_from(s: &str, c: char, start: uint) -> Option<uint> {
|
|
||||||
rfind_char_between(s, c, start, 0u)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the byte index of the last matching character within a given range
|
|
||||||
*
|
|
||||||
* # Arguments
|
|
||||||
*
|
|
||||||
* * `s` - The string to search
|
|
||||||
* * `c` - The character to search for
|
|
||||||
* * `start` - The byte index to begin searching at, exclusive
|
|
||||||
* * `end` - The byte index to end searching at, inclusive
|
|
||||||
*
|
|
||||||
* # Return value
|
|
||||||
*
|
|
||||||
* An `option` containing the byte index of the last matching character
|
|
||||||
* or `none` if there is no match
|
|
||||||
*
|
|
||||||
* # Failure
|
|
||||||
*
|
|
||||||
* `end` must be less than or equal to `start` and `start` must be less than
|
|
||||||
* or equal to `s.len()`. `start` must be the index of a character boundary,
|
|
||||||
* as defined by `is_char_boundary`.
|
|
||||||
*/
|
|
||||||
pub fn rfind_char_between(s: &str, c: char, start: uint, end: uint) -> Option<uint> {
|
|
||||||
if c < 128u as char {
|
|
||||||
assert!(start >= end);
|
|
||||||
assert!(start <= s.len());
|
|
||||||
let mut i = start;
|
|
||||||
let b = c as u8;
|
|
||||||
while i > end {
|
|
||||||
i -= 1u;
|
|
||||||
if s[i] == b { return Some(i); }
|
|
||||||
}
|
|
||||||
return None;
|
|
||||||
} else {
|
|
||||||
rfind_between(s, start, end, |x| x == c)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the byte index of the first character that satisfies
|
|
||||||
* the given predicate
|
|
||||||
*
|
|
||||||
* # Arguments
|
|
||||||
*
|
|
||||||
* * `s` - The string to search
|
|
||||||
* * `f` - The predicate to satisfy
|
|
||||||
*
|
|
||||||
* # Return value
|
|
||||||
*
|
|
||||||
* An `option` containing the byte index of the first matching character
|
|
||||||
* or `none` if there is no match
|
|
||||||
*/
|
|
||||||
pub fn find(s: &str, f: &fn(char) -> bool) -> Option<uint> {
|
|
||||||
find_between(s, 0u, s.len(), f)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the byte index of the first character that satisfies
|
|
||||||
* the given predicate, beginning from a given byte offset
|
|
||||||
*
|
|
||||||
* # Arguments
|
|
||||||
*
|
|
||||||
* * `s` - The string to search
|
|
||||||
* * `start` - The byte index to begin searching at, inclusive
|
|
||||||
* * `f` - The predicate to satisfy
|
|
||||||
*
|
|
||||||
* # Return value
|
|
||||||
*
|
|
||||||
* An `option` containing the byte index of the first matching charactor
|
|
||||||
* or `none` if there is no match
|
|
||||||
*
|
|
||||||
* # Failure
|
|
||||||
*
|
|
||||||
* `start` must be less than or equal to `s.len()`. `start` must be the
|
|
||||||
* index of a character boundary, as defined by `is_char_boundary`.
|
|
||||||
*/
|
|
||||||
pub fn find_from(s: &str, start: uint, f: &fn(char)
|
|
||||||
-> bool) -> Option<uint> {
|
|
||||||
find_between(s, start, s.len(), f)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the byte index of the first character that satisfies
|
|
||||||
* the given predicate, within a given range
|
|
||||||
*
|
|
||||||
* # Arguments
|
|
||||||
*
|
|
||||||
* * `s` - The string to search
|
|
||||||
* * `start` - The byte index to begin searching at, inclusive
|
|
||||||
* * `end` - The byte index to end searching at, exclusive
|
|
||||||
* * `f` - The predicate to satisfy
|
|
||||||
*
|
|
||||||
* # Return value
|
|
||||||
*
|
|
||||||
* An `option` containing the byte index of the first matching character
|
|
||||||
* or `none` if there is no match
|
|
||||||
*
|
|
||||||
* # Failure
|
|
||||||
*
|
|
||||||
* `start` must be less than or equal to `end` and `end` must be less than
|
|
||||||
* or equal to `s.len()`. `start` must be the index of a character
|
|
||||||
* boundary, as defined by `is_char_boundary`.
|
|
||||||
*/
|
|
||||||
pub fn find_between(s: &str, start: uint, end: uint, f: &fn(char) -> bool) -> Option<uint> {
|
|
||||||
assert!(start <= end);
|
|
||||||
assert!(end <= s.len());
|
|
||||||
assert!(is_char_boundary(s, start));
|
|
||||||
let mut i = start;
|
|
||||||
while i < end {
|
|
||||||
let CharRange {ch, next} = char_range_at(s, i);
|
|
||||||
if f(ch) { return Some(i); }
|
|
||||||
i = next;
|
|
||||||
}
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the byte index of the last character that satisfies
|
|
||||||
* the given predicate
|
|
||||||
*
|
|
||||||
* # Arguments
|
|
||||||
*
|
|
||||||
* * `s` - The string to search
|
|
||||||
* * `f` - The predicate to satisfy
|
|
||||||
*
|
|
||||||
* # Return value
|
|
||||||
*
|
|
||||||
* An option containing the byte index of the last matching character
|
|
||||||
* or `none` if there is no match
|
|
||||||
*/
|
|
||||||
pub fn rfind(s: &str, f: &fn(char) -> bool) -> Option<uint> {
|
|
||||||
rfind_between(s, s.len(), 0u, f)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the byte index of the last character that satisfies
|
|
||||||
* the given predicate, beginning from a given byte offset
|
|
||||||
*
|
|
||||||
* # Arguments
|
|
||||||
*
|
|
||||||
* * `s` - The string to search
|
|
||||||
* * `start` - The byte index to begin searching at, exclusive
|
|
||||||
* * `f` - The predicate to satisfy
|
|
||||||
*
|
|
||||||
* # Return value
|
|
||||||
*
|
|
||||||
* An `option` containing the byte index of the last matching character
|
|
||||||
* or `none` if there is no match
|
|
||||||
*
|
|
||||||
* # Failure
|
|
||||||
*
|
|
||||||
* `start` must be less than or equal to `s.len()', `start` must be the
|
|
||||||
* index of a character boundary, as defined by `is_char_boundary`
|
|
||||||
*/
|
|
||||||
pub fn rfind_from(s: &str, start: uint, f: &fn(char) -> bool) -> Option<uint> {
|
|
||||||
rfind_between(s, start, 0u, f)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the byte index of the last character that satisfies
|
|
||||||
* the given predicate, within a given range
|
|
||||||
*
|
|
||||||
* # Arguments
|
|
||||||
*
|
|
||||||
* * `s` - The string to search
|
|
||||||
* * `start` - The byte index to begin searching at, exclusive
|
|
||||||
* * `end` - The byte index to end searching at, inclusive
|
|
||||||
* * `f` - The predicate to satisfy
|
|
||||||
*
|
|
||||||
* # Return value
|
|
||||||
*
|
|
||||||
* An `option` containing the byte index of the last matching character
|
|
||||||
* or `none` if there is no match
|
|
||||||
*
|
|
||||||
* # Failure
|
|
||||||
*
|
|
||||||
* `end` must be less than or equal to `start` and `start` must be less
|
|
||||||
* than or equal to `s.len()`. `start` must be the index of a character
|
|
||||||
* boundary, as defined by `is_char_boundary`
|
|
||||||
*/
|
|
||||||
pub fn rfind_between(s: &str, start: uint, end: uint, f: &fn(char) -> bool) -> Option<uint> {
|
|
||||||
assert!(start >= end);
|
|
||||||
assert!(start <= s.len());
|
|
||||||
assert!(is_char_boundary(s, start));
|
|
||||||
let mut i = start;
|
|
||||||
while i > end {
|
|
||||||
let CharRange {ch, next: prev} = char_range_at_reverse(s, i);
|
|
||||||
if f(ch) { return Some(prev); }
|
|
||||||
i = prev;
|
|
||||||
}
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Utility used by various searching functions
|
// Utility used by various searching functions
|
||||||
fn match_at<'a,'b>(haystack: &'a str, needle: &'b str, at: uint) -> bool {
|
fn match_at<'a,'b>(haystack: &'a str, needle: &'b str, at: uint) -> bool {
|
||||||
let mut i = at;
|
let mut i = at;
|
||||||
|
@ -1580,7 +1270,7 @@ pub fn contains<'a,'b>(haystack: &'a str, needle: &'b str) -> bool {
|
||||||
* * needle - The char to look for
|
* * needle - The char to look for
|
||||||
*/
|
*/
|
||||||
pub fn contains_char(haystack: &str, needle: char) -> bool {
|
pub fn contains_char(haystack: &str, needle: char) -> bool {
|
||||||
find_char(haystack, needle).is_some()
|
haystack.find(needle).is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2415,11 +2105,9 @@ pub trait StrSlice<'self> {
|
||||||
fn rev_iter(&self) -> StrCharRevIterator<'self>;
|
fn rev_iter(&self) -> StrCharRevIterator<'self>;
|
||||||
fn bytes_iter(&self) -> StrBytesIterator<'self>;
|
fn bytes_iter(&self) -> StrBytesIterator<'self>;
|
||||||
fn bytes_rev_iter(&self) -> StrBytesRevIterator<'self>;
|
fn bytes_rev_iter(&self) -> StrBytesRevIterator<'self>;
|
||||||
fn split_iter<Sep: StrCharSplitSeparator>(&self, sep: Sep) -> StrCharSplitIterator<'self, Sep>;
|
fn split_iter<Sep: CharEq>(&self, sep: Sep) -> StrCharSplitIterator<'self, Sep>;
|
||||||
fn splitn_iter<Sep: StrCharSplitSeparator>(&self, sep: Sep, count: uint)
|
fn splitn_iter<Sep: CharEq>(&self, sep: Sep, count: uint) -> StrCharSplitIterator<'self, Sep>;
|
||||||
-> StrCharSplitIterator<'self, Sep>;
|
fn split_options_iter<Sep: CharEq>(&self, sep: Sep, count: uint, allow_trailing_empty: bool)
|
||||||
fn split_options_iter<Sep: StrCharSplitSeparator>(&self, sep: Sep,
|
|
||||||
count: uint, allow_trailing_empty: bool)
|
|
||||||
-> StrCharSplitIterator<'self, Sep>;
|
-> StrCharSplitIterator<'self, Sep>;
|
||||||
/// An iterator over the start and end indices of each match of
|
/// An iterator over the start and end indices of each match of
|
||||||
/// `sep` within `self`.
|
/// `sep` within `self`.
|
||||||
|
@ -2448,6 +2136,8 @@ 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 slice_from(&self, begin: uint) -> &'self str;
|
||||||
|
fn slice_to(&self, end: uint) -> &'self str;
|
||||||
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;
|
||||||
|
@ -2463,6 +2153,9 @@ pub trait StrSlice<'self> {
|
||||||
fn char_at(&self, i: uint) -> char;
|
fn char_at(&self, i: uint) -> char;
|
||||||
fn char_at_reverse(&self, i: uint) -> char;
|
fn char_at_reverse(&self, i: uint) -> char;
|
||||||
fn to_bytes(&self) -> ~[u8];
|
fn to_bytes(&self) -> ~[u8];
|
||||||
|
|
||||||
|
fn find<C: CharEq>(&self, search: C) -> Option<uint>;
|
||||||
|
fn rfind<C: CharEq>(&self, search: C) -> Option<uint>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Extension methods for strings
|
/// Extension methods for strings
|
||||||
|
@ -2500,16 +2193,14 @@ impl<'self> StrSlice<'self> for &'self str {
|
||||||
StrBytesRevIterator { it: as_bytes_slice(*self).rev_iter() }
|
StrBytesRevIterator { it: as_bytes_slice(*self).rev_iter() }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn split_iter<Sep: StrCharSplitSeparator>(&self, sep: Sep) -> StrCharSplitIterator<'self, Sep> {
|
fn split_iter<Sep: CharEq>(&self, sep: Sep) -> StrCharSplitIterator<'self, Sep> {
|
||||||
self.split_options_iter(sep, self.len(), true)
|
self.split_options_iter(sep, self.len(), true)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn splitn_iter<Sep: StrCharSplitSeparator>(&self, sep: Sep, count: uint)
|
fn splitn_iter<Sep: CharEq>(&self, sep: Sep, count: uint) -> StrCharSplitIterator<'self, Sep> {
|
||||||
-> StrCharSplitIterator<'self, Sep> {
|
|
||||||
self.split_options_iter(sep, count, true)
|
self.split_options_iter(sep, count, true)
|
||||||
}
|
}
|
||||||
fn split_options_iter<Sep: StrCharSplitSeparator>(&self, sep: Sep,
|
fn split_options_iter<Sep: CharEq>(&self, sep: Sep, count: uint, allow_trailing_empty: bool)
|
||||||
count: uint, allow_trailing_empty: bool)
|
|
||||||
-> StrCharSplitIterator<'self, Sep> {
|
-> StrCharSplitIterator<'self, Sep> {
|
||||||
let only_ascii = sep.only_ascii();
|
let only_ascii = sep.only_ascii();
|
||||||
StrCharSplitIterator {
|
StrCharSplitIterator {
|
||||||
|
@ -2590,6 +2281,14 @@ impl<'self> StrSlice<'self> for &'self str {
|
||||||
unsafe { raw::slice_bytes(*self, begin, end) }
|
unsafe { raw::slice_bytes(*self, begin, end) }
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
|
fn slice_from(&self, begin: uint) -> &'self str {
|
||||||
|
self.slice(begin, self.len())
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
fn slice_to(&self, end: uint) -> &'self str {
|
||||||
|
self.slice(0, end)
|
||||||
|
}
|
||||||
|
#[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)
|
||||||
}
|
}
|
||||||
|
@ -2654,6 +2353,54 @@ impl<'self> StrSlice<'self> for &'self str {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_bytes(&self) -> ~[u8] { to_bytes(*self) }
|
fn to_bytes(&self) -> ~[u8] { to_bytes(*self) }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the byte index of the first character of `self` that matches `search`
|
||||||
|
*
|
||||||
|
* # Return value
|
||||||
|
*
|
||||||
|
* `Some` containing the byte index of the last matching character
|
||||||
|
* or `None` if there is no match
|
||||||
|
*/
|
||||||
|
fn find<C: CharEq>(&self, search: C) -> Option<uint> {
|
||||||
|
if search.only_ascii() {
|
||||||
|
for self.bytes_iter().enumerate().advance |(i, b)| {
|
||||||
|
if search.matches(b as char) { return Some(i) }
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let mut index = 0;
|
||||||
|
for self.iter().advance |c| {
|
||||||
|
if search.matches(c) { return Some(index); }
|
||||||
|
index += c.len_utf8_bytes();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Returns the byte index of the last character of `self` that matches `search`
|
||||||
|
*
|
||||||
|
* # Return value
|
||||||
|
*
|
||||||
|
* `Some` containing the byte index of the last matching character
|
||||||
|
* or `None` if there is no match
|
||||||
|
*/
|
||||||
|
fn rfind<C: CharEq>(&self, search: C) -> Option<uint> {
|
||||||
|
let mut index = self.len();
|
||||||
|
if search.only_ascii() {
|
||||||
|
for self.bytes_rev_iter().advance |b| {
|
||||||
|
index -= 1;
|
||||||
|
if search.matches(b as char) { return Some(index); }
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for self.rev_iter().advance |c| {
|
||||||
|
index -= c.len_utf8_bytes();
|
||||||
|
if search.matches(c) { return Some(index); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(missing_doc)]
|
#[allow(missing_doc)]
|
||||||
|
@ -2803,12 +2550,23 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_rfind_char() {
|
fn test_find() {
|
||||||
assert_eq!(rfind_char("hello", 'l'), Some(3u));
|
assert_eq!("hello".find('l'), Some(2u));
|
||||||
assert_eq!(rfind_char("hello", 'o'), Some(4u));
|
assert_eq!("hello".find(|c:char| c == 'o'), Some(4u));
|
||||||
assert_eq!(rfind_char("hello", 'h'), Some(0u));
|
assert!("hello".find('x').is_none());
|
||||||
assert!(rfind_char("hello", 'z').is_none());
|
assert!("hello".find(|c:char| c == 'x').is_none());
|
||||||
assert_eq!(rfind_char("ประเทศไทย中华Việt Nam", '华'), Some(30u));
|
assert_eq!("ประเทศไทย中华Việt Nam".find('华'), Some(30u));
|
||||||
|
assert_eq!("ประเทศไทย中华Việt Nam".find(|c: char| c == '华'), Some(30u));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_rfind() {
|
||||||
|
assert_eq!("hello".rfind('l'), Some(3u));
|
||||||
|
assert_eq!("hello".rfind(|c:char| c == 'o'), Some(4u));
|
||||||
|
assert!("hello".rfind('x').is_none());
|
||||||
|
assert!("hello".rfind(|c:char| c == 'x').is_none());
|
||||||
|
assert_eq!("ประเทศไทย中华Việt Nam".rfind('华'), Some(30u));
|
||||||
|
assert_eq!("ประเทศไทย中华Việt Nam".rfind(|c: char| c == '华'), Some(30u));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -3122,6 +2880,19 @@ mod tests {
|
||||||
"中华Việt Nam".slice(0u, 2u);
|
"中华Việt Nam".slice(0u, 2u);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_slice_from() {
|
||||||
|
assert_eq!("abcd".slice_from(0), "abcd");
|
||||||
|
assert_eq!("abcd".slice_from(2), "cd");
|
||||||
|
assert_eq!("abcd".slice_from(4), "");
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn test_slice_to() {
|
||||||
|
assert_eq!("abcd".slice_to(0), "");
|
||||||
|
assert_eq!("abcd".slice_to(2), "ab");
|
||||||
|
assert_eq!("abcd".slice_to(4), "abcd");
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_trim_left_chars() {
|
fn test_trim_left_chars() {
|
||||||
assert!(trim_left_chars(" *** foo *** ", []) == " *** foo *** ");
|
assert!(trim_left_chars(" *** foo *** ", []) == " *** foo *** ");
|
||||||
|
|
|
@ -24,7 +24,6 @@ source code snippets, etc.
|
||||||
use core::prelude::*;
|
use core::prelude::*;
|
||||||
|
|
||||||
use core::cmp;
|
use core::cmp;
|
||||||
use core::str;
|
|
||||||
use core::to_bytes;
|
use core::to_bytes;
|
||||||
use core::uint;
|
use core::uint;
|
||||||
use extra::serialize::{Encodable, Decodable, Encoder, Decoder};
|
use extra::serialize::{Encodable, Decodable, Encoder, Decoder};
|
||||||
|
@ -288,11 +287,11 @@ impl FileMap {
|
||||||
pub fn get_line(&self, line: int) -> ~str {
|
pub fn get_line(&self, line: int) -> ~str {
|
||||||
let begin: BytePos = self.lines[line] - self.start_pos;
|
let begin: BytePos = self.lines[line] - self.start_pos;
|
||||||
let begin = begin.to_uint();
|
let begin = begin.to_uint();
|
||||||
let end = match str::find_char_from(*self.src, '\n', begin) {
|
let slice = self.src.slice_from(begin);
|
||||||
Some(e) => e,
|
match slice.find('\n') {
|
||||||
None => self.src.len()
|
Some(e) => slice.slice_to(e).to_owned(),
|
||||||
};
|
None => slice.to_owned()
|
||||||
self.src.slice(begin, end).to_owned()
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn record_multibyte_char(&self, pos: BytePos, bytes: uint) {
|
pub fn record_multibyte_char(&self, pos: BytePos, bytes: uint) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue