auto merge of #5479 : Kimundi/rust/str-dealloc, r=z0w0

This makes the `trim` and `substr` functions return a slice instead of an `~str`, and removes the unnecessary `Trimmable` trait (`StrSlice` already contains the same functionality).

Also moves the `ToStr` implementations for the three str types into the str module in anticipation of further untangling.
This commit is contained in:
bors 2013-03-21 19:39:53 -07:00
commit 5f2d4102c5
14 changed files with 116 additions and 110 deletions

View File

@ -198,7 +198,7 @@ pub use path::WindowsPath;
pub use path::PosixPath;
pub use tuple::{CopyableTuple, ImmutableTuple, ExtendedTupleOps};
pub use str::{StrSlice, Trimmable};
pub use str::{StrSlice};
pub use container::{Container, Mutable};
pub use vec::{CopyableVector, ImmutableVector};
pub use vec::{ImmutableEqVector, ImmutableCopyableVector};

View File

@ -36,7 +36,7 @@
pub use path::PosixPath;
pub use path::WindowsPath;
pub use ptr::Ptr;
pub use str::{StrSlice, Trimmable, OwnedStr};
pub use str::{StrSlice, OwnedStr};
pub use to_bytes::IterBytes;
pub use to_str::ToStr;
pub use tuple::{CopyableTuple, ImmutableTuple, ExtendedTupleOps};

View File

@ -29,6 +29,7 @@
use u8;
use uint;
use vec;
use to_str::ToStr;
#[cfg(notest)] use cmp::{Eq, Ord};
@ -53,6 +54,19 @@
unsafe { raw::slice_bytes_unique(s, 0, len(s)) }
}
impl ToStr for ~str {
#[inline(always)]
pure fn to_str(&self) -> ~str { copy *self }
}
impl ToStr for &'self str {
#[inline(always)]
pure fn to_str(&self) -> ~str { ::str::from_slice(*self) }
}
impl ToStr for @str {
#[inline(always)]
pure fn to_str(&self) -> ~str { ::str::from_slice(*self) }
}
/**
* Convert a byte to a UTF-8 string
*
@ -299,12 +313,12 @@ pub fn unshift_char(s: &mut ~str, ch: char) {
* * chars_to_trim - A vector of chars
*
*/
pub pure fn trim_left_chars(s: &str, chars_to_trim: &[char]) -> ~str {
if chars_to_trim.is_empty() { return from_slice(s); }
pub pure fn trim_left_chars(s: &'a str, chars_to_trim: &[char]) -> &'a str {
if chars_to_trim.is_empty() { return s; }
match find(s, |c| !chars_to_trim.contains(&c)) {
None => ~"",
Some(first) => unsafe { raw::slice_bytes_unique(s, first, s.len()) }
None => "",
Some(first) => unsafe { raw::slice_bytes(s, first, s.len()) }
}
}
@ -317,14 +331,14 @@ pub fn unshift_char(s: &mut ~str, ch: char) {
* * chars_to_trim - A vector of chars
*
*/
pub pure fn trim_right_chars(s: &str, chars_to_trim: &[char]) -> ~str {
if chars_to_trim.is_empty() { return str::from_slice(s); }
pub pure fn trim_right_chars(s: &'a str, chars_to_trim: &[char]) -> &'a str {
if chars_to_trim.is_empty() { return s; }
match rfind(s, |c| !chars_to_trim.contains(&c)) {
None => ~"",
None => "",
Some(last) => {
let next = char_range_at(s, last).next;
unsafe { raw::slice_bytes_unique(s, 0u, next) }
unsafe { raw::slice_bytes(s, 0u, next) }
}
}
}
@ -338,31 +352,31 @@ pub fn unshift_char(s: &mut ~str, ch: char) {
* * chars_to_trim - A vector of chars
*
*/
pub pure fn trim_chars(s: &str, chars_to_trim: &[char]) -> ~str {
pub pure fn trim_chars(s: &'a str, chars_to_trim: &[char]) -> &'a str {
trim_left_chars(trim_right_chars(s, chars_to_trim), chars_to_trim)
}
/// Returns a string with leading whitespace removed
pub pure fn trim_left(s: &str) -> ~str {
pub pure fn trim_left(s: &'a str) -> &'a str {
match find(s, |c| !char::is_whitespace(c)) {
None => ~"",
Some(first) => unsafe { raw::slice_bytes_unique(s, first, len(s)) }
None => "",
Some(first) => unsafe { raw::slice_bytes(s, first, len(s)) }
}
}
/// Returns a string with trailing whitespace removed
pub pure fn trim_right(s: &str) -> ~str {
pub pure fn trim_right(s: &'a str) -> &'a str {
match rfind(s, |c| !char::is_whitespace(c)) {
None => ~"",
None => "",
Some(last) => {
let next = char_range_at(s, last).next;
unsafe { raw::slice_bytes_unique(s, 0u, next) }
unsafe { raw::slice_bytes(s, 0u, next) }
}
}
}
/// Returns a string with leading and trailing whitespace removed
pub pure fn trim(s: &str) -> ~str { trim_left(trim_right(s)) }
pub pure fn trim(s: &'a str) -> &'a str { trim_left(trim_right(s)) }
/*
Section: Transforming strings
@ -407,8 +421,8 @@ pub fn unshift_char(s: &mut ~str, ch: char) {
* Returns a string containing `n` characters starting at byte offset
* `begin`.
*/
pub pure fn substr(s: &str, begin: uint, n: uint) -> ~str {
slice(s, begin, begin + count_bytes(s, begin, n)).to_owned()
pub pure fn substr(s: &'a str, begin: uint, n: uint) -> &'a str {
slice(s, begin, begin + count_bytes(s, begin, n))
}
/**
@ -2221,25 +2235,6 @@ fn test_from_buf_len() {
}
pub trait Trimmable {
pure fn trim(&self) -> Self;
pure fn trim_left(&self) -> Self;
pure fn trim_right(&self) -> Self;
}
/// Extension methods for strings
impl Trimmable for ~str {
/// Returns a string with leading and trailing whitespace removed
#[inline]
pure fn trim(&self) -> ~str { trim(*self) }
/// Returns a string with leading whitespace removed
#[inline]
pure fn trim_left(&self) -> ~str { trim_left(*self) }
/// Returns a string with trailing whitespace removed
#[inline]
pure fn trim_right(&self) -> ~str { trim_right(*self) }
}
#[cfg(notest)]
pub mod traits {
use ops::Add;
@ -2280,14 +2275,17 @@ pub trait StrSlice {
pure fn split_char(&self, sep: char) -> ~[~str];
pure fn split_str(&self, sep: &'a str) -> ~[~str];
pure fn starts_with(&self, needle: &'a str) -> bool;
pure fn substr(&self, begin: uint, n: uint) -> ~str;
pure fn substr(&self, begin: uint, n: uint) -> &'self str;
pure fn to_lower(&self) -> ~str;
pure fn to_upper(&self) -> ~str;
pure fn escape_default(&self) -> ~str;
pure fn escape_unicode(&self) -> ~str;
pure fn trim(&self) -> ~str;
pure fn trim_left(&self) -> ~str;
pure fn trim_right(&self) -> ~str;
pure fn trim(&self) -> &'self str;
pure fn trim_left(&self) -> &'self str;
pure fn trim_right(&self) -> &'self str;
pure fn trim_chars(&self, chars_to_trim: &[char]) -> &'self str;
pure fn trim_left_chars(&self, chars_to_trim: &[char]) -> &'self str;
pure fn trim_right_chars(&self, chars_to_trim: &[char]) -> &'self str;
pure fn to_owned(&self) -> ~str;
pure fn to_managed(&self) -> @str;
pure fn char_at(&self, i: uint) -> char;
@ -2421,7 +2419,7 @@ impl StrSlice for &'self str {
* `begin`.
*/
#[inline]
pure fn substr(&self, begin: uint, n: uint) -> ~str {
pure fn substr(&self, begin: uint, n: uint) -> &'self str {
substr(*self, begin, n)
}
/// Convert a string to lowercase
@ -2439,13 +2437,27 @@ impl StrSlice for &'self str {
/// Returns a string with leading and trailing whitespace removed
#[inline]
pure fn trim(&self) -> ~str { trim(*self) }
pure fn trim(&self) -> &'self str { trim(*self) }
/// Returns a string with leading whitespace removed
#[inline]
pure fn trim_left(&self) -> ~str { trim_left(*self) }
pure fn trim_left(&self) -> &'self str { trim_left(*self) }
/// Returns a string with trailing whitespace removed
#[inline]
pure fn trim_right(&self) -> ~str { trim_right(*self) }
pure fn trim_right(&self) -> &'self str { trim_right(*self) }
#[inline]
pure fn trim_chars(&self, chars_to_trim: &[char]) -> &'self str {
trim_chars(*self, chars_to_trim)
}
#[inline]
pure fn trim_left_chars(&self, chars_to_trim: &[char]) -> &'self str {
trim_left_chars(*self, chars_to_trim)
}
#[inline]
pure fn trim_right_chars(&self, chars_to_trim: &[char]) -> &'self str {
trim_right_chars(*self, chars_to_trim)
}
#[inline]
pure fn to_owned(&self) -> ~str { from_slice(*self) }
@ -2805,11 +2817,11 @@ fn test_find_str_between() {
#[test]
fn test_substr() {
fn t(a: &str, b: &str, start: int) {
fail_unless!(substr(a, start as uint, len(b)) == b.to_str());
fail_unless!(substr(a, start as uint, len(b)) == b);
}
t(~"hello", ~"llo", 2);
t(~"hello", ~"el", 1);
fail_unless!(~"ะเทศไท" == substr(~"ประเทศไทย中华Việt Nam", 6u, 6u));
t("hello", "llo", 2);
t("hello", "el", 1);
fail_unless!("ะเทศไท" == substr("ประเทศไทย中华Việt Nam", 6u, 6u));
}
#[test]
@ -3042,62 +3054,62 @@ fn test_slice_fail() {
#[test]
fn test_trim_left_chars() {
fail_unless!(trim_left_chars(~" *** foo *** ", ~[]) ==
~" *** foo *** ");
fail_unless!(trim_left_chars(~" *** foo *** ", ~['*', ' ']) ==
~"foo *** ");
fail_unless!(trim_left_chars(~" *** *** ", ~['*', ' ']) == ~"");
fail_unless!(trim_left_chars(~"foo *** ", ~['*', ' ']) ==
~"foo *** ");
fail_unless!(trim_left_chars(" *** foo *** ", ~[]) ==
" *** foo *** ");
fail_unless!(trim_left_chars(" *** foo *** ", ~['*', ' ']) ==
"foo *** ");
fail_unless!(trim_left_chars(" *** *** ", ~['*', ' ']) == "");
fail_unless!(trim_left_chars("foo *** ", ~['*', ' ']) ==
"foo *** ");
}
#[test]
fn test_trim_right_chars() {
fail_unless!(trim_right_chars(~" *** foo *** ", ~[]) ==
~" *** foo *** ");
fail_unless!(trim_right_chars(~" *** foo *** ", ~['*', ' ']) ==
~" *** foo");
fail_unless!(trim_right_chars(~" *** *** ", ~['*', ' ']) == ~"");
fail_unless!(trim_right_chars(~" *** foo", ~['*', ' ']) ==
~" *** foo");
fail_unless!(trim_right_chars(" *** foo *** ", ~[]) ==
" *** foo *** ");
fail_unless!(trim_right_chars(" *** foo *** ", ~['*', ' ']) ==
" *** foo");
fail_unless!(trim_right_chars(" *** *** ", ~['*', ' ']) == "");
fail_unless!(trim_right_chars(" *** foo", ~['*', ' ']) ==
" *** foo");
}
#[test]
fn test_trim_chars() {
fail_unless!(trim_chars(~" *** foo *** ", ~[]) == ~" *** foo *** ");
fail_unless!(trim_chars(~" *** foo *** ", ~['*', ' ']) == ~"foo");
fail_unless!(trim_chars(~" *** *** ", ~['*', ' ']) == ~"");
fail_unless!(trim_chars(~"foo", ~['*', ' ']) == ~"foo");
fail_unless!(trim_chars(" *** foo *** ", ~[]) == " *** foo *** ");
fail_unless!(trim_chars(" *** foo *** ", ~['*', ' ']) == "foo");
fail_unless!(trim_chars(" *** *** ", ~['*', ' ']) == "");
fail_unless!(trim_chars("foo", ~['*', ' ']) == "foo");
}
#[test]
fn test_trim_left() {
fail_unless!((trim_left(~"") == ~""));
fail_unless!((trim_left(~"a") == ~"a"));
fail_unless!((trim_left(~" ") == ~""));
fail_unless!((trim_left(~" blah") == ~"blah"));
fail_unless!((trim_left(~" \u3000 wut") == ~"wut"));
fail_unless!((trim_left(~"hey ") == ~"hey "));
fail_unless!((trim_left("") == ""));
fail_unless!((trim_left("a") == "a"));
fail_unless!((trim_left(" ") == ""));
fail_unless!((trim_left(" blah") == "blah"));
fail_unless!((trim_left(" \u3000 wut") == "wut"));
fail_unless!((trim_left("hey ") == "hey "));
}
#[test]
fn test_trim_right() {
fail_unless!((trim_right(~"") == ~""));
fail_unless!((trim_right(~"a") == ~"a"));
fail_unless!((trim_right(~" ") == ~""));
fail_unless!((trim_right(~"blah ") == ~"blah"));
fail_unless!((trim_right(~"wut \u3000 ") == ~"wut"));
fail_unless!((trim_right(~" hey") == ~" hey"));
fail_unless!((trim_right("") == ""));
fail_unless!((trim_right("a") == "a"));
fail_unless!((trim_right(" ") == ""));
fail_unless!((trim_right("blah ") == "blah"));
fail_unless!((trim_right("wut \u3000 ") == "wut"));
fail_unless!((trim_right(" hey") == " hey"));
}
#[test]
fn test_trim() {
fail_unless!((trim(~"") == ~""));
fail_unless!((trim(~"a") == ~"a"));
fail_unless!((trim(~" ") == ~""));
fail_unless!((trim(~" blah ") == ~"blah"));
fail_unless!((trim(~"\nwut \u3000 ") == ~"wut"));
fail_unless!((trim(~" hey dude ") == ~"hey dude"));
fail_unless!((trim("") == ""));
fail_unless!((trim("a") == "a"));
fail_unless!((trim(" ") == ""));
fail_unless!((trim(" blah ") == "blah"));
fail_unless!((trim("\nwut \u3000 ") == "wut"));
fail_unless!((trim(" hey dude ") == "hey dude"));
}
#[test]

View File

@ -28,18 +28,6 @@ impl ToStr for () {
#[inline(always)]
pure fn to_str(&self) -> ~str { ~"()" }
}
impl ToStr for ~str {
#[inline(always)]
pure fn to_str(&self) -> ~str { copy *self }
}
impl ToStr for &'self str {
#[inline(always)]
pure fn to_str(&self) -> ~str { ::str::from_slice(*self) }
}
impl ToStr for @str {
#[inline(always)]
pure fn to_str(&self) -> ~str { ::str::from_slice(*self) }
}
// FIXME #4898: impl for one-tuples

View File

@ -537,7 +537,7 @@ pub struct Conv {
let mut unpadded = match cv.precision {
CountImplied => s.to_owned(),
CountIs(max) => if (max as uint) < str::char_len(s) {
str::substr(s, 0, max as uint)
str::substr(s, 0, max as uint).to_owned()
} else {
s.to_owned()
}

View File

@ -1849,6 +1849,7 @@ fn trans_assign_op(bcx: block,
return result_datum.copy_to_datum(bcx, DROP_EXISTING, dst_datum);
}
// NOTE: Mode neccessary here?
fn shorten(+x: ~str) -> ~str {
if x.len() > 60 { x.substr(0, 60) } else { x }
if x.len() > 60 { x.substr(0, 60).to_owned() } else { x }
}

View File

@ -311,7 +311,7 @@ pub fn mk_doc(source: ~str) -> doc::Doc {
let doc = (attr_pass::mk_pass().f)(srv.clone(), doc);
let doc = (desc_to_brief_pass::mk_pass().f)(srv.clone(), doc);
let doc = (sectionalize_pass::mk_pass().f)(srv.clone(), doc);
(mk_pass(~"", |s| str::trim(s) ).f)(srv.clone(), doc)
(mk_pass(~"", |s| str::trim(s).to_owned() ).f)(srv.clone(), doc)
}
}
}

View File

@ -21,7 +21,7 @@
use core::str;
pub fn mk_pass() -> Pass {
text_pass::mk_pass(~"trim", |s| str::trim(s) )
text_pass::mk_pass(~"trim", |s| s.trim().to_owned() )
}
#[test]

View File

@ -78,7 +78,7 @@ fn unindent(s: &str) -> ~str {
};
if !lines.is_empty() {
let unindented = ~[lines.head().trim()]
let unindented = ~[lines.head().trim().to_owned()]
+ do lines.tail().map |line| {
if str::is_whitespace(*line) {
copy *line

View File

@ -283,7 +283,7 @@ fn run_cmd(repl: &mut Repl, _in: @io::Reader, _out: @io::Writer,
for args.each |arg| {
let (crate, filename) =
if arg.ends_with(".rs") || arg.ends_with(".rc") {
(arg.substr(0, arg.len() - 3), *arg)
(arg.substr(0, arg.len() - 3).to_owned(), *arg)
} else {
(*arg, arg + ~".rs")
};

View File

@ -458,10 +458,11 @@ pub impl BigUint {
pure fn fill_concat(v: &[BigDigit], radix: uint, l: uint) -> ~str {
if v.is_empty() { return ~"0" }
str::trim_left_chars(str::concat(vec::reversed(v).map(|n| {
let s = str::concat(vec::reversed(v).map(|n| {
let s = uint::to_str_radix(*n as uint, radix);
str::from_chars(vec::from_elem(l - s.len(), '0')) + s
})), ['0'])
}));
str::trim_left_chars(s, ['0']).to_owned()
}
}

View File

@ -228,7 +228,7 @@ pub fn parse(s: &str) -> Option<Version> {
do bad_parse::cond.trap(|_| { debug!("bad"); bad = true }).in {
do io::with_str_reader(s) |rdr| {
let v = parse_reader(rdr);
if bad || v.to_str() != s {
if bad || v.to_str() != s.to_owned() {
None
} else {
Some(v)

View File

@ -109,7 +109,10 @@ fn block_trim(lines: ~[~str], chars: ~str, max: Option<uint>) -> ~[~str] {
}
if comment.starts_with(~"//") {
return comment.slice(3u, comment.len()).trim();
// FIXME #5475:
// return comment.slice(3u, comment.len()).trim().to_owned();
let r = comment.slice(3u, comment.len()); return r.trim().to_owned();
}
if comment.starts_with(~"/*") {

View File

@ -67,7 +67,8 @@ pub fn equal(&self, other: &Sudoku) -> bool {
let mut g = vec::from_fn(10u, { |_i| ~[0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8] });
while !reader.eof() {
let comps = str::split_char(str::trim(reader.read_line()), ',');
let line = reader.read_line();
let comps = str::split_char(line.trim(), ',');
if vec::len(comps) == 3u {
let row = uint::from_str(comps[0]).get() as u8;
let col = uint::from_str(comps[1]).get() as u8;