Skip to content

Commit 7a87258

Browse files
Grahame Bowlandbrson
Grahame Bowland
authored andcommitted
Rewrite str::push_char in rust.
Avoid crossing to C to reallocate underlying array when possible, if we must we now only cross once per char (not once per byte.)
1 parent b7b66b6 commit 7a87258

File tree

1 file changed

+67
-28
lines changed

1 file changed

+67
-28
lines changed

src/libcore/str.rs

+67-28
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ export
1313
from_byte,
1414
from_char,
1515
from_chars,
16-
push_char,
1716
concat,
1817
connect,
1918

@@ -102,6 +101,8 @@ export
102101
native mod rustrt {
103102
fn rust_str_push(&s: str, ch: u8);
104103
fn str_reserve_shared(&ss: str, nn: libc::size_t);
104+
#[rust_stack]
105+
fn upcall_vec_grow(&s: str, new_sz: libc::size_t);
105106
}
106107

107108
/*
@@ -138,34 +139,72 @@ fn from_byte(b: u8) -> str unsafe {
138139
#[doc = "Appends a character at the end of a string"]
139140
fn push_char(&s: str, ch: char) unsafe {
140141
let code = ch as uint;
141-
if code < max_one_b {
142-
rustrt::rust_str_push(s, code as u8);
143-
} else if code < max_two_b {
144-
rustrt::rust_str_push(s, (code >> 6u & 31u | tag_two_b) as u8);
145-
rustrt::rust_str_push(s, (code & 63u | tag_cont) as u8);
146-
} else if code < max_three_b {
147-
rustrt::rust_str_push(s, (code >> 12u & 15u | tag_three_b) as u8);
148-
rustrt::rust_str_push(s, (code >> 6u & 63u | tag_cont) as u8);
149-
rustrt::rust_str_push(s, (code & 63u | tag_cont) as u8);
150-
} else if code < max_four_b {
151-
rustrt::rust_str_push(s, (code >> 18u & 7u | tag_four_b) as u8);
152-
rustrt::rust_str_push(s, (code >> 12u & 63u | tag_cont) as u8);
153-
rustrt::rust_str_push(s, (code >> 6u & 63u | tag_cont) as u8);
154-
rustrt::rust_str_push(s, (code & 63u | tag_cont) as u8);
155-
} else if code < max_five_b {
156-
rustrt::rust_str_push(s, (code >> 24u & 3u | tag_five_b) as u8);
157-
rustrt::rust_str_push(s, (code >> 18u & 63u | tag_cont) as u8);
158-
rustrt::rust_str_push(s, (code >> 12u & 63u | tag_cont) as u8);
159-
rustrt::rust_str_push(s, (code >> 6u & 63u | tag_cont) as u8);
160-
rustrt::rust_str_push(s, (code & 63u | tag_cont) as u8);
142+
let nb = if code < max_one_b { 1u }
143+
else if code < max_two_b { 2u }
144+
else if code < max_three_b { 3u }
145+
else if code < max_four_b { 4u }
146+
else if code < max_five_b { 5u }
147+
else { 6u };
148+
let mut repr: *vec::unsafe::vec_repr = ::unsafe::reinterpret_cast(s);
149+
let fill = (*repr).fill;
150+
if fill + nb <= (*repr).alloc {
151+
(*repr).fill = fill + nb;
161152
} else {
162-
rustrt::rust_str_push(s, (code >> 30u & 1u | tag_six_b) as u8);
163-
rustrt::rust_str_push(s, (code >> 24u & 63u | tag_cont) as u8);
164-
rustrt::rust_str_push(s, (code >> 18u & 63u | tag_cont) as u8);
165-
rustrt::rust_str_push(s, (code >> 12u & 63u | tag_cont) as u8);
166-
rustrt::rust_str_push(s, (code >> 6u & 63u | tag_cont) as u8);
167-
rustrt::rust_str_push(s, (code & 63u | tag_cont) as u8);
168-
}
153+
rustrt::upcall_vec_grow(s, fill + nb);
154+
// possibly realloc'd
155+
repr = ::unsafe::reinterpret_cast(s);
156+
}
157+
let off = fill - 1u;
158+
if nb == 1u {
159+
*ptr::mut_offset(ptr::mut_addr_of((*repr).data), off) =
160+
code as u8;
161+
} else if nb == 2u {
162+
*ptr::mut_offset(ptr::mut_addr_of((*repr).data), off) =
163+
(code >> 6u & 31u | tag_two_b) as u8;
164+
*ptr::mut_offset(ptr::mut_addr_of((*repr).data), off + 1u) =
165+
(code & 63u | tag_cont) as u8;
166+
} else if nb == 3u {
167+
*ptr::mut_offset(ptr::mut_addr_of((*repr).data), off) =
168+
(code >> 12u & 15u | tag_three_b) as u8;
169+
*ptr::mut_offset(ptr::mut_addr_of((*repr).data), off + 1u) =
170+
(code >> 6u & 63u | tag_cont) as u8;
171+
*ptr::mut_offset(ptr::mut_addr_of((*repr).data), off + 2u) =
172+
(code & 63u | tag_cont) as u8;
173+
} else if nb == 4u {
174+
*ptr::mut_offset(ptr::mut_addr_of((*repr).data), off) =
175+
(code >> 18u & 7u | tag_four_b) as u8;
176+
*ptr::mut_offset(ptr::mut_addr_of((*repr).data), off + 1u) =
177+
(code >> 12u & 63u | tag_cont) as u8;
178+
*ptr::mut_offset(ptr::mut_addr_of((*repr).data), off + 2u) =
179+
(code >> 6u & 63u | tag_cont) as u8;
180+
*ptr::mut_offset(ptr::mut_addr_of((*repr).data), off + 3u) =
181+
(code & 63u | tag_cont) as u8;
182+
} else if nb == 5u {
183+
*ptr::mut_offset(ptr::mut_addr_of((*repr).data), off) =
184+
(code >> 24u & 3u | tag_five_b) as u8;
185+
*ptr::mut_offset(ptr::mut_addr_of((*repr).data), off + 1u) =
186+
(code >> 18u & 63u | tag_cont) as u8;
187+
*ptr::mut_offset(ptr::mut_addr_of((*repr).data), off + 2u) =
188+
(code >> 12u & 63u | tag_cont) as u8;
189+
*ptr::mut_offset(ptr::mut_addr_of((*repr).data), off + 3u) =
190+
(code >> 6u & 63u | tag_cont) as u8;
191+
*ptr::mut_offset(ptr::mut_addr_of((*repr).data), off + 4u) =
192+
(code & 63u | tag_cont) as u8;
193+
} else if nb == 6u {
194+
*ptr::mut_offset(ptr::mut_addr_of((*repr).data), off) =
195+
(code >> 30u & 1u | tag_six_b) as u8;
196+
*ptr::mut_offset(ptr::mut_addr_of((*repr).data), off + 1u) =
197+
(code >> 24u & 63u | tag_cont) as u8;
198+
*ptr::mut_offset(ptr::mut_addr_of((*repr).data), off + 2u) =
199+
(code >> 18u & 63u | tag_cont) as u8;
200+
*ptr::mut_offset(ptr::mut_addr_of((*repr).data), off + 3u) =
201+
(code >> 12u & 63u | tag_cont) as u8;
202+
*ptr::mut_offset(ptr::mut_addr_of((*repr).data), off + 4u) =
203+
(code >> 6u & 63u | tag_cont) as u8;
204+
*ptr::mut_offset(ptr::mut_addr_of((*repr).data), off + 5u) =
205+
(code & 63u | tag_cont) as u8;
206+
}
207+
*ptr::mut_offset(ptr::mut_addr_of((*repr).data), off + nb) = 0u8;
169208
}
170209

171210
#[doc = "Convert a char to a string"]

0 commit comments

Comments
 (0)