about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2013-09-16 06:30:51 -0700
committerbors <bors@rust-lang.org>2013-09-16 06:30:51 -0700
commit2562f480f53fd3d15822034d441441ffbd04dbe4 (patch)
tree5d1e9493efdcf2ac805496a605e58e70fccf9ab7 /src/libstd
parent3e1803f3af1adc1b2e5595650f6920f40bbedc2e (diff)
parent51470f3b97428756bee70e564db026ba2e2bceb6 (diff)
downloadrust-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.rs77
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);
+    }
 }