@@ -61,16 +61,17 @@ do my_string.with_c_str |c_buffer| {
61
61
*/
62
62
63
63
use cast;
64
+ use container:: Container ;
64
65
use iter:: { Iterator , range} ;
65
66
use libc;
66
67
use ops:: Drop ;
67
68
use option:: { Option , Some , None } ;
68
69
use ptr:: RawPtr ;
69
70
use ptr;
70
- use str;
71
71
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;
74
75
75
76
/// Resolution options for the `null_byte` condition
76
77
pub enum NullByteResolution {
@@ -241,24 +242,22 @@ impl<'self> ToCStr for &'self str {
241
242
unsafe fn to_c_str_unchecked ( & self ) -> CString {
242
243
self . as_bytes ( ) . to_c_str_unchecked ( )
243
244
}
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
+ }
244
250
}
245
251
252
+ // The length of the stack allocated buffer for `vec.with_c_str()`
253
+ static BUF_LEN : uint = 32 ;
254
+
246
255
impl < ' self > ToCStr for & ' self [ u8 ] {
247
256
fn to_c_str ( & self ) -> CString {
248
257
#[ fixed_stack_segment] ; #[ inline( never) ] ;
249
258
let mut cs = unsafe { self . to_c_str_unchecked ( ) } ;
250
259
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) ;
262
261
}
263
262
cs
264
263
}
@@ -277,6 +276,45 @@ impl<'self> ToCStr for &'self [u8] {
277
276
CString :: new ( buf as * libc:: c_char , true )
278
277
}
279
278
}
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
+ }
280
318
}
281
319
282
320
/// External iterator for a CString's bytes.
0 commit comments