diff options
| author | bors <bors@rust-lang.org> | 2013-09-16 06:30:51 -0700 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2013-09-16 06:30:51 -0700 |
| commit | 2562f480f53fd3d15822034d441441ffbd04dbe4 (patch) | |
| tree | 5d1e9493efdcf2ac805496a605e58e70fccf9ab7 /src/libstd | |
| parent | 3e1803f3af1adc1b2e5595650f6920f40bbedc2e (diff) | |
| parent | 51470f3b97428756bee70e564db026ba2e2bceb6 (diff) | |
| download | rust-2562f480f53fd3d15822034d441441ffbd04dbe4.tar.gz rust-2562f480f53fd3d15822034d441441ffbd04dbe4.zip | |
auto merge of #9220 : kballard/rust/c_str-as_str, r=thestinger
Also rustify .as_bytes(), so it no longer calls libc::strlen() and is inlineable.
Diffstat (limited to 'src/libstd')
| -rw-r--r-- | src/libstd/c_str.rs | 77 |
1 files changed, 74 insertions, 3 deletions
diff --git a/src/libstd/c_str.rs b/src/libstd/c_str.rs index 51b70a07be8..a2842efbf8a 100644 --- a/src/libstd/c_str.rs +++ b/src/libstd/c_str.rs @@ -15,6 +15,7 @@ use ops::Drop; use option::{Option, Some, None}; use ptr::RawPtr; use ptr; +use str; use str::StrSlice; use vec::{ImmutableVector, CopyableVector}; use container::Container; @@ -97,15 +98,25 @@ impl CString { /// # Failure /// /// Fails if the CString is null. + #[inline] pub fn as_bytes<'a>(&'a self) -> &'a [u8] { - #[fixed_stack_segment]; #[inline(never)]; if self.buf.is_null() { fail!("CString is null!"); } unsafe { - let len = libc::strlen(self.buf) as uint; + let len = ptr::position(self.buf, |c| *c == 0); cast::transmute((self.buf, len + 1)) } } + /// Converts the CString into a `&str` without copying. + /// Returns None if the CString is not UTF-8 or is null. + #[inline] + pub fn as_str<'a>(&'a self) -> Option<&'a str> { + if self.buf.is_null() { return None; } + let buf = self.as_bytes(); + let buf = buf.slice_to(buf.len()-1); // chop off the trailing NUL + str::from_utf8_slice_opt(buf) + } + /// Return a CString iterator. pub fn iter<'a>(&'a self) -> CStringIterator<'a> { CStringIterator { @@ -238,7 +249,7 @@ mod tests { use option::{Some, None}; #[test] - fn test_to_c_str() { + fn test_str_to_c_str() { do "".to_c_str().with_ref |buf| { unsafe { assert_eq!(*ptr::offset(buf, 0), 0); @@ -258,6 +269,37 @@ mod tests { } #[test] + fn test_vec_to_c_str() { + let b: &[u8] = []; + do b.to_c_str().with_ref |buf| { + unsafe { + assert_eq!(*ptr::offset(buf, 0), 0); + } + } + + do bytes!("hello").to_c_str().with_ref |buf| { + unsafe { + assert_eq!(*ptr::offset(buf, 0), 'h' as libc::c_char); + assert_eq!(*ptr::offset(buf, 1), 'e' as libc::c_char); + assert_eq!(*ptr::offset(buf, 2), 'l' as libc::c_char); + assert_eq!(*ptr::offset(buf, 3), 'l' as libc::c_char); + assert_eq!(*ptr::offset(buf, 4), 'o' as libc::c_char); + assert_eq!(*ptr::offset(buf, 5), 0); + } + } + + do bytes!("foo", 0xff).to_c_str().with_ref |buf| { + unsafe { + assert_eq!(*ptr::offset(buf, 0), 'f' as libc::c_char); + assert_eq!(*ptr::offset(buf, 1), 'o' as libc::c_char); + assert_eq!(*ptr::offset(buf, 2), 'o' as libc::c_char); + assert_eq!(*ptr::offset(buf, 3), 0xff); + assert_eq!(*ptr::offset(buf, 4), 0); + } + } + } + + #[test] fn test_is_null() { let c_str = unsafe { CString::new(ptr::null(), false) }; assert!(c_str.is_null()); @@ -349,4 +391,33 @@ mod tests { } } } + + #[test] + fn test_as_bytes() { + let c_str = "hello".to_c_str(); + assert_eq!(c_str.as_bytes(), bytes!("hello", 0)); + let c_str = "".to_c_str(); + assert_eq!(c_str.as_bytes(), bytes!(0)); + let c_str = bytes!("foo", 0xff).to_c_str(); + assert_eq!(c_str.as_bytes(), bytes!("foo", 0xff, 0)); + } + + #[test] + #[should_fail] + fn test_as_bytes_fail() { + let c_str = unsafe { CString::new(ptr::null(), false) }; + c_str.as_bytes(); + } + + #[test] + fn test_as_str() { + let c_str = "hello".to_c_str(); + assert_eq!(c_str.as_str(), Some("hello")); + let c_str = "".to_c_str(); + assert_eq!(c_str.as_str(), Some("")); + let c_str = bytes!("foo", 0xff).to_c_str(); + assert_eq!(c_str.as_str(), None); + let c_str = unsafe { CString::new(ptr::null(), false) }; + assert_eq!(c_str.as_str(), None); + } } |
