diff --git a/src/libcore/str.rs b/src/libcore/str.rs index cd172476563..f05410bafe9 100644 --- a/src/libcore/str.rs +++ b/src/libcore/str.rs @@ -26,6 +26,7 @@ export unpack_slice, // Adding things to and removing things from a string + push_str_no_overallocate, push_str, push_char, pop_char, @@ -235,13 +236,29 @@ pure fn from_chars(chs: &[const char]) -> str { ret buf; } +/// Appends a string slice to the back of a string, without overallocating +#[inline(always)] +fn push_str_no_overallocate(&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); + } +} /// 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); + reserve_at_least(lhs, llen + rlen); do as_buf(lhs) |lbuf| { do unpack_slice(rhs) |rbuf, _rlen| { let dst = ptr::offset(lbuf, llen); @@ -257,7 +274,7 @@ fn push_str(&lhs: str, rhs: str/&) { pure fn append(+lhs: str, rhs: str/&) -> str { let mut v <- lhs; unchecked { - push_str(v, rhs); + push_str_no_overallocate(v, rhs); } ret v; } diff --git a/src/libstd/sha1.rs b/src/libstd/sha1.rs index 607388bd559..dc136af639a 100644 --- a/src/libstd/sha1.rs +++ b/src/libstd/sha1.rs @@ -265,7 +265,7 @@ 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 { str::push_str(rs, "aaaaaaaaaa"); i += 1; } ret rs; } // Test messages from FIPS 180-1