]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #35871 - bluss:cstring-new, r=alexcrichton
authorbors <bors@rust-lang.org>
Mon, 22 Aug 2016 15:29:41 +0000 (08:29 -0700)
committerGitHub <noreply@github.com>
Mon, 22 Aug 2016 15:29:41 +0000 (08:29 -0700)
cstring: avoid excessive growth just to 0-terminate

Based on following what happens in CString::new("string literal"):

1. Using `Into<Vec<u8>>`, a Vec is allocated with capacity exactly equal
   to the string's input length.
2. By `v.push(0)`, the Vec is grown to twice capacity, since it was full.
3. By `v.into_boxed_slice()`, the Vec capacity is shrunk to fit the length again.

If we use `.reserve_exact(1)` just before the push, then we avoid the
capacity doubling that we're going to have to shrink anyway.

Growing by just 1 byte means that the step (2) is less likely to have to
move the memory to a larger allocation chunk, and that the step (3) does
not have to reallocate.

Addresses part of #35838

1  2 
src/libstd/ffi/c_str.rs

index 18a7c7c8457043de80004199a7f45f90322b6573,6f217be31fe678e513fbf5a3ac95a9b5d1b1cd1a..5dae1a09bf410f7330a3786c8270b32fbc1b90ff
@@@ -211,19 -211,9 +211,20 @@@ impl CString 
      /// This method is equivalent to `new` except that no runtime assertion
      /// is made that `v` contains no 0 bytes, and it requires an actual
      /// byte vector, not anything that can be converted to one with Into.
 +    ///
 +    /// # Examples
 +    ///
 +    /// ```
 +    /// use std::ffi::CString;
 +    ///
 +    /// let raw = b"foo".to_vec();
 +    /// unsafe {
 +    ///     let c_string = CString::from_vec_unchecked(raw);
 +    /// }
 +    /// ```
      #[stable(feature = "rust1", since = "1.0.0")]
      pub unsafe fn from_vec_unchecked(mut v: Vec<u8>) -> CString {
+         v.reserve_exact(1);
          v.push(0);
          CString { inner: v.into_boxed_slice() }
      }