]> git.lizzy.rs Git - rust.git/commitdiff
c_str: add `.as_ptr` & `.as_mut_ptr` to replace `.with_[mut_]ref`.
authorHuon Wilson <dbau.pp+github@gmail.com>
Sat, 14 Jun 2014 12:46:50 +0000 (22:46 +1000)
committerHuon Wilson <dbau.pp+github@gmail.com>
Sun, 29 Jun 2014 11:15:26 +0000 (21:15 +1000)
These forms return the pointer directly, rather than the added
indirection, indentation, and inefficiencies of the closures in
`.with_ref` and `.with_mut_ref`. The two closure functions are
deprecated.

Replace

    foo(c_str.with_ref(|p| p))

    c_str.with_ref(|p| {
        foo(p);
        bar(p);
    })

with

    foo(c_str.as_ptr())

    let p = c_str.as_ptr();
    foo(p);
    bar(p);

This change does mean that one has to be careful to avoid writing `let p
= x.to_c_str().as_ptr();` since the `CString` will be freed at the end
of the statement. Previously, `with_ref` was used (and `as_ptr` avoided)
for this reason, but Rust has strongly moved away from closures to more
RAII-style code, and most uses of `.with_ref` where in the form
`.with_ref(|p| p)` anyway, that is, they were exactly `.as_ptr`.

[breaking-change]

src/librustrt/c_str.rs

index 26216f655304e734757d588d8c2d9ef85a35f0a6..bc3e64c519ad9f6037a176fc6868cb61a76756be 100644 (file)
@@ -133,11 +133,79 @@ pub unsafe fn unwrap(self) -> *const libc::c_char {
         c_str.buf
     }
 
+    /// Return a pointer to the NUL-terminated string data.
+    ///
+    /// `.as_ptr` returns an internal pointer into the `CString`, and
+    /// may be invalidated when the `CString` falls out of scope (the
+    /// destructor will run, freeing the allocation if there is
+    /// one).
+    ///
+    /// ```rust
+    /// let foo = "some string";
+    ///
+    /// // right
+    /// let x = foo.to_c_str();
+    /// let p = x.as_ptr();
+    ///
+    /// // wrong (the CString will be freed, invalidating `p`)
+    /// let p = foo.to_c_str().as_ptr();
+    /// ```
+    ///
+    /// # Failure
+    ///
+    /// Fails if the CString is null.
+    ///
+    /// # Example
+    ///
+    /// ```rust
+    /// extern crate libc;
+    ///
+    /// fn main() {
+    ///     let c_str = "foo bar".to_c_str();
+    ///     unsafe {
+    ///         libc::puts(c_str.as_ptr());
+    ///     }
+    /// }
+    /// ```
+    pub fn as_ptr(&self) -> *const libc::c_char {
+        if self.buf.is_null() { fail!("CString is null!"); }
+
+        self.buf
+    }
+
+    /// Return a mutable pointer to the NUL-terminated string data.
+    ///
+    /// `.as_mut_ptr` returns an internal pointer into the `CString`, and
+    /// may be invalidated when the `CString` falls out of scope (the
+    /// destructor will run, freeing the allocation if there is
+    /// one).
+    ///
+    /// ```rust
+    /// let foo = "some string";
+    ///
+    /// // right
+    /// let mut x = foo.to_c_str();
+    /// let p = x.as_mut_ptr();
+    ///
+    /// // wrong (the CString will be freed, invalidating `p`)
+    /// let p = foo.to_c_str().as_mut_ptr();
+    /// ```
+    ///
+    /// # Failure
+    ///
+    /// Fails if the CString is null.
+    pub fn as_mut_ptr(&mut self) -> *mut libc::c_char {
+        if self.buf.is_null() { fail!("CString is null!") }
+
+        self.buf as *mut _
+    }
+
     /// Calls a closure with a reference to the underlying `*libc::c_char`.
     ///
     /// # Failure
     ///
     /// Fails if the CString is null.
+    #[deprecated="use `.as_ptr()`"]
     pub fn with_ref<T>(&self, f: |*const libc::c_char| -> T) -> T {
         if self.buf.is_null() { fail!("CString is null!"); }
         f(self.buf)
@@ -148,6 +216,7 @@ pub fn with_ref<T>(&self, f: |*const libc::c_char| -> T) -> T {
     /// # Failure
     ///
     /// Fails if the CString is null.
+    #[deprecated="use `.as_mut_ptr()`"]
     pub fn with_mut_ref<T>(&mut self, f: |*mut libc::c_char| -> T) -> T {
         if self.buf.is_null() { fail!("CString is null!"); }
         f(self.buf as *mut libc::c_char)