From ee0177b9082ffc2521141c615d332a994708c8a2 Mon Sep 17 00:00:00 2001 From: Michael Sullivan Date: Fri, 6 Jul 2012 11:35:46 -0700 Subject: [PATCH] Move string append to libraries. Closes #2710. --- src/libcore/char.rs | 6 +-- src/libcore/rand.rs | 6 +-- src/libcore/str.rs | 58 ++++++++++++++++++----- src/libcore/to_str.rs | 6 +-- src/rustc/middle/ty.rs | 4 +- src/test/run-pass/module-polymorphism.rc | 2 +- src/test/run-pass/module-polymorphism4.rc | 2 - 7 files changed, 59 insertions(+), 25 deletions(-) diff --git a/src/libcore/char.rs b/src/libcore/char.rs index 28645df1b46c0..d68800a96fc78 100644 --- a/src/libcore/char.rs +++ b/src/libcore/char.rs @@ -139,9 +139,9 @@ fn escape_unicode(c: char) -> str { else { ('U', 8u) }); assert str::len(s) <= pad; let mut out = "\\"; - out += str::from_char(c); - for uint::range(str::len(s), pad) |_i| { out += "0"; } - out += s; + str::push_str(out, str::from_char(c)); + for uint::range(str::len(s), pad) |_i| { str::push_str(out, "0"); } + str::push_str(out, s); ret out; } diff --git a/src/libcore/rand.rs b/src/libcore/rand.rs index 4db2cdb086d5e..ce4a29f376ae5 100644 --- a/src/libcore/rand.rs +++ b/src/libcore/rand.rs @@ -144,9 +144,9 @@ impl extensions for rng { * Return a random string of the specified length composed of A-Z,a-z,0-9 */ fn gen_str(len: uint) -> str { - let charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + - "abcdefghijklmnopqrstuvwxyz" + - "0123456789"; + let charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ\ + abcdefghijklmnopqrstuvwxyz\ + 0123456789"; let mut s = ""; let mut i = 0u; while (i < len) { diff --git a/src/libcore/str.rs b/src/libcore/str.rs index 43a9e8f6981bf..2d9d97979097e 100644 --- a/src/libcore/str.rs +++ b/src/libcore/str.rs @@ -15,6 +15,7 @@ export from_byte, from_char, from_chars, + append, concat, connect, @@ -25,6 +26,7 @@ export unpack_slice, // Adding things to and removing things from a string + push_str, push_char, pop_char, shift_char, @@ -233,10 +235,38 @@ pure fn from_chars(chs: &[const char]) -> str { ret buf; } +/// Appends a string slice to the back of a string +#[inline(always)] +fn push_str(&lhs: str, rhs: str/&) { + unsafe { + let llen = lhs.len(); + let rlen = rhs.len(); + reserve(lhs, llen + rlen); + do as_buf(lhs) |lbuf| { + do unpack_slice(rhs) |rbuf, _rlen| { + let dst = ptr::offset(lbuf, llen); + ptr::memcpy(dst, rbuf, rlen); + } + } + unsafe::set_len(lhs, llen + rlen); + } +} + +/// Concatenate two strings together +#[inline(always)] +pure fn append(+lhs: str, rhs: str/&) -> str { + let mut v <- lhs; + unchecked { + push_str(v, rhs); + } + ret v; +} + + /// Concatenate a vector of strings pure fn concat(v: &[const str]) -> str { let mut s: str = ""; - for vec::each(v) |ss| { s += ss; } + for vec::each(v) |ss| { unchecked { push_str(s, ss) }; } ret s; } @@ -244,8 +274,8 @@ pure fn concat(v: &[const str]) -> str { pure fn connect(v: &[const str], sep: str) -> str { let mut s = "", first = true; for vec::each(v) |ss| { - if first { first = false; } else { s += sep; } - s += ss; + if first { first = false; } else { unchecked { push_str(s, sep); } } + unchecked { push_str(s, ss) }; } ret s; } @@ -576,8 +606,8 @@ pure fn to_upper(s: str/&) -> str { pure fn replace(s: str, from: str, to: str) -> str { let mut result = "", first = true; do iter_between_matches(s, from) |start, end| { - if first { first = false; } else { result += to; } - unsafe { result += unsafe::slice_bytes(s, start, end); } + if first { first = false; } else { unchecked {push_str(result, to); }} + unsafe { push_str(result, unsafe::slice_bytes(s, start, end)); } } result } @@ -1694,7 +1724,7 @@ pure fn escape_default(s: str/&) -> str { let mut out: str = ""; unchecked { reserve_at_least(out, str::len(s)); - chars_iter(s, |c| out += char::escape_default(c)); + chars_iter(s, |c| push_str(out, char::escape_default(c))); } ret out; } @@ -1704,7 +1734,7 @@ pure fn escape_unicode(s: str/&) -> str { let mut out: str = ""; unchecked { reserve_at_least(out, str::len(s)); - chars_iter(s, |c| out += char::escape_unicode(c)); + chars_iter(s, |c| push_str(out, char::escape_unicode(c))); } ret out; } @@ -1863,6 +1893,12 @@ impl extensions for str { /// Returns a string with trailing whitespace removed #[inline] fn trim_right() -> str { trim_right(self) } + + /// Concatenate two strings: operator version + #[inline(always)] + pure fn +(rhs: str/&) -> str { + append(self, rhs) + } } /// Extension methods for strings @@ -2311,13 +2347,13 @@ mod tests { fn a_million_letter_a() -> str { let mut i = 0; let mut rs = ""; - while i < 100000 { rs += "aaaaaaaaaa"; i += 1; } + while i < 100000 { push_str(rs, "aaaaaaaaaa"); i += 1; } ret rs; } fn half_a_million_letter_a() -> str { let mut i = 0; let mut rs = ""; - while i < 100000 { rs += "aaaaa"; i += 1; } + while i < 100000 { push_str(rs, "aaaaa"); i += 1; } ret rs; } assert eq(half_a_million_letter_a(), @@ -2422,13 +2458,13 @@ mod tests { fn a_million_letter_X() -> str { let mut i = 0; let mut rs = ""; - while i < 100000 { rs += "华华华华华华华华华华"; i += 1; } + while i < 100000 { push_str(rs, "华华华华华华华华华华"); i += 1; } ret rs; } fn half_a_million_letter_X() -> str { let mut i = 0; let mut rs = ""; - while i < 100000 { rs += "华华华华华"; i += 1; } + while i < 100000 { push_str(rs, "华华华华华"); i += 1; } ret rs; } assert eq(half_a_million_letter_X(), diff --git a/src/libcore/to_str.rs b/src/libcore/to_str.rs index 359f5ea4a9cd8..c54a8887f8465 100644 --- a/src/libcore/to_str.rs +++ b/src/libcore/to_str.rs @@ -61,10 +61,10 @@ impl of to_str for ~[A] { let mut acc = "[", first = true; for vec::each(self) |elt| { if first { first = false; } - else { acc += ", "; } - acc += elt.to_str(); + else { str::push_str(acc, ", "); } + str::push_str(acc, elt.to_str()); } - acc += "]"; + str::push_char(acc, ']'); acc } } diff --git a/src/rustc/middle/ty.rs b/src/rustc/middle/ty.rs index 6580feab3301c..fba8d54cfba01 100644 --- a/src/rustc/middle/ty.rs +++ b/src/rustc/middle/ty.rs @@ -2963,8 +2963,8 @@ fn is_binopable(_cx: ctxt, ty: t, op: ast::binop) -> bool { /*bool*/ ~[f, f, f, f, t, t, t, t], /*int*/ ~[t, t, t, t, t, t, t, f], /*float*/ ~[t, t, t, f, t, t, f, f], - /*str*/ ~[t, f, f, f, t, t, f, f], - /*vec*/ ~[t, f, f, f, t, t, f, f], + /*str*/ ~[f, f, f, f, t, t, f, f], + /*vec*/ ~[f, f, f, f, t, t, f, f], /*bot*/ ~[f, f, f, f, t, t, f, f], /*struct*/ ~[t, t, t, t, t, t, t, t]]; diff --git a/src/test/run-pass/module-polymorphism.rc b/src/test/run-pass/module-polymorphism.rc index ed8e8be283ea6..781e3a279b194 100644 --- a/src/test/run-pass/module-polymorphism.rc +++ b/src/test/run-pass/module-polymorphism.rc @@ -42,4 +42,4 @@ mod f32 { #[path = "template.rs"] mod template; -} \ No newline at end of file +} diff --git a/src/test/run-pass/module-polymorphism4.rc b/src/test/run-pass/module-polymorphism4.rc index 04348ad6dc220..bbca74cd397cc 100644 --- a/src/test/run-pass/module-polymorphism4.rc +++ b/src/test/run-pass/module-polymorphism4.rc @@ -1,5 +1,3 @@ -#[no_core]; - #[path = "module-polymorphism4-files"] mod cat {