@@ -16,9 +16,9 @@ use base::{CFRelease, CFRetain, CFTypeID, CFTypeRef, TCFType};
16
16
use base:: { kCFAllocatorDefault, kCFAllocatorNull} ;
17
17
18
18
use libc;
19
+ use std:: ffi:: CStr ;
19
20
use std:: fmt;
20
- use std:: str:: FromStr ;
21
- use std:: string:: ToString ;
21
+ use std:: str:: { self , FromStr } ;
22
22
use std:: mem;
23
23
use std:: ptr;
24
24
use std:: vec:: Vec ;
@@ -228,7 +228,6 @@ impl Drop for CFString {
228
228
}
229
229
}
230
230
231
-
232
231
impl TCFType < CFStringRef > for CFString {
233
232
#[ inline]
234
233
fn as_concrete_TypeRef ( & self ) -> CFStringRef {
@@ -265,69 +264,84 @@ impl TCFType<CFStringRef> for CFString {
265
264
impl FromStr for CFString {
266
265
type Err = ( ) ;
267
266
268
- /// Creates a new `CFString` instance from a Rust string.
267
+ /// # Deprecated
268
+ ///
269
+ /// Use CFString::new instead.
269
270
#[ inline]
270
271
fn from_str ( string : & str ) -> Result < CFString , ( ) > {
271
- unsafe {
272
- let string_ref = CFStringCreateWithBytes ( kCFAllocatorDefault,
273
- string. as_ptr ( ) ,
274
- string. len ( ) . to_CFIndex ( ) ,
275
- kCFStringEncodingUTF8,
276
- false as Boolean ,
277
- kCFAllocatorNull) ;
278
- Some ( TCFType :: wrap_under_create_rule ( string_ref) ) . ok_or ( ( ) )
279
- }
272
+ Ok ( CFString :: new ( string) )
280
273
}
281
274
}
282
275
283
- impl ToString for CFString {
284
- fn to_string ( & self ) -> String {
276
+ impl fmt :: Display for CFString {
277
+ fn fmt ( & self , fmt : & mut fmt :: Formatter ) -> fmt :: Result {
285
278
unsafe {
286
- let char_len = self . char_len ( ) ;
287
-
288
- // First, ask how big the buffer ought to be.
289
- let mut bytes_required: CFIndex = 0 ;
290
- CFStringGetBytes ( self . obj ,
291
- CFRange :: init ( 0 , char_len) ,
292
- kCFStringEncodingUTF8,
293
- 0 ,
294
- false as Boolean ,
295
- ptr:: null_mut ( ) ,
296
- 0 ,
297
- & mut bytes_required) ;
298
-
299
- // Then, allocate the buffer and actually copy.
300
- let mut buffer = Vec :: with_capacity ( bytes_required as usize ) ;
301
- for _ in ( 0 ..bytes_required) { buffer. push ( '\x00' as u8 ) }
302
-
303
- let mut bytes_used: CFIndex = 0 ;
304
- let chars_written = CFStringGetBytes ( self . obj ,
305
- CFRange :: init ( 0 , char_len) ,
306
- kCFStringEncodingUTF8,
307
- 0 ,
308
- false as Boolean ,
309
- buffer. as_mut_ptr ( ) ,
310
- buffer. len ( ) . to_CFIndex ( ) ,
311
- & mut bytes_used) as usize ;
312
- assert ! ( chars_written. to_CFIndex( ) == char_len) ;
313
-
314
- // This is dangerous; we over-allocate and null-terminate the string (during
315
- // initialization).
316
- assert ! ( bytes_used == buffer. len( ) . to_CFIndex( ) ) ;
317
- String :: from_utf8 ( buffer) . unwrap ( )
279
+ // Do this without allocating if we can get away with it
280
+ let c_string = CFStringGetCStringPtr ( self . obj , kCFStringEncodingUTF8) ;
281
+ if c_string != ptr:: null ( ) {
282
+ let c_str = CStr :: from_ptr ( c_string) ;
283
+ fmt. write_str ( str:: from_utf8_unchecked ( c_str. to_bytes ( ) ) )
284
+ } else {
285
+ let char_len = self . char_len ( ) ;
286
+
287
+ // First, ask how big the buffer ought to be.
288
+ let mut bytes_required: CFIndex = 0 ;
289
+ CFStringGetBytes ( self . obj ,
290
+ CFRange :: init ( 0 , char_len) ,
291
+ kCFStringEncodingUTF8,
292
+ 0 ,
293
+ false as Boolean ,
294
+ ptr:: null_mut ( ) ,
295
+ 0 ,
296
+ & mut bytes_required) ;
297
+
298
+ // Then, allocate the buffer and actually copy.
299
+ let mut buffer = Vec :: with_capacity ( bytes_required as usize ) ;
300
+ for _ in ( 0 ..bytes_required) { buffer. push ( '\x00' as u8 ) }
301
+
302
+ let mut bytes_used: CFIndex = 0 ;
303
+ let chars_written = CFStringGetBytes ( self . obj ,
304
+ CFRange :: init ( 0 , char_len) ,
305
+ kCFStringEncodingUTF8,
306
+ 0 ,
307
+ false as Boolean ,
308
+ buffer. as_mut_ptr ( ) ,
309
+ buffer. len ( ) . to_CFIndex ( ) ,
310
+ & mut bytes_used) as usize ;
311
+ assert ! ( chars_written. to_CFIndex( ) == char_len) ;
312
+
313
+ // This is dangerous; we over-allocate and null-terminate the string (during
314
+ // initialization).
315
+ assert ! ( bytes_used == buffer. len( ) . to_CFIndex( ) ) ;
316
+ fmt. write_str ( str:: from_utf8_unchecked ( & buffer) )
317
+ }
318
318
}
319
319
}
320
320
}
321
321
322
322
impl fmt:: Debug for CFString {
323
323
fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
324
- write ! ( f, "{}" , self . to_string ( ) )
324
+ write ! ( f, "\" {} \" " , self )
325
325
}
326
326
}
327
327
328
328
329
329
impl CFString {
330
- /// Like `CFString::from_string`, but references a string that can be used as a backing store
330
+ /// Creates a new `CFString` instance from a Rust string.
331
+ #[ inline]
332
+ pub fn new ( string : & str ) -> CFString {
333
+ unsafe {
334
+ let string_ref = CFStringCreateWithBytes ( kCFAllocatorDefault,
335
+ string. as_ptr ( ) ,
336
+ string. len ( ) . to_CFIndex ( ) ,
337
+ kCFStringEncodingUTF8,
338
+ false as Boolean ,
339
+ kCFAllocatorNull) ;
340
+ CFString :: wrap_under_create_rule ( string_ref)
341
+ }
342
+ }
343
+
344
+ /// Like `CFString::new`, but references a string that can be used as a backing store
331
345
/// by virtue of being statically allocated.
332
346
#[ inline]
333
347
pub fn from_static_string ( string : & ' static str ) -> CFString {
@@ -420,7 +434,9 @@ extern {
420
434
//fn CFStringGetCharactersPtr
421
435
//fn CFStringGetCharacterFromInlineBuffer
422
436
//fn CFStringGetCString
423
- //fn CFStringGetCStringPtr
437
+ fn CFStringGetCStringPtr ( theString : CFStringRef ,
438
+ encoding : CFStringEncoding )
439
+ -> * const libc:: c_char ;
424
440
fn CFStringGetLength ( theString : CFStringRef ) -> CFIndex ;
425
441
//fn CFStringGetPascalString
426
442
//fn CFStringGetPascalStringPtr
0 commit comments