1 // Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
12 use iter::IteratorExt;
16 use slice::{self, SliceExt, AsSlice};
20 /// A type representing a C-compatible string
22 /// This type serves the primary purpose of being able to generate a
23 /// C-compatible string from a Rust byte slice or vector. An instance of this
24 /// type is a static guarantee that the underlying bytes contain no interior 0
25 /// bytes and the final byte is 0.
27 /// A `CString` is created from either a byte slice or a byte vector. After
28 /// being created, a `CString` predominately inherits all of its methods from
29 /// the `Deref` implementation to `[libc::c_char]`. Note that the underlying
30 /// array is represented as an array of `libc::c_char` as opposed to `u8`. A
31 /// `u8` slice can be obtained with the `as_bytes` method. Slices produced from
32 /// a `CString` do *not* contain the trailing nul terminator unless otherwise
38 /// # extern crate libc;
40 /// use std::ffi::CString;
44 /// fn my_printer(s: *const libc::c_char);
47 /// let to_print = "Hello, world!";
48 /// let c_to_print = CString::from_slice(to_print.as_bytes());
50 /// my_printer(c_to_print.as_ptr());
54 #[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
56 inner: Vec<libc::c_char>,
60 /// Create a new C-compatible string from a byte slice.
62 /// This method will copy the data of the slice provided into a new
63 /// allocation, ensuring that there is a trailing 0 byte.
67 /// This function will panic if there are any 0 bytes already in the slice
69 pub fn from_slice(v: &[u8]) -> CString {
70 CString::from_vec(v.to_vec())
73 /// Create a C-compatible string from a byte vector.
75 /// This method will consume ownership of the provided vector, appending a 0
76 /// byte to the end after verifying that there are no interior 0 bytes.
80 /// This function will panic if there are any 0 bytes already in the vector
82 pub fn from_vec(v: Vec<u8>) -> CString {
83 assert!(!v.iter().any(|&x| x == 0));
84 unsafe { CString::from_vec_unchecked(v) }
87 /// Create a C-compatibel string from a byte vector without checking for
90 /// This method is equivalent to `from_vec` except that no runtime assertion
91 /// is made that `v` contains no 0 bytes.
92 pub unsafe fn from_vec_unchecked(mut v: Vec<u8>) -> CString {
94 CString { inner: mem::transmute(v) }
97 /// Create a view into this C string which includes the trailing nul
98 /// terminator at the end of the string.
99 pub fn as_slice_with_nul(&self) -> &[libc::c_char] { self.inner.as_slice() }
101 /// Similar to the `as_slice` method, but returns a `u8` slice instead of a
102 /// `libc::c_char` slice.
103 pub fn as_bytes(&self) -> &[u8] {
104 unsafe { mem::transmute(self.as_slice()) }
107 /// Equivalend to `as_slice_with_nul` except that the type returned is a
108 /// `u8` slice instead of a `libc::c_char` slice.
109 pub fn as_bytes_with_nul(&self) -> &[u8] {
110 unsafe { mem::transmute(self.as_slice_with_nul()) }
114 impl Deref for CString {
115 type Target = [libc::c_char];
117 fn deref(&self) -> &[libc::c_char] {
118 self.inner.slice_to(self.inner.len() - 1)
122 impl fmt::Show for CString {
123 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
124 String::from_utf8_lossy(self.as_bytes()).fmt(f)
128 /// Interpret a C string as a byte slice.
130 /// This function will calculate the length of the C string provided, and it
131 /// will then return a corresponding slice for the contents of the C string not
132 /// including the nul terminator.
134 /// This function will tie the lifetime of the returned slice to the lifetime of
135 /// the pointer provided. This is done to help prevent the slice from escaping
136 /// the lifetime of the pointer itself. If a longer lifetime is needed, then
137 /// `mem::copy_lifetime` should be used.
139 /// This function is unsafe because there is no guarantee of the validity of the
140 /// pointer `raw` or a guarantee that a nul terminator will be found.
145 /// # extern crate libc;
152 /// fn my_string() -> *const libc::c_char;
156 /// let to_print = my_string();
157 /// let slice = ffi::c_str_to_bytes(&to_print);
158 /// println!("string returned: {}", str::from_utf8(slice).unwrap());
162 pub unsafe fn c_str_to_bytes<'a>(raw: &'a *const libc::c_char) -> &'a [u8] {
163 let len = libc::strlen(*raw);
164 slice::from_raw_buf(&*(raw as *const _ as *const *const u8), len as uint)
167 /// Interpret a C string as a byte slice with the nul terminator.
169 /// This function is identical to `from_raw_buf` except that the returned slice
170 /// will include the nul terminator of the string.
171 pub unsafe fn c_str_to_bytes_with_nul<'a>(raw: &'a *const libc::c_char) -> &'a [u8] {
172 let len = libc::strlen(*raw) + 1;
173 slice::from_raw_buf(&*(raw as *const _ as *const *const u8), len as uint)
186 let ptr = data.as_ptr() as *const libc::c_char;
188 assert_eq!(c_str_to_bytes(&ptr), b"123");
189 assert_eq!(c_str_to_bytes_with_nul(&ptr), b"123\0");
195 let s = CString::from_slice(b"1234");
196 assert_eq!(s.as_bytes(), b"1234");
197 assert_eq!(s.as_bytes_with_nul(), b"1234\0");
199 assert_eq!(s.as_slice(),
200 mem::transmute::<_, &[libc::c_char]>(b"1234"));
201 assert_eq!(s.as_slice_with_nul(),
202 mem::transmute::<_, &[libc::c_char]>(b"1234\0"));
206 #[should_fail] #[test]
207 fn build_with_zero1() { CString::from_slice(b"\0"); }
208 #[should_fail] #[test]
209 fn build_with_zero2() { CString::from_vec(vec![0]); }
212 fn build_with_zero3() {
214 let s = CString::from_vec_unchecked(vec![0]);
215 assert_eq!(s.as_bytes(), b"\0");