Make str::pop_char and str::unsafe::pop_byte efficient

O(1) rather than O(string len)
This commit is contained in:
Marijn Haverbeke
2012-02-23 10:12:20 +01:00
parent c2984b46b4
commit 35e9192762

View File

@@ -9,8 +9,6 @@ but UTF-8 unsafe operations should be avoided.
For some heavy-duty uses, try std::rope. For some heavy-duty uses, try std::rope.
*/ */
import option::{some, none};
export export
// Creating a string // Creating a string
from_bytes, from_bytes,
@@ -276,10 +274,10 @@ Remove the final character from a string and return it.
Failure: Failure:
If the string does not contain any characters. If the string does not contain any characters.
*/ */
fn pop_char(&s: str) -> char unsafe { fn pop_char(&s: str) -> char {
let end = len(s); let end = len(s);
let {ch:ch, prev:end} = char_range_at_reverse(s, end); let {ch, prev} = char_range_at_reverse(s, end);
s = unsafe::slice_bytes(s, 0u, end); unsafe { unsafe::set_len(s, prev); }
ret ch; ret ch;
} }
@@ -1125,12 +1123,8 @@ fn is_whitespace(s: str) -> bool {
// Returns the string length/size in bytes // Returns the string length/size in bytes
// not counting the null terminator // not counting the null terminator
pure fn len(s: str) -> uint unsafe { pure fn len(s: str) -> uint unsafe {
as_bytes(s) { |v| let repr: *vec::unsafe::vec_repr = ::unsafe::reinterpret_cast(s);
let vlen = vec::len(v); (*repr).fill - 1u
// There should always be a null terminator
assert (vlen > 0u);
vlen - 1u
}
} }
// FIXME: delete? // FIXME: delete?
@@ -1466,7 +1460,8 @@ mod unsafe {
push_byte, push_byte,
push_bytes, push_bytes,
pop_byte, pop_byte,
shift_byte; shift_byte,
set_len;
// Function: unsafe::from_bytes // Function: unsafe::from_bytes
// //
@@ -1540,7 +1535,7 @@ mod unsafe {
let len = len(s); let len = len(s);
assert (len > 0u); assert (len > 0u);
let b = s[len - 1u]; let b = s[len - 1u];
s = unsafe::slice_bytes(s, 0u, len - 1u); set_len(s, len - 1u);
ret b; ret b;
} }
@@ -1554,7 +1549,13 @@ mod unsafe {
s = unsafe::slice_bytes(s, 1u, len); s = unsafe::slice_bytes(s, 1u, len);
ret b; ret b;
} }
unsafe fn set_len(&v: str, new_len: uint) {
let repr: *vec::unsafe::vec_repr = ::unsafe::reinterpret_cast(v);
(*repr).fill = new_len + 1u;
let null = ptr::mut_offset(ptr::mut_addr_of((*repr).data), new_len);
*null = 0u8;
}
} }