impl Clone for CString
Clone tests
This commit is contained in:
parent
2bcd951749
commit
73024e4b85
1 changed files with 48 additions and 4 deletions
|
@ -68,6 +68,7 @@ use iter::{Iterator, range};
|
||||||
use libc;
|
use libc;
|
||||||
use kinds::marker;
|
use kinds::marker;
|
||||||
use ops::Drop;
|
use ops::Drop;
|
||||||
|
use clone::Clone;
|
||||||
use option::{Option, Some, None};
|
use option::{Option, Some, None};
|
||||||
use ptr::RawPtr;
|
use ptr::RawPtr;
|
||||||
use ptr;
|
use ptr;
|
||||||
|
@ -76,6 +77,7 @@ use str;
|
||||||
use vec::{CloneableVector, ImmutableVector, MutableVector};
|
use vec::{CloneableVector, ImmutableVector, MutableVector};
|
||||||
use vec;
|
use vec;
|
||||||
use unstable::intrinsics;
|
use unstable::intrinsics;
|
||||||
|
use rt::global_heap::malloc_raw;
|
||||||
|
|
||||||
/// Resolution options for the `null_byte` condition
|
/// Resolution options for the `null_byte` condition
|
||||||
pub enum NullByteResolution {
|
pub enum NullByteResolution {
|
||||||
|
@ -99,6 +101,21 @@ pub struct CString {
|
||||||
priv owns_buffer_: bool,
|
priv owns_buffer_: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Clone for CString {
|
||||||
|
/// Clone this CString into a new, uniquely owned CString. For safety
|
||||||
|
/// reasons, this is always a deep clone, rather than the usual shallow
|
||||||
|
/// clone.
|
||||||
|
fn clone(&self) -> CString {
|
||||||
|
if self.buf.is_null() {
|
||||||
|
CString { buf: self.buf, owns_buffer_: self.owns_buffer_ }
|
||||||
|
} else {
|
||||||
|
let buf = unsafe { malloc_raw(self.len()) } as *mut libc::c_char;
|
||||||
|
unsafe { ptr::copy_nonoverlapping_memory(buf, self.buf, self.len()); }
|
||||||
|
CString { buf: buf as *libc::c_char, owns_buffer_: true }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl CString {
|
impl CString {
|
||||||
/// Create a C String from a pointer.
|
/// Create a C String from a pointer.
|
||||||
pub unsafe fn new(buf: *libc::c_char, owns_buffer: bool) -> CString {
|
pub unsafe fn new(buf: *libc::c_char, owns_buffer: bool) -> CString {
|
||||||
|
@ -287,10 +304,7 @@ impl<'a> ToCStr for &'a [u8] {
|
||||||
|
|
||||||
unsafe fn to_c_str_unchecked(&self) -> CString {
|
unsafe fn to_c_str_unchecked(&self) -> CString {
|
||||||
let self_len = self.len();
|
let self_len = self.len();
|
||||||
let buf = libc::malloc(self_len as libc::size_t + 1) as *mut u8;
|
let buf = malloc_raw(self_len + 1);
|
||||||
if buf.is_null() {
|
|
||||||
fail!("failed to allocate memory!");
|
|
||||||
}
|
|
||||||
|
|
||||||
ptr::copy_memory(buf, self.as_ptr(), self_len);
|
ptr::copy_memory(buf, self.as_ptr(), self_len);
|
||||||
*ptr::mut_offset(buf, self_len as int) = 0;
|
*ptr::mut_offset(buf, self_len as int) = 0;
|
||||||
|
@ -598,6 +612,36 @@ mod tests {
|
||||||
let c_str = unsafe { CString::new(ptr::null(), false) };
|
let c_str = unsafe { CString::new(ptr::null(), false) };
|
||||||
c_str.iter();
|
c_str.iter();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_clone() {
|
||||||
|
let c_str = "hello".to_c_str();
|
||||||
|
assert!(c_str == c_str.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_clone_noleak() {
|
||||||
|
fn foo(f: |c: &CString|) {
|
||||||
|
let s = ~"test";
|
||||||
|
let c = s.to_c_str();
|
||||||
|
// give the closure a non-owned CString
|
||||||
|
let mut c_ = c.with_ref(|c| unsafe { CString::new(c, false) } );
|
||||||
|
f(&c_);
|
||||||
|
// muck with the buffer for later printing
|
||||||
|
c_.with_mut_ref(|c| unsafe { *c = 'X' as libc::c_char } );
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut c_: Option<CString> = None;
|
||||||
|
foo(|c| {
|
||||||
|
c_ = Some(c.clone());
|
||||||
|
c.clone();
|
||||||
|
// force a copy, reading the memory
|
||||||
|
c.as_bytes().to_owned();
|
||||||
|
});
|
||||||
|
let c_ = c_.unwrap();
|
||||||
|
// force a copy, reading the memory
|
||||||
|
c_.as_bytes().to_owned();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue