diff options
| author | Erick Tryzelaar <erick.tryzelaar@gmail.com> | 2013-08-03 17:13:14 -0700 |
|---|---|---|
| committer | Erick Tryzelaar <erick.tryzelaar@gmail.com> | 2013-08-04 14:13:17 -0700 |
| commit | 3102b1797e24b9dd8eef2f68a74ec83749d7b53d (patch) | |
| tree | c68578899941c134b1bc4e59999d5a40047f89f0 /src/libstd | |
| parent | 0512475fdab549182e73a42c2cd02df0cb710ebf (diff) | |
| download | rust-3102b1797e24b9dd8eef2f68a74ec83749d7b53d.tar.gz rust-3102b1797e24b9dd8eef2f68a74ec83749d7b53d.zip | |
std: replace str::as_c_str with std::c_str
Diffstat (limited to 'src/libstd')
| -rw-r--r-- | src/libstd/c_str.rs | 291 | ||||
| -rw-r--r-- | src/libstd/io.rs | 14 | ||||
| -rw-r--r-- | src/libstd/os.rs | 63 | ||||
| -rw-r--r-- | src/libstd/path.rs | 21 | ||||
| -rw-r--r-- | src/libstd/prelude.rs | 1 | ||||
| -rw-r--r-- | src/libstd/ptr.rs | 23 | ||||
| -rw-r--r-- | src/libstd/rt/borrowck.rs | 7 | ||||
| -rw-r--r-- | src/libstd/rt/logging.rs | 4 | ||||
| -rw-r--r-- | src/libstd/rt/uv/uvio.rs | 26 | ||||
| -rw-r--r-- | src/libstd/rt/uv/uvll.rs | 5 | ||||
| -rw-r--r-- | src/libstd/run.rs | 15 | ||||
| -rw-r--r-- | src/libstd/std.rs | 1 | ||||
| -rw-r--r-- | src/libstd/str.rs | 98 | ||||
| -rw-r--r-- | src/libstd/sys.rs | 10 | ||||
| -rw-r--r-- | src/libstd/unstable/dynamic_lib.rs | 6 | ||||
| -rw-r--r-- | src/libstd/unstable/lang.rs | 3 |
16 files changed, 403 insertions, 185 deletions
diff --git a/src/libstd/c_str.rs b/src/libstd/c_str.rs new file mode 100644 index 00000000000..29aa68b1533 --- /dev/null +++ b/src/libstd/c_str.rs @@ -0,0 +1,291 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use cast; +use iterator::Iterator; +use libc; +use ops::Drop; +use option::{Option, Some, None}; +use ptr::RawPtr; +use ptr; +use str::StrSlice; +use vec::ImmutableVector; + +/** + * The representation of a C String. + * + * This structure wraps a `*libc::c_char`, and will automatically free the + * memory it is pointing to when it goes out of scope. + */ +pub struct CString { + priv buf: *libc::c_char, +} + +impl<'self> CString { + /** + * Create a C String from a str. + */ + pub fn from_str(s: &str) -> CString { + s.to_c_str() + } + + /** + * Take the wrapped `*libc::c_char` from the `CString` wrapper. + * + * # Failure + * + * If the wrapper is empty. + */ + pub unsafe fn take(&mut self) -> *libc::c_char { + if self.buf.is_null() { + fail!("CString has no wrapped `*libc::c_char`"); + } + let buf = self.buf; + self.buf = ptr::null(); + buf + } + + /** + * Puts a `*libc::c_char` into the `CString` wrapper. + * + * # Failure + * + * If the `*libc::c_char` is null. + * If the wrapper is not empty. + */ + pub fn put_back(&mut self, buf: *libc::c_char) { + if buf.is_null() { + fail!("attempt to put a null pointer into a CString"); + } + if self.buf.is_not_null() { + fail!("CString already wraps a `*libc::c_char`"); + } + self.buf = buf; + } + + /** + * Calls a closure with a reference to the underlying `*libc::c_char`. + */ + pub fn with_ref<T>(&self, f: &fn(*libc::c_char) -> T) -> T { + if self.buf.is_null() { + fail!("CString already wraps a `*libc::c_char`"); + } + f(self.buf) + } + + /** + * Calls a closure with a mutable reference to the underlying `*libc::c_char`. + */ + pub fn with_mut_ref<T>(&mut self, f: &fn(*mut libc::c_char) -> T) -> T { + if self.buf.is_not_null() { + fail!("CString already wraps a `*libc::c_char`"); + } + f(unsafe { cast::transmute(self.buf) }) + } + + /** + * Returns true if the CString does not wrap a `*libc::c_char`. + */ + pub fn is_empty(&self) -> bool { + self.buf.is_null() + } + + /** + * Returns true if the CString wraps a `*libc::c_char`. + */ + pub fn is_not_empty(&self) -> bool { + self.buf.is_not_null() + } + + /** + * Converts the CString into a `&[u8]` without copying. + */ + pub fn as_bytes(&self) -> &'self [u8] { + unsafe { + let len = libc::strlen(self.buf) as uint; + cast::transmute((self.buf, len + 1)) + } + } + + /** + * Return a CString iterator. + */ + fn iter(&self) -> CStringIterator<'self> { + CStringIterator { + ptr: self.buf, + lifetime: unsafe { cast::transmute(self.buf) }, + } + } +} + +impl Drop for CString { + fn drop(&self) { + if self.buf.is_not_null() { + unsafe { + libc::free(self.buf as *libc::c_void) + }; + } + } +} + +/** + * A generic trait for converting a value to a CString. + */ +pub trait ToCStr { + /** + * Create a C String. + */ + fn to_c_str(&self) -> CString; +} + +impl<'self> ToCStr for &'self str { + /** + * Create a C String from a `&str`. + */ + fn to_c_str(&self) -> CString { + self.as_bytes().to_c_str() + } +} + +impl<'self> ToCStr for &'self [u8] { + /** + * Create a C String from a `&[u8]`. + */ + fn to_c_str(&self) -> CString { + do self.as_imm_buf |self_buf, self_len| { + unsafe { + let buf = libc::malloc(self_len as u64 + 1) as *mut u8; + if buf.is_null() { + fail!("failed to allocate memory!"); + } + + ptr::copy_memory(buf, self_buf, self_len); + *ptr::mut_offset(buf, self_len as int) = 0; + CString { buf: buf as *libc::c_char } + } + } + } +} + +/** + * External iterator for a CString's bytes. + * + * Use with the `std::iterator` module. + */ +pub struct CStringIterator<'self> { + priv ptr: *libc::c_char, + priv lifetime: &'self libc::c_char, // FIXME: #5922 +} + +impl<'self> Iterator<libc::c_char> for CStringIterator<'self> { + /** + * Advance the iterator. + */ + fn next(&mut self) -> Option<libc::c_char> { + if self.ptr.is_null() { + None + } else { + let ch = unsafe { *self.ptr }; + self.ptr = ptr::offset(self.ptr, 1); + Some(ch) + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use libc; + use ptr; + + #[test] + fn test_to_c_str() { + do "".to_c_str().with_ref |buf| { + unsafe { + assert_eq!(*ptr::offset(buf, 0), 0); + } + } + + do "hello".to_c_str().with_ref |buf| { + unsafe { + assert_eq!(*ptr::offset(buf, 0), 'h' as libc::c_char); + assert_eq!(*ptr::offset(buf, 1), 'e' as libc::c_char); + assert_eq!(*ptr::offset(buf, 2), 'l' as libc::c_char); + assert_eq!(*ptr::offset(buf, 3), 'l' as libc::c_char); + assert_eq!(*ptr::offset(buf, 4), 'o' as libc::c_char); + assert_eq!(*ptr::offset(buf, 5), 0); + } + } + } + + #[test] + fn test_take() { + let mut c_str = "hello".to_c_str(); + unsafe { libc::free(c_str.take() as *libc::c_void) } + assert!(c_str.is_empty()); + } + + #[test] + fn test_take_and_put_back() { + let mut c_str = "hello".to_c_str(); + assert!(c_str.is_not_empty()); + + let buf = unsafe { c_str.take() }; + + assert!(c_str.is_empty()); + + c_str.put_back(buf); + + assert!(c_str.is_not_empty()); + } + + #[test] + #[should_fail] + #[ignore(cfg(windows))] + fn test_take_empty_fail() { + let mut c_str = "hello".to_c_str(); + unsafe { + libc::free(c_str.take() as *libc::c_void); + c_str.take(); + } + } + + #[test] + #[should_fail] + #[ignore(cfg(windows))] + fn test_put_back_null_fail() { + let mut c_str = "hello".to_c_str(); + c_str.put_back(ptr::null()); + } + + #[test] + #[should_fail] + #[ignore(cfg(windows))] + fn test_put_back_full_fail() { + let mut c_str = "hello".to_c_str(); + c_str.put_back(0xdeadbeef as *libc::c_char); + } + + fn test_with() { + let c_str = "hello".to_c_str(); + let len = unsafe { c_str.with_ref(|buf| libc::strlen(buf)) }; + assert!(c_str.is_not_empty()); + assert_eq!(len, 5); + } + + #[test] + #[should_fail] + #[ignore(cfg(windows))] + fn test_with_empty_fail() { + let mut c_str = "hello".to_c_str(); + unsafe { libc::free(c_str.take() as *libc::c_void) } + c_str.with_ref(|_| ()); + } +} diff --git a/src/libstd/io.rs b/src/libstd/io.rs index 606c958b408..78c6e8d5342 100644 --- a/src/libstd/io.rs +++ b/src/libstd/io.rs @@ -48,6 +48,7 @@ implement `Reader` and `Writer`, where appropriate. use cast; use clone::Clone; +use c_str::ToCStr; use container::Container; use int; use iterator::Iterator; @@ -1040,8 +1041,8 @@ pub fn stdin() -> @Reader { } pub fn file_reader(path: &Path) -> Result<@Reader, ~str> { - let f = do path.to_str().as_c_str |pathbuf| { - do "r".as_c_str |modebuf| { + let f = do path.to_c_str().with_ref |pathbuf| { + do "r".to_c_str().with_ref |modebuf| { unsafe { libc::fopen(pathbuf, modebuf as *libc::c_char) } } }; @@ -1290,9 +1291,8 @@ pub fn mk_file_writer(path: &Path, flags: &[FileFlag]) } } let fd = unsafe { - do path.to_str().as_c_str |pathbuf| { - libc::open(pathbuf, fflags, - (S_IRUSR | S_IWUSR) as c_int) + do path.to_c_str().with_ref |pathbuf| { + libc::open(pathbuf, fflags, (S_IRUSR | S_IWUSR) as c_int) } }; if fd < (0 as c_int) { @@ -1574,8 +1574,8 @@ pub fn file_writer(path: &Path, flags: &[FileFlag]) -> Result<@Writer, ~str> { // FIXME: fileflags // #2004 pub fn buffered_file_writer(path: &Path) -> Result<@Writer, ~str> { unsafe { - let f = do path.to_str().as_c_str |pathbuf| { - do "w".as_c_str |modebuf| { + let f = do path.to_c_str().with_ref |pathbuf| { + do "w".to_c_str().with_ref |modebuf| { libc::fopen(pathbuf, modebuf) } }; diff --git a/src/libstd/os.rs b/src/libstd/os.rs index f17a59db38f..fb4f14d33c6 100644 --- a/src/libstd/os.rs +++ b/src/libstd/os.rs @@ -28,6 +28,7 @@ #[allow(missing_doc)]; +use c_str::ToCStr; use cast; use clone::Clone; use container::Container; @@ -241,7 +242,9 @@ pub fn env() -> ~[(~str,~str)] { pub fn getenv(n: &str) -> Option<~str> { unsafe { do with_env_lock { - let s = n.as_c_str(|s| libc::getenv(s as *libc::c_char)); + let s = do n.to_c_str().with_ref |buf| { + libc::getenv(buf) + }; if ptr::null::<u8>() == cast::transmute(s) { None } else { @@ -274,8 +277,8 @@ pub fn getenv(n: &str) -> Option<~str> { pub fn setenv(n: &str, v: &str) { unsafe { do with_env_lock { - do n.to_str().as_c_str |nbuf| { - do v.to_str().as_c_str |vbuf| { + do n.to_c_str().with_ref |nbuf| { + do v.to_c_str().with_ref |vbuf| { libc::funcs::posix01::unistd::setenv(nbuf, vbuf, 1); } } @@ -306,7 +309,7 @@ pub fn unsetenv(n: &str) { fn _unsetenv(n: &str) { unsafe { do with_env_lock { - do n.to_str().as_c_str |nbuf| { + do n.to_c_str().with_ref |nbuf| { libc::funcs::posix01::unistd::unsetenv(nbuf); } } @@ -328,7 +331,7 @@ pub fn unsetenv(n: &str) { } pub fn fdopen(fd: c_int) -> *FILE { - do "r".as_c_str |modebuf| { + do "r".to_c_str().with_ref |modebuf| { unsafe { libc::fdopen(fd, modebuf) } @@ -462,9 +465,9 @@ pub fn self_exe_path() -> Option<Path> { use libc::funcs::posix01::unistd::readlink; let mut path_str = str::with_capacity(TMPBUF_SZ); - let len = do path_str.as_c_str |buf| { + let len = do path_str.to_c_str().with_ref |buf| { let buf = buf as *mut c_char; - do "/proc/self/exe".as_c_str |proc_self_buf| { + do "/proc/self/exe".to_c_str().with_ref |proc_self_buf| { readlink(proc_self_buf, buf, TMPBUF_SZ as size_t) } }; @@ -595,7 +598,7 @@ pub fn walk_dir(p: &Path, f: &fn(&Path) -> bool) -> bool { /// Indicates whether a path represents a directory pub fn path_is_dir(p: &Path) -> bool { unsafe { - do p.to_str().as_c_str |buf| { + do p.to_c_str().with_ref |buf| { rustrt::rust_path_is_dir(buf) != 0 as c_int } } @@ -604,7 +607,7 @@ pub fn path_is_dir(p: &Path) -> bool { /// Indicates whether a path exists pub fn path_exists(p: &Path) -> bool { unsafe { - do p.to_str().as_c_str |buf| { + do p.to_c_str().with_ref |buf| { rustrt::rust_path_exists(buf) != 0 as c_int } } @@ -647,7 +650,7 @@ pub fn make_dir(p: &Path, mode: c_int) -> bool { #[cfg(unix)] fn mkdir(p: &Path, mode: c_int) -> bool { - do p.to_str().as_c_str |buf| { + do p.to_c_str().with_ref |buf| { unsafe { libc::mkdir(buf, mode as libc::mode_t) == (0 as c_int) } @@ -823,7 +826,7 @@ pub fn remove_dir(p: &Path) -> bool { #[cfg(unix)] fn rmdir(p: &Path) -> bool { - do p.to_str().as_c_str |buf| { + do p.to_c_str().with_ref |buf| { unsafe { libc::rmdir(buf) == (0 as c_int) } @@ -848,7 +851,7 @@ pub fn change_dir(p: &Path) -> bool { #[cfg(unix)] fn chdir(p: &Path) -> bool { - do p.to_str().as_c_str |buf| { + do p.to_c_str().with_ref |buf| { unsafe { libc::chdir(buf) == (0 as c_int) } @@ -876,8 +879,8 @@ pub fn copy_file(from: &Path, to: &Path) -> bool { #[cfg(unix)] fn do_copy_file(from: &Path, to: &Path) -> bool { unsafe { - let istream = do from.to_str().as_c_str |fromp| { - do "rb".as_c_str |modebuf| { + let istream = do from.to_c_str().with_ref |fromp| { + do "rb".to_c_str().with_ref |modebuf| { libc::fopen(fromp, modebuf) } }; @@ -888,8 +891,8 @@ pub fn copy_file(from: &Path, to: &Path) -> bool { let from_mode = from.get_mode().expect("copy_file: couldn't get permissions \ for source file"); - let ostream = do to.to_str().as_c_str |top| { - do "w+b".as_c_str |modebuf| { + let ostream = do to.to_c_str().with_ref |top| { + do "w+b".to_c_str().with_ref |modebuf| { libc::fopen(top, modebuf) } }; @@ -921,7 +924,7 @@ pub fn copy_file(from: &Path, to: &Path) -> bool { fclose(ostream); // Give the new file the old file's permissions - if do to.to_str().as_c_str |to_buf| { + if do to.to_c_str().with_ref |to_buf| { libc::chmod(to_buf, from_mode as libc::mode_t) } != 0 { return false; // should be a condition... @@ -948,7 +951,7 @@ pub fn remove_file(p: &Path) -> bool { #[cfg(unix)] fn unlink(p: &Path) -> bool { unsafe { - do p.to_str().as_c_str |buf| { + do p.to_c_str().with_ref |buf| { libc::unlink(buf) == (0 as c_int) } } @@ -1294,7 +1297,7 @@ pub fn glob(pattern: &str) -> ~[Path] { } let mut g = default_glob_t(); - do pattern.as_c_str |c_pattern| { + do pattern.to_c_str().with_ref |c_pattern| { unsafe { libc::glob(c_pattern, 0, ptr::null(), &mut g) } }; do(|| { @@ -1699,6 +1702,7 @@ pub mod consts { #[cfg(test)] mod tests { + use c_str::ToCStr; use libc::{c_int, c_void, size_t}; use libc; use option::Some; @@ -1711,7 +1715,6 @@ mod tests { use rand; use run; use str::StrSlice; - use vec::CopyableVector; use libc::consts::os::posix88::{S_IRUSR, S_IWUSR, S_IXUSR}; @@ -1941,19 +1944,19 @@ mod tests { let out = tempdir.push("out.txt"); /* Write the temp input file */ - let ostream = do input.to_str().as_c_str |fromp| { - do "w+b".as_c_str |modebuf| { + let ostream = do input.to_c_str().with_ref |fromp| { + do "w+b".to_c_str().with_ref |modebuf| { libc::fopen(fromp, modebuf) } }; assert!((ostream as uint != 0u)); let s = ~"hello"; - let mut buf = s.to_owned().to_c_str(); - let len = buf.len(); - do buf.as_mut_buf |b, _len| { - assert_eq!(libc::fwrite(b as *c_void, 1u as size_t, - (s.len() + 1u) as size_t, ostream), - len as size_t) + do "hello".to_c_str().with_ref |buf| { + let write_len = libc::fwrite(buf as *c_void, + 1u as size_t, + (s.len() + 1u) as size_t, + ostream); + assert_eq!(write_len, (s.len() + 1) as size_t) } assert_eq!(libc::fclose(ostream), (0u as c_int)); let in_mode = input.get_mode(); @@ -2025,11 +2028,11 @@ mod tests { remove_file(&path); let fd = unsafe { - let fd = do path.to_str().as_c_str |path| { + let fd = do path.to_c_str().with_ref |path| { open(path, O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR) }; lseek_(fd, size); - do "x".as_c_str |x| { + do "x".to_c_str().with_ref |x| { assert!(write(fd, x as *c_void, 1) == 1); } fd diff --git a/src/libstd/path.rs b/src/libstd/path.rs index 989a5cbd35b..fe8776c21d5 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -16,9 +16,11 @@ Cross-platform file path handling #[allow(missing_doc)]; +use c_str::ToCStr; +use c_str; use clone::Clone; -use container::Container; use cmp::Eq; +use container::Container; use iterator::{Iterator, IteratorUtil}; use libc; use option::{None, Option, Some}; @@ -341,7 +343,7 @@ mod stat { #[cfg(target_os = "win32")] impl WindowsPath { pub fn stat(&self) -> Option<libc::stat> { - do self.to_str().as_c_str |buf| { + do self.to_c_str().with_ref |buf| { let mut st = stat::arch::default_stat(); match unsafe { libc::stat(buf, &mut st) } { 0 => Some(st), @@ -375,7 +377,7 @@ impl WindowsPath { #[cfg(not(target_os = "win32"))] impl PosixPath { pub fn stat(&self) -> Option<libc::stat> { - do self.to_str().as_c_str |buf| { + do self.to_c_str().with_ref |buf| { let mut st = stat::arch::default_stat(); match unsafe { libc::stat(buf as *libc::c_char, &mut st) } { 0 => Some(st), @@ -453,7 +455,7 @@ impl PosixPath { #[cfg(unix)] impl PosixPath { pub fn lstat(&self) -> Option<libc::stat> { - do self.to_str().as_c_str |buf| { + do self.to_c_str().with_ref |buf| { let mut st = stat::arch::default_stat(); match unsafe { libc::lstat(buf, &mut st) } { 0 => Some(st), @@ -525,6 +527,12 @@ impl ToStr for PosixPath { } } +impl ToCStr for PosixPath { + fn to_c_str(&self) -> c_str::CString { + self.to_str().to_c_str() + } +} + // FIXME (#3227): when default methods in traits are working, de-duplicate // PosixPath and WindowsPath, most of their methods are common. impl GenericPath for PosixPath { @@ -730,6 +738,11 @@ impl ToStr for WindowsPath { } } +impl c_str::ToCStr for WindowsPath { + fn to_c_str(&self) -> c_str::CString { + self.to_str().to_c_str() + } +} impl GenericPath for WindowsPath { fn from_str(s: &str) -> WindowsPath { diff --git a/src/libstd/prelude.rs b/src/libstd/prelude.rs index 7e21504c1d2..5b8833f3f36 100644 --- a/src/libstd/prelude.rs +++ b/src/libstd/prelude.rs @@ -43,6 +43,7 @@ pub use io::{print, println}; pub use iterator::range; // Reexported types and traits +pub use c_str::ToCStr; pub use clone::{Clone, DeepClone}; pub use cmp::{Eq, ApproxEq, Ord, TotalEq, TotalOrd, Ordering, Less, Equal, Greater, Equiv}; pub use char::Char; diff --git a/src/libstd/ptr.rs b/src/libstd/ptr.rs index 3af4769fcdb..77222490f17 100644 --- a/src/libstd/ptr.rs +++ b/src/libstd/ptr.rs @@ -486,24 +486,25 @@ pub mod ptr_tests { #[test] fn test_position() { + use c_str::ToCStr; use libc::c_char; - let s = ~"hello"; - unsafe { - assert!(2u == s.as_c_str(|p| position(p, |c| *c == 'l' as c_char))); - assert!(4u == s.as_c_str(|p| position(p, |c| *c == 'o' as c_char))); - assert!(5u == s.as_c_str(|p| position(p, |c| *c == 0 as c_char))); + do "hello".to_c_str().with_ref |p| { + unsafe { + assert!(2u == position(p, |c| *c == 'l' as c_char)); + assert!(4u == position(p, |c| *c == 'o' as c_char)); + assert!(5u == position(p, |c| *c == 0 as c_char)); + } } } #[test] fn test_buf_len() { - let s0 = ~"hello"; - let s1 = ~"there"; - let s2 = ~"thing"; - do s0.as_c_str |p0| { - do s1.as_c_str |p1| { - do s2.as_c_str |p2| { + use c_str::ToCStr; + + do "hello".to_c_str().with_ref |p0| { + do "there".to_c_str().with_ref |p1| { + do "thing".to_c_str().with_ref |p2| { let v = ~[p0, p1, p2, null()]; do v.as_imm_buf |vp, len| { assert_eq!(unsafe { buf_len(vp) }, 3u); diff --git a/src/libstd/rt/borrowck.rs b/src/libstd/rt/borrowck.rs index 4a6a9585b93..3a51fd032c0 100644 --- a/src/libstd/rt/borrowck.rs +++ b/src/libstd/rt/borrowck.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use c_str::ToCStr; use cast::transmute; use libc::{c_char, c_void, size_t, STDERR_FILENO}; use io; @@ -76,7 +77,7 @@ unsafe fn fail_borrowed(box: *mut raw::Box<()>, file: *c_char, line: size_t) { match try_take_task_borrow_list() { None => { // not recording borrows let msg = "borrowed"; - do msg.as_c_str |msg_p| { + do msg.to_c_str().with_ref |msg_p| { sys::begin_unwind_(msg_p, file, line); } } @@ -92,7 +93,7 @@ unsafe fn fail_borrowed(box: *mut raw::Box<()>, file: *c_char, line: size_t) { sep = " and at "; } } - do msg.as_c_str |msg_p| { + do msg.to_c_str().with_ref |msg_p| { sys::begin_unwind_(msg_p, file, line) } } @@ -231,7 +232,7 @@ pub unsafe fn unrecord_borrow(a: *u8, old_ref_count: uint, let br = borrow_list.pop(); if br.box != a || br.file != file || br.line != line { let err = fmt!("wrong borrow found, br=%?", br); - do err.as_c_str |msg_p| { + do err.to_c_str().with_ref |msg_p| { sys::begin_unwind_(msg_p, file, line) } } diff --git a/src/libstd/rt/logging.rs b/src/libstd/rt/logging.rs index 11d11daebc2..76619704bee 100644 --- a/src/libstd/rt/logging.rs +++ b/src/libstd/rt/logging.rs @@ -45,15 +45,15 @@ impl Logger for StdErrLogger { /// Configure logging by traversing the crate map and setting the /// per-module global logging flags based on the logging spec pub fn init(crate_map: *u8) { + use c_str::ToCStr; use os; - use str::StrSlice; use ptr; use option::{Some, None}; let log_spec = os::getenv("RUST_LOG"); match log_spec { Some(spec) => { - do spec.as_c_str |buf| { + do spec.to_c_str().with_ref |buf| { unsafe { rust_update_log_settings(crate_map, buf) } } } diff --git a/src/libstd/rt/uv/uvio.rs b/src/libstd/rt/uv/uvio.rs index e15e3adb8c9..071a90f4a83 100644 --- a/src/libstd/rt/uv/uvio.rs +++ b/src/libstd/rt/uv/uvio.rs @@ -8,26 +8,26 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use option::*; -use result::*; -use ops::Drop; -use cell::Cell; -use cast; +use c_str::ToCStr; use cast::transmute; +use cast; +use cell::Cell; use clone::Clone; use libc::{c_int, c_uint, c_void}; +use ops::Drop; +use option::*; use ptr; +use result::*; use rt::io::IoError; use rt::io::net::ip::{IpAddr, Ipv4, Ipv6}; -use rt::uv::*; -use rt::uv::idle::IdleWatcher; -use rt::uv::net::{UvIpv4, UvIpv6}; +use rt::io::{standard_error, OtherIoError}; +use rt::local::Local; use rt::rtio::*; use rt::sched::Scheduler; -use rt::io::{standard_error, OtherIoError}; use rt::tube::Tube; -use rt::local::Local; -use str::StrSlice; +use rt::uv::*; +use rt::uv::idle::IdleWatcher; +use rt::uv::net::{UvIpv4, UvIpv6}; use unstable::sync::Exclusive; #[cfg(test)] use container::Container; @@ -663,7 +663,7 @@ impl RtioUdpSocket for UvUdpSocket { }; let r = unsafe { - do ip_str.as_c_str |m_addr| { + do ip_str.to_c_str().with_ref |m_addr| { uvll::udp_set_membership(self.native_handle(), m_addr, ptr::null(), uvll::UV_JOIN_GROUP) } @@ -686,7 +686,7 @@ impl RtioUdpSocket for UvUdpSocket { }; let r = unsafe { - do ip_str.as_c_str |m_addr| { + do ip_str.to_c_str().with_ref |m_addr| { uvll::udp_set_membership(self.native_handle(), m_addr, ptr::null(), uvll::UV_LEAVE_GROUP) } diff --git a/src/libstd/rt/uv/uvll.rs b/src/libstd/rt/uv/uvll.rs index 07264839c35..bd2d28f8642 100644 --- a/src/libstd/rt/uv/uvll.rs +++ b/src/libstd/rt/uv/uvll.rs @@ -29,6 +29,7 @@ #[allow(non_camel_case_types)]; // C types +use c_str::ToCStr; use libc::{size_t, c_int, c_uint, c_void, c_char, uintptr_t}; use libc::{malloc, free}; use libc; @@ -372,12 +373,12 @@ pub unsafe fn is_ip6_addr(addr: *sockaddr) -> bool { } pub unsafe fn malloc_ip4_addr(ip: &str, port: int) -> *sockaddr_in { - do ip.as_c_str |ip_buf| { + do ip.to_c_str().with_ref |ip_buf| { rust_uv_ip4_addrp(ip_buf as *u8, port as libc::c_int) } } pub unsafe fn malloc_ip6_addr(ip: &str, port: int) -> *sockaddr_in6 { - do ip.as_c_str |ip_buf| { + do ip.to_c_str().with_ref |ip_buf| { rust_uv_ip6_addrp(ip_buf as *u8, port as libc::c_int) } } diff --git a/src/libstd/run.rs b/src/libstd/run.rs index 9114c4879b2..6e447d3ded4 100644 --- a/src/libstd/run.rs +++ b/src/libstd/run.rs @@ -12,6 +12,7 @@ #[allow(missing_doc)]; +use c_str::ToCStr; use cast; use clone::Clone; use comm::{stream, SharedChan, GenericChan, GenericPort}; @@ -506,7 +507,7 @@ fn spawn_process_os(prog: &str, args: &[~str], do with_envp(env) |envp| { do with_dirp(dir) |dirp| { - do cmd.as_c_str |cmdp| { + do cmd.to_c_str().with_ref |cmdp| { let created = CreateProcessA(ptr::null(), cast::transmute(cmdp), ptr::mut_null(), ptr::mut_null(), TRUE, 0, envp, dirp, &mut si, &mut pi); @@ -697,17 +698,17 @@ fn with_argv<T>(prog: &str, args: &[~str], cb: &fn(**libc::c_char) -> T) -> T { // hold all the ~[u8] byte strings. let mut tmps = vec::with_capacity(args.len() + 1); - tmps.push(prog.to_owned().to_c_str()); + tmps.push(prog.to_c_str()); foreach arg in args.iter() { - tmps.push(arg.to_owned().to_c_str()); + tmps.push(arg.to_c_str()); } // Next, convert each of the byte strings into a pointer. This is // technically unsafe as the caller could leak these pointers out of our // scope. let mut ptrs = do tmps.map |tmp| { - tmp.as_imm_buf(|buf, _| buf as *libc::c_char) + tmp.with_ref(|buf| buf) }; // Finally, make sure we add a null pointer. @@ -734,7 +735,7 @@ fn with_envp<T>(env: Option<&[(~str, ~str)]>, cb: &fn(*c_void) -> T) -> T { // Once again, this is unsafe. let mut ptrs = do tmps.map |tmp| { - tmp.as_imm_buf(|buf, _| buf as *libc::c_char) + tmp.with_ref(|buf| buf) }; ptrs.push(ptr::null()); @@ -757,7 +758,7 @@ fn with_envp<T>(env: Option<&[(~str, ~str)]>, cb: &fn(*mut c_void) -> T) -> T { foreach pair in env.iter() { let kv = fmt!("%s=%s", pair.first(), pair.second()); - blk.push_all(kv.to_c_str()); + blk.push_all(kv.to_c_str().as_bytes()); } blk.push(0); @@ -772,7 +773,7 @@ fn with_envp<T>(env: Option<&[(~str, ~str)]>, cb: &fn(*mut c_void) -> T) -> T { fn with_dirp<T>(d: Option<&Path>, cb: &fn(*libc::c_char) -> T) -> T { match d { - Some(dir) => dir.to_str().as_c_str(cb), + Some(dir) => dir.to_c_str().with_ref(|buf| cb(buf)), None => cb(ptr::null()) } } diff --git a/src/libstd/std.rs b/src/libstd/std.rs index 76d65192e01..d51f0de1d27 100644 --- a/src/libstd/std.rs +++ b/src/libstd/std.rs @@ -172,6 +172,7 @@ pub mod local_data; pub mod gc; pub mod libc; +pub mod c_str; pub mod os; pub mod path; pub mod rand; diff --git a/src/libstd/str.rs b/src/libstd/str.rs index f75bbcf20eb..851a9326392 100644 --- a/src/libstd/str.rs +++ b/src/libstd/str.rs @@ -1182,7 +1182,6 @@ pub trait StrSlice<'self> { fn subslice_offset(&self, inner: &str) -> uint; fn as_imm_buf<T>(&self, f: &fn(*u8, uint) -> T) -> T; - fn as_c_str<T>(&self, f: &fn(*libc::c_char) -> T) -> T; } /// Extension methods for strings @@ -1931,32 +1930,6 @@ impl<'self> StrSlice<'self> for &'self str { let v: &[u8] = unsafe { cast::transmute(*self) }; v.as_imm_buf(f) } - - /// Work with the byte buffer of a string as a null-terminated C string. - /// - /// Allows for unsafe manipulation of strings, which is useful for foreign - /// interop. This is similar to `str::as_buf`, but guarantees null-termination. - /// If the given slice is not already null-terminated, this function will - /// allocate a temporary, copy the slice, null terminate it, and pass - /// that instead. - /// - /// # Example - /// - /// ~~~ {.rust} - /// let s = "PATH".as_c_str(|path| libc::getenv(path)); - /// ~~~ - #[inline] - fn as_c_str<T>(&self, f: &fn(*libc::c_char) -> T) -> T { - do self.as_imm_buf |buf, len| { - // NB: len includes the trailing null. - assert!(len > 0); - if unsafe { *(ptr::offset(buf, (len - 1) as int)) != 0 } { - self.to_owned().as_c_str(|s| f(s)) - } else { - f(buf as *libc::c_char) - } - } - } } #[allow(missing_doc)] @@ -1973,13 +1946,6 @@ pub trait OwnedStr { fn capacity(&self) -> uint; fn to_bytes_with_null(self) -> ~[u8]; - /// Allocates a null terminate byte array. - /// - /// # Failure - /// - /// Fails if there are any null characters inside the byte array. - fn to_c_str(self) -> ~[u8]; - /// Work with the mutable byte buffer and length of a slice. /// /// The given length is one byte longer than the 'official' indexable @@ -2172,13 +2138,6 @@ impl OwnedStr for ~str { } #[inline] - fn to_c_str(self) -> ~[u8] { - let bytes = self.to_bytes_with_null(); - assert!(bytes.slice(0, bytes.len() - 1).iter().all(|byte| *byte != 0)); - bytes - } - - #[inline] fn as_mut_buf<T>(&mut self, f: &fn(*mut u8, uint) -> T) -> T { let v: &mut ~[u8] = unsafe { cast::transmute(self) }; v.as_mut_buf(f) @@ -2916,63 +2875,6 @@ mod tests { } #[test] - fn test_as_c_str() { - let a = ~""; - do a.as_c_str |buf| { - unsafe { - assert_eq!(*ptr::offset(buf, 0), 0); - } - } - - let a = ~"hello"; - do a.as_c_str |buf| { - unsafe { - assert_eq!(*ptr::offset(buf, 0), 'h' as libc::c_char); - assert_eq!(*ptr::offset(buf, 1), 'e' as libc::c_char); - assert_eq!(*ptr::offset(buf, 2), 'l' as libc::c_char); - assert_eq!(*ptr::offset(buf, 3), 'l' as libc::c_char); - assert_eq!(*ptr::offset(buf, 4), 'o' as libc::c_char); - assert_eq!(*ptr::offset(buf, 5), 0); - } - } - } - - #[test] - fn test_to_c_str() { - let s = ~"ศไทย中华Việt Nam"; - let v = ~[ - 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228, - 184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97, - 109, 0 - ]; - assert_eq!((~"").to_c_str(), ~[0]); - assert_eq!((~"abc").to_c_str(), ~['a' as u8, 'b' as u8, 'c' as u8, 0]); - assert_eq!(s.to_c_str(), v); - } - - #[test] - fn test_as_c_str() { - let a = ~""; - do a.as_c_str |buf| { - unsafe { - assert_eq!(*ptr::offset(buf, 0), 0); - } - } - - let a = ~"hello"; - do a.as_c_str |buf| { - unsafe { - assert_eq!(*ptr::offset(buf, 0), 'h' as libc::c_char); - assert_eq!(*ptr::offset(buf, 1), 'e' as libc::c_char); - assert_eq!(*ptr::offset(buf, 2), 'l' as libc::c_char); - assert_eq!(*ptr::offset(buf, 3), 'l' as libc::c_char); - assert_eq!(*ptr::offset(buf, 4), 'o' as libc::c_char); - assert_eq!(*ptr::offset(buf, 5), 0); - } - } - } - - #[test] fn test_subslice_offset() { let a = "kernelsprite"; let b = a.slice(7, a.len()); diff --git a/src/libstd/sys.rs b/src/libstd/sys.rs index 51609709cdb..b40f87617a9 100644 --- a/src/libstd/sys.rs +++ b/src/libstd/sys.rs @@ -12,13 +12,13 @@ #[allow(missing_doc)]; +use c_str::ToCStr; use cast; use gc; use io; use libc; use libc::{c_char, size_t}; use repr; -use str::StrSlice; use str; use unstable::intrinsics; @@ -115,8 +115,8 @@ pub trait FailWithCause { impl FailWithCause for ~str { fn fail_with(cause: ~str, file: &'static str, line: uint) -> ! { - do cause.as_c_str |msg_buf| { - do file.as_c_str |file_buf| { + do cause.to_c_str().with_ref |msg_buf| { + do file.to_c_str().with_ref |file_buf| { begin_unwind_(msg_buf, file_buf, line as libc::size_t) } } @@ -125,8 +125,8 @@ impl FailWithCause for ~str { impl FailWithCause for &'static str { fn fail_with(cause: &'static str, file: &'static str, line: uint) -> ! { - do cause.as_c_str |msg_buf| { - do file.as_c_str |file_buf| { + do cause.to_c_str().with_ref |msg_buf| { + do file.to_c_str().with_ref |file_buf| { begin_unwind_(msg_buf, file_buf, line as libc::size_t) } } diff --git a/src/libstd/unstable/dynamic_lib.rs b/src/libstd/unstable/dynamic_lib.rs index 8d5654255f1..49e3e0777df 100644 --- a/src/libstd/unstable/dynamic_lib.rs +++ b/src/libstd/unstable/dynamic_lib.rs @@ -15,6 +15,7 @@ Dynamic library facilities. A simple wrapper over the platforms dynamic library facilities */ +use c_str::ToCStr; use cast; use path; use libc; @@ -65,7 +66,7 @@ impl DynamicLibrary { // T but that feature is still unimplemented let maybe_symbol_value = do dl::check_for_errors_in { - do symbol.as_c_str |raw_string| { + do symbol.to_c_str().with_ref |raw_string| { dl::symbol(self.handle, raw_string) } }; @@ -135,6 +136,7 @@ mod test { #[cfg(target_os = "macos")] #[cfg(target_os = "freebsd")] mod dl { + use c_str::ToCStr; use libc; use path; use ptr; @@ -143,7 +145,7 @@ mod dl { use result::*; pub unsafe fn open_external(filename: &path::Path) -> *libc::c_void { - do filename.to_str().as_c_str |raw_name| { + do filename.to_c_str().with_ref |raw_name| { dlopen(raw_name, Lazy as libc::c_int) } } diff --git a/src/libstd/unstable/lang.rs b/src/libstd/unstable/lang.rs index e0c4950b38e..1ea815f721c 100644 --- a/src/libstd/unstable/lang.rs +++ b/src/libstd/unstable/lang.rs @@ -10,6 +10,7 @@ //! Runtime calls emitted by the compiler. +use c_str::ToCStr; use cast::transmute; use libc::{c_char, c_uchar, c_void, size_t, uintptr_t, c_int}; use str; @@ -49,7 +50,7 @@ pub fn fail_bounds_check(file: *c_char, line: size_t, index: size_t, len: size_t) { let msg = fmt!("index out of bounds: the len is %d but the index is %d", len as int, index as int); - do msg.as_c_str |buf| { + do msg.to_c_str().with_ref |buf| { fail_(buf, file, line); } } |
