// Allocate the C string with an explicit local that owns the string. The
// `c_buffer` pointer will be deallocated when `my_c_string` goes out of scope.
let my_c_string = my_string.to_c_str();
- my_c_string.with_ref(|c_buffer| {
- unsafe { puts(c_buffer); }
- });
+ unsafe {
+ puts(my_c_string.as_ptr());
+ }
- // Don't save off the allocation of the C string, the `c_buffer` will be
+ // Don't save/return the pointer to the C string, the `c_buffer` will be
// deallocated when this block returns!
my_string.with_c_str(|c_buffer| {
unsafe { puts(c_buffer); }
use alloc::libc_heap::malloc_raw;
use collections::string::String;
+use collections::hash;
use core::kinds::marker;
use core::mem;
use core::ptr;
}
}
+impl PartialOrd for CString {
+ #[inline]
+ fn partial_cmp(&self, other: &CString) -> Option<Ordering> {
+ self.as_bytes().partial_cmp(&other.as_bytes())
+ }
+}
+
+impl Eq for CString {}
+
+impl<S: hash::Writer> hash::Hash<S> for CString {
+ #[inline]
+ fn hash(&self, state: &mut S) {
+ self.as_bytes().hash(state)
+ }
+}
+
impl CString {
/// Create a C String from a pointer.
pub unsafe fn new(buf: *const libc::c_char, owns_buffer: bool) -> CString {
CString { buf: buf, owns_buffer_: owns_buffer }
}
- /// Unwraps the wrapped `*libc::c_char` from the `CString` wrapper.
- ///
- /// The original object is destructed after this method is called, and if
- /// the underlying pointer was previously allocated, care must be taken to
- /// ensure that it is deallocated properly.
- pub unsafe fn unwrap(self) -> *const libc::c_char {
- let mut c_str = self;
- c_str.owns_buffer_ = false;
- c_str.buf
- }
-
/// Return a pointer to the NUL-terminated string data.
///
/// `.as_ptr` returns an internal pointer into the `CString`, and
marker: marker::ContravariantLifetime,
}
}
+
+ /// Unwraps the wrapped `*libc::c_char` from the `CString` wrapper.
+ ///
+ /// Any ownership of the buffer by the `CString` wrapper is
+ /// forgotten, meaning that the backing allocation of this
+ /// `CString` is not automatically freed if it owns the
+ /// allocation. In this case, a user of `.unwrap()` should ensure
+ /// the allocation is freed, to avoid leaking memory.
+ ///
+ /// Prefer `.as_ptr()` when just retrieving a pointer to the
+ /// string data, as that does not relinquish ownership.
+ pub unsafe fn unwrap(mut self) -> *const libc::c_char {
+ self.owns_buffer_ = false;
+ self.buf
+ }
+
}
impl Drop for CString {
/// Fails the task if the receiver has an interior null.
#[inline]
fn with_c_str<T>(&self, f: |*const libc::c_char| -> T) -> T {
- self.to_c_str().with_ref(f)
+ let c_str = self.to_c_str();
+ f(c_str.as_ptr())
}
/// Unsafe variant of `with_c_str()` that doesn't check for nulls.
#[inline]
unsafe fn with_c_str_unchecked<T>(&self, f: |*const libc::c_char| -> T) -> T {
- self.to_c_str_unchecked().with_ref(f)
+ let c_str = self.to_c_str_unchecked();
+ f(c_str.as_ptr())
}
}
// (without forcing an additional & around &str). So we are instead
// temporarily adding an instance for ~str and String, so that we can
// take ToCStr as owned. When DST lands, the string instances should
-// be revisted, and arguments bound by ToCStr should be passed by
+// be revisited, and arguments bound by ToCStr should be passed by
// reference.
impl<'a> ToCStr for &'a str {
impl<'a> ToCStr for &'a [u8] {
fn to_c_str(&self) -> CString {
let mut cs = unsafe { self.to_c_str_unchecked() };
- cs.with_mut_ref(|buf| check_for_null(*self, buf));
+ check_for_null(*self, cs.as_mut_ptr());
cs
}
// Unsafe function that handles possibly copying the &[u8] into a stack array.
unsafe fn with_c_str<T>(v: &[u8], checked: bool,
f: |*const libc::c_char| -> T) -> T {
- if v.len() < BUF_LEN {
+ let c_str = if v.len() < BUF_LEN {
let mut buf: [u8, .. BUF_LEN] = mem::uninitialized();
slice::bytes::copy_memory(buf, v);
buf[v.len()] = 0;
check_for_null(v, buf as *mut libc::c_char);
}
- f(buf as *const libc::c_char)
+ return f(buf as *const libc::c_char)
} else if checked {
- v.to_c_str().with_ref(f)
+ v.to_c_str()
} else {
- v.to_c_str_unchecked().with_ref(f)
- }
+ v.to_c_str_unchecked()
+ };
+
+ f(c_str.as_ptr())
}
#[inline]
#[test]
fn test_str_to_c_str() {
- "".to_c_str().with_ref(|buf| {
- unsafe {
- assert_eq!(*buf.offset(0), 0);
- }
- });
+ let c_str = "".to_c_str();
+ unsafe {
+ assert_eq!(*c_str.as_ptr().offset(0), 0);
+ }
- "hello".to_c_str().with_ref(|buf| {
- unsafe {
- assert_eq!(*buf.offset(0), 'h' as libc::c_char);
- assert_eq!(*buf.offset(1), 'e' as libc::c_char);
- assert_eq!(*buf.offset(2), 'l' as libc::c_char);
- assert_eq!(*buf.offset(3), 'l' as libc::c_char);
- assert_eq!(*buf.offset(4), 'o' as libc::c_char);
- assert_eq!(*buf.offset(5), 0);
- }
- })
+ let c_str = "hello".to_c_str();
+ let buf = c_str.as_ptr();
+ unsafe {
+ assert_eq!(*buf.offset(0), 'h' as libc::c_char);
+ assert_eq!(*buf.offset(1), 'e' as libc::c_char);
+ assert_eq!(*buf.offset(2), 'l' as libc::c_char);
+ assert_eq!(*buf.offset(3), 'l' as libc::c_char);
+ assert_eq!(*buf.offset(4), 'o' as libc::c_char);
+ assert_eq!(*buf.offset(5), 0);
+ }
}
#[test]
fn test_vec_to_c_str() {
let b: &[u8] = [];
- b.to_c_str().with_ref(|buf| {
- unsafe {
- assert_eq!(*buf.offset(0), 0);
- }
- });
+ let c_str = b.to_c_str();
+ unsafe {
+ assert_eq!(*c_str.as_ptr().offset(0), 0);
+ }
- let _ = b"hello".to_c_str().with_ref(|buf| {
- unsafe {
- assert_eq!(*buf.offset(0), 'h' as libc::c_char);
- assert_eq!(*buf.offset(1), 'e' as libc::c_char);
- assert_eq!(*buf.offset(2), 'l' as libc::c_char);
- assert_eq!(*buf.offset(3), 'l' as libc::c_char);
- assert_eq!(*buf.offset(4), 'o' as libc::c_char);
- assert_eq!(*buf.offset(5), 0);
- }
- });
+ let c_str = b"hello".to_c_str();
+ let buf = c_str.as_ptr();
+ unsafe {
+ assert_eq!(*buf.offset(0), 'h' as libc::c_char);
+ assert_eq!(*buf.offset(1), 'e' as libc::c_char);
+ assert_eq!(*buf.offset(2), 'l' as libc::c_char);
+ assert_eq!(*buf.offset(3), 'l' as libc::c_char);
+ assert_eq!(*buf.offset(4), 'o' as libc::c_char);
+ assert_eq!(*buf.offset(5), 0);
+ }
- let _ = b"foo\xFF".to_c_str().with_ref(|buf| {
- unsafe {
- assert_eq!(*buf.offset(0), 'f' as libc::c_char);
- assert_eq!(*buf.offset(1), 'o' as libc::c_char);
- assert_eq!(*buf.offset(2), 'o' as libc::c_char);
- assert_eq!(*buf.offset(3), 0xff as i8);
- assert_eq!(*buf.offset(4), 0);
- }
- });
+ let c_str = b"foo\xFF".to_c_str();
+ let buf = c_str.as_ptr();
+ unsafe {
+ assert_eq!(*buf.offset(0), 'f' as libc::c_char);
+ assert_eq!(*buf.offset(1), 'o' as libc::c_char);
+ assert_eq!(*buf.offset(2), 'o' as libc::c_char);
+ assert_eq!(*buf.offset(3), 0xffu8 as i8);
+ assert_eq!(*buf.offset(4), 0);
+ }
}
#[test]
}
#[test]
- fn test_with_ref() {
+ fn test_as_ptr() {
let c_str = "hello".to_c_str();
- let len = unsafe { c_str.with_ref(|buf| libc::strlen(buf)) };
+ let len = unsafe { libc::strlen(c_str.as_ptr()) };
assert!(!c_str.is_null());
assert!(c_str.is_not_null());
assert_eq!(len, 5);
}
-
#[test]
#[should_fail]
- fn test_with_ref_empty_fail() {
+ fn test_as_ptr_empty_fail() {
let c_str = unsafe { CString::new(ptr::null(), false) };
- c_str.with_ref(|_| ());
+ c_str.as_ptr();
}
#[test]
#[test]
fn test_to_c_str_unchecked() {
unsafe {
- "he\x00llo".to_c_str_unchecked().with_ref(|buf| {
- assert_eq!(*buf.offset(0), 'h' as libc::c_char);
- assert_eq!(*buf.offset(1), 'e' as libc::c_char);
- assert_eq!(*buf.offset(2), 0);
- assert_eq!(*buf.offset(3), 'l' as libc::c_char);
- assert_eq!(*buf.offset(4), 'l' as libc::c_char);
- assert_eq!(*buf.offset(5), 'o' as libc::c_char);
- assert_eq!(*buf.offset(6), 0);
- })
+ let c_string = "he\x00llo".to_c_str_unchecked();
+ let buf = c_string.as_ptr();
+ assert_eq!(*buf.offset(0), 'h' as libc::c_char);
+ assert_eq!(*buf.offset(1), 'e' as libc::c_char);
+ assert_eq!(*buf.offset(2), 0);
+ assert_eq!(*buf.offset(3), 'l' as libc::c_char);
+ assert_eq!(*buf.offset(4), 'l' as libc::c_char);
+ assert_eq!(*buf.offset(5), 'o' as libc::c_char);
+ assert_eq!(*buf.offset(6), 0);
}
}
let s = "test".to_string();
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) } );
+ let mut c_ = unsafe { CString::new(c.as_ptr(), false) };
f(&c_);
// muck with the buffer for later printing
- c_.with_mut_ref(|c| unsafe { *c = 'X' as libc::c_char } );
+ unsafe { *c_.as_mut_ptr() = 'X' as libc::c_char }
}
let mut c_: Option<CString> = None;
Mary had a little lamb, Little lamb
Mary had a little lamb, Little lamb";
- fn bench_to_str(b: &mut Bencher, s: &str) {
+ fn bench_to_string(b: &mut Bencher, s: &str) {
b.iter(|| {
let c_str = s.to_c_str();
- c_str.with_ref(|c_str_buf| check(s, c_str_buf))
+ check(s, c_str.as_ptr());
})
}
#[bench]
fn bench_to_c_str_short(b: &mut Bencher) {
- bench_to_str(b, s_short)
+ bench_to_string(b, s_short)
}
#[bench]
fn bench_to_c_str_medium(b: &mut Bencher) {
- bench_to_str(b, s_medium)
+ bench_to_string(b, s_medium)
}
#[bench]
fn bench_to_c_str_long(b: &mut Bencher) {
- bench_to_str(b, s_long)
+ bench_to_string(b, s_long)
}
fn bench_to_c_str_unchecked(b: &mut Bencher, s: &str) {
b.iter(|| {
let c_str = unsafe { s.to_c_str_unchecked() };
- c_str.with_ref(|c_str_buf| check(s, c_str_buf))
+ check(s, c_str.as_ptr())
})
}