Skip to content

Commit 438ff3a

Browse files
committed
---
yaml --- r: 82712 b: refs/heads/auto c: e02d1eb h: refs/heads/master v: v3
1 parent 9ac37af commit 438ff3a

File tree

2 files changed

+53
-15
lines changed

2 files changed

+53
-15
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ refs/heads/try3: 9387340aab40a73e8424c48fd42f0c521a4875c0
1313
refs/tags/release-0.3.1: 495bae036dfe5ec6ceafd3312b4dca48741e845b
1414
refs/tags/release-0.4: e828ea2080499553b97dfe33b3f4d472b4562ad7
1515
refs/tags/release-0.5: 7e3bcfbf21278251ee936ad53e92e9b719702d73
16-
refs/heads/auto: 410a96cc79df4fbb3c2f30bdb2682b867df41a7e
16+
refs/heads/auto: e02d1eb1717fee3c513baa0cb5fc39b8fa630335
1717
refs/heads/servo: af82457af293e2a842ba6b7759b70288da276167
1818
refs/tags/release-0.6: b4ebcfa1812664df5e142f0134a5faea3918544c
1919
refs/tags/0.1: b19db808c2793fe2976759b85a355c3ad8c8b336

branches/auto/src/libstd/c_str.rs

Lines changed: 52 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -61,16 +61,17 @@ do my_string.with_c_str |c_buffer| {
6161
*/
6262

6363
use cast;
64+
use container::Container;
6465
use iter::{Iterator, range};
6566
use libc;
6667
use ops::Drop;
6768
use option::{Option, Some, None};
6869
use ptr::RawPtr;
6970
use ptr;
70-
use str;
7171
use str::StrSlice;
72-
use vec::{ImmutableVector, CopyableVector};
73-
use container::Container;
72+
use str;
73+
use vec::{CopyableVector, ImmutableVector, MutableVector};
74+
use unstable::intrinsics;
7475

7576
/// Resolution options for the `null_byte` condition
7677
pub enum NullByteResolution {
@@ -241,24 +242,22 @@ impl<'self> ToCStr for &'self str {
241242
unsafe fn to_c_str_unchecked(&self) -> CString {
242243
self.as_bytes().to_c_str_unchecked()
243244
}
245+
246+
#[inline]
247+
fn with_c_str<T>(&self, f: &fn(*libc::c_char) -> T) -> T {
248+
self.as_bytes().with_c_str(f)
249+
}
244250
}
245251

252+
// The length of the stack allocated buffer for `vec.with_c_str()`
253+
static BUF_LEN: uint = 32;
254+
246255
impl<'self> ToCStr for &'self [u8] {
247256
fn to_c_str(&self) -> CString {
248257
#[fixed_stack_segment]; #[inline(never)];
249258
let mut cs = unsafe { self.to_c_str_unchecked() };
250259
do cs.with_mut_ref |buf| {
251-
for i in range(0, self.len()) {
252-
unsafe {
253-
let p = buf.offset(i as int);
254-
if *p == 0 {
255-
match null_byte::cond.raise(self.to_owned()) {
256-
Truncate => break,
257-
ReplaceWith(c) => *p = c
258-
}
259-
}
260-
}
261-
}
260+
check_for_null(*self, buf);
262261
}
263262
cs
264263
}
@@ -277,6 +276,45 @@ impl<'self> ToCStr for &'self [u8] {
277276
CString::new(buf as *libc::c_char, true)
278277
}
279278
}
279+
280+
/// WARNING: This function uses an optimization to only malloc a temporary
281+
/// CString when the source string is small. Do not save a reference to
282+
/// the `*libc::c_char` as it may be invalid after this function call.
283+
fn with_c_str<T>(&self, f: &fn(*libc::c_char) -> T) -> T {
284+
if self.len() < BUF_LEN {
285+
do self.as_imm_buf |self_buf, self_len| {
286+
unsafe {
287+
let mut buf: [u8, .. BUF_LEN] = intrinsics::uninit();
288+
289+
do buf.as_mut_buf |buf, _| {
290+
ptr::copy_memory(buf, self_buf, self_len);
291+
*ptr::mut_offset(buf, self_len as int) = 0;
292+
293+
check_for_null(*self, buf as *mut libc::c_char);
294+
295+
f(buf as *libc::c_char)
296+
}
297+
}
298+
}
299+
} else {
300+
self.to_c_str().with_ref(f)
301+
}
302+
}
303+
}
304+
305+
#[inline]
306+
fn check_for_null(v: &[u8], buf: *mut libc::c_char) {
307+
for i in range(0, v.len()) {
308+
unsafe {
309+
let p = buf.offset(i as int);
310+
if *p == 0 {
311+
match null_byte::cond.raise(v.to_owned()) {
312+
Truncate => break,
313+
ReplaceWith(c) => *p = c
314+
}
315+
}
316+
}
317+
}
280318
}
281319

282320
/// External iterator for a CString's bytes.

0 commit comments

Comments
 (0)