~~~no_run
extern crate libc;
-use std::c_str::ToCStr;
+use std::ffi::CString;
use std::ptr;
#[link(name = "readline")]
}
fn main() {
- "[my-awesome-shell] $".with_c_str(|buf| {
- unsafe { rl_prompt = buf; }
- // get a line, process it
- unsafe { rl_prompt = ptr::null(); }
- });
+ let prompt = CString::from_slice(b"[my-awesome-shell] $");
+ unsafe { rl_prompt = prompt.as_ptr(); }
+ // get a line, process it
+ unsafe { rl_prompt = ptr::null(); }
}
~~~
# Interoperability with foreign code
-Rust guarantees that the layout of a `struct` is compatible with the platform's representation in C
-only if the `#[repr(C)]` attribute is applied to it. `#[repr(C, packed)]` can be used to lay out
-struct members without padding. `#[repr(C)]` can also be applied to an enum.
-
-Rust's owned boxes (`Box<T>`) use non-nullable pointers as handles which point to the contained
-object. However, they should not be manually created because they are managed by internal
-allocators. References can safely be assumed to be non-nullable pointers directly to the type.
-However, breaking the borrow checking or mutability rules is not guaranteed to be safe, so prefer
-using raw pointers (`*`) if that's needed because the compiler can't make as many assumptions about
-them.
-
-Vectors and strings share the same basic memory layout, and utilities are available in the `vec` and
-`str` modules for working with C APIs. However, strings are not terminated with `\0`. If you need a
-NUL-terminated string for interoperability with C, you should use the `c_str::to_c_str` function.
-
-The standard library includes type aliases and function definitions for the C standard library in
-the `libc` module, and Rust links against `libc` and `libm` by default.
+Rust guarantees that the layout of a `struct` is compatible with the platform's
+representation in C only if the `#[repr(C)]` attribute is applied to it.
+`#[repr(C, packed)]` can be used to lay out struct members without padding.
+`#[repr(C)]` can also be applied to an enum.
+
+Rust's owned boxes (`Box<T>`) use non-nullable pointers as handles which point
+to the contained object. However, they should not be manually created because
+they are managed by internal allocators. References can safely be assumed to be
+non-nullable pointers directly to the type. However, breaking the borrow
+checking or mutability rules is not guaranteed to be safe, so prefer using raw
+pointers (`*`) if that's needed because the compiler can't make as many
+assumptions about them.
+
+Vectors and strings share the same basic memory layout, and utilities are
+available in the `vec` and `str` modules for working with C APIs. However,
+strings are not terminated with `\0`. If you need a NUL-terminated string for
+interoperability with C, you should use the `CString` type in the `std::ffi`
+module.
+
+The standard library includes type aliases and function definitions for the C
+standard library in the `libc` module, and Rust links against `libc` and `libm`
+by default.
# The "nullable pointer optimization"
}
}
- /// Creates a `String` from a null-terminated `*const u8` buffer.
- ///
- /// This function is unsafe because we dereference memory until we find the
- /// NUL character, which is not guaranteed to be present. Additionally, the
- /// slice is not checked to see whether it contains valid UTF-8
- #[unstable = "just renamed from `mod raw`"]
- pub unsafe fn from_raw_buf(buf: *const u8) -> String {
- String::from_str(str::from_c_str(buf as *const i8))
- }
-
- /// Creates a `String` from a `*const u8` buffer of the given length.
- ///
- /// This function is unsafe because it blindly assumes the validity of the
- /// pointer `buf` for `len` bytes of memory. This function will copy the
- /// memory from `buf` into a new allocation (owned by the returned
- /// `String`).
- ///
- /// This function is also unsafe because it does not validate that the
- /// buffer is valid UTF-8 encoded data.
- #[unstable = "just renamed from `mod raw`"]
- pub unsafe fn from_raw_buf_len(buf: *const u8, len: uint) -> String {
- String::from_utf8_unchecked(Vec::from_raw_buf(buf, len))
- }
-
/// Converts a vector of bytes to a new `String` without checking if
/// it contains valid UTF-8. This is unsafe because it assumes that
/// the UTF-8-ness of the vector has already been validated.
String::from_str("\u{FFFD}𐒋\u{FFFD}"));
}
- #[test]
- fn test_from_buf_len() {
- unsafe {
- let a = vec![65u8, 65, 65, 65, 65, 65, 65, 0];
- assert_eq!(String::from_raw_buf_len(a.as_ptr(), 3), String::from_str("AAA"));
- }
- }
-
- #[test]
- fn test_from_buf() {
- unsafe {
- let a = vec![65, 65, 65, 65, 65, 65, 65, 0];
- let b = a.as_ptr();
- let c = String::from_raw_buf(b);
- assert_eq!(c, String::from_str("AAAAAAA"));
- }
- }
-
#[test]
fn test_push_bytes() {
let mut s = String::from_str("ABC");
/// # Panics
///
/// This function will panic if the string pointed to by `s` is not valid UTF-8.
-#[unstable = "may change location based on the outcome of the c_str module"]
+#[deprecated = "use std::ffi::c_str_to_bytes + str::from_utf8"]
pub unsafe fn from_c_str(s: *const i8) -> &'static str {
let s = s as *const u8;
let mut len = 0u;
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
html_root_url = "http://doc.rust-lang.org/nightly/")]
-#![feature(phase, unboxed_closures)]
+#![feature(phase, unboxed_closures, associated_types)]
#[cfg(test)] #[phase(plugin, link)] extern crate log;
extern crate libc;
use libc::{c_void, size_t, c_int};
-use std::c_vec::CVec;
+use std::ops::Deref;
use std::ptr::Unique;
+use std::slice;
+
+pub struct Bytes {
+ ptr: Unique<u8>,
+ len: uint,
+}
+
+impl Deref for Bytes {
+ type Target = [u8];
+ fn deref(&self) -> &[u8] {
+ unsafe { slice::from_raw_mut_buf(&self.ptr.0, self.len) }
+ }
+}
+
+impl Drop for Bytes {
+ fn drop(&mut self) {
+ unsafe { libc::free(self.ptr.0 as *mut _); }
+ }
+}
#[link(name = "miniz", kind = "static")]
extern {
static TINFL_FLAG_PARSE_ZLIB_HEADER : c_int = 0x1; // parse zlib header and adler32 checksum
static TDEFL_WRITE_ZLIB_HEADER : c_int = 0x01000; // write zlib header and adler32 checksum
-fn deflate_bytes_internal(bytes: &[u8], flags: c_int) -> Option<CVec<u8>> {
+fn deflate_bytes_internal(bytes: &[u8], flags: c_int) -> Option<Bytes> {
unsafe {
let mut outsz : size_t = 0;
let res = tdefl_compress_mem_to_heap(bytes.as_ptr() as *const _,
&mut outsz,
flags);
if !res.is_null() {
- let res = Unique(res);
- Some(CVec::new_with_dtor(res.0 as *mut u8, outsz as uint, move|:| libc::free(res.0)))
+ let res = Unique(res as *mut u8);
+ Some(Bytes { ptr: res, len: outsz as uint })
} else {
None
}
}
/// Compress a buffer, without writing any sort of header on the output.
-pub fn deflate_bytes(bytes: &[u8]) -> Option<CVec<u8>> {
+pub fn deflate_bytes(bytes: &[u8]) -> Option<Bytes> {
deflate_bytes_internal(bytes, LZ_NORM)
}
/// Compress a buffer, using a header that zlib can understand.
-pub fn deflate_bytes_zlib(bytes: &[u8]) -> Option<CVec<u8>> {
+pub fn deflate_bytes_zlib(bytes: &[u8]) -> Option<Bytes> {
deflate_bytes_internal(bytes, LZ_NORM | TDEFL_WRITE_ZLIB_HEADER)
}
-fn inflate_bytes_internal(bytes: &[u8], flags: c_int) -> Option<CVec<u8>> {
+fn inflate_bytes_internal(bytes: &[u8], flags: c_int) -> Option<Bytes> {
unsafe {
let mut outsz : size_t = 0;
let res = tinfl_decompress_mem_to_heap(bytes.as_ptr() as *const _,
&mut outsz,
flags);
if !res.is_null() {
- let res = Unique(res);
- Some(CVec::new_with_dtor(res.0 as *mut u8, outsz as uint, move|:| libc::free(res.0)))
+ let res = Unique(res as *mut u8);
+ Some(Bytes { ptr: res, len: outsz as uint })
} else {
None
}
}
/// Decompress a buffer, without parsing any sort of header on the input.
-pub fn inflate_bytes(bytes: &[u8]) -> Option<CVec<u8>> {
+pub fn inflate_bytes(bytes: &[u8]) -> Option<Bytes> {
inflate_bytes_internal(bytes, 0)
}
/// Decompress a buffer that starts with a zlib header.
-pub fn inflate_bytes_zlib(bytes: &[u8]) -> Option<CVec<u8>> {
+pub fn inflate_bytes_zlib(bytes: &[u8]) -> Option<Bytes> {
inflate_bytes_internal(bytes, TINFL_FLAG_PARSE_ZLIB_HEADER)
}
use util::nodemap::{FnvHashMap, NodeMap};
use std::cell::RefCell;
-use std::c_vec::CVec;
use std::rc::Rc;
+use flate::Bytes;
use syntax::ast;
use syntax::codemap::Span;
use syntax::parse::token::IdentInterner;
pub type cnum_map = FnvHashMap<ast::CrateNum, ast::CrateNum>;
pub enum MetadataBlob {
- MetadataVec(CVec<u8>),
+ MetadataVec(Bytes),
MetadataArchive(loader::ArchiveMetadata),
}
use syntax::diagnostic::SpanHandler;
use util::fs;
-use std::c_str::ToCStr;
+use std::ffi::CString;
use std::cmp;
use std::collections::{HashMap, HashSet};
use std::io::fs::PathExtensions;
}
}
unsafe {
- let mb = filename.with_c_str(|buf| {
- llvm::LLVMRustCreateMemoryBufferWithContentsOfFile(buf)
- });
+ let buf = CString::from_slice(filename.as_vec());
+ let mb = llvm::LLVMRustCreateMemoryBufferWithContentsOfFile(buf.as_ptr());
if mb as int == 0 {
return Err(format!("error reading library: '{}'",
filename.display()))
while llvm::LLVMIsSectionIteratorAtEnd(of.llof, si.llsi) == False {
let mut name_buf = ptr::null();
let name_len = llvm::LLVMRustGetSectionName(si.llsi, &mut name_buf);
- let name = String::from_raw_buf_len(name_buf as *const u8,
- name_len as uint);
+ let name = slice::from_raw_buf(&(name_buf as *const u8),
+ name_len as uint).to_vec();
+ let name = String::from_utf8(name).unwrap();
debug!("get_metadata_section: name {}", name);
if read_meta_section_name(is_osx) == name {
let cbuf = llvm::LLVMGetSectionContents(si.llsi);
use libc;
use ArchiveRef;
-use std::c_str::ToCStr;
+use std::ffi::CString;
use std::mem;
use std::raw;
/// raised.
pub fn open(dst: &Path) -> Option<ArchiveRO> {
unsafe {
- let ar = dst.with_c_str(|dst| {
- ::LLVMRustOpenArchive(dst)
- });
+ let s = CString::from_slice(dst.as_vec());
+ let ar = ::LLVMRustOpenArchive(s.as_ptr());
if ar.is_null() {
None
} else {
pub fn read<'a>(&'a self, file: &str) -> Option<&'a [u8]> {
unsafe {
let mut size = 0 as libc::size_t;
- let ptr = file.with_c_str(|file| {
- ::LLVMRustArchiveReadSection(self.ptr, file, &mut size)
- });
+ let file = CString::from_slice(file.as_bytes());
+ let ptr = ::LLVMRustArchiveReadSection(self.ptr, file.as_ptr(),
+ &mut size);
if ptr.is_null() {
None
} else {
pub use self::DiagnosticSeverity::*;
pub use self::Linkage::*;
-use std::c_str::ToCStr;
+use std::ffi::CString;
use std::cell::RefCell;
use std::{raw, mem};
use libc::{c_uint, c_ushort, uint64_t, c_int, size_t, c_char};
}
pub fn mk_target_data(string_rep: &str) -> TargetData {
+ let string_rep = CString::from_slice(string_rep.as_bytes());
TargetData {
- lltd: string_rep.with_c_str(|buf| {
- unsafe { LLVMCreateTargetData(buf) }
- })
+ lltd: unsafe { LLVMCreateTargetData(string_rep.as_ptr()) }
}
}
use libc;
use flate;
-use std::c_str::ToCStr;
+use std::ffi::CString;
use std::iter;
use std::mem;
use std::num::Int;
}
// Internalize everything but the reachable symbols of the current module
- let cstrs: Vec<::std::c_str::CString> =
- reachable.iter().map(|s| s.to_c_str()).collect();
- let arr: Vec<*const libc::c_char> = cstrs.iter().map(|c| c.as_ptr()).collect();
+ let cstrs: Vec<CString> = reachable.iter().map(|s| {
+ CString::from_slice(s.as_bytes())
+ }).collect();
+ let arr: Vec<*const i8> = cstrs.iter().map(|c| c.as_ptr()).collect();
let ptr = arr.as_ptr();
unsafe {
llvm::LLVMRustRunRestrictionPass(llmod,
unsafe {
let pm = llvm::LLVMCreatePassManager();
llvm::LLVMRustAddAnalysisPasses(tm, pm, llmod);
- "verify".with_c_str(|s| llvm::LLVMRustAddPass(pm, s));
+ llvm::LLVMRustAddPass(pm, "verify\0".as_ptr() as *const _);
let builder = llvm::LLVMPassManagerBuilderCreate();
llvm::LLVMPassManagerBuilderPopulateLTOPassManager(builder, pm,
/* RunInliner = */ True);
llvm::LLVMPassManagerBuilderDispose(builder);
- "verify".with_c_str(|s| llvm::LLVMRustAddPass(pm, s));
+ llvm::LLVMRustAddPass(pm, "verify\0".as_ptr() as *const _);
time(sess.time_passes(), "LTO passes", (), |()|
llvm::LLVMRunPassManager(pm, llmod));
use syntax::diagnostic;
use syntax::diagnostic::{Emitter, Handler, Level, mk_handler};
-use std::c_str::{ToCStr, CString};
+use std::ffi::{mod, CString};
use std::io::Command;
use std::io::fs;
use std::iter::Unfold;
use std::sync::{Arc, Mutex};
use std::sync::mpsc::channel;
use std::thread;
-use libc::{c_uint, c_int, c_void};
+use libc::{mod, c_uint, c_int, c_void};
#[derive(Clone, Copy, PartialEq, PartialOrd, Ord, Eq)]
pub enum OutputType {
if cstr == ptr::null() {
handler.fatal(msg[]);
} else {
- let err = CString::new(cstr, true);
- let err = String::from_utf8_lossy(err.as_bytes());
+ let err = ffi::c_str_to_bytes(&cstr);
+ let err = String::from_utf8_lossy(err.as_slice()).to_string();
+ libc::free(cstr as *mut _);
handler.fatal(format!("{}: {}",
msg[],
err[])[]);
output: &Path,
file_type: llvm::FileType) {
unsafe {
- output.with_c_str(|output| {
- let result = llvm::LLVMRustWriteOutputFile(
- target, pm, m, output, file_type);
- if !result {
- llvm_err(handler, "could not write output".to_string());
- }
- })
+ let output = CString::from_slice(output.as_vec());
+ let result = llvm::LLVMRustWriteOutputFile(
+ target, pm, m, output.as_ptr(), file_type);
+ if !result {
+ llvm_err(handler, "could not write output".to_string());
+ }
}
}
let triple = sess.target.target.llvm_target[];
let tm = unsafe {
- triple.with_c_str(|t| {
- let cpu = match sess.opts.cg.target_cpu {
- Some(ref s) => s[],
- None => sess.target.target.options.cpu[]
- };
- cpu.with_c_str(|cpu| {
- target_feature(sess).with_c_str(|features| {
- llvm::LLVMRustCreateTargetMachine(
- t, cpu, features,
- code_model,
- reloc_model,
- opt_level,
- true /* EnableSegstk */,
- use_softfp,
- no_fp_elim,
- !any_library && reloc_model == llvm::RelocPIC,
- ffunction_sections,
- fdata_sections,
- )
- })
- })
- })
+ let triple = CString::from_slice(triple.as_bytes());
+ let cpu = match sess.opts.cg.target_cpu {
+ Some(ref s) => s.as_slice(),
+ None => sess.target.target.options.cpu.as_slice()
+ };
+ let cpu = CString::from_slice(cpu.as_bytes());
+ let features = CString::from_slice(target_feature(sess).as_bytes());
+ llvm::LLVMRustCreateTargetMachine(
+ triple.as_ptr(), cpu.as_ptr(), features.as_ptr(),
+ code_model,
+ reloc_model,
+ opt_level,
+ true /* EnableSegstk */,
+ use_softfp,
+ no_fp_elim,
+ !any_library && reloc_model == llvm::RelocPIC,
+ ffunction_sections,
+ fdata_sections,
+ )
};
if tm.is_null() {
match llvm::diagnostic::Diagnostic::unpack(info) {
llvm::diagnostic::Optimization(opt) => {
- let pass_name = CString::new(opt.pass_name, false);
- let pass_name = pass_name.as_str().expect("got a non-UTF8 pass name from LLVM");
+ let pass_name = str::from_utf8(ffi::c_str_to_bytes(&opt.pass_name))
+ .ok()
+ .expect("got a non-UTF8 pass name from LLVM");
let enabled = match cgcx.remark {
AllPasses => true,
SomePasses(ref v) => v.iter().any(|s| *s == pass_name),
if config.emit_no_opt_bc {
let ext = format!("{}.no-opt.bc", name_extra);
- output_names.with_extension(ext[]).with_c_str(|buf| {
- llvm::LLVMWriteBitcodeToFile(llmod, buf);
- })
+ let out = output_names.with_extension(ext.as_slice());
+ let out = CString::from_slice(out.as_vec());
+ llvm::LLVMWriteBitcodeToFile(llmod, out.as_ptr());
}
match config.opt_level {
// If we're verifying or linting, add them to the function pass
// manager.
let addpass = |&: pass: &str| {
- pass.with_c_str(|s| llvm::LLVMRustAddPass(fpm, s))
+ let pass = CString::from_slice(pass.as_bytes());
+ llvm::LLVMRustAddPass(fpm, pass.as_ptr())
};
if !config.no_verify { assert!(addpass("verify")); }
}
for pass in config.passes.iter() {
- pass.with_c_str(|s| {
- if !llvm::LLVMRustAddPass(mpm, s) {
- cgcx.handler.warn(format!("unknown pass {}, ignoring",
- *pass)[]);
- }
- })
+ let pass = CString::from_slice(pass.as_bytes());
+ if !llvm::LLVMRustAddPass(mpm, pass.as_ptr()) {
+ cgcx.handler.warn(format!("unknown pass {}, ignoring",
+ pass).as_slice());
+ }
}
// Finally, run the actual optimization passes
if config.emit_lto_bc {
let name = format!("{}.lto.bc", name_extra);
- output_names.with_extension(name[]).with_c_str(|buf| {
- llvm::LLVMWriteBitcodeToFile(llmod, buf);
- })
+ let out = output_names.with_extension(name.as_slice());
+ let out = CString::from_slice(out.as_vec());
+ llvm::LLVMWriteBitcodeToFile(llmod, out.as_ptr());
}
},
_ => {},
if config.emit_bc {
let ext = format!("{}.bc", name_extra);
- output_names.with_extension(ext[]).with_c_str(|buf| {
- llvm::LLVMWriteBitcodeToFile(llmod, buf);
- })
+ let out = output_names.with_extension(ext.as_slice());
+ let out = CString::from_slice(out.as_vec());
+ llvm::LLVMWriteBitcodeToFile(llmod, out.as_ptr());
}
time(config.time_passes, "codegen passes", (), |()| {
if config.emit_ir {
let ext = format!("{}.ll", name_extra);
- output_names.with_extension(ext[]).with_c_str(|output| {
- with_codegen(tm, llmod, config.no_builtins, |cpm| {
- llvm::LLVMRustPrintModule(cpm, llmod, output);
- })
+ let out = output_names.with_extension(ext.as_slice());
+ let out = CString::from_slice(out.as_vec());
+ with_codegen(tm, llmod, config.no_builtins, |cpm| {
+ llvm::LLVMRustPrintModule(cpm, llmod, out.as_ptr());
})
}
let mut llvm_args = Vec::new();
{
let mut add = |&mut : arg: &str| {
- let s = arg.to_c_str();
+ let s = CString::from_slice(arg.as_bytes());
llvm_args.push(s.as_ptr());
llvm_c_strs.push(s);
};
match opt {
llvm::CodeGenLevelDefault | llvm::CodeGenLevelAggressive => {
- "mergefunc".with_c_str(|s| llvm::LLVMRustAddPass(mpm, s));
+ llvm::LLVMRustAddPass(mpm, "mergefunc\0".as_ptr() as *const _);
}
_ => {}
};
use trans::type_of;
use trans::type_::Type;
-use std::c_str::ToCStr;
-use std::string::String;
use syntax::ast;
+use std::ffi::CString;
use libc::{c_uint, c_char};
// Take an inline assembly expression and splat it out via LLVM
ast::AsmIntel => llvm::AD_Intel
};
- let r = ia.asm.get().with_c_str(|a| {
- constraints.with_c_str(|c| {
- InlineAsmCall(bcx,
- a,
- c,
- inputs[],
+ let asm = CString::from_slice(ia.asm.get().as_bytes());
+ let constraints = CString::from_slice(constraints.as_bytes());
+ let r = InlineAsmCall(bcx,
+ asm.as_ptr(),
+ constraints.as_ptr(),
+ inputs.as_slice(),
output_type,
ia.volatile,
ia.alignstack,
- dialect)
- })
- });
+ dialect);
// Again, based on how many outputs we have
if num_outputs == 1 {
use arena::TypedArena;
use libc::{c_uint, uint64_t};
-use std::c_str::ToCStr;
+use std::ffi::{mod, CString};
use std::cell::{Cell, RefCell};
use std::collections::HashSet;
use std::mem;
use std::rc::Rc;
+use std::str;
use std::{i8, i16, i32, i64};
use syntax::abi::{Rust, RustCall, RustIntrinsic, Abi};
use syntax::ast_util::local_def;
pub fn decl_fn(ccx: &CrateContext, name: &str, cc: llvm::CallConv,
ty: Type, output: ty::FnOutput) -> ValueRef {
- let llfn: ValueRef = name.with_c_str(|buf| {
- unsafe {
- llvm::LLVMGetOrInsertFunction(ccx.llmod(), buf, ty.to_ref())
- }
- });
+ let buf = CString::from_slice(name.as_bytes());
+ let llfn: ValueRef = unsafe {
+ llvm::LLVMGetOrInsertFunction(ccx.llmod(), buf.as_ptr(), ty.to_ref())
+ };
// diverging functions may unwind, but can never return normally
if output == ty::FnDiverging {
None => ()
}
unsafe {
- let c = name.with_c_str(|buf| {
- llvm::LLVMAddGlobal(ccx.llmod(), ty.to_ref(), buf)
- });
+ let buf = CString::from_slice(name.as_bytes());
+ let c = llvm::LLVMAddGlobal(ccx.llmod(), ty.to_ref(), buf.as_ptr());
// Thread-local statics in some other crate need to *always* be linked
// against in a thread-local fashion, so we need to be sure to apply the
// thread-local attribute locally if it was present remotely. If we
}
pub fn set_split_stack(f: ValueRef) {
- "split-stack".with_c_str(|buf| {
- unsafe { llvm::LLVMAddFunctionAttrString(f, llvm::FunctionIndex as c_uint, buf); }
- })
+ unsafe {
+ llvm::LLVMAddFunctionAttrString(f, llvm::FunctionIndex as c_uint,
+ "split-stack\0".as_ptr() as *const _);
+ }
}
pub fn unset_split_stack(f: ValueRef) {
- "split-stack".with_c_str(|buf| {
- unsafe { llvm::LLVMRemoveFunctionAttrString(f, llvm::FunctionIndex as c_uint, buf); }
- })
+ unsafe {
+ llvm::LLVMRemoveFunctionAttrString(f, llvm::FunctionIndex as c_uint,
+ "split-stack\0".as_ptr() as *const _);
+ }
}
// Double-check that we never ask LLVM to declare the same symbol twice. It
// Structural comparison: a rather involved form of glue.
pub fn maybe_name_value(cx: &CrateContext, v: ValueRef, s: &str) {
if cx.sess().opts.cg.save_temps {
- s.with_c_str(|buf| {
- unsafe {
- llvm::LLVMSetValueName(v, buf)
- }
- })
+ let buf = CString::from_slice(s.as_bytes());
+ unsafe { llvm::LLVMSetValueName(v, buf.as_ptr()) }
}
}
unsafe { llvm::LLVMRustSetDLLExportStorageClass(llfn) }
}
- let llbb = "top".with_c_str(|buf| {
- unsafe {
- llvm::LLVMAppendBasicBlockInContext(ccx.llcx(), llfn, buf)
- }
- });
+ let llbb = unsafe {
+ llvm::LLVMAppendBasicBlockInContext(ccx.llcx(), llfn,
+ "top\0".as_ptr() as *const _)
+ };
let bld = ccx.raw_builder();
unsafe {
llvm::LLVMPositionBuilderAtEnd(bld, llbb);
};
let args = {
- let opaque_rust_main = "rust_main".with_c_str(|buf| {
- llvm::LLVMBuildPointerCast(bld, rust_main, Type::i8p(ccx).to_ref(), buf)
- });
+ let opaque_rust_main = llvm::LLVMBuildPointerCast(bld,
+ rust_main, Type::i8p(ccx).to_ref(),
+ "rust_main\0".as_ptr() as *const _);
vec!(
opaque_rust_main,
format!("Illegal null byte in export_name \
value: `{}`", sym)[]);
}
- let g = sym.with_c_str(|buf| {
- llvm::LLVMAddGlobal(ccx.llmod(), llty, buf)
- });
+ let buf = CString::from_slice(sym.as_bytes());
+ let g = llvm::LLVMAddGlobal(ccx.llmod(), llty,
+ buf.as_ptr());
if attr::contains_name(i.attrs[],
"thread_local") {
sect.get())[]);
}
unsafe {
- sect.get().with_c_str(|buf| {
- llvm::LLVMSetSection(v, buf);
- })
+ let buf = CString::from_slice(sect.get().as_bytes());
+ llvm::LLVMSetSection(v, buf.as_ptr());
}
},
None => ()
let name = format!("rust_metadata_{}_{}",
cx.link_meta().crate_name,
cx.link_meta().crate_hash);
- let llglobal = name.with_c_str(|buf| {
- unsafe {
- llvm::LLVMAddGlobal(cx.metadata_llmod(), val_ty(llconst).to_ref(), buf)
- }
- });
+ let buf = CString::from_vec(name.into_bytes());
+ let llglobal = unsafe {
+ llvm::LLVMAddGlobal(cx.metadata_llmod(), val_ty(llconst).to_ref(),
+ buf.as_ptr())
+ };
unsafe {
llvm::LLVMSetInitializer(llglobal, llconst);
let name = loader::meta_section_name(cx.sess().target.target.options.is_like_osx);
- name.with_c_str(|buf| {
- llvm::LLVMSetSection(llglobal, buf)
- });
+ let name = CString::from_slice(name.as_bytes());
+ llvm::LLVMSetSection(llglobal, name.as_ptr())
}
return metadata;
}
/// Find any symbols that are defined in one compilation unit, but not declared
/// in any other compilation unit. Give these symbols internal linkage.
fn internalize_symbols(cx: &SharedCrateContext, reachable: &HashSet<String>) {
- use std::c_str::CString;
-
unsafe {
let mut declared = HashSet::new();
continue
}
- let name = CString::new(llvm::LLVMGetValueName(val), false);
+ let name = ffi::c_str_to_bytes(&llvm::LLVMGetValueName(val))
+ .to_vec();
declared.insert(name);
}
}
continue
}
- let name = CString::new(llvm::LLVMGetValueName(val), false);
+ let name = ffi::c_str_to_bytes(&llvm::LLVMGetValueName(val))
+ .to_vec();
if !declared.contains(&name) &&
- !reachable.contains(name.as_str().unwrap()) {
+ !reachable.contains(str::from_utf8(name.as_slice()).unwrap()) {
llvm::SetLinkage(val, llvm::InternalLinkage);
}
}
use trans::type_::Type;
use util::nodemap::FnvHashMap;
use libc::{c_uint, c_char};
-use std::c_str::ToCStr;
+
+use std::ffi::CString;
use syntax::codemap::Span;
pub struct Builder<'a, 'tcx: 'a> {
if name.is_empty() {
llvm::LLVMBuildAlloca(self.llbuilder, ty.to_ref(), noname())
} else {
- name.with_c_str(|c| {
- llvm::LLVMBuildAlloca(self.llbuilder, ty.to_ref(), c)
- })
+ let name = CString::from_slice(name.as_bytes());
+ llvm::LLVMBuildAlloca(self.llbuilder, ty.to_ref(),
+ name.as_ptr())
}
}
}
let comment_text = format!("{} {}", "#",
sanitized.replace("\n", "\n\t# "));
self.count_insn("inlineasm");
- let asm = comment_text.with_c_str(|c| {
- unsafe {
- llvm::LLVMConstInlineAsm(Type::func(&[], &Type::void(self.ccx)).to_ref(),
- c, noname(), False, False)
- }
- });
+ let comment_text = CString::from_vec(comment_text.into_bytes());
+ let asm = unsafe {
+ llvm::LLVMConstInlineAsm(Type::func(&[], &Type::void(self.ccx)).to_ref(),
+ comment_text.as_ptr(), noname(), False,
+ False)
+ };
self.call(asm, &[], None);
}
}
let bb: BasicBlockRef = llvm::LLVMGetInsertBlock(self.llbuilder);
let fn_: ValueRef = llvm::LLVMGetBasicBlockParent(bb);
let m: ModuleRef = llvm::LLVMGetGlobalParent(fn_);
- let t: ValueRef = "llvm.trap".with_c_str(|buf| {
- llvm::LLVMGetNamedFunction(m, buf)
- });
+ let p = "llvm.trap\0".as_ptr();
+ let t: ValueRef = llvm::LLVMGetNamedFunction(m, p as *const _);
assert!((t as int != 0));
let args: &[ValueRef] = &[];
self.count_insn("trap");
use arena::TypedArena;
use libc::{c_uint, c_char};
-use std::c_str::ToCStr;
+use std::ffi::CString;
use std::cell::{Cell, RefCell};
use std::vec::Vec;
use syntax::ast::Ident;
if self.llreturn.get().is_none() {
self.llreturn.set(Some(unsafe {
- "return".with_c_str(|buf| {
- llvm::LLVMAppendBasicBlockInContext(self.ccx.llcx(), self.llfn, buf)
- })
+ llvm::LLVMAppendBasicBlockInContext(self.ccx.llcx(), self.llfn,
+ "return\0".as_ptr() as *const _)
}))
}
opt_node_id: Option<ast::NodeId>)
-> Block<'a, 'tcx> {
unsafe {
- let llbb = name.with_c_str(|buf| {
- llvm::LLVMAppendBasicBlockInContext(self.ccx.llcx(),
- self.llfn,
- buf)
- });
+ let name = CString::from_slice(name.as_bytes());
+ let llbb = llvm::LLVMAppendBasicBlockInContext(self.ccx.llcx(),
+ self.llfn,
+ name.as_ptr());
BlockS::new(llbb, is_lpad, opt_node_id, self)
}
}
pub fn C_floating(s: &str, t: Type) -> ValueRef {
unsafe {
- s.with_c_str(|buf| llvm::LLVMConstRealOfString(t.to_ref(), buf))
+ let s = CString::from_slice(s.as_bytes());
+ llvm::LLVMConstRealOfString(t.to_ref(), s.as_ptr())
}
}
!null_terminated as Bool);
let gsym = token::gensym("str");
- let g = format!("str{}", gsym.uint()).with_c_str(|buf| {
- llvm::LLVMAddGlobal(cx.llmod(), val_ty(sc).to_ref(), buf)
- });
+ let buf = CString::from_vec(format!("str{}", gsym.uint()).into_bytes());
+ let g = llvm::LLVMAddGlobal(cx.llmod(), val_ty(sc).to_ref(), buf.as_ptr());
llvm::LLVMSetInitializer(g, sc);
llvm::LLVMSetGlobalConstant(g, True);
llvm::SetLinkage(g, llvm::InternalLinkage);
let lldata = C_bytes(cx, data);
let gsym = token::gensym("binary");
- let g = format!("binary{}", gsym.uint()).with_c_str(|buf| {
- llvm::LLVMAddGlobal(cx.llmod(), val_ty(lldata).to_ref(), buf)
- });
+ let name = format!("binary{}", gsym.uint());
+ let name = CString::from_vec(name.into_bytes());
+ let g = llvm::LLVMAddGlobal(cx.llmod(), val_ty(lldata).to_ref(),
+ name.as_ptr());
llvm::LLVMSetInitializer(g, lldata);
llvm::LLVMSetGlobalConstant(g, True);
llvm::SetLinkage(g, llvm::InternalLinkage);
use middle::ty::{self, Ty};
use util::ppaux::{Repr, ty_to_string};
-use std::c_str::ToCStr;
use std::iter::repeat;
use libc::c_uint;
use syntax::{ast, ast_util};
pub fn const_addr_of(cx: &CrateContext, cv: ValueRef, mutbl: ast::Mutability) -> ValueRef {
unsafe {
- let gv = "const".with_c_str(|name| {
- llvm::LLVMAddGlobal(cx.llmod(), val_ty(cv).to_ref(), name)
- });
+ let gv = llvm::LLVMAddGlobal(cx.llmod(), val_ty(cv).to_ref(),
+ "const\0".as_ptr() as *const _);
llvm::LLVMSetInitializer(gv, cv);
llvm::LLVMSetGlobalConstant(gv,
if mutbl == ast::MutImmutable {True} else {False});
use util::sha2::Sha256;
use util::nodemap::{NodeMap, NodeSet, DefIdMap, FnvHashMap, FnvHashSet};
+use std::ffi::CString;
use std::cell::{Cell, RefCell};
-use std::c_str::ToCStr;
use std::ptr;
use std::rc::Rc;
use syntax::ast;
unsafe fn create_context_and_module(sess: &Session, mod_name: &str) -> (ContextRef, ModuleRef) {
let llcx = llvm::LLVMContextCreate();
- let llmod = mod_name.with_c_str(|buf| {
- llvm::LLVMModuleCreateWithNameInContext(buf, llcx)
- });
- sess.target
- .target
- .data_layout
- .with_c_str(|buf| {
- llvm::LLVMSetDataLayout(llmod, buf);
- });
- sess.target
- .target
- .llvm_target
- .with_c_str(|buf| {
- llvm::LLVMRustSetNormalizedTarget(llmod, buf);
- });
+ let mod_name = CString::from_slice(mod_name.as_bytes());
+ let llmod = llvm::LLVMModuleCreateWithNameInContext(mod_name.as_ptr(), llcx);
+
+ let data_layout = sess.target.target.data_layout.as_slice();
+ let data_layout = CString::from_slice(data_layout.as_bytes());
+ llvm::LLVMSetDataLayout(llmod, data_layout.as_ptr());
+
+ let llvm_target = sess.target.target.llvm_target.as_slice();
+ let llvm_target = CString::from_slice(llvm_target.as_bytes());
+ llvm::LLVMRustSetNormalizedTarget(llmod, llvm_target.as_ptr());
(llcx, llmod)
}
use util::ppaux;
use libc::c_uint;
-use std::c_str::{CString, ToCStr};
+use std::ffi::CString;
use std::cell::{Cell, RefCell};
use std::ptr;
use std::rc::{Rc, Weak};
// for OS X to understand. For more info see #11352
// This can be overridden using --llvm-opts -dwarf-version,N.
if cx.sess().target.target.options.is_like_osx {
- "Dwarf Version".with_c_str(
- |s| llvm::LLVMRustAddModuleFlag(cx.llmod(), s, 2));
+ llvm::LLVMRustAddModuleFlag(cx.llmod(),
+ "Dwarf Version\0".as_ptr() as *const _,
+ 2)
}
// Prevent bitcode readers from deleting the debug info.
- "Debug Info Version".with_c_str(
- |s| llvm::LLVMRustAddModuleFlag(cx.llmod(), s,
- llvm::LLVMRustDebugMetadataVersion));
+ let ptr = "Debug Info Version\0".as_ptr();
+ llvm::LLVMRustAddModuleFlag(cx.llmod(), ptr as *const _,
+ llvm::LLVMRustDebugMetadataVersion);
};
}
namespace_node.mangled_name_of_contained_item(var_name[]);
let var_scope = namespace_node.scope;
- var_name.with_c_str(|var_name| {
- linkage_name.with_c_str(|linkage_name| {
- unsafe {
- llvm::LLVMDIBuilderCreateStaticVariable(DIB(cx),
- var_scope,
- var_name,
- linkage_name,
- file_metadata,
- line_number,
- type_metadata,
- is_local_to_unit,
- global,
- ptr::null_mut());
- }
- })
- });
+ let var_name = CString::from_slice(var_name.as_bytes());
+ let linkage_name = CString::from_slice(linkage_name.as_bytes());
+ unsafe {
+ llvm::LLVMDIBuilderCreateStaticVariable(DIB(cx),
+ var_scope,
+ var_name.as_ptr(),
+ linkage_name.as_ptr(),
+ file_metadata,
+ line_number,
+ type_metadata,
+ is_local_to_unit,
+ global,
+ ptr::null_mut());
+ }
}
/// Creates debug information for the given local variable.
let is_local_to_unit = is_node_local_to_unit(cx, fn_ast_id);
- let fn_metadata = function_name.with_c_str(|function_name| {
- linkage_name.with_c_str(|linkage_name| {
- unsafe {
- llvm::LLVMDIBuilderCreateFunction(
- DIB(cx),
- containing_scope,
- function_name,
- linkage_name,
- file_metadata,
- loc.line as c_uint,
- function_type_metadata,
- is_local_to_unit,
- true,
- scope_line as c_uint,
- FlagPrototyped as c_uint,
- cx.sess().opts.optimize != config::No,
- llfn,
- template_parameters,
- ptr::null_mut())
- }
- })
- });
+ let function_name = CString::from_slice(function_name.as_bytes());
+ let linkage_name = CString::from_slice(linkage_name.as_bytes());
+ let fn_metadata = unsafe {
+ llvm::LLVMDIBuilderCreateFunction(
+ DIB(cx),
+ containing_scope,
+ function_name.as_ptr(),
+ linkage_name.as_ptr(),
+ file_metadata,
+ loc.line as c_uint,
+ function_type_metadata,
+ is_local_to_unit,
+ true,
+ scope_line as c_uint,
+ FlagPrototyped as c_uint,
+ cx.sess().opts.optimize != config::No,
+ llfn,
+ template_parameters,
+ ptr::null_mut())
+ };
let scope_map = create_scope_map(cx,
fn_decl.inputs.as_slice(),
let ident = special_idents::type_self;
- let param_metadata = token::get_ident(ident).get()
- .with_c_str(|name| {
- unsafe {
- llvm::LLVMDIBuilderCreateTemplateTypeParameter(
- DIB(cx),
- file_metadata,
- name,
- actual_self_type_metadata,
- ptr::null_mut(),
- 0,
- 0)
- }
- });
+ let ident = token::get_ident(ident);
+ let name = CString::from_slice(ident.get().as_bytes());
+ let param_metadata = unsafe {
+ llvm::LLVMDIBuilderCreateTemplateTypeParameter(
+ DIB(cx),
+ file_metadata,
+ name.as_ptr(),
+ actual_self_type_metadata,
+ ptr::null_mut(),
+ 0,
+ 0)
+ };
template_params.push(param_metadata);
}
// Again, only create type information if full debuginfo is enabled
if cx.sess().opts.debuginfo == FullDebugInfo {
let actual_type_metadata = type_metadata(cx, actual_type, codemap::DUMMY_SP);
- let param_metadata = token::get_ident(ident).get()
- .with_c_str(|name| {
- unsafe {
- llvm::LLVMDIBuilderCreateTemplateTypeParameter(
- DIB(cx),
- file_metadata,
- name,
- actual_type_metadata,
- ptr::null_mut(),
- 0,
- 0)
- }
- });
+ let ident = token::get_ident(ident);
+ let name = CString::from_slice(ident.get().as_bytes());
+ let param_metadata = unsafe {
+ llvm::LLVMDIBuilderCreateTemplateTypeParameter(
+ DIB(cx),
+ file_metadata,
+ name.as_ptr(),
+ actual_type_metadata,
+ ptr::null_mut(),
+ 0,
+ 0)
+ };
template_params.push(param_metadata);
}
}
} else {
match abs_path.path_relative_from(work_dir) {
Some(ref p) if p.is_relative() => {
- // prepend "./" if necessary
- let dotdot = b"..";
- let prefix = [dotdot[0], ::std::path::SEP_BYTE];
- let mut path_bytes = p.as_vec().to_vec();
-
- if path_bytes.slice_to(2) != prefix &&
- path_bytes.slice_to(2) != dotdot {
- path_bytes.insert(0, prefix[0]);
- path_bytes.insert(1, prefix[1]);
- }
-
- path_bytes.to_c_str()
+ // prepend "./" if necessary
+ let dotdot = b"..";
+ let prefix: &[u8] = &[dotdot[0], ::std::path::SEP_BYTE];
+ let mut path_bytes = p.as_vec().to_vec();
+
+ if path_bytes.slice_to(2) != prefix &&
+ path_bytes.slice_to(2) != dotdot {
+ path_bytes.insert(0, prefix[0]);
+ path_bytes.insert(1, prefix[1]);
}
+
+ CString::from_vec(path_bytes)
+ }
_ => fallback_path(cx)
}
}
(option_env!("CFG_VERSION")).expect("CFG_VERSION"));
let compile_unit_name = compile_unit_name.as_ptr();
- return work_dir.as_vec().with_c_str(|work_dir| {
- producer.with_c_str(|producer| {
- "".with_c_str(|flags| {
- "".with_c_str(|split_name| {
- unsafe {
- llvm::LLVMDIBuilderCreateCompileUnit(
- debug_context(cx).builder,
- DW_LANG_RUST,
- compile_unit_name,
- work_dir,
- producer,
- cx.sess().opts.optimize != config::No,
- flags,
- 0,
- split_name)
- }
- })
- })
- })
- });
+ let work_dir = CString::from_slice(work_dir.as_vec());
+ let producer = CString::from_slice(producer.as_bytes());
+ let flags = "\0";
+ let split_name = "\0";
+ return unsafe {
+ llvm::LLVMDIBuilderCreateCompileUnit(
+ debug_context(cx).builder,
+ DW_LANG_RUST,
+ compile_unit_name,
+ work_dir.as_ptr(),
+ producer.as_ptr(),
+ cx.sess().opts.optimize != config::No,
+ flags.as_ptr() as *const _,
+ 0,
+ split_name.as_ptr() as *const _)
+ };
fn fallback_path(cx: &CrateContext) -> CString {
- cx.link_meta().crate_name.to_c_str()
+ CString::from_slice(cx.link_meta().crate_name.as_bytes())
}
}
CapturedVariable => (0, DW_TAG_auto_variable)
};
- let (var_alloca, var_metadata) = name.get().with_c_str(|name| {
- match variable_access {
- DirectVariable { alloca } => (
- alloca,
- unsafe {
- llvm::LLVMDIBuilderCreateLocalVariable(
- DIB(cx),
- dwarf_tag,
- scope_metadata,
- name,
- file_metadata,
- loc.line as c_uint,
- type_metadata,
- cx.sess().opts.optimize != config::No,
- 0,
- argument_index)
- }
- ),
- IndirectVariable { alloca, address_operations } => (
- alloca,
- unsafe {
- llvm::LLVMDIBuilderCreateComplexVariable(
- DIB(cx),
- dwarf_tag,
- scope_metadata,
- name,
- file_metadata,
- loc.line as c_uint,
- type_metadata,
- address_operations.as_ptr(),
- address_operations.len() as c_uint,
- argument_index)
- }
- )
- }
- });
+ let name = CString::from_slice(name.get().as_bytes());
+ let (var_alloca, var_metadata) = match variable_access {
+ DirectVariable { alloca } => (
+ alloca,
+ unsafe {
+ llvm::LLVMDIBuilderCreateLocalVariable(
+ DIB(cx),
+ dwarf_tag,
+ scope_metadata,
+ name.as_ptr(),
+ file_metadata,
+ loc.line as c_uint,
+ type_metadata,
+ cx.sess().opts.optimize != config::No,
+ 0,
+ argument_index)
+ }
+ ),
+ IndirectVariable { alloca, address_operations } => (
+ alloca,
+ unsafe {
+ llvm::LLVMDIBuilderCreateComplexVariable(
+ DIB(cx),
+ dwarf_tag,
+ scope_metadata,
+ name.as_ptr(),
+ file_metadata,
+ loc.line as c_uint,
+ type_metadata,
+ address_operations.as_ptr(),
+ address_operations.len() as c_uint,
+ argument_index)
+ }
+ )
+ };
set_debug_location(cx, DebugLocation::new(scope_metadata,
loc.line,
full_path
};
- let file_metadata =
- file_name.with_c_str(|file_name| {
- work_dir.with_c_str(|work_dir| {
- unsafe {
- llvm::LLVMDIBuilderCreateFile(DIB(cx), file_name, work_dir)
- }
- })
- });
+ let file_name = CString::from_slice(file_name.as_bytes());
+ let work_dir = CString::from_slice(work_dir.as_bytes());
+ let file_metadata = unsafe {
+ llvm::LLVMDIBuilderCreateFile(DIB(cx), file_name.as_ptr(),
+ work_dir.as_ptr())
+ };
let mut created_files = debug_context(cx).created_files.borrow_mut();
created_files.insert(full_path.to_string(), file_metadata);
}
fn diverging_type_metadata(cx: &CrateContext) -> DIType {
- "!".with_c_str(|name| {
- unsafe {
- llvm::LLVMDIBuilderCreateBasicType(
- DIB(cx),
- name,
- bytes_to_bits(0),
- bytes_to_bits(0),
- DW_ATE_unsigned)
- }
- })
+ unsafe {
+ llvm::LLVMDIBuilderCreateBasicType(
+ DIB(cx),
+ "!\0".as_ptr() as *const _,
+ bytes_to_bits(0),
+ bytes_to_bits(0),
+ DW_ATE_unsigned)
+ }
}
fn basic_type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
let llvm_type = type_of::type_of(cx, t);
let (size, align) = size_and_align_of(cx, llvm_type);
- let ty_metadata = name.with_c_str(|name| {
- unsafe {
- llvm::LLVMDIBuilderCreateBasicType(
- DIB(cx),
- name,
- bytes_to_bits(size),
- bytes_to_bits(align),
- encoding)
- }
- });
+ let name = CString::from_slice(name.as_bytes());
+ let ty_metadata = unsafe {
+ llvm::LLVMDIBuilderCreateBasicType(
+ DIB(cx),
+ name.as_ptr(),
+ bytes_to_bits(size),
+ bytes_to_bits(align),
+ encoding)
+ };
return ty_metadata;
}
let pointer_llvm_type = type_of::type_of(cx, pointer_type);
let (pointer_size, pointer_align) = size_and_align_of(cx, pointer_llvm_type);
let name = compute_debuginfo_type_name(cx, pointer_type, false);
- let ptr_metadata = name.with_c_str(|name| {
- unsafe {
- llvm::LLVMDIBuilderCreatePointerType(
- DIB(cx),
- pointee_type_metadata,
- bytes_to_bits(pointer_size),
- bytes_to_bits(pointer_align),
- name)
- }
- });
+ let name = CString::from_slice(name.as_bytes());
+ let ptr_metadata = unsafe {
+ llvm::LLVMDIBuilderCreatePointerType(
+ DIB(cx),
+ pointee_type_metadata,
+ bytes_to_bits(pointer_size),
+ bytes_to_bits(pointer_align),
+ name.as_ptr())
+ };
return ptr_metadata;
}
let enumerators_metadata: Vec<DIDescriptor> = variants
.iter()
.map(|v| {
- token::get_name(v.name).get().with_c_str(|name| {
- unsafe {
- llvm::LLVMDIBuilderCreateEnumerator(
- DIB(cx),
- name,
- v.disr_val as u64)
- }
- })
+ let token = token::get_name(v.name);
+ let name = CString::from_slice(token.get().as_bytes());
+ unsafe {
+ llvm::LLVMDIBuilderCreateEnumerator(
+ DIB(cx),
+ name.as_ptr(),
+ v.disr_val as u64)
+ }
})
.collect();
codemap::DUMMY_SP);
let discriminant_name = get_enum_discriminant_name(cx, enum_def_id);
- let discriminant_type_metadata = discriminant_name.get().with_c_str(|name| {
- unsafe {
- llvm::LLVMDIBuilderCreateEnumerationType(
- DIB(cx),
- containing_scope,
- name,
- UNKNOWN_FILE_METADATA,
- UNKNOWN_LINE_NUMBER,
- bytes_to_bits(discriminant_size),
- bytes_to_bits(discriminant_align),
- create_DIArray(DIB(cx), enumerators_metadata[]),
- discriminant_base_type_metadata)
- }
- });
+ let name = CString::from_slice(discriminant_name.get().as_bytes());
+ let discriminant_type_metadata = unsafe {
+ llvm::LLVMDIBuilderCreateEnumerationType(
+ DIB(cx),
+ containing_scope,
+ name.as_ptr(),
+ UNKNOWN_FILE_METADATA,
+ UNKNOWN_LINE_NUMBER,
+ bytes_to_bits(discriminant_size),
+ bytes_to_bits(discriminant_align),
+ create_DIArray(DIB(cx), enumerators_metadata.as_slice()),
+ discriminant_base_type_metadata)
+ };
debug_context(cx).created_enum_disr_types
.borrow_mut()
.borrow()
.get_unique_type_id_as_string(unique_type_id);
- let enum_metadata = enum_name.with_c_str(|enum_name| {
- unique_type_id_str.with_c_str(|unique_type_id_str| {
- unsafe {
- llvm::LLVMDIBuilderCreateUnionType(
- DIB(cx),
- containing_scope,
- enum_name,
- UNKNOWN_FILE_METADATA,
- UNKNOWN_LINE_NUMBER,
- bytes_to_bits(enum_type_size),
- bytes_to_bits(enum_type_align),
- 0, // Flags
- ptr::null_mut(),
- 0, // RuntimeLang
- unique_type_id_str)
- }
- })
- });
+ let enum_name = CString::from_slice(enum_name.as_bytes());
+ let unique_type_id_str = CString::from_slice(unique_type_id_str.as_bytes());
+ let enum_metadata = unsafe {
+ llvm::LLVMDIBuilderCreateUnionType(
+ DIB(cx),
+ containing_scope,
+ enum_name.as_ptr(),
+ UNKNOWN_FILE_METADATA,
+ UNKNOWN_LINE_NUMBER,
+ bytes_to_bits(enum_type_size),
+ bytes_to_bits(enum_type_align),
+ 0, // Flags
+ ptr::null_mut(),
+ 0, // RuntimeLang
+ unique_type_id_str.as_ptr())
+ };
return create_and_register_recursive_type_forward_declaration(
cx,
ComputedMemberOffset => machine::llelement_offset(cx, composite_llvm_type, i)
};
- member_description.name.with_c_str(|member_name| {
- unsafe {
- llvm::LLVMDIBuilderCreateMemberType(
- DIB(cx),
- composite_type_metadata,
- member_name,
- UNKNOWN_FILE_METADATA,
- UNKNOWN_LINE_NUMBER,
- bytes_to_bits(member_size),
- bytes_to_bits(member_align),
- bytes_to_bits(member_offset),
- member_description.flags,
- member_description.type_metadata)
- }
- })
+ let member_name = CString::from_slice(member_description.name.as_bytes());
+ unsafe {
+ llvm::LLVMDIBuilderCreateMemberType(
+ DIB(cx),
+ composite_type_metadata,
+ member_name.as_ptr(),
+ UNKNOWN_FILE_METADATA,
+ UNKNOWN_LINE_NUMBER,
+ bytes_to_bits(member_size),
+ bytes_to_bits(member_align),
+ bytes_to_bits(member_offset),
+ member_description.flags,
+ member_description.type_metadata)
+ }
})
.collect();
let unique_type_id_str = debug_context(cx).type_map
.borrow()
.get_unique_type_id_as_string(unique_type_id);
+ let name = CString::from_slice(struct_type_name.as_bytes());
+ let unique_type_id = CString::from_slice(unique_type_id_str.as_bytes());
let metadata_stub = unsafe {
- struct_type_name.with_c_str(|name| {
- unique_type_id_str.with_c_str(|unique_type_id| {
- // LLVMDIBuilderCreateStructType() wants an empty array. A null
- // pointer will lead to hard to trace and debug LLVM assertions
- // later on in llvm/lib/IR/Value.cpp.
- let empty_array = create_DIArray(DIB(cx), &[]);
-
- llvm::LLVMDIBuilderCreateStructType(
- DIB(cx),
- containing_scope,
- name,
- UNKNOWN_FILE_METADATA,
- UNKNOWN_LINE_NUMBER,
- bytes_to_bits(struct_size),
- bytes_to_bits(struct_align),
- 0,
- ptr::null_mut(),
- empty_array,
- 0,
- ptr::null_mut(),
- unique_type_id)
- })
- })
+ // LLVMDIBuilderCreateStructType() wants an empty array. A null
+ // pointer will lead to hard to trace and debug LLVM assertions
+ // later on in llvm/lib/IR/Value.cpp.
+ let empty_array = create_DIArray(DIB(cx), &[]);
+
+ llvm::LLVMDIBuilderCreateStructType(
+ DIB(cx),
+ containing_scope,
+ name.as_ptr(),
+ UNKNOWN_FILE_METADATA,
+ UNKNOWN_LINE_NUMBER,
+ bytes_to_bits(struct_size),
+ bytes_to_bits(struct_align),
+ 0,
+ ptr::null_mut(),
+ empty_array,
+ 0,
+ ptr::null_mut(),
+ unique_type_id.as_ptr())
};
return metadata_stub;
None => ptr::null_mut()
};
let namespace_name = token::get_name(name);
- let scope = namespace_name.get().with_c_str(|namespace_name| {
- unsafe {
- llvm::LLVMDIBuilderCreateNameSpace(
- DIB(cx),
- parent_scope,
- namespace_name,
- // cannot reconstruct file ...
- ptr::null_mut(),
- // ... or line information, but that's not so important.
- 0)
- }
- });
+ let namespace_name = CString::from_slice(namespace_name
+ .get().as_bytes());
+ let scope = unsafe {
+ llvm::LLVMDIBuilderCreateNameSpace(
+ DIB(cx),
+ parent_scope,
+ namespace_name.as_ptr(),
+ // cannot reconstruct file ...
+ ptr::null_mut(),
+ // ... or line information, but that's not so important.
+ 0)
+ };
let node = Rc::new(NamespaceTreeNode {
name: name,
/// .debug_gdb_scripts global is referenced, so it isn't removed by the linker.
pub fn insert_reference_to_gdb_debug_scripts_section_global(ccx: &CrateContext) {
if needs_gdb_debug_scripts_section(ccx) {
- let empty = b"".to_c_str();
+ let empty = CString::from_slice(b"");
let gdb_debug_scripts_section_global =
get_or_insert_gdb_debug_scripts_section_global(ccx);
unsafe {
/// section.
fn get_or_insert_gdb_debug_scripts_section_global(ccx: &CrateContext)
-> llvm::ValueRef {
- let section_var_name = b"__rustc_debug_gdb_scripts_section__".to_c_str();
+ let section_var_name = b"__rustc_debug_gdb_scripts_section__\0";
let section_var = unsafe {
- llvm::LLVMGetNamedGlobal(ccx.llmod(), section_var_name.as_ptr())
+ llvm::LLVMGetNamedGlobal(ccx.llmod(),
+ section_var_name.as_ptr() as *const _)
};
if section_var == ptr::null_mut() {
- let section_name = b".debug_gdb_scripts".to_c_str();
+ let section_name = b".debug_gdb_scripts\0";
let section_contents = b"\x01gdb_load_rust_pretty_printers.py\0";
unsafe {
section_contents.len() as u64);
let section_var = llvm::LLVMAddGlobal(ccx.llmod(),
llvm_type.to_ref(),
- section_var_name.as_ptr());
- llvm::LLVMSetSection(section_var, section_name.as_ptr());
+ section_var_name.as_ptr()
+ as *const _);
+ llvm::LLVMSetSection(section_var, section_name.as_ptr() as *const _);
llvm::LLVMSetInitializer(section_var, C_bytes(ccx, section_contents));
llvm::LLVMSetGlobalConstant(section_var, llvm::True);
llvm::LLVMSetUnnamedAddr(section_var, llvm::True);
use trans::type_of::*;
use trans::type_of;
use middle::ty::{self, Ty};
-use middle::subst::{Substs};
+use middle::subst::Substs;
+
+use std::ffi::CString;
use std::cmp;
-use std::c_str::ToCStr;
use libc::c_uint;
use syntax::abi::{Cdecl, Aapcs, C, Win64, Abi};
use syntax::abi::{RustIntrinsic, Rust, RustCall, Stdcall, Fastcall, System};
};
unsafe {
// Declare a symbol `foo` with the desired linkage.
- let g1 = ident.get().with_c_str(|buf| {
- llvm::LLVMAddGlobal(ccx.llmod(), llty2.to_ref(), buf)
- });
+ let buf = CString::from_slice(ident.get().as_bytes());
+ let g1 = llvm::LLVMAddGlobal(ccx.llmod(), llty2.to_ref(),
+ buf.as_ptr());
llvm::SetLinkage(g1, linkage);
// Declare an internal global `extern_with_linkage_foo` which
// zero.
let mut real_name = "_rust_extern_with_linkage_".to_string();
real_name.push_str(ident.get());
- let g2 = real_name.with_c_str(|buf| {
- llvm::LLVMAddGlobal(ccx.llmod(), llty.to_ref(), buf)
- });
+ let real_name = CString::from_vec(real_name.into_bytes());
+ let g2 = llvm::LLVMAddGlobal(ccx.llmod(), llty.to_ref(),
+ real_name.as_ptr());
llvm::SetLinkage(g2, llvm::InternalLinkage);
llvm::LLVMSetInitializer(g2, g1);
g2
}
None => unsafe {
// Generate an external declaration.
- ident.get().with_c_str(|buf| {
- llvm::LLVMAddGlobal(ccx.llmod(), llty.to_ref(), buf)
- })
+ let buf = CString::from_slice(ident.get().as_bytes());
+ llvm::LLVMAddGlobal(ccx.llmod(), llty.to_ref(), buf.as_ptr())
}
}
}
// return r;
// }
- let the_block =
- "the block".with_c_str(
- |s| llvm::LLVMAppendBasicBlockInContext(ccx.llcx(), llwrapfn, s));
+ let ptr = "the block\0".as_ptr();
+ let the_block = llvm::LLVMAppendBasicBlockInContext(ccx.llcx(), llwrapfn,
+ ptr as *const _);
let builder = ccx.builder();
builder.position_at_end(the_block);
use util::ppaux;
use arena::TypedArena;
-use std::c_str::ToCStr;
use libc::c_uint;
+use std::ffi::CString;
use syntax::ast;
use syntax::parse::token;
let llalign = llalign_of(ccx, llty);
let name = mangle_internal_name_by_type_and_seq(ccx, t, "tydesc");
debug!("+++ declare_tydesc {} {}", ppaux::ty_to_string(ccx.tcx(), t), name);
- let gvar = name.with_c_str(|buf| {
- unsafe {
- llvm::LLVMAddGlobal(ccx.llmod(), ccx.tydesc_type().to_ref(), buf)
- }
- });
+ let buf = CString::from_slice(name.as_bytes());
+ let gvar = unsafe {
+ llvm::LLVMAddGlobal(ccx.llmod(), ccx.tydesc_type().to_ref(),
+ buf.as_ptr())
+ };
note_unique_llvm_symbol(ccx, name);
let ty_name = token::intern_and_get_ident(
use middle::ty::MethodCall;
use util::ppaux::Repr;
-use std::c_str::ToCStr;
+use std::ffi::CString;
use std::rc::Rc;
use syntax::abi::{Rust, RustCall};
use syntax::parse::token;
unsafe {
let tbl = C_struct(ccx, components[], false);
let sym = token::gensym("vtable");
- let vt_gvar = format!("vtable{}", sym.uint()).with_c_str(|buf| {
- llvm::LLVMAddGlobal(ccx.llmod(), val_ty(tbl).to_ref(), buf)
- });
+ let buf = CString::from_vec(format!("vtable{}", sym.uint()).into_bytes());
+ let vt_gvar = llvm::LLVMAddGlobal(ccx.llmod(), val_ty(tbl).to_ref(),
+ buf.as_ptr());
llvm::LLVMSetInitializer(vt_gvar, tbl);
llvm::LLVMSetGlobalConstant(vt_gvar, llvm::True);
llvm::SetLinkage(vt_gvar, llvm::InternalLinkage);
use syntax::ast;
-use std::c_str::ToCStr;
+use std::ffi::CString;
use std::mem;
use std::cell::RefCell;
use std::iter::repeat;
}
pub fn named_struct(ccx: &CrateContext, name: &str) -> Type {
- ty!(name.with_c_str(|s| llvm::LLVMStructCreateNamed(ccx.llcx(), s)))
+ let name = CString::from_slice(name.as_bytes());
+ ty!(llvm::LLVMStructCreateNamed(ccx.llcx(), name.as_ptr()))
}
pub fn empty_struct(ccx: &CrateContext) -> Type {
#[cfg(unix)]
mod imp {
+ use std::ffi::CString;
use libc;
- use std::c_str::ToCStr;
#[cfg(target_os = "linux")]
mod os {
impl Lock {
pub fn new(p: &Path) -> Lock {
- let fd = p.with_c_str(|s| unsafe {
- libc::open(s, libc::O_RDWR | libc::O_CREAT, libc::S_IRWXU)
- });
+ let buf = CString::from_slice(p.as_vec());
+ let fd = unsafe {
+ libc::open(buf.as_ptr(), libc::O_RDWR | libc::O_CREAT,
+ libc::S_IRWXU)
+ };
assert!(fd > 0);
let flock = os::flock {
l_start: 0,
use libc;
use std::ascii::AsciiExt;
-use std::c_str::ToCStr;
+use std::ffi::CString;
use std::cell::{RefCell, Cell};
use std::collections::HashMap;
use std::fmt;
let id = id.as_ref().map(|a| a.as_slice());
s.push_str(highlight::highlight(text.as_slice(), None, id)
.as_slice());
- let output = s.to_c_str();
+ let output = CString::from_vec(s.into_bytes());
hoedown_buffer_puts(ob, output.as_ptr());
})
}
extern fn header(ob: *mut hoedown_buffer, text: *const hoedown_buffer,
level: libc::c_int, opaque: *mut libc::c_void) {
// hoedown does this, we may as well too
- "\n".with_c_str(|p| unsafe { hoedown_buffer_puts(ob, p) });
+ unsafe { hoedown_buffer_puts(ob, "\n\0".as_ptr() as *const _); }
// Extract the text provided
let s = if text.is_null() {
"".to_string()
} else {
- unsafe {
- String::from_raw_buf_len((*text).data, (*text).size as uint)
- }
+ let s = unsafe {
+ slice::from_raw_buf(&(*text).data, (*text).size as uint)
+ };
+ str::from_utf8(s).unwrap().to_string()
};
// Transform the contents of the header into a hyphenated string
format!("{} ", sec)
});
- text.with_c_str(|p| unsafe { hoedown_buffer_puts(ob, p) });
+ let text = CString::from_vec(text.into_bytes());
+ unsafe { hoedown_buffer_puts(ob, text.as_ptr()) }
}
reset_headers();
+++ /dev/null
-// 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.
-
-//! C-string manipulation and management
-//!
-//! This modules provides the basic methods for creating and manipulating
-//! null-terminated strings for use with FFI calls (back to C). Most C APIs require
-//! that the string being passed to them is null-terminated, and by default rust's
-//! string types are *not* null terminated.
-//!
-//! The other problem with translating Rust strings to C strings is that Rust
-//! strings can validly contain a null-byte in the middle of the string (0 is a
-//! valid Unicode codepoint). This means that not all Rust strings can actually be
-//! translated to C strings.
-//!
-//! # Creation of a C string
-//!
-//! A C string is managed through the `CString` type defined in this module. It
-//! "owns" the internal buffer of characters and will automatically deallocate the
-//! buffer when the string is dropped. The `ToCStr` trait is implemented for `&str`
-//! and `&[u8]`, but the conversions can fail due to some of the limitations
-//! explained above.
-//!
-//! This also means that currently whenever a C string is created, an allocation
-//! must be performed to place the data elsewhere (the lifetime of the C string is
-//! not tied to the lifetime of the original string/data buffer). If C strings are
-//! heavily used in applications, then caching may be advisable to prevent
-//! unnecessary amounts of allocations.
-//!
-//! Be carefull to remember that the memory is managed by C allocator API and not
-//! by Rust allocator API.
-//! That means that the CString pointers should be freed with C allocator API
-//! if you intend to do that on your own, as the behaviour if you free them with
-//! Rust's allocator API is not well defined
-//!
-//! An example of creating and using a C string would be:
-//!
-//! ```rust
-//! extern crate libc;
-//!
-//! use std::c_str::ToCStr;
-//!
-//! extern {
-//! fn puts(s: *const libc::c_char);
-//! }
-//!
-//! fn main() {
-//! let my_string = "Hello, world!";
-//!
-//! // 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();
-//! unsafe {
-//! puts(my_c_string.as_ptr());
-//! }
-//!
-//! // 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 core::prelude::*;
-use libc;
-
-use cmp::Ordering;
-use fmt;
-use hash;
-use mem;
-use ptr;
-use slice::{self, IntSliceExt};
-use str;
-use string::String;
-use core::kinds::marker;
-
-/// 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.
-#[allow(missing_copy_implementations)]
-pub struct CString {
- buf: *const libc::c_char,
- owns_buffer_: bool,
-}
-
-unsafe impl Send for CString { }
-unsafe impl Sync for CString { }
-
-impl Clone for CString {
- /// Clone this CString into a new, uniquely owned CString. For safety
- /// reasons, this is always a deep clone with the memory allocated
- /// with C's allocator API, rather than the usual shallow clone.
- fn clone(&self) -> CString {
- let len = self.len() + 1;
- let buf = unsafe { libc::malloc(len as libc::size_t) } as *mut libc::c_char;
- if buf.is_null() { ::alloc::oom() }
- unsafe { ptr::copy_nonoverlapping_memory(buf, self.buf, len); }
- CString { buf: buf as *const libc::c_char, owns_buffer_: true }
- }
-}
-
-impl PartialEq for CString {
- fn eq(&self, other: &CString) -> bool {
- // Check if the two strings share the same buffer
- if self.buf as uint == other.buf as uint {
- true
- } else {
- unsafe {
- libc::strcmp(self.buf, other.buf) == 0
- }
- }
- }
-}
-
-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, with memory managed by C's allocator
- /// API, so avoid calling it with a pointer to memory managed by Rust's
- /// allocator API, as the behaviour would not be well defined.
- ///
- ///# Panics
- ///
- /// Panics if `buf` is null
- pub unsafe fn new(buf: *const libc::c_char, owns_buffer: bool) -> CString {
- assert!(!buf.is_null());
- CString { buf: buf, owns_buffer_: owns_buffer }
- }
-
- /// 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
- /// use std::c_str::ToCStr;
- ///
- /// 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();
- /// ```
- ///
- /// # Example
- ///
- /// ```rust
- /// extern crate libc;
- ///
- /// use std::c_str::ToCStr;
- ///
- /// 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 {
- 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
- /// use std::c_str::ToCStr;
- ///
- /// 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();
- /// ```
- pub fn as_mut_ptr(&mut self) -> *mut libc::c_char {
- self.buf as *mut _
- }
-
- /// Returns whether or not the `CString` owns the buffer.
- pub fn owns_buffer(&self) -> bool {
- self.owns_buffer_
- }
-
- /// Converts the CString into a `&[u8]` without copying.
- /// Includes the terminating NUL byte.
- #[inline]
- pub fn as_bytes<'a>(&'a self) -> &'a [u8] {
- unsafe {
- slice::from_raw_buf(&self.buf, self.len() + 1).as_unsigned()
- }
- }
-
- /// Converts the CString into a `&[u8]` without copying.
- /// Does not include the terminating NUL byte.
- #[inline]
- pub fn as_bytes_no_nul<'a>(&'a self) -> &'a [u8] {
- unsafe {
- slice::from_raw_buf(&self.buf, self.len()).as_unsigned()
- }
- }
-
- /// Converts the CString into a `&str` without copying.
- /// Returns None if the CString is not UTF-8.
- #[inline]
- pub fn as_str<'a>(&'a self) -> Option<&'a str> {
- let buf = self.as_bytes_no_nul();
- str::from_utf8(buf).ok()
- }
-
- /// Return a CString iterator.
- pub fn iter<'a>(&'a self) -> CChars<'a> {
- CChars {
- ptr: self.buf,
- 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. You should
- /// use libc's memory allocator in this case.
- ///
- /// Prefer `.as_ptr()` when just retrieving a pointer to the
- /// string data, as that does not relinquish ownership.
- pub unsafe fn into_inner(mut self) -> *const libc::c_char {
- self.owns_buffer_ = false;
- self.buf
- }
-
- /// Return the number of bytes in the CString (not including the NUL
- /// terminator).
- #[inline]
- pub fn len(&self) -> uint {
- unsafe { libc::strlen(self.buf) as uint }
- }
-
- /// Returns if there are no bytes in this string
- #[inline]
- pub fn is_empty(&self) -> bool { self.len() == 0 }
-}
-
-impl Drop for CString {
- fn drop(&mut self) {
- if self.owns_buffer_ {
- unsafe {
- libc::free(self.buf as *mut libc::c_void)
- }
- }
- }
-}
-
-impl fmt::Show for CString {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- String::from_utf8_lossy(self.as_bytes_no_nul()).fmt(f)
- }
-}
-
-/// A generic trait for converting a value to a CString.
-pub trait ToCStr for Sized? {
- /// Copy the receiver into a CString.
- ///
- /// # Panics
- ///
- /// Panics the task if the receiver has an interior null.
- fn to_c_str(&self) -> CString;
-
- /// Unsafe variant of `to_c_str()` that doesn't check for nulls.
- unsafe fn to_c_str_unchecked(&self) -> CString;
-
- /// Work with a temporary CString constructed from the receiver.
- /// The provided `*libc::c_char` will be freed immediately upon return.
- ///
- /// # Example
- ///
- /// ```rust
- /// extern crate libc;
- ///
- /// use std::c_str::ToCStr;
- ///
- /// fn main() {
- /// let s = "PATH".with_c_str(|path| unsafe {
- /// libc::getenv(path)
- /// });
- /// }
- /// ```
- ///
- /// # Panics
- ///
- /// Panics the task if the receiver has an interior null.
- #[inline]
- fn with_c_str<T, F>(&self, f: F) -> T where
- F: FnOnce(*const libc::c_char) -> T,
- {
- 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, F>(&self, f: F) -> T where
- F: FnOnce(*const libc::c_char) -> T,
- {
- let c_str = self.to_c_str_unchecked();
- f(c_str.as_ptr())
- }
-}
-
-impl ToCStr for str {
- #[inline]
- fn to_c_str(&self) -> CString {
- self.as_bytes().to_c_str()
- }
-
- #[inline]
- unsafe fn to_c_str_unchecked(&self) -> CString {
- self.as_bytes().to_c_str_unchecked()
- }
-
- #[inline]
- fn with_c_str<T, F>(&self, f: F) -> T where
- F: FnOnce(*const libc::c_char) -> T,
- {
- self.as_bytes().with_c_str(f)
- }
-
- #[inline]
- unsafe fn with_c_str_unchecked<T, F>(&self, f: F) -> T where
- F: FnOnce(*const libc::c_char) -> T,
- {
- self.as_bytes().with_c_str_unchecked(f)
- }
-}
-
-impl ToCStr for String {
- #[inline]
- fn to_c_str(&self) -> CString {
- self.as_bytes().to_c_str()
- }
-
- #[inline]
- unsafe fn to_c_str_unchecked(&self) -> CString {
- self.as_bytes().to_c_str_unchecked()
- }
-
- #[inline]
- fn with_c_str<T, F>(&self, f: F) -> T where
- F: FnOnce(*const libc::c_char) -> T,
- {
- self.as_bytes().with_c_str(f)
- }
-
- #[inline]
- unsafe fn with_c_str_unchecked<T, F>(&self, f: F) -> T where
- F: FnOnce(*const libc::c_char) -> T,
- {
- self.as_bytes().with_c_str_unchecked(f)
- }
-}
-
-// The length of the stack allocated buffer for `vec.with_c_str()`
-const BUF_LEN: uint = 128;
-
-impl ToCStr for [u8] {
- fn to_c_str(&self) -> CString {
- let mut cs = unsafe { self.to_c_str_unchecked() };
- check_for_null(self, cs.as_mut_ptr());
- cs
- }
-
- unsafe fn to_c_str_unchecked(&self) -> CString {
- let self_len = self.len();
- let buf = libc::malloc(self_len as libc::size_t + 1) as *mut u8;
- if buf.is_null() { ::alloc::oom() }
-
- ptr::copy_memory(buf, self.as_ptr(), self_len);
- *buf.offset(self_len as int) = 0;
-
- CString::new(buf as *const libc::c_char, true)
- }
-
- fn with_c_str<T, F>(&self, f: F) -> T where
- F: FnOnce(*const libc::c_char) -> T,
- {
- unsafe { with_c_str(self, true, f) }
- }
-
- unsafe fn with_c_str_unchecked<T, F>(&self, f: F) -> T where
- F: FnOnce(*const libc::c_char) -> T,
- {
- with_c_str(self, false, f)
- }
-}
-
-impl<'a, Sized? T: ToCStr> ToCStr for &'a T {
- #[inline]
- fn to_c_str(&self) -> CString {
- (**self).to_c_str()
- }
-
- #[inline]
- unsafe fn to_c_str_unchecked(&self) -> CString {
- (**self).to_c_str_unchecked()
- }
-
- #[inline]
- fn with_c_str<T, F>(&self, f: F) -> T where
- F: FnOnce(*const libc::c_char) -> T,
- {
- (**self).with_c_str(f)
- }
-
- #[inline]
- unsafe fn with_c_str_unchecked<T, F>(&self, f: F) -> T where
- F: FnOnce(*const libc::c_char) -> T,
- {
- (**self).with_c_str_unchecked(f)
- }
-}
-
-// Unsafe function that handles possibly copying the &[u8] into a stack array.
-unsafe fn with_c_str<T, F>(v: &[u8], checked: bool, f: F) -> T where
- F: FnOnce(*const libc::c_char) -> T,
-{
- let c_str = if v.len() < BUF_LEN {
- let mut buf: [u8; BUF_LEN] = mem::uninitialized();
- slice::bytes::copy_memory(&mut buf, v);
- buf[v.len()] = 0;
-
- let buf = buf.as_mut_ptr();
- if checked {
- check_for_null(v, buf as *mut libc::c_char);
- }
-
- return f(buf as *const libc::c_char)
- } else if checked {
- v.to_c_str()
- } else {
- v.to_c_str_unchecked()
- };
-
- f(c_str.as_ptr())
-}
-
-#[inline]
-fn check_for_null(v: &[u8], buf: *mut libc::c_char) {
- for i in range(0, v.len()) {
- unsafe {
- let p = buf.offset(i as int);
- assert!(*p != 0);
- }
- }
-}
-
-/// External iterator for a CString's bytes.
-///
-/// Use with the `std::iter` module.
-#[allow(raw_pointer_deriving)]
-#[derive(Clone)]
-pub struct CChars<'a> {
- ptr: *const libc::c_char,
- marker: marker::ContravariantLifetime<'a>,
-}
-
-impl<'a> Iterator for CChars<'a> {
- type Item = libc::c_char;
-
- fn next(&mut self) -> Option<libc::c_char> {
- let ch = unsafe { *self.ptr };
- if ch == 0 {
- None
- } else {
- self.ptr = unsafe { self.ptr.offset(1) };
- Some(ch)
- }
- }
-}
-
-/// Parses a C "multistring", eg windows env values or
-/// the req->ptr result in a uv_fs_readdir() call.
-///
-/// Optionally, a `count` can be passed in, limiting the
-/// parsing to only being done `count`-times.
-///
-/// The specified closure is invoked with each string that
-/// is found, and the number of strings found is returned.
-pub unsafe fn from_c_multistring<F>(buf: *const libc::c_char,
- count: Option<uint>,
- mut f: F)
- -> uint where
- F: FnMut(&CString),
-{
-
- let mut curr_ptr: uint = buf as uint;
- let mut ctr = 0;
- let (limited_count, limit) = match count {
- Some(limit) => (true, limit),
- None => (false, 0)
- };
- while ((limited_count && ctr < limit) || !limited_count)
- && *(curr_ptr as *const libc::c_char) != 0 as libc::c_char {
- let cstr = CString::new(curr_ptr as *const libc::c_char, false);
- f(&cstr);
- curr_ptr += cstr.len() + 1;
- ctr += 1;
- }
- return ctr;
-}
-
-#[cfg(test)]
-mod tests {
- use prelude::v1::*;
- use super::*;
- use ptr;
- use thread::Thread;
- use libc;
-
- #[test]
- fn test_str_multistring_parsing() {
- unsafe {
- let input = b"zero\0one\0\0";
- let ptr = input.as_ptr();
- let expected = ["zero", "one"];
- let mut it = expected.iter();
- let result = from_c_multistring(ptr as *const libc::c_char, None, |c| {
- let cbytes = c.as_bytes_no_nul();
- assert_eq!(cbytes, it.next().unwrap().as_bytes());
- });
- assert_eq!(result, 2);
- assert!(it.next().is_none());
- }
- }
-
- #[test]
- fn test_str_to_c_str() {
- let c_str = "".to_c_str();
- unsafe {
- assert_eq!(*c_str.as_ptr().offset(0), 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] = &[];
- let c_str = b.to_c_str();
- unsafe {
- assert_eq!(*c_str.as_ptr().offset(0), 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 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 libc::c_char);
- assert_eq!(*buf.offset(4), 0);
- }
- }
-
- #[test]
- fn test_unwrap() {
- let c_str = "hello".to_c_str();
- unsafe { libc::free(c_str.into_inner() as *mut libc::c_void) }
- }
-
- #[test]
- fn test_as_ptr() {
- let c_str = "hello".to_c_str();
- let len = unsafe { libc::strlen(c_str.as_ptr()) };
- assert_eq!(len, 5);
- }
-
- #[test]
- fn test_iterator() {
- let c_str = "".to_c_str();
- let mut iter = c_str.iter();
- assert_eq!(iter.next(), None);
-
- let c_str = "hello".to_c_str();
- let mut iter = c_str.iter();
- assert_eq!(iter.next(), Some('h' as libc::c_char));
- assert_eq!(iter.next(), Some('e' as libc::c_char));
- assert_eq!(iter.next(), Some('l' as libc::c_char));
- assert_eq!(iter.next(), Some('l' as libc::c_char));
- assert_eq!(iter.next(), Some('o' as libc::c_char));
- assert_eq!(iter.next(), None);
- }
-
- #[test]
- fn test_to_c_str_fail() {
- assert!(Thread::spawn(move|| { "he\x00llo".to_c_str() }).join().is_err());
- }
-
- #[test]
- fn test_to_c_str_unchecked() {
- unsafe {
- 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);
- }
- }
-
- #[test]
- fn test_as_bytes() {
- let c_str = "hello".to_c_str();
- assert_eq!(c_str.as_bytes(), b"hello\0");
- let c_str = "".to_c_str();
- assert_eq!(c_str.as_bytes(), b"\0");
- let c_str = b"foo\xFF".to_c_str();
- assert_eq!(c_str.as_bytes(), b"foo\xFF\0");
- }
-
- #[test]
- fn test_as_bytes_no_nul() {
- let c_str = "hello".to_c_str();
- assert_eq!(c_str.as_bytes_no_nul(), b"hello");
- let c_str = "".to_c_str();
- let exp: &[u8] = &[];
- assert_eq!(c_str.as_bytes_no_nul(), exp);
- let c_str = b"foo\xFF".to_c_str();
- assert_eq!(c_str.as_bytes_no_nul(), b"foo\xFF");
- }
-
- #[test]
- fn test_as_str() {
- let c_str = "hello".to_c_str();
- assert_eq!(c_str.as_str(), Some("hello"));
- let c_str = "".to_c_str();
- assert_eq!(c_str.as_str(), Some(""));
- let c_str = b"foo\xFF".to_c_str();
- assert_eq!(c_str.as_str(), None);
- }
-
- #[test]
- #[should_fail]
- fn test_new_fail() {
- let _c_str = unsafe { CString::new(ptr::null(), false) };
- }
-
- #[test]
- fn test_clone() {
- let a = "hello".to_c_str();
- let b = a.clone();
- assert!(a == b);
- }
-
- #[test]
- fn test_clone_noleak() {
- fn foo<F>(f: F) where F: FnOnce(&CString) {
- let s = "test".to_string();
- let c = s.to_c_str();
- // give the closure a non-owned CString
- let mut c_ = unsafe { CString::new(c.as_ptr(), false) };
- f(&c_);
- // muck with the buffer for later printing
- unsafe { *c_.as_mut_ptr() = '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_vec();
- });
- let c_ = c_.unwrap();
- // force a copy, reading the memory
- c_.as_bytes().to_vec();
- }
-}
-
-#[cfg(test)]
-mod bench {
- extern crate test;
-
- use prelude::v1::*;
- use self::test::Bencher;
- use libc;
- use c_str::ToCStr;
-
- #[inline]
- fn check(s: &str, c_str: *const libc::c_char) {
- let s_buf = s.as_ptr();
- for i in range(0, s.len()) {
- unsafe {
- assert_eq!(
- *s_buf.offset(i as int) as libc::c_char,
- *c_str.offset(i as int));
- }
- }
- }
-
- static S_SHORT: &'static str = "Mary";
- static S_MEDIUM: &'static str = "Mary had a little lamb";
- static S_LONG: &'static str = "\
- Mary had a little lamb, Little lamb
- Mary had a little lamb, Little lamb
- Mary had a little lamb, Little lamb
- Mary had a little lamb, Little lamb
- Mary had a little lamb, Little lamb
- Mary had a little lamb, Little lamb";
-
- fn bench_to_string(b: &mut Bencher, s: &str) {
- b.iter(|| {
- let c_str = s.to_c_str();
- check(s, c_str.as_ptr());
- })
- }
-
- #[bench]
- fn bench_to_c_str_short(b: &mut Bencher) {
- bench_to_string(b, S_SHORT)
- }
-
- #[bench]
- fn bench_to_c_str_medium(b: &mut Bencher) {
- bench_to_string(b, S_MEDIUM)
- }
-
- #[bench]
- fn bench_to_c_str_long(b: &mut Bencher) {
- 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() };
- check(s, c_str.as_ptr())
- })
- }
-
- #[bench]
- fn bench_to_c_str_unchecked_short(b: &mut Bencher) {
- bench_to_c_str_unchecked(b, S_SHORT)
- }
-
- #[bench]
- fn bench_to_c_str_unchecked_medium(b: &mut Bencher) {
- bench_to_c_str_unchecked(b, S_MEDIUM)
- }
-
- #[bench]
- fn bench_to_c_str_unchecked_long(b: &mut Bencher) {
- bench_to_c_str_unchecked(b, S_LONG)
- }
-
- fn bench_with_c_str(b: &mut Bencher, s: &str) {
- b.iter(|| {
- s.with_c_str(|c_str_buf| check(s, c_str_buf))
- })
- }
-
- #[bench]
- fn bench_with_c_str_short(b: &mut Bencher) {
- bench_with_c_str(b, S_SHORT)
- }
-
- #[bench]
- fn bench_with_c_str_medium(b: &mut Bencher) {
- bench_with_c_str(b, S_MEDIUM)
- }
-
- #[bench]
- fn bench_with_c_str_long(b: &mut Bencher) {
- bench_with_c_str(b, S_LONG)
- }
-
- fn bench_with_c_str_unchecked(b: &mut Bencher, s: &str) {
- b.iter(|| {
- unsafe {
- s.with_c_str_unchecked(|c_str_buf| check(s, c_str_buf))
- }
- })
- }
-
- #[bench]
- fn bench_with_c_str_unchecked_short(b: &mut Bencher) {
- bench_with_c_str_unchecked(b, S_SHORT)
- }
-
- #[bench]
- fn bench_with_c_str_unchecked_medium(b: &mut Bencher) {
- bench_with_c_str_unchecked(b, S_MEDIUM)
- }
-
- #[bench]
- fn bench_with_c_str_unchecked_long(b: &mut Bencher) {
- bench_with_c_str_unchecked(b, S_LONG)
- }
-}
+++ /dev/null
-// 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.
-
-//! Library to interface with chunks of memory allocated in C.
-//!
-//! It is often desirable to safely interface with memory allocated from C,
-//! encapsulating the unsafety into allocation and destruction time. Indeed,
-//! allocating memory externally is currently the only way to give Rust shared
-//! mut state with C programs that keep their own references; vectors are
-//! unsuitable because they could be reallocated or moved at any time, and
-//! importing C memory into a vector takes a one-time snapshot of the memory.
-//!
-//! This module simplifies the usage of such external blocks of memory. Memory
-//! is encapsulated into an opaque object after creation; the lifecycle of the
-//! memory can be optionally managed by Rust, if an appropriate destructor
-//! closure is provided. Safety is ensured by bounds-checking accesses, which
-//! are marshalled through get and set functions.
-//!
-//! There are three unsafe functions: the two constructors, and the
-//! unwrap method. The constructors are unsafe for the
-//! obvious reason (they act on a pointer that cannot be checked inside the
-//! method), but `unwrap()` is somewhat more subtle in its unsafety.
-//! It returns the contained pointer, but at the same time destroys the CVec
-//! without running its destructor. This can be used to pass memory back to
-//! C, but care must be taken that the ownership of underlying resources are
-//! handled correctly, i.e. that allocated memory is eventually freed
-//! if necessary.
-
-#![experimental]
-
-use kinds::Send;
-use mem;
-use ops::{Drop, FnOnce};
-use option::Option;
-use option::Option::{Some, None};
-use ptr::PtrExt;
-use ptr;
-use raw;
-use slice::AsSlice;
-use thunk::{Thunk};
-
-/// The type representing a foreign chunk of memory
-pub struct CVec<T> {
- base: *mut T,
- len: uint,
- dtor: Option<Thunk>,
-}
-
-#[unsafe_destructor]
-impl<T> Drop for CVec<T> {
- fn drop(&mut self) {
- match self.dtor.take() {
- None => (),
- Some(f) => f.invoke(())
- }
- }
-}
-
-impl<T> CVec<T> {
- /// Create a `CVec` from a raw pointer to a buffer with a given length.
- ///
- /// Panics if the given pointer is null. The returned vector will not attempt
- /// to deallocate the vector when dropped.
- ///
- /// # Arguments
- ///
- /// * base - A raw pointer to a buffer
- /// * len - The number of elements in the buffer
- pub unsafe fn new(base: *mut T, len: uint) -> CVec<T> {
- assert!(base != ptr::null_mut());
- CVec {
- base: base,
- len: len,
- dtor: None,
- }
- }
-
- /// Create a `CVec` from a foreign buffer, with a given length,
- /// and a function to run upon destruction.
- ///
- /// Panics if the given pointer is null.
- ///
- /// # Arguments
- ///
- /// * base - A foreign pointer to a buffer
- /// * len - The number of elements in the buffer
- /// * dtor - A fn to run when the value is destructed, useful
- /// for freeing the buffer, etc.
- pub unsafe fn new_with_dtor<F>(base: *mut T,
- len: uint,
- dtor: F)
- -> CVec<T>
- where F : FnOnce(), F : Send
- {
- assert!(base != ptr::null_mut());
- let dtor: Thunk = Thunk::new(dtor);
- CVec {
- base: base,
- len: len,
- dtor: Some(dtor)
- }
- }
-
- /// View the stored data as a mutable slice.
- pub fn as_mut_slice<'a>(&'a mut self) -> &'a mut [T] {
- unsafe {
- mem::transmute(raw::Slice { data: self.base as *const T, len: self.len })
- }
- }
-
- /// Retrieves an element at a given index, returning `None` if the requested
- /// index is greater than the length of the vector.
- pub fn get<'a>(&'a self, ofs: uint) -> Option<&'a T> {
- if ofs < self.len {
- Some(unsafe { &*self.base.offset(ofs as int) })
- } else {
- None
- }
- }
-
- /// Retrieves a mutable element at a given index, returning `None` if the
- /// requested index is greater than the length of the vector.
- pub fn get_mut<'a>(&'a mut self, ofs: uint) -> Option<&'a mut T> {
- if ofs < self.len {
- Some(unsafe { &mut *self.base.offset(ofs as int) })
- } else {
- None
- }
- }
-
- /// Unwrap the pointer without running the destructor
- ///
- /// This method retrieves the underlying pointer, and in the process
- /// destroys the CVec but without running the destructor. A use case
- /// would be transferring ownership of the buffer to a C function, as
- /// in this case you would not want to run the destructor.
- ///
- /// Note that if you want to access the underlying pointer without
- /// cancelling the destructor, you can simply call `transmute` on the return
- /// value of `get(0)`.
- pub unsafe fn into_inner(mut self) -> *mut T {
- self.dtor = None;
- self.base
- }
-
- /// Returns the number of items in this vector.
- pub fn len(&self) -> uint { self.len }
-
- /// Returns whether this vector is empty.
- pub fn is_empty(&self) -> bool { self.len() == 0 }
-}
-
-impl<T> AsSlice<T> for CVec<T> {
- /// View the stored data as a slice.
- fn as_slice<'a>(&'a self) -> &'a [T] {
- unsafe {
- mem::transmute(raw::Slice { data: self.base as *const T, len: self.len })
- }
- }
-}
-
-#[cfg(test)]
-mod tests {
- use prelude::v1::*;
-
- use super::CVec;
- use libc;
- use ptr;
-
- fn malloc(n: uint) -> CVec<u8> {
- unsafe {
- let mem = ptr::Unique(libc::malloc(n as libc::size_t));
- if mem.0.is_null() { ::alloc::oom() }
-
- CVec::new_with_dtor(mem.0 as *mut u8,
- n,
- move|| { libc::free(mem.0 as *mut libc::c_void); })
- }
- }
-
- #[test]
- fn test_basic() {
- let mut cv = malloc(16);
-
- *cv.get_mut(3).unwrap() = 8;
- *cv.get_mut(4).unwrap() = 9;
- assert_eq!(*cv.get(3).unwrap(), 8);
- assert_eq!(*cv.get(4).unwrap(), 9);
- assert_eq!(cv.len(), 16);
- }
-
- #[test]
- #[should_fail]
- fn test_panic_at_null() {
- unsafe {
- CVec::new(ptr::null_mut::<u8>(), 9);
- }
- }
-
- #[test]
- fn test_overrun_get() {
- let cv = malloc(16);
-
- assert!(cv.get(17).is_none());
- }
-
- #[test]
- fn test_overrun_set() {
- let mut cv = malloc(16);
-
- assert!(cv.get_mut(17).is_none());
- }
-
- #[test]
- fn test_unwrap() {
- unsafe {
- let cv = CVec::new_with_dtor(1 as *mut int,
- 0,
- move|:| panic!("Don't run this destructor!"));
- let p = cv.into_inner();
- assert_eq!(p, 1 as *mut int);
- }
- }
-
-}
use prelude::v1::*;
-use c_str::ToCStr;
+use ffi::CString;
use mem;
use os;
use str;
/// Lazily open a dynamic library. When passed None it gives a
/// handle to the calling process
- pub fn open<T: ToCStr>(filename: Option<T>)
- -> Result<DynamicLibrary, String> {
+ pub fn open(filename: Option<&Path>) -> Result<DynamicLibrary, String> {
unsafe {
- let mut filename = filename;
let maybe_library = dl::check_for_errors_in(|| {
- match filename.take() {
- Some(name) => dl::open_external(name),
+ match filename {
+ Some(name) => dl::open_external(name.as_vec()),
None => dl::open_internal()
}
});
// T but that feature is still unimplemented
let maybe_symbol_value = dl::check_for_errors_in(|| {
- symbol.with_c_str(|raw_string| {
- dl::symbol(self.handle, raw_string)
- })
+ let raw_string = CString::from_slice(symbol.as_bytes());
+ dl::symbol(self.handle, raw_string.as_ptr())
});
// The value must not be constructed if there is an error so
fn test_loading_cosine() {
// The math library does not need to be loaded since it is already
// statically linked in
- let none: Option<Path> = None; // appease the typechecker
+ let none: Option<&Path> = None; // appease the typechecker
let libm = match DynamicLibrary::open(none) {
Err(error) => panic!("Could not load self as module: {}", error),
Ok(libm) => libm
target_os = "freebsd",
target_os = "dragonfly"))]
pub mod dl {
- use self::Rtld::*;
-
+ pub use self::Rtld::*;
use prelude::v1::*;
- use c_str::{CString, ToCStr};
+
+ use ffi::{self, CString};
+ use str;
use libc;
use ptr;
- pub unsafe fn open_external<T: ToCStr>(filename: T) -> *mut u8 {
- filename.with_c_str(|raw_name| {
- dlopen(raw_name, Lazy as libc::c_int) as *mut u8
- })
+ pub unsafe fn open_external(filename: &[u8]) -> *mut u8 {
+ let s = CString::from_slice(filename);
+ dlopen(s.as_ptr(), Lazy as libc::c_int) as *mut u8
}
pub unsafe fn open_internal() -> *mut u8 {
let ret = if ptr::null() == last_error {
Ok(result)
} else {
- Err(String::from_str(CString::new(last_error, false).as_str()
- .unwrap()))
+ let s = ffi::c_str_to_bytes(&last_error);
+ Err(str::from_utf8(s).unwrap().to_string())
};
ret
#[cfg(target_os = "windows")]
pub mod dl {
- use c_str::ToCStr;
use iter::IteratorExt;
use libc;
use ops::FnOnce;
use string::String;
use vec::Vec;
- pub unsafe fn open_external<T: ToCStr>(filename: T) -> *mut u8 {
+ pub unsafe fn open_external(filename: &[u8]) -> *mut u8 {
// Windows expects Unicode data
- let filename_cstr = filename.to_c_str();
- let filename_str = str::from_utf8(filename_cstr.as_bytes_no_nul()).unwrap();
+ let filename_str = str::from_utf8(filename).unwrap();
let mut filename_str: Vec<u16> = filename_str.utf16_units().collect();
filename_str.push(0);
LoadLibraryW(filename_str.as_ptr() as *const libc::c_void) as *mut u8
--- /dev/null
+// 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 fmt;
+use iter::IteratorExt;
+use libc;
+use mem;
+use ops::Deref;
+use slice::{self, SliceExt, AsSlice};
+use string::String;
+use vec::Vec;
+
+/// A type representing a C-compatible string
+///
+/// This type serves the primary purpose of being able to generate a
+/// C-compatible string from a Rust byte slice or vector. An instance of this
+/// type is a static guarantee that the underlying bytes contain no interior 0
+/// bytes and the final byte is 0.
+///
+/// A `CString` is created from either a byte slice or a byte vector. After
+/// being created, a `CString` predominately inherits all of its methods from
+/// the `Deref` implementation to `[libc::c_char]`. Note that the underlying
+/// array is represented as an array of `libc::c_char` as opposed to `u8`. A
+/// `u8` slice can be obtained with the `as_bytes` method. Slices produced from
+/// a `CString` do *not* contain the trailing nul terminator unless otherwise
+/// specified.
+///
+/// # Example
+///
+/// ```no_run
+/// # extern crate libc;
+/// # fn main() {
+/// use std::ffi::CString;
+/// use libc;
+///
+/// extern {
+/// fn my_printer(s: *const libc::c_char);
+/// }
+///
+/// let to_print = "Hello, world!";
+/// let c_to_print = CString::from_slice(to_print.as_bytes());
+/// unsafe {
+/// my_printer(c_to_print.as_ptr());
+/// }
+/// # }
+/// ```
+#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+pub struct CString {
+ inner: Vec<libc::c_char>,
+}
+
+impl CString {
+ /// Create a new C-compatible string from a byte slice.
+ ///
+ /// This method will copy the data of the slice provided into a new
+ /// allocation, ensuring that there is a trailing 0 byte.
+ ///
+ /// # Panics
+ ///
+ /// This function will panic if there are any 0 bytes already in the slice
+ /// provided.
+ pub fn from_slice(v: &[u8]) -> CString {
+ CString::from_vec(v.to_vec())
+ }
+
+ /// Create a C-compatible string from a byte vector.
+ ///
+ /// This method will consume ownership of the provided vector, appending a 0
+ /// byte to the end after verifying that there are no interior 0 bytes.
+ ///
+ /// # Panics
+ ///
+ /// This function will panic if there are any 0 bytes already in the vector
+ /// provided.
+ pub fn from_vec(v: Vec<u8>) -> CString {
+ assert!(!v.iter().any(|&x| x == 0));
+ unsafe { CString::from_vec_unchecked(v) }
+ }
+
+ /// Create a C-compatibel string from a byte vector without checking for
+ /// interior 0 bytes.
+ ///
+ /// This method is equivalent to `from_vec` except that no runtime assertion
+ /// is made that `v` contains no 0 bytes.
+ pub unsafe fn from_vec_unchecked(mut v: Vec<u8>) -> CString {
+ v.push(0);
+ CString { inner: mem::transmute(v) }
+ }
+
+ /// Create a view into this C string which includes the trailing nul
+ /// terminator at the end of the string.
+ pub fn as_slice_with_nul(&self) -> &[libc::c_char] { self.inner.as_slice() }
+
+ /// Similar to the `as_slice` method, but returns a `u8` slice instead of a
+ /// `libc::c_char` slice.
+ pub fn as_bytes(&self) -> &[u8] {
+ unsafe { mem::transmute(self.as_slice()) }
+ }
+
+ /// Equivalend to `as_slice_with_nul` except that the type returned is a
+ /// `u8` slice instead of a `libc::c_char` slice.
+ pub fn as_bytes_with_nul(&self) -> &[u8] {
+ unsafe { mem::transmute(self.as_slice_with_nul()) }
+ }
+}
+
+impl Deref for CString {
+ type Target = [libc::c_char];
+
+ fn deref(&self) -> &[libc::c_char] {
+ self.inner.slice_to(self.inner.len() - 1)
+ }
+}
+
+impl fmt::Show for CString {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ String::from_utf8_lossy(self.as_bytes()).fmt(f)
+ }
+}
+
+/// Interpret a C string as a byte slice.
+///
+/// This function will calculate the length of the C string provided, and it
+/// will then return a corresponding slice for the contents of the C string not
+/// including the nul terminator.
+///
+/// This function will tie the lifetime of the returned slice to the lifetime of
+/// the pointer provided. This is done to help prevent the slice from escaping
+/// the lifetime of the pointer itself. If a longer lifetime is needed, then
+/// `mem::copy_lifetime` should be used.
+///
+/// This function is unsafe because there is no guarantee of the validity of the
+/// pointer `raw` or a guarantee that a nul terminator will be found.
+///
+/// # Example
+///
+/// ```no_run
+/// # extern crate libc;
+/// # fn main() {
+/// use std::ffi;
+/// use std::str;
+/// use libc;
+///
+/// extern {
+/// fn my_string() -> *const libc::c_char;
+/// }
+///
+/// unsafe {
+/// let to_print = my_string();
+/// let slice = ffi::c_str_to_bytes(&to_print);
+/// println!("string returned: {}", str::from_utf8(slice).unwrap());
+/// }
+/// # }
+/// ```
+pub unsafe fn c_str_to_bytes<'a>(raw: &'a *const libc::c_char) -> &'a [u8] {
+ let len = libc::strlen(*raw);
+ slice::from_raw_buf(&*(raw as *const _ as *const *const u8), len as uint)
+}
+
+/// Interpret a C string as a byte slice with the nul terminator.
+///
+/// This function is identical to `from_raw_buf` except that the returned slice
+/// will include the nul terminator of the string.
+pub unsafe fn c_str_to_bytes_with_nul<'a>(raw: &'a *const libc::c_char) -> &'a [u8] {
+ let len = libc::strlen(*raw) + 1;
+ slice::from_raw_buf(&*(raw as *const _ as *const *const u8), len as uint)
+}
+
+#[cfg(test)]
+mod tests {
+ use prelude::v1::*;
+ use super::*;
+ use libc;
+ use mem;
+
+ #[test]
+ fn c_to_rust() {
+ let data = b"123\0";
+ let ptr = data.as_ptr() as *const libc::c_char;
+ unsafe {
+ assert_eq!(c_str_to_bytes(&ptr), b"123");
+ assert_eq!(c_str_to_bytes_with_nul(&ptr), b"123\0");
+ }
+ }
+
+ #[test]
+ fn simple() {
+ let s = CString::from_slice(b"1234");
+ assert_eq!(s.as_bytes(), b"1234");
+ assert_eq!(s.as_bytes_with_nul(), b"1234\0");
+ unsafe {
+ assert_eq!(s.as_slice(),
+ mem::transmute::<_, &[libc::c_char]>(b"1234"));
+ assert_eq!(s.as_slice_with_nul(),
+ mem::transmute::<_, &[libc::c_char]>(b"1234\0"));
+ }
+ }
+
+ #[should_fail] #[test]
+ fn build_with_zero1() { CString::from_slice(b"\0"); }
+ #[should_fail] #[test]
+ fn build_with_zero2() { CString::from_vec(vec![0]); }
+
+ #[test]
+ fn build_with_zero3() {
+ unsafe {
+ let s = CString::from_vec_unchecked(vec![0]);
+ assert_eq!(s.as_bytes(), b"\0");
+ }
+ }
+}
--- /dev/null
+// Copyright 2015 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.
+
+//! Utilities related to FFI bindings.
+
+#![unstable = "module just underwent fairly large reorganization and the dust \
+ still needs to settle"]
+
+pub use self::c_str::CString;
+pub use self::c_str::c_str_to_bytes;
+pub use self::c_str::c_str_to_bytes_with_nul;
+
+mod c_str;
use prelude::v1::*;
-use c_str::ToCStr;
+use ffi::CString;
+use path::BytesContainer;
use io::{Listener, Acceptor, IoResult, TimedOut, standard_error};
use sys::pipe::UnixAcceptor as UnixAcceptorImp;
use sys::pipe::UnixListener as UnixListenerImp;
/// let mut stream = UnixStream::connect(&server);
/// stream.write(&[1, 2, 3]);
/// ```
- pub fn connect<P: ToCStr>(path: &P) -> IoResult<UnixStream> {
- UnixStreamImp::connect(&path.to_c_str(), None)
+ pub fn connect<P: BytesContainer>(path: P) -> IoResult<UnixStream> {
+ let path = CString::from_slice(path.container_as_bytes());
+ UnixStreamImp::connect(&path, None)
.map(|inner| UnixStream { inner: inner })
}
/// If a `timeout` with zero or negative duration is specified then
/// the function returns `Err`, with the error kind set to `TimedOut`.
#[experimental = "the timeout argument is likely to change types"]
- pub fn connect_timeout<P: ToCStr>(path: &P,
- timeout: Duration) -> IoResult<UnixStream> {
+ pub fn connect_timeout<P>(path: P, timeout: Duration)
+ -> IoResult<UnixStream>
+ where P: BytesContainer {
if timeout <= Duration::milliseconds(0) {
return Err(standard_error(TimedOut));
}
- UnixStreamImp::connect(&path.to_c_str(), Some(timeout.num_milliseconds() as u64))
+ let path = CString::from_slice(path.container_as_bytes());
+ UnixStreamImp::connect(&path, Some(timeout.num_milliseconds() as u64))
.map(|inner| UnixStream { inner: inner })
}
/// }
/// # }
/// ```
- pub fn bind<P: ToCStr>(path: &P) -> IoResult<UnixListener> {
- UnixListenerImp::bind(&path.to_c_str())
+ pub fn bind<P: BytesContainer>(path: P) -> IoResult<UnixListener> {
+ let path = CString::from_slice(path.container_as_bytes());
+ UnixListenerImp::bind(&path)
.map(|inner| UnixListener { inner: inner })
}
}
use prelude::v1::*;
-use c_str::{CString, ToCStr};
use collections::HashMap;
+use ffi::CString;
use fmt;
use hash::Hash;
use io::pipe::{PipeStream, PipePair};
use thread::Thread;
#[cfg(windows)] use std::hash::sip::SipState;
+#[cfg(windows)] use str;
/// Signal a process to exit, without forcibly killing it. Corresponds to
/// SIGTERM on unix platforms.
impl Hash for EnvKey {
fn hash(&self, state: &mut SipState) {
let &EnvKey(ref x) = self;
- match x.as_str() {
- Some(s) => for ch in s.chars() {
+ match str::from_utf8(x.as_bytes()) {
+ Ok(s) => for ch in s.chars() {
(ch as u8 as char).to_lowercase().hash(state);
},
- None => x.hash(state)
+ Err(..) => x.hash(state)
}
}
}
fn eq(&self, other: &EnvKey) -> bool {
let &EnvKey(ref x) = self;
let &EnvKey(ref y) = other;
- match (x.as_str(), y.as_str()) {
- (Some(xs), Some(ys)) => {
+ match (str::from_utf8(x.as_bytes()), str::from_utf8(y.as_bytes())) {
+ (Ok(xs), Ok(ys)) => {
if xs.len() != ys.len() {
return false
} else {
}
// FIXME (#12938): Until DST lands, we cannot decompose &str into & and str, so
-// we cannot usefully take ToCStr arguments by reference (without forcing an
+// we cannot usefully take BytesContainer arguments by reference (without forcing an
// additional & around &str). So we are instead temporarily adding an instance
-// for &Path, so that we can take ToCStr as owned. When DST lands, the &Path
-// instance should be removed, and arguments bound by ToCStr should be passed by
+// for &Path, so that we can take BytesContainer as owned. When DST lands, the &Path
+// instance should be removed, and arguments bound by BytesContainer should be passed by
// reference. (Here: {new, arg, args, env}.)
impl Command {
///
/// Builder methods are provided to change these defaults and
/// otherwise configure the process.
- pub fn new<T:ToCStr>(program: T) -> Command {
+ pub fn new<T: BytesContainer>(program: T) -> Command {
Command {
- program: program.to_c_str(),
+ program: CString::from_slice(program.container_as_bytes()),
args: Vec::new(),
env: None,
cwd: None,
}
/// Add an argument to pass to the program.
- pub fn arg<'a, T: ToCStr>(&'a mut self, arg: T) -> &'a mut Command {
- self.args.push(arg.to_c_str());
+ pub fn arg<'a, T: BytesContainer>(&'a mut self, arg: T) -> &'a mut Command {
+ self.args.push(CString::from_slice(arg.container_as_bytes()));
self
}
/// Add multiple arguments to pass to the program.
- pub fn args<'a, T: ToCStr>(&'a mut self, args: &[T]) -> &'a mut Command {
- self.args.extend(args.iter().map(|arg| arg.to_c_str()));;
+ pub fn args<'a, T: BytesContainer>(&'a mut self, args: &[T]) -> &'a mut Command {
+ self.args.extend(args.iter().map(|arg| {
+ CString::from_slice(arg.container_as_bytes())
+ }));
self
}
// Get a mutable borrow of the environment variable map for this `Command`.
- fn get_env_map<'a>(&'a mut self) -> &'a mut EnvMap {
+ fn get_env_map<'a>(&'a mut self) -> &'a mut EnvMap {
match self.env {
Some(ref mut map) => map,
None => {
// if the env is currently just inheriting from the parent's,
// materialize the parent's env into a hashtable.
- self.env = Some(os::env_as_bytes().into_iter()
- .map(|(k, v)| (EnvKey(k.to_c_str()),
- v.to_c_str()))
- .collect());
+ self.env = Some(os::env_as_bytes().into_iter().map(|(k, v)| {
+ (EnvKey(CString::from_slice(k.as_slice())),
+ CString::from_slice(v.as_slice()))
+ }).collect());
self.env.as_mut().unwrap()
}
}
///
/// Note that environment variable names are case-insensitive (but case-preserving) on Windows,
/// and case-sensitive on all other platforms.
- pub fn env<'a, T: ToCStr, U: ToCStr>(&'a mut self, key: T, val: U)
- -> &'a mut Command {
- self.get_env_map().insert(EnvKey(key.to_c_str()), val.to_c_str());
+ pub fn env<'a, T, U>(&'a mut self, key: T, val: U)
+ -> &'a mut Command
+ where T: BytesContainer, U: BytesContainer {
+ let key = EnvKey(CString::from_slice(key.container_as_bytes()));
+ let val = CString::from_slice(val.container_as_bytes());
+ self.get_env_map().insert(key, val);
self
}
/// Removes an environment variable mapping.
- pub fn env_remove<'a, T: ToCStr>(&'a mut self, key: T) -> &'a mut Command {
- self.get_env_map().remove(&EnvKey(key.to_c_str()));
+ pub fn env_remove<'a, T>(&'a mut self, key: T) -> &'a mut Command
+ where T: BytesContainer {
+ let key = EnvKey(CString::from_slice(key.container_as_bytes()));
+ self.get_env_map().remove(&key);
self
}
///
/// If the given slice contains multiple instances of an environment
/// variable, the *rightmost* instance will determine the value.
- pub fn env_set_all<'a, T: ToCStr, U: ToCStr>(&'a mut self, env: &[(T,U)])
- -> &'a mut Command {
- self.env = Some(env.iter().map(|&(ref k, ref v)| (EnvKey(k.to_c_str()), v.to_c_str()))
- .collect());
+ pub fn env_set_all<'a, T, U>(&'a mut self, env: &[(T,U)])
+ -> &'a mut Command
+ where T: BytesContainer, U: BytesContainer {
+ self.env = Some(env.iter().map(|&(ref k, ref v)| {
+ (EnvKey(CString::from_slice(k.container_as_bytes())),
+ CString::from_slice(v.container_as_bytes()))
+ }).collect());
self
}
/// Set the working directory for the child process.
pub fn cwd<'a>(&'a mut self, dir: &Path) -> &'a mut Command {
- self.cwd = Some(dir.to_c_str());
+ self.cwd = Some(CString::from_slice(dir.as_vec()));
self
}
/// non-utf8 data is lossily converted using the utf8 replacement
/// character.
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- try!(write!(f, "{}", String::from_utf8_lossy(self.program.as_bytes_no_nul())));
+ try!(write!(f, "{}", String::from_utf8_lossy(self.program.as_bytes())));
for arg in self.args.iter() {
- try!(write!(f, " '{}'", String::from_utf8_lossy(arg.as_bytes_no_nul())));
+ try!(write!(f, " '{}'", String::from_utf8_lossy(arg.as_bytes())));
}
Ok(())
}
#[test]
#[cfg(windows)]
fn env_map_keys_ci() {
- use c_str::ToCStr;
+ use ffi::CString;
use super::EnvKey;
let mut cmd = Command::new("");
cmd.env("path", "foo");
cmd.env("Path", "bar");
let env = &cmd.env.unwrap();
- let val = env.get(&EnvKey("PATH".to_c_str()));
- assert!(val.unwrap() == &"bar".to_c_str());
+ let val = env.get(&EnvKey(CString::from_slice(b"PATH")));
+ assert!(val.unwrap() == &CString::from_slice(b"bar"));
}
}
/* Runtime and platform support */
-pub mod thread_local;
-pub mod c_str;
-pub mod c_vec;
+pub mod thread_local; // first for macros
+
pub mod dynamic_lib;
+pub mod ffi;
pub mod fmt;
pub mod io;
pub mod os;
use sync::atomic::{AtomicInt, ATOMIC_INT_INIT, Ordering};
use vec::Vec;
-#[cfg(unix)] use c_str::ToCStr;
+#[cfg(unix)] use ffi::{self, CString};
-#[cfg(unix)]
-pub use sys::ext as unix;
-#[cfg(windows)]
-pub use sys::ext as windows;
+#[cfg(unix)] pub use sys::ext as unix;
+#[cfg(windows)] pub use sys::ext as windows;
/// Get the number of cores available
pub fn num_cpus() -> uint {
///
/// Panics if `n` has any interior NULs.
pub fn getenv_as_bytes(n: &str) -> Option<Vec<u8>> {
- use c_str::CString;
-
unsafe {
with_env_lock(|| {
- let s = n.with_c_str(|buf| libc::getenv(buf));
+ let s = CString::from_slice(n.as_bytes());
+ let s = libc::getenv(s.as_ptr()) as *const _;
if s.is_null() {
None
} else {
- Some(CString::new(s as *const libc::c_char, false).as_bytes_no_nul().to_vec())
+ Some(ffi::c_str_to_bytes(&s).to_vec())
}
})
}
fn _setenv(n: &str, v: &[u8]) {
unsafe {
with_env_lock(|| {
- n.with_c_str(|nbuf| {
- v.with_c_str(|vbuf| {
- if libc::funcs::posix01::unistd::setenv(nbuf, vbuf, 1) != 0 {
- panic!(IoError::last_error());
- }
- })
- })
+ let k = CString::from_slice(n.as_bytes());
+ let v = CString::from_slice(v);
+ if libc::funcs::posix01::unistd::setenv(k.as_ptr(),
+ v.as_ptr(), 1) != 0 {
+ panic!(IoError::last_error());
+ }
})
}
}
fn _unsetenv(n: &str) {
unsafe {
with_env_lock(|| {
- n.with_c_str(|nbuf| {
- if libc::funcs::posix01::unistd::unsetenv(nbuf) != 0 {
- panic!(IoError::last_error());
- }
- })
+ let nbuf = CString::from_slice(n.as_bytes());
+ if libc::funcs::posix01::unistd::unsetenv(nbuf.as_ptr()) != 0 {
+ panic!(IoError::last_error());
+ }
})
}
}
#[cfg(target_os = "macos")]
unsafe fn load_argc_and_argv(argc: int,
argv: *const *const c_char) -> Vec<Vec<u8>> {
- use c_str::CString;
use iter::range;
range(0, argc as uint).map(|i| {
- CString::new(*argv.offset(i as int), false).as_bytes_no_nul().to_vec()
+ ffi::c_str_to_bytes(&*argv.offset(i as int)).to_vec()
}).collect()
}
// res
#[cfg(target_os = "ios")]
fn real_args_as_bytes() -> Vec<Vec<u8>> {
- use c_str::CString;
use iter::range;
use mem;
#![experimental]
use core::kinds::Sized;
-use c_str::CString;
+use ffi::CString;
use clone::Clone;
use fmt;
use iter::IteratorExt;
impl BytesContainer for CString {
#[inline]
fn container_as_bytes<'a>(&'a self) -> &'a [u8] {
- self.as_bytes_no_nul()
+ self.as_bytes()
}
}
fn contains_nul<T: BytesContainer>(v: &T) -> bool {
v.container_as_bytes().iter().any(|&x| x == 0)
}
-
-#[cfg(test)]
-mod tests {
- use prelude::v1::*;
- use c_str::ToCStr;
- use path::{WindowsPath, PosixPath};
-
- #[test]
- fn test_cstring() {
- let input = "/foo/bar/baz";
- let path: PosixPath = PosixPath::new(input.to_c_str());
- assert_eq!(path.as_vec(), input.as_bytes());
-
- let input = r"\foo\bar\baz";
- let path: WindowsPath = WindowsPath::new(input.to_c_str());
- assert_eq!(path.as_str().unwrap(), input);
- }
-}
//! POSIX file path handling
-use c_str::{CString, ToCStr};
use clone::Clone;
-use cmp::{PartialEq, Eq, PartialOrd, Ord, Ordering};
+use cmp::{Ordering, Eq, Ord, PartialEq, PartialOrd};
use hash;
use io::Writer;
use iter::{AdditiveIterator, Extend};
use iter::{Iterator, IteratorExt, Map};
-use option::Option;
-use option::Option::{None, Some};
use kinds::Sized;
-use str::{FromStr, Str};
-use str;
-use slice::{Split, AsSlice, SliceConcatExt, SliceExt};
+use option::Option::{self, Some, None};
+use slice::{AsSlice, Split, SliceExt, SliceConcatExt};
+use str::{self, FromStr, StrExt};
use vec::Vec;
use super::{BytesContainer, GenericPath, GenericPathUnsafe};
}
}
-// FIXME (#12938): Until DST lands, we cannot decompose &str into & and str, so
-// we cannot usefully take ToCStr arguments by reference (without forcing an
-// additional & around &str). So we are instead temporarily adding an instance
-// for &Path, so that we can take ToCStr as owned. When DST lands, the &Path
-// instance should be removed, and arguments bound by ToCStr should be passed by
-// reference.
-
-impl ToCStr for Path {
- #[inline]
- fn to_c_str(&self) -> CString {
- // The Path impl guarantees no internal NUL
- unsafe { self.to_c_str_unchecked() }
- }
-
- #[inline]
- unsafe fn to_c_str_unchecked(&self) -> CString {
- self.as_vec().to_c_str_unchecked()
- }
-}
-
impl<S: hash::Writer> hash::Hash<S> for Path {
#[inline]
fn hash(&self, state: &mut S) {
use self::PathPrefix::*;
use ascii::AsciiExt;
-use c_str::{CString, ToCStr};
use char::CharExt;
use clone::Clone;
-use cmp::{PartialEq, Eq, PartialOrd, Ord, Ordering};
+use cmp::{Ordering, Eq, Ord, PartialEq, PartialOrd};
use hash;
use io::Writer;
use iter::{AdditiveIterator, Extend};
use iter::{Iterator, IteratorExt, Map, repeat};
use mem;
-use option::Option;
-use option::Option::{Some, None};
+use option::Option::{self, Some, None};
use slice::{SliceExt, SliceConcatExt};
use str::{SplitTerminator, FromStr, StrExt};
use string::{String, ToString};
}
}
-// FIXME (#12938): Until DST lands, we cannot decompose &str into & and str, so
-// we cannot usefully take ToCStr arguments by reference (without forcing an
-// additional & around &str). So we are instead temporarily adding an instance
-// for &Path, so that we can take ToCStr as owned. When DST lands, the &Path
-// instance should be removed, and arguments bound by ToCStr should be passed by
-// reference.
-
-impl ToCStr for Path {
- #[inline]
- fn to_c_str(&self) -> CString {
- // The Path impl guarantees no internal NUL
- unsafe { self.to_c_str_unchecked() }
- }
-
- #[inline]
- unsafe fn to_c_str_unchecked(&self) -> CString {
- self.as_vec().to_c_str_unchecked()
- }
-}
-
impl<S: hash::Writer> hash::Hash<S> for Path {
#[cfg(not(test))]
#[inline]
mod imp {
use prelude::v1::*;
+ use libc;
use mem;
- use slice;
+ use ffi;
use sync::{StaticMutex, MUTEX_INIT};
}
unsafe fn load_argc_and_argv(argc: int, argv: *const *const u8) -> Vec<Vec<u8>> {
+ let argv = argv as *const *const libc::c_char;
range(0, argc as uint).map(|i| {
- let arg = *argv.offset(i as int);
- let mut len = 0u;
- while *arg.offset(len as int) != 0 {
- len += 1u;
- }
- slice::from_raw_buf(&arg, len).to_vec()
+ ffi::c_str_to_bytes(&*argv.offset(i as int)).to_vec()
}).collect()
}
use prelude::v1::*;
use os;
-use sync::atomic::{mod, Ordering};
+use sync::atomic::{self, Ordering};
pub use sys::backtrace::write;
use intrinsics;
use libc::c_void;
use mem;
-use sync::atomic::{mod, Ordering};
+use sync::atomic::{self, Ordering};
use sync::{Once, ONCE_INIT};
use rt::libunwind as uw;
use os;
use slice;
use str;
-use sync::atomic::{mod, Ordering};
+use sync::atomic::{self, Ordering};
/// Dynamically inquire about whether we're running under V.
/// You should usually not use this unless your test definitely
use io::{self, IoError, IoResult};
use prelude::v1::*;
use sys::{last_error, retry};
-use c_str::CString;
+use ffi::CString;
use num::Int;
use path::BytesContainer;
use collections;
use self::SocketStatus::*;
use self::InAddr::*;
-use c_str::ToCStr;
+use ffi::CString;
+use ffi;
use io::net::addrinfo;
use io::net::ip::{SocketAddr, IpAddr, Ipv4Addr, Ipv6Addr};
use io::{IoResult, IoError};
use libc::{self, c_char, c_int};
-use c_str::CString;
use mem;
use num::Int;
use ptr::{self, null, null_mut};
+use str;
use sys::{self, retry, c, sock_t, last_error, last_net_error, last_gai_error, close_sock,
wrlen, msglen_t, os, wouldblock, set_nonblocking, timer, ms_to_timeval,
decode_error_detailed};
assert!(host.is_some() || servname.is_some());
- let c_host = host.map(|x| x.to_c_str());
+ let c_host = host.map(|x| CString::from_slice(x.as_bytes()));
let c_host = c_host.as_ref().map(|x| x.as_ptr()).unwrap_or(null());
- let c_serv = servname.map(|x| x.to_c_str());
+ let c_serv = servname.map(|x| CString::from_slice(x.as_bytes()));
let c_serv = c_serv.as_ref().map(|x| x.as_ptr()).unwrap_or(null());
let hint = hint.map(|hint| {
}
unsafe {
- Ok(CString::new(hostbuf.as_ptr(), false).as_str().unwrap().to_string())
+ Ok(str::from_utf8(ffi::c_str_to_bytes(&hostbuf.as_ptr()))
+ .unwrap().to_string())
}
}
/// to symbols. This is a bit of a hokey implementation as-is, but it works for
/// all unix platforms we support right now, so it at least gets the job done.
-use c_str::CString;
-use io::{IoResult, Writer};
+use prelude::v1::*;
+
+use ffi;
+use io::IoResult;
use libc;
use mem;
-use option::Option::{self, Some, None};
-use result::Result::{Ok, Err};
+use str;
use sync::{StaticMutex, MUTEX_INIT};
use sys_common::backtrace::*;
#[cfg(all(target_os = "ios", target_arch = "arm"))]
#[inline(never)]
pub fn write(w: &mut Writer) -> IoResult<()> {
- use iter::{IteratorExt, range};
use result;
- use slice::SliceExt;
extern {
fn backtrace(buf: *mut *mut libc::c_void,
output(w, idx,addr, None)
} else {
output(w, idx, addr, Some(unsafe {
- CString::new(info.dli_sname, false)
+ ffi::c_str_to_bytes(&info.dli_sname)
}))
}
}
#[cfg(not(any(target_os = "macos", target_os = "ios")))]
fn print(w: &mut Writer, idx: int, addr: *mut libc::c_void) -> IoResult<()> {
- use iter::{Iterator, IteratorExt};
use os;
- use path::GenericPath;
- use ptr::PtrExt;
use ptr;
- use slice::SliceExt;
////////////////////////////////////////////////////////////////////////
// libbacktrace.h API
if ret == 0 || data.is_null() {
output(w, idx, addr, None)
} else {
- output(w, idx, addr, Some(unsafe { CString::new(data, false) }))
+ output(w, idx, addr, Some(unsafe { ffi::c_str_to_bytes(&data) }))
}
}
// Finally, after all that work above, we can emit a symbol.
fn output(w: &mut Writer, idx: int, addr: *mut libc::c_void,
- s: Option<CString>) -> IoResult<()> {
+ s: Option<&[u8]>) -> IoResult<()> {
try!(write!(w, " {:2}: {:2$} - ", idx, addr, HEX_WIDTH));
- match s.as_ref().and_then(|c| c.as_str()) {
+ match s.and_then(|s| str::from_utf8(s).ok()) {
Some(string) => try!(demangle(w, string)),
None => try!(write!(w, "<unknown>")),
}
use prelude::v1::*;
-use c_str::{CString, ToCStr};
+use ffi::{self, CString};
use io::{FilePermission, Write, UnstableFileStat, Open, FileAccess, FileMode};
use io::{IoResult, FileStat, SeekStyle};
use io::{Read, Truncate, SeekCur, SeekSet, ReadWrite, SeekEnd, Append};
}
}
+fn cstr(path: &Path) -> CString {
+ CString::from_slice(path.as_vec())
+}
+
pub fn open(path: &Path, fm: FileMode, fa: FileAccess) -> IoResult<FileDesc> {
let flags = match fm {
Open => 0,
libc::S_IRUSR | libc::S_IWUSR),
};
- let path = path.to_c_str();
+ let path = cstr(path);
match retry(|| unsafe { libc::open(path.as_ptr(), flags, mode) }) {
-1 => Err(super::last_error()),
fd => Ok(FileDesc::new(fd, true)),
}
pub fn mkdir(p: &Path, mode: uint) -> IoResult<()> {
- let p = p.to_c_str();
+ let p = cstr(p);
mkerr_libc(unsafe { libc::mkdir(p.as_ptr(), mode as libc::mode_t) })
}
use libc::{opendir, readdir_r, closedir};
fn prune(root: &CString, dirs: Vec<Path>) -> Vec<Path> {
- let root = unsafe { CString::new(root.as_ptr(), false) };
let root = Path::new(root);
dirs.into_iter().filter(|path| {
let mut buf = Vec::<u8>::with_capacity(size as uint);
let ptr = buf.as_mut_ptr() as *mut dirent_t;
- let p = p.to_c_str();
+ let p = CString::from_slice(p.as_vec());
let dir_ptr = unsafe {opendir(p.as_ptr())};
if dir_ptr as uint != 0 {
let mut entry_ptr = 0 as *mut dirent_t;
while unsafe { readdir_r(dir_ptr, ptr, &mut entry_ptr) == 0 } {
if entry_ptr.is_null() { break }
- let cstr = unsafe {
- CString::new(rust_list_dir_val(entry_ptr), false)
- };
- paths.push(Path::new(cstr));
+ paths.push(unsafe {
+ Path::new(ffi::c_str_to_bytes(&rust_list_dir_val(entry_ptr)))
+ });
}
assert_eq!(unsafe { closedir(dir_ptr) }, 0);
Ok(prune(&p, paths))
}
pub fn unlink(p: &Path) -> IoResult<()> {
- let p = p.to_c_str();
+ let p = cstr(p);
mkerr_libc(unsafe { libc::unlink(p.as_ptr()) })
}
pub fn rename(old: &Path, new: &Path) -> IoResult<()> {
- let old = old.to_c_str();
- let new = new.to_c_str();
+ let old = cstr(old);
+ let new = cstr(new);
mkerr_libc(unsafe {
libc::rename(old.as_ptr(), new.as_ptr())
})
}
pub fn chmod(p: &Path, mode: uint) -> IoResult<()> {
- let p = p.to_c_str();
+ let p = cstr(p);
mkerr_libc(retry(|| unsafe {
libc::chmod(p.as_ptr(), mode as libc::mode_t)
}))
}
pub fn rmdir(p: &Path) -> IoResult<()> {
- let p = p.to_c_str();
+ let p = cstr(p);
mkerr_libc(unsafe { libc::rmdir(p.as_ptr()) })
}
pub fn chown(p: &Path, uid: int, gid: int) -> IoResult<()> {
- let p = p.to_c_str();
+ let p = cstr(p);
mkerr_libc(retry(|| unsafe {
libc::chown(p.as_ptr(), uid as libc::uid_t, gid as libc::gid_t)
}))
}
pub fn readlink(p: &Path) -> IoResult<Path> {
- let c_path = p.to_c_str();
+ let c_path = cstr(p);
let p = c_path.as_ptr();
let mut len = unsafe { libc::pathconf(p as *mut _, libc::_PC_NAME_MAX) };
if len == -1 {
}
pub fn symlink(src: &Path, dst: &Path) -> IoResult<()> {
- let src = src.to_c_str();
- let dst = dst.to_c_str();
+ let src = cstr(src);
+ let dst = cstr(dst);
mkerr_libc(unsafe { libc::symlink(src.as_ptr(), dst.as_ptr()) })
}
pub fn link(src: &Path, dst: &Path) -> IoResult<()> {
- let src = src.to_c_str();
- let dst = dst.to_c_str();
+ let src = cstr(src);
+ let dst = cstr(dst);
mkerr_libc(unsafe { libc::link(src.as_ptr(), dst.as_ptr()) })
}
}
pub fn stat(p: &Path) -> IoResult<FileStat> {
- let p = p.to_c_str();
+ let p = cstr(p);
let mut stat: libc::stat = unsafe { mem::zeroed() };
match unsafe { libc::stat(p.as_ptr(), &mut stat) } {
0 => Ok(mkstat(&stat)),
}
pub fn lstat(p: &Path) -> IoResult<FileStat> {
- let p = p.to_c_str();
+ let p = cstr(p);
let mut stat: libc::stat = unsafe { mem::zeroed() };
match unsafe { libc::lstat(p.as_ptr(), &mut stat) } {
0 => Ok(mkstat(&stat)),
}
pub fn utime(p: &Path, atime: u64, mtime: u64) -> IoResult<()> {
- let p = p.to_c_str();
+ let p = cstr(p);
let buf = libc::utimbuf {
actime: (atime / 1000) as libc::time_t,
modtime: (mtime / 1000) as libc::time_t,
#![allow(unused_unsafe)]
#![allow(unused_mut)]
-extern crate libc;
-
-use num;
-use num::{Int, SignedInt};
use prelude::v1::*;
+
+use ffi;
use io::{self, IoResult, IoError};
+use libc;
+use num::{Int, SignedInt};
+use num;
+use str;
use sys_common::mkerr_libc;
macro_rules! helper_init { (static $name:ident: Helper<$m:ty>) => (
}
pub fn last_gai_error(s: libc::c_int) -> IoError {
- use c_str::CString;
let mut err = decode_error(s);
err.detail = Some(unsafe {
- CString::new(gai_strerror(s), false).as_str().unwrap().to_string()
+ str::from_utf8(ffi::c_str_to_bytes(&gai_strerror(s))).unwrap().to_string()
});
err
}
use prelude::v1::*;
-use c_str::ToCStr;
use error::{FromError, Error};
+use ffi::{self, CString};
use fmt;
use io::{IoError, IoResult};
use libc::{self, c_int, c_char, c_void};
+use os::TMPBUF_SZ;
use os;
use path::{BytesContainer};
use ptr;
+use str;
use sys::fs::FileDesc;
-use os::TMPBUF_SZ;
-
const BUF_BYTES : uint = 2048u;
/// Returns the platform-specific value of errno
panic!("strerror_r failure");
}
- String::from_raw_buf(p as *const u8)
+ let p = p as *const _;
+ str::from_utf8(ffi::c_str_to_bytes(&p)).unwrap().to_string()
}
}
}
pub fn getcwd() -> IoResult<Path> {
- use c_str::CString;
-
let mut buf = [0 as c_char; BUF_BYTES];
unsafe {
if libc::getcwd(buf.as_mut_ptr(), buf.len() as libc::size_t).is_null() {
Err(IoError::last_error())
} else {
- Ok(Path::new(CString::new(buf.as_ptr(), false)))
+ Ok(Path::new(ffi::c_str_to_bytes(&buf.as_ptr())))
}
}
}
pub unsafe fn get_env_pairs() -> Vec<Vec<u8>> {
- use c_str::CString;
-
extern {
fn rust_env_pairs() -> *const *const c_char;
}
}
let mut result = Vec::new();
while *environ != 0 as *const _ {
- let env_pair =
- CString::new(*environ, false).as_bytes_no_nul().to_vec();
+ let env_pair = ffi::c_str_to_bytes(&*environ).to_vec();
result.push(env_pair);
environ = environ.offset(1);
}
}
pub fn chdir(p: &Path) -> IoResult<()> {
- p.with_c_str(|buf| {
- unsafe {
- match libc::chdir(buf) == (0 as c_int) {
- true => Ok(()),
- false => Err(IoError::last_error()),
- }
+ let p = CString::from_slice(p.as_vec());
+ unsafe {
+ match libc::chdir(p.as_ptr()) == (0 as c_int) {
+ true => Ok(()),
+ false => Err(IoError::last_error()),
}
- })
+ }
}
pub fn page_size() -> uint {
use prelude::v1::*;
+use ffi::CString;
use libc;
-use c_str::CString;
use mem;
use sync::{Arc, Mutex};
use sync::atomic::{AtomicBool, Ordering};
}
s.sun_family = libc::AF_UNIX as libc::sa_family_t;
for (slot, value) in s.sun_path.iter_mut().zip(addr.iter()) {
- *slot = value;
+ *slot = *value;
}
// count the null terminator
use prelude::v1::*;
use self::Req::*;
-use c_str::{CString, ToCStr};
use collections;
+use ffi::CString;
use hash::Hash;
use io::process::{ProcessExit, ExitStatus, ExitSignal};
use io::{self, IoResult, IoError, EndOfFile};
// We may use this in the child, so perform allocations before the
// fork
- let devnull = "/dev/null".to_c_str();
+ let devnull = b"/dev/null\0";
set_cloexec(output.fd());
} else {
libc::O_RDWR
};
- libc::open(devnull.as_ptr(), flags, 0)
+ libc::open(devnull.as_ptr() as *const _, flags, 0)
}
Some(obj) => {
let fd = obj.as_inner().fd();
use mem;
use os;
use ptr;
-use sync::atomic::{mod, Ordering};
+use sync::atomic::{self, Ordering};
use sync::mpsc::{channel, Sender, Receiver, TryRecvError};
use sys::c;
use sys::fs::FileDesc;
/// copy of that function in my mingw install (maybe it was broken?). Instead,
/// this takes the route of using StackWalk64 in order to walk the stack.
-use c_str::CString;
+use dynamic_lib::DynamicLibrary;
+use ffi;
use intrinsics;
use io::{IoResult, Writer};
use libc;
use option::Option::{Some, None};
use path::Path;
use result::Result::{Ok, Err};
-use sync::{StaticMutex, MUTEX_INIT};
use slice::SliceExt;
-use str::StrExt;
-use dynamic_lib::DynamicLibrary;
+use str::{self, StrExt};
+use sync::{StaticMutex, MUTEX_INIT};
use sys_common::backtrace::*;
if ret == libc::TRUE {
try!(write!(w, " - "));
- let cstr = unsafe { CString::new(info.Name.as_ptr(), false) };
- let bytes = cstr.as_bytes();
- match cstr.as_str() {
- Some(s) => try!(demangle(w, s)),
- None => try!(w.write(bytes[..bytes.len()-1])),
+ let ptr = info.Name.as_ptr() as *const libc::c_char;
+ let bytes = unsafe { ffi::c_str_to_bytes(&ptr) };
+ match str::from_utf8(bytes) {
+ Ok(s) => try!(demangle(w, s)),
+ Err(..) => try!(w.write(bytes[..bytes.len()-1])),
}
}
try!(w.write(&['\n' as u8]));
use intrinsics::{atomic_store_relaxed, transmute};
use libc::types::os::arch::extra::{LPCWSTR, HMODULE, LPCSTR, LPVOID};
use prelude::v1::*;
- use c_str::ToCStr;
+ use ffi::CString;
extern "system" {
fn GetModuleHandleW(lpModuleName: LPCWSTR) -> HMODULE;
unsafe fn store_func(ptr: *mut uint, module: &str, symbol: &str, fallback: uint) {
let mut module: Vec<u16> = module.utf16_units().collect();
module.push(0);
- symbol.with_c_str(|symbol| {
- let handle = GetModuleHandleW(module.as_ptr());
- let func: uint = transmute(GetProcAddress(handle, symbol));
- atomic_store_relaxed(ptr, if func == 0 {
- fallback
- } else {
- func
- })
+ let symbol = CString::from_slice(symbol.as_bytes());
+ let handle = GetModuleHandleW(module.as_ptr());
+ let func: uint = transmute(GetProcAddress(handle, symbol.as_ptr()));
+ atomic_store_relaxed(ptr, if func == 0 {
+ fallback
+ } else {
+ func
})
}
use alloc::arc::Arc;
use libc::{self, c_int};
-use c_str::CString;
use mem;
use sys::os::fill_utf16_buf_and_decode;
use path;
use prelude::v1::*;
use libc;
-use c_str::CString;
+use ffi::CString;
+use io::{self, IoError, IoResult};
use mem;
use ptr;
-use sync::{Arc, Mutex};
+use str;
use sync::atomic::{AtomicBool, Ordering};
-use io::{self, IoError, IoResult};
+use sync::{Arc, Mutex};
use sys_common::{self, eof};
-use super::{c, os, timer, to_utf16, decode_error_detailed};
+use super::{c, os, timer, decode_error_detailed};
+
+fn to_utf16(c: &CString) -> IoResult<Vec<u16>> {
+ super::to_utf16(str::from_utf8(c.as_bytes()).ok())
+}
struct Event(libc::HANDLE);
}
pub fn connect(addr: &CString, timeout: Option<u64>) -> IoResult<UnixStream> {
- let addr = try!(to_utf16(addr.as_str()));
+ let addr = try!(to_utf16(addr));
let start = timer::now();
loop {
match UnixStream::try_connect(addr.as_ptr()) {
// Although we technically don't need the pipe until much later, we
// create the initial handle up front to test the validity of the name
// and such.
- let addr_v = try!(to_utf16(addr.as_str()));
+ let addr_v = try!(to_utf16(addr));
let ret = unsafe { pipe(addr_v.as_ptr(), true) };
if ret == libc::INVALID_HANDLE_VALUE {
Err(super::last_error())
// proceed in accepting new clients in the future
if self.inner.closed.load(Ordering::SeqCst) { return Err(eof()) }
- let name = try!(to_utf16(self.listener.name.as_str()));
+ let name = try!(to_utf16(&self.listener.name));
// Once we've got a "server handle", we need to wait for a client to
// connect. The ConnectNamedPipe function will block this thread until
impl Clone for UnixAcceptor {
fn clone(&self) -> UnixAcceptor {
- let name = to_utf16(self.listener.name.as_str()).ok().unwrap();
+ let name = to_utf16(&self.listener.name).ok().unwrap();
UnixAcceptor {
inner: self.inner.clone(),
event: Event::new(true, false).ok().unwrap(),
use prelude::v1::*;
+use collections;
+use ffi::CString;
+use hash::Hash;
+use io::fs::PathExtensions;
+use io::process::{ProcessExit, ExitStatus, ExitSignal};
+use io::{IoResult, IoError};
+use io;
use libc::{pid_t, c_void, c_int};
use libc;
-use c_str::{CString, ToCStr};
-use io;
use mem;
use os;
-use ptr;
-use io::process::{ProcessExit, ExitStatus, ExitSignal};
-use collections;
use path::BytesContainer;
-use hash::Hash;
-use io::{IoResult, IoError};
-
+use ptr;
+use str;
+use sys::fs::FileDesc;
use sys::fs;
use sys::{self, retry, c, wouldblock, set_nonblocking, ms_to_timeval, timer};
-use sys::fs::FileDesc;
use sys_common::helper_thread::Helper;
use sys_common::{AsInner, mkerr_libc, timeout};
-use io::fs::PathExtensions;
-
pub use sys_common::ProcessConfig;
/// A value representing a child process.
// Split the value and test each path to see if the
// program exists.
for path in os::split_paths(v.container_as_bytes()).into_iter() {
- let path = path.join(cfg.program().as_bytes_no_nul())
+ let path = path.join(cfg.program().as_bytes())
.with_extension(os::consts::EXE_EXTENSION);
if path.exists() {
- return Some(path.to_c_str())
+ return Some(CString::from_slice(path.as_vec()))
}
}
break
fn make_command_line(prog: &CString, args: &[CString]) -> String {
let mut cmd = String::new();
- append_arg(&mut cmd, prog.as_str()
+ append_arg(&mut cmd, str::from_utf8(prog.as_bytes()).ok()
.expect("expected program name to be utf-8 encoded"));
for arg in args.iter() {
cmd.push(' ');
- append_arg(&mut cmd, arg.as_str()
+ append_arg(&mut cmd, str::from_utf8(arg.as_bytes()).ok()
.expect("expected argument to be utf-8 encoded"));
}
return cmd;
{
match d {
Some(dir) => {
- let dir_str = dir.as_str()
+ let dir_str = str::from_utf8(dir.as_bytes()).ok()
.expect("expected workingdirectory to be utf-8 encoded");
let mut dir_str: Vec<u16> = dir_str.utf16_units().collect();
dir_str.push(0);
fn baz() { }
pub fn test() {
- let none: Option<Path> = None; // appease the typechecker
+ let none: Option<&Path> = None; // appease the typechecker
let lib = DynamicLibrary::open(none).unwrap();
unsafe {
assert!(lib.symbol::<int>("foo").is_ok());
extern crate libc;
-use std::c_str::ToCStr;
+use std::ffi::CString;
mod mlibc {
use libc::{c_char, c_long, c_longlong};
}
fn atol(s: String) -> int {
- s.as_slice().with_c_str(|x| unsafe { mlibc::atol(x) as int })
+ let c = CString::from_slice(s.as_bytes());
+ unsafe { mlibc::atol(c.as_ptr()) as int }
}
fn atoll(s: String) -> i64 {
- s.as_slice().with_c_str(|x| unsafe { mlibc::atoll(x) as i64 })
+ let c = CString::from_slice(s.as_bytes());
+ unsafe { mlibc::atoll(c.as_ptr()) as i64 }
}
pub fn main() {
// except according to those terms.
use std::{str, string};
-use std::c_str::ToCStr;
const A: [u8; 2] = ['h' as u8, 'i' as u8];
const B: &'static [u8; 2] = &A;
assert_eq!(String::from_raw_buf_len(C, B.len()), "hi".to_string());
assert!(*C == A[0]);
assert!(*(&B[0] as *const u8) == A[0]);
-
- let bar = str::from_utf8_unchecked(&A).to_c_str();
- assert_eq!(bar.as_str(), "hi".to_c_str().as_str());
}
}
// ignore-fast doesn't like extern crate
extern crate libc;
-use std::c_str::ToCStr;
+use std::ffi::CString;
mod mlibc {
use libc::{c_char, size_t};
fn strlen(str: String) -> uint {
// C string is terminated with a zero
- str.as_slice().with_c_str(|buf| {
- unsafe {
- mlibc::my_strlen(buf) as uint
- }
- })
+ let s = CString::from_slice(str.as_bytes());
+ unsafe {
+ mlibc::my_strlen(s.as_ptr()) as uint
+ }
}
pub fn main() {
extern crate libc;
+use std::ffi::CString;
use std::io::TempDir;
-use std::c_str::ToCStr;
use std::io::fs::PathExtensions;
use std::io::fs;
use std::io;
let test_file = &old_path.join("temp.txt");
/* Write the temp input file */
- let ostream = test_file.with_c_str(|fromp| {
- "w+b".with_c_str(|modebuf| {
- libc::fopen(fromp, modebuf)
- })
- });
+ let fromp = CString::from_slice(test_file.as_vec());
+ let modebuf = CString::from_slice(b"w+b");
+ let ostream = libc::fopen(fromp.as_ptr(), modebuf.as_ptr());
assert!((ostream as uint != 0u));
let s = "hello".to_string();
- "hello".with_c_str(|buf| {
- let write_len = libc::fwrite(buf as *const libc::c_void,
- 1u as libc::size_t,
- (s.len() + 1u) as libc::size_t,
- ostream);
- assert_eq!(write_len, (s.len() + 1) as libc::size_t)
- });
+ let buf = CString::from_slice(b"hello");
+ let write_len = libc::fwrite(buf.as_ptr() as *mut _,
+ 1u as libc::size_t,
+ (s.len() + 1u) as libc::size_t,
+ ostream);
+ assert_eq!(write_len, (s.len() + 1) as libc::size_t);
assert_eq!(libc::fclose(ostream), (0u as libc::c_int));
let new_path = tmpdir.join_many(&["quux", "blat"]);
extern crate libc;
-use std::c_str::{CString, ToCStr};
+use std::ffi::{self, CString};
use libc::{c_char, c_int};
// ignore-fast doesn't like extern crate
unsafe fn check<T>(expected: &str, f: |*mut c_char| -> T) {
let mut x = [0 as c_char; 50];
f(&mut x[0] as *mut c_char);
- let res = CString::new(&x[0], false);
- assert_eq!(expected, res.as_str().unwrap());
+ assert_eq!(expected.as_bytes(), ffi::c_str_to_bytes(&x.as_ptr()));
}
pub fn main() {
unsafe {
// Call with just the named parameter
- "Hello World\n".with_c_str(|c| {
- check("Hello World\n", |s| sprintf(s, c));
- });
+ let c = CString::from_slice(b"Hello World\n");
+ check("Hello World\n", |s| sprintf(s, c.as_ptr()));
// Call with variable number of arguments
- "%d %f %c %s\n".with_c_str(|c| {
- check("42 42.500000 a %d %f %c %s\n\n", |s| {
- sprintf(s, c, 42i, 42.5f64, 'a' as c_int, c);
- })
+ let c = CString::from_slice(b"%d %f %c %s\n");
+ check("42 42.500000 a %d %f %c %s\n\n", |s| {
+ sprintf(s, c.as_ptr(), 42i, 42.5f64, 'a' as c_int, c.as_ptr());
});
// Make a function pointer
- let x: unsafe extern "C" fn(*mut c_char, *const c_char, ...) -> c_int = sprintf;
+ let x: unsafe extern fn(*mut c_char, *const c_char, ...) -> c_int = sprintf;
// A function that takes a function pointer
- unsafe fn call(p: unsafe extern "C" fn(*mut c_char, *const c_char, ...) -> c_int) {
- // Call with just the named parameter via fn pointer
- "Hello World\n".with_c_str(|c| {
- check("Hello World\n", |s| p(s, c));
- });
+ unsafe fn call(p: unsafe extern fn(*mut c_char, *const c_char, ...) -> c_int) {
+ // Call with just the named parameter
+ let c = CString::from_slice(b"Hello World\n");
+ check("Hello World\n", |s| sprintf(s, c.as_ptr()));
// Call with variable number of arguments
- "%d %f %c %s\n".with_c_str(|c| {
- check("42 42.500000 a %d %f %c %s\n\n", |s| {
- p(s, c, 42i, 42.5f64, 'a' as c_int, c);
- })
+ let c = CString::from_slice(b"%d %f %c %s\n");
+ check("42 42.500000 a %d %f %c %s\n\n", |s| {
+ sprintf(s, c.as_ptr(), 42i, 42.5f64, 'a' as c_int, c.as_ptr());
});
}