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.
11 #![unstable(feature = "std_misc")]
14 use cmp::{PartialEq, Eq, PartialOrd, Ord, Ordering};
15 use error::{Error, FromError};
24 use option::Option::{self, Some, None};
25 use result::Result::{self, Ok, Err};
30 /// A type representing an owned C-compatible string
32 /// This type serves the primary purpose of being able to safely generate a
33 /// C-compatible string from a Rust byte slice or vector. An instance of this
34 /// type is a static guarantee that the underlying bytes contain no interior 0
35 /// bytes and the final byte is 0.
37 /// A `CString` is created from either a byte slice or a byte vector. After
38 /// being created, a `CString` predominately inherits all of its methods from
39 /// the `Deref` implementation to `[libc::c_char]`. Note that the underlying
40 /// array is represented as an array of `libc::c_char` as opposed to `u8`. A
41 /// `u8` slice can be obtained with the `as_bytes` method. Slices produced from
42 /// a `CString` do *not* contain the trailing nul terminator unless otherwise
48 /// # #![feature(libc)]
49 /// # extern crate libc;
51 /// use std::ffi::CString;
55 /// fn my_printer(s: *const libc::c_char);
58 /// let to_print = &b"Hello, world!"[..];
59 /// let c_to_print = CString::new(to_print).unwrap();
61 /// my_printer(c_to_print.as_ptr());
65 #[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
66 #[stable(feature = "rust1", since = "1.0.0")]
71 /// Representation of a borrowed C string.
73 /// This dynamically sized type is only safely constructed via a borrowed
74 /// version of an instance of `CString`. This type can be constructed from a raw
75 /// C string as well and represents a C string borrowed from another location.
77 /// Note that this structure is **not** `repr(C)` and is not recommended to be
78 /// placed in the signatures of FFI functions. Instead safe wrappers of FFI
79 /// functions may leverage the unsafe `from_ptr` constructor to provide a safe
80 /// interface to other consumers.
84 /// Inspecting a foreign C string
87 /// # #![feature(libc)]
88 /// extern crate libc;
89 /// use std::ffi::CStr;
91 /// extern { fn my_string() -> *const libc::c_char; }
95 /// let slice = CStr::from_ptr(my_string());
96 /// println!("string length: {}", slice.to_bytes().len());
101 /// Passing a Rust-originating C string
104 /// # #![feature(libc)]
105 /// extern crate libc;
106 /// use std::ffi::{CString, CStr};
108 /// fn work(data: &CStr) {
109 /// extern { fn work_with(data: *const libc::c_char); }
111 /// unsafe { work_with(data.as_ptr()) }
115 /// let s = CString::new("data data data data").unwrap();
120 #[stable(feature = "rust1", since = "1.0.0")]
122 // FIXME: this should not be represented with a DST slice but rather with
123 // just a raw `libc::c_char` along with some form of marker to make
124 // this an unsized type. Essentially `sizeof(&CStr)` should be the
125 // same as `sizeof(&c_char)` but `CStr` should be an unsized type.
126 inner: [libc::c_char]
129 /// An error returned from `CString::new` to indicate that a nul byte was found
130 /// in the vector provided.
131 #[derive(Clone, PartialEq, Debug)]
132 #[stable(feature = "rust1", since = "1.0.0")]
133 pub struct NulError(usize, Vec<u8>);
135 /// A conversion trait used by the constructor of `CString` for types that can
136 /// be converted to a vector of bytes.
137 #[deprecated(since = "1.0.0", reason = "use std::convert::Into<Vec<u8>> instead")]
138 #[unstable(feature = "std_misc")]
139 pub trait IntoBytes {
140 /// Consumes this container, returning a vector of bytes.
141 fn into_bytes(self) -> Vec<u8>;
145 /// Create a new C-compatible string from a container of bytes.
147 /// This method will consume the provided data and use the underlying bytes
148 /// to construct a new string, ensuring that there is a trailing 0 byte.
153 /// # #![feature(libc)]
154 /// extern crate libc;
155 /// use std::ffi::CString;
157 /// extern { fn puts(s: *const libc::c_char); }
160 /// let to_print = CString::new("Hello!").unwrap();
162 /// puts(to_print.as_ptr());
169 /// This function will return an error if the bytes yielded contain an
170 /// internal 0 byte. The error returned will contain the bytes as well as
171 /// the position of the nul byte.
172 #[stable(feature = "rust1", since = "1.0.0")]
173 pub fn new<T: Into<Vec<u8>>>(t: T) -> Result<CString, NulError> {
174 let bytes = t.into();
175 match bytes.iter().position(|x| *x == 0) {
176 Some(i) => Err(NulError(i, bytes)),
177 None => Ok(unsafe { CString::from_vec_unchecked(bytes) }),
181 /// Create a new C-compatible string from a byte slice.
183 /// This method will copy the data of the slice provided into a new
184 /// allocation, ensuring that there is a trailing 0 byte.
189 /// # #![feature(libc)]
190 /// extern crate libc;
191 /// use std::ffi::CString;
193 /// extern { fn puts(s: *const libc::c_char); }
196 /// let to_print = CString::new("Hello!").unwrap();
198 /// puts(to_print.as_ptr());
205 /// This function will panic if the provided slice contains any
206 /// interior nul bytes.
207 #[unstable(feature = "std_misc")]
208 #[deprecated(since = "1.0.0", reason = "use CString::new instead")]
210 pub fn from_slice(v: &[u8]) -> CString {
211 CString::from_vec(v.to_vec())
214 /// Create a C-compatible string from a byte vector.
216 /// This method will consume ownership of the provided vector, appending a 0
217 /// byte to the end after verifying that there are no interior 0 bytes.
221 /// This function will panic if the provided slice contains any
222 /// interior nul bytes.
223 #[unstable(feature = "std_misc")]
224 #[deprecated(since = "1.0.0", reason = "use CString::new instead")]
225 pub fn from_vec(v: Vec<u8>) -> CString {
226 match v.iter().position(|x| *x == 0) {
227 Some(i) => panic!("null byte found in slice at: {}", i),
228 None => unsafe { CString::from_vec_unchecked(v) },
232 /// Create a C-compatible string from a byte vector without checking for
233 /// interior 0 bytes.
235 /// This method is equivalent to `from_vec` except that no runtime assertion
236 /// is made that `v` contains no 0 bytes.
237 #[stable(feature = "rust1", since = "1.0.0")]
238 pub unsafe fn from_vec_unchecked(mut v: Vec<u8>) -> CString {
243 /// Returns the contents of this `CString` as a slice of bytes.
245 /// The returned slice does **not** contain the trailing nul separator and
246 /// it is guaranteed to not have any interior nul bytes.
247 #[stable(feature = "rust1", since = "1.0.0")]
248 pub fn as_bytes(&self) -> &[u8] {
249 &self.inner[..self.inner.len() - 1]
252 /// Equivalent to the `as_bytes` function except that the returned slice
253 /// includes the trailing nul byte.
254 #[stable(feature = "rust1", since = "1.0.0")]
255 pub fn as_bytes_with_nul(&self) -> &[u8] {
260 #[stable(feature = "rust1", since = "1.0.0")]
261 impl Deref for CString {
264 fn deref(&self) -> &CStr {
265 unsafe { mem::transmute(self.as_bytes_with_nul()) }
269 #[stable(feature = "rust1", since = "1.0.0")]
270 impl fmt::Debug for CString {
271 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
272 fmt::Debug::fmt(&String::from_utf8_lossy(self.as_bytes()), f)
277 /// Returns the position of the nul byte in the slice that was provided to
278 /// `CString::from_vec`.
279 #[stable(feature = "rust1", since = "1.0.0")]
280 pub fn nul_position(&self) -> usize { self.0 }
282 /// Consumes this error, returning the underlying vector of bytes which
283 /// generated the error in the first place.
284 #[stable(feature = "rust1", since = "1.0.0")]
285 pub fn into_vec(self) -> Vec<u8> { self.1 }
288 #[stable(feature = "rust1", since = "1.0.0")]
289 impl Error for NulError {
290 fn description(&self) -> &str { "nul byte found in data" }
293 #[stable(feature = "rust1", since = "1.0.0")]
294 impl fmt::Display for NulError {
295 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
296 write!(f, "nul byte found in provided data at position: {}", self.0)
300 #[stable(feature = "rust1", since = "1.0.0")]
301 impl FromError<NulError> for io::Error {
302 fn from_error(_: NulError) -> io::Error {
303 io::Error::new(io::ErrorKind::InvalidInput,
304 "data provided contains a nul byte", None)
308 #[stable(feature = "rust1", since = "1.0.0")]
310 impl FromError<NulError> for old_io::IoError {
311 fn from_error(_: NulError) -> old_io::IoError {
313 kind: old_io::IoErrorKind::InvalidInput,
314 desc: "data provided contains a nul byte",
321 /// Cast a raw C string to a safe C string wrapper.
323 /// This function will cast the provided `ptr` to the `CStr` wrapper which
324 /// allows inspection and interoperation of non-owned C strings. This method
325 /// is unsafe for a number of reasons:
327 /// * There is no guarantee to the validity of `ptr`
328 /// * The returned lifetime is not guaranteed to be the actual lifetime of
330 /// * There is no guarantee that the memory pointed to by `ptr` contains a
331 /// valid nul terminator byte at the end of the string.
333 /// > **Note**: This operation is intended to be a 0-cost cast but it is
334 /// > currently implemented with an up-front calculation of the length of
335 /// > the string. This is not guaranteed to always be the case.
340 /// # #![feature(libc)]
341 /// # extern crate libc;
343 /// use std::ffi::CStr;
348 /// fn my_string() -> *const libc::c_char;
352 /// let slice = CStr::from_ptr(my_string());
353 /// println!("string returned: {}",
354 /// str::from_utf8(slice.to_bytes()).unwrap());
358 #[stable(feature = "rust1", since = "1.0.0")]
359 pub unsafe fn from_ptr<'a>(ptr: *const libc::c_char) -> &'a CStr {
360 let len = libc::strlen(ptr);
361 mem::transmute(slice::from_raw_parts(ptr, len as usize + 1))
364 /// Return the inner pointer to this C string.
366 /// The returned pointer will be valid for as long as `self` is and points
367 /// to a contiguous region of memory terminated with a 0 byte to represent
368 /// the end of the string.
369 #[stable(feature = "rust1", since = "1.0.0")]
370 pub fn as_ptr(&self) -> *const libc::c_char {
374 /// Convert this C string to a byte slice.
376 /// This function will calculate the length of this string (which normally
377 /// requires a linear amount of work to be done) and then return the
378 /// resulting slice of `u8` elements.
380 /// The returned slice will **not** contain the trailing nul that this C
383 /// > **Note**: This method is currently implemented as a 0-cost cast, but
384 /// > it is planned to alter its definition in the future to perform the
385 /// > length calculation whenever this method is called.
386 #[stable(feature = "rust1", since = "1.0.0")]
387 pub fn to_bytes(&self) -> &[u8] {
388 let bytes = self.to_bytes_with_nul();
389 &bytes[..bytes.len() - 1]
392 /// Convert this C string to a byte slice containing the trailing 0 byte.
394 /// This function is the equivalent of `to_bytes` except that it will retain
395 /// the trailing nul instead of chopping it off.
397 /// > **Note**: This method is currently implemented as a 0-cost cast, but
398 /// > it is planned to alter its definition in the future to perform the
399 /// > length calculation whenever this method is called.
400 #[stable(feature = "rust1", since = "1.0.0")]
401 pub fn to_bytes_with_nul(&self) -> &[u8] {
402 unsafe { mem::transmute::<&[libc::c_char], &[u8]>(&self.inner) }
406 #[stable(feature = "rust1", since = "1.0.0")]
407 impl PartialEq for CStr {
408 fn eq(&self, other: &CStr) -> bool {
409 self.to_bytes().eq(other.to_bytes())
412 #[stable(feature = "rust1", since = "1.0.0")]
414 #[stable(feature = "rust1", since = "1.0.0")]
415 impl PartialOrd for CStr {
416 fn partial_cmp(&self, other: &CStr) -> Option<Ordering> {
417 self.to_bytes().partial_cmp(&other.to_bytes())
420 #[stable(feature = "rust1", since = "1.0.0")]
422 fn cmp(&self, other: &CStr) -> Ordering {
423 self.to_bytes().cmp(&other.to_bytes())
427 /// Deprecated in favor of `CStr`
428 #[unstable(feature = "std_misc")]
429 #[deprecated(since = "1.0.0", reason = "use CStr::from_ptr(p).to_bytes() instead")]
430 pub unsafe fn c_str_to_bytes<'a>(raw: &'a *const libc::c_char) -> &'a [u8] {
431 let len = libc::strlen(*raw);
432 slice::from_raw_parts(*(raw as *const _ as *const *const u8), len as usize)
435 /// Deprecated in favor of `CStr`
436 #[unstable(feature = "std_misc")]
437 #[deprecated(since = "1.0.0",
438 reason = "use CStr::from_ptr(p).to_bytes_with_nul() instead")]
439 pub unsafe fn c_str_to_bytes_with_nul<'a>(raw: &'a *const libc::c_char)
441 let len = libc::strlen(*raw) + 1;
442 slice::from_raw_parts(*(raw as *const _ as *const *const u8), len as usize)
446 impl<'a> IntoBytes for &'a str {
447 fn into_bytes(self) -> Vec<u8> { self.as_bytes().to_vec() }
450 impl<'a> IntoBytes for &'a [u8] {
451 fn into_bytes(self) -> Vec<u8> { self.to_vec() }
454 impl IntoBytes for String {
455 fn into_bytes(self) -> Vec<u8> { self.into_bytes() }
458 impl IntoBytes for Vec<u8> {
459 fn into_bytes(self) -> Vec<u8> { self }
471 let ptr = data.as_ptr() as *const libc::c_char;
473 assert_eq!(CStr::from_ptr(ptr).to_bytes(), b"123");
474 assert_eq!(CStr::from_ptr(ptr).to_bytes_with_nul(), b"123\0");
480 let s = CString::new("1234").unwrap();
481 assert_eq!(s.as_bytes(), b"1234");
482 assert_eq!(s.as_bytes_with_nul(), b"1234\0");
486 fn build_with_zero1() {
487 assert!(CString::new(&b"\0"[..]).is_err());
490 fn build_with_zero2() {
491 assert!(CString::new(vec![0]).is_err());
495 fn build_with_zero3() {
497 let s = CString::from_vec_unchecked(vec![0]);
498 assert_eq!(s.as_bytes(), b"\0");
504 let s = CString::new(&b"12"[..]).unwrap();
505 assert_eq!(format!("{:?}", s), "\"12\"");
511 let s = CStr::from_ptr(b"12\0".as_ptr() as *const _);
512 assert_eq!(s.to_bytes(), b"12");
513 assert_eq!(s.to_bytes_with_nul(), b"12\0");