auto merge of #8296 : erickt/rust/remove-str-trailing-nulls, r=erickt
This PR fixes #7235 and #3371, which removes trailing nulls from `str` types. Instead, it replaces the creation of c strings with a new type, `std::c_str::CString`, which wraps a malloced byte array, and respects: * No interior nulls * Ends with a trailing null
This commit is contained in:
commit
60f5011005
@ -11,7 +11,7 @@
|
||||
// FIXME #3921. This is unsafe because linenoise uses global mutable
|
||||
// state without mutexes.
|
||||
|
||||
|
||||
use std::c_str::ToCStr;
|
||||
use std::libc::{c_char, c_int};
|
||||
use std::local_data;
|
||||
use std::str;
|
||||
@ -32,7 +32,7 @@ pub mod rustrt {
|
||||
|
||||
/// Add a line to history
|
||||
pub unsafe fn add_history(line: &str) -> bool {
|
||||
do line.as_c_str |buf| {
|
||||
do line.to_c_str().with_ref |buf| {
|
||||
rustrt::linenoiseHistoryAdd(buf) == 1 as c_int
|
||||
}
|
||||
}
|
||||
@ -44,21 +44,21 @@ pub unsafe fn set_history_max_len(len: int) -> bool {
|
||||
|
||||
/// Save line history to a file
|
||||
pub unsafe fn save_history(file: &str) -> bool {
|
||||
do file.as_c_str |buf| {
|
||||
do file.to_c_str().with_ref |buf| {
|
||||
rustrt::linenoiseHistorySave(buf) == 1 as c_int
|
||||
}
|
||||
}
|
||||
|
||||
/// Load line history from a file
|
||||
pub unsafe fn load_history(file: &str) -> bool {
|
||||
do file.as_c_str |buf| {
|
||||
do file.to_c_str().with_ref |buf| {
|
||||
rustrt::linenoiseHistoryLoad(buf) == 1 as c_int
|
||||
}
|
||||
}
|
||||
|
||||
/// Print out a prompt and then wait for input and return it
|
||||
pub unsafe fn read(prompt: &str) -> Option<~str> {
|
||||
do prompt.as_c_str |buf| {
|
||||
do prompt.to_c_str().with_ref |buf| {
|
||||
let line = rustrt::linenoise(buf);
|
||||
|
||||
if line.is_null() { None }
|
||||
@ -80,7 +80,7 @@ pub unsafe fn complete(cb: CompletionCb) {
|
||||
|
||||
unsafe {
|
||||
do cb(str::raw::from_c_str(line)) |suggestion| {
|
||||
do suggestion.as_c_str |buf| {
|
||||
do suggestion.to_c_str().with_ref |buf| {
|
||||
rustrt::linenoiseAddCompletion(completions, buf);
|
||||
}
|
||||
}
|
||||
|
@ -476,6 +476,7 @@ impl FormatOp {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(stage0)]
|
||||
fn format(val: Param, op: FormatOp, flags: Flags) -> Result<~[u8],~str> {
|
||||
let mut s = match val {
|
||||
Number(d) => {
|
||||
@ -545,8 +546,103 @@ fn format(val: Param, op: FormatOp, flags: Flags) -> Result<~[u8],~str> {
|
||||
String(s) => {
|
||||
match op {
|
||||
FormatString => {
|
||||
let mut s = s.to_bytes_with_null();
|
||||
s.pop(); // remove the null
|
||||
let mut s = s.as_bytes().to_owned();
|
||||
if flags.precision > 0 && flags.precision < s.len() {
|
||||
s.truncate(flags.precision);
|
||||
}
|
||||
s
|
||||
}
|
||||
_ => {
|
||||
return Err(fmt!("non-string on stack with %%%c", op.to_char()))
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
if flags.width > s.len() {
|
||||
let n = flags.width - s.len();
|
||||
if flags.left {
|
||||
s.grow(n, &(' ' as u8));
|
||||
} else {
|
||||
let mut s_ = vec::with_capacity(flags.width);
|
||||
s_.grow(n, &(' ' as u8));
|
||||
s_.push_all_move(s);
|
||||
s = s_;
|
||||
}
|
||||
}
|
||||
Ok(s)
|
||||
}
|
||||
|
||||
#[cfg(not(stage0))]
|
||||
fn format(val: Param, op: FormatOp, flags: Flags) -> Result<~[u8],~str> {
|
||||
let mut s = match val {
|
||||
Number(d) => {
|
||||
match op {
|
||||
FormatString => {
|
||||
return Err(~"non-number on stack with %s")
|
||||
}
|
||||
_ => {
|
||||
let radix = match op {
|
||||
FormatDigit => 10,
|
||||
FormatOctal => 8,
|
||||
FormatHex|FormatHEX => 16,
|
||||
FormatString => util::unreachable()
|
||||
};
|
||||
let mut s = ~[];
|
||||
match op {
|
||||
FormatDigit => {
|
||||
let sign = if flags.sign { SignAll } else { SignNeg };
|
||||
do int_to_str_bytes_common(d, radix, sign) |c| {
|
||||
s.push(c);
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
do int_to_str_bytes_common(d as uint, radix, SignNone) |c| {
|
||||
s.push(c);
|
||||
}
|
||||
}
|
||||
};
|
||||
if flags.precision > s.len() {
|
||||
let mut s_ = vec::with_capacity(flags.precision);
|
||||
let n = flags.precision - s.len();
|
||||
s_.grow(n, &('0' as u8));
|
||||
s_.push_all_move(s);
|
||||
s = s_;
|
||||
}
|
||||
assert!(!s.is_empty(), "string conversion produced empty result");
|
||||
match op {
|
||||
FormatDigit => {
|
||||
if flags.space && !(s[0] == '-' as u8 || s[0] == '+' as u8) {
|
||||
s.unshift(' ' as u8);
|
||||
}
|
||||
}
|
||||
FormatOctal => {
|
||||
if flags.alternate && s[0] != '0' as u8 {
|
||||
s.unshift('0' as u8);
|
||||
}
|
||||
}
|
||||
FormatHex => {
|
||||
if flags.alternate {
|
||||
let s_ = util::replace(&mut s, ~['0' as u8, 'x' as u8]);
|
||||
s.push_all_move(s_);
|
||||
}
|
||||
}
|
||||
FormatHEX => {
|
||||
s = s.into_ascii().to_upper().into_bytes();
|
||||
if flags.alternate {
|
||||
let s_ = util::replace(&mut s, ~['0' as u8, 'X' as u8]);
|
||||
s.push_all_move(s_);
|
||||
}
|
||||
}
|
||||
FormatString => util::unreachable()
|
||||
}
|
||||
s
|
||||
}
|
||||
}
|
||||
}
|
||||
String(s) => {
|
||||
match op {
|
||||
FormatString => {
|
||||
let mut s = s.as_bytes().to_owned();
|
||||
if flags.precision > 0 && flags.precision < s.len() {
|
||||
s.truncate(flags.precision);
|
||||
}
|
||||
|
@ -284,10 +284,14 @@ fn do_strptime(s: &str, format: &str) -> Result<Tm, ~str> {
|
||||
fn match_digits(ss: &str, pos: uint, digits: uint, ws: bool)
|
||||
-> Option<(i32, uint)> {
|
||||
let mut pos = pos;
|
||||
let len = ss.len();
|
||||
let mut value = 0_i32;
|
||||
|
||||
let mut i = 0u;
|
||||
while i < digits {
|
||||
if pos >= len {
|
||||
return None;
|
||||
}
|
||||
let range = ss.char_range_at(pos);
|
||||
pos = range.next;
|
||||
|
||||
@ -853,7 +857,7 @@ fn do_strftime(format: &str, tm: &Tm) -> ~str {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use time::*;
|
||||
use super::*;
|
||||
|
||||
use std::float;
|
||||
use std::os;
|
||||
@ -901,7 +905,7 @@ mod tests {
|
||||
os::setenv("TZ", "America/Los_Angeles");
|
||||
tzset();
|
||||
|
||||
let time = ::time::Timespec::new(1234567890, 54321);
|
||||
let time = Timespec::new(1234567890, 54321);
|
||||
let utc = at_utc(time);
|
||||
|
||||
assert!(utc.tm_sec == 30_i32);
|
||||
@ -922,7 +926,7 @@ mod tests {
|
||||
os::setenv("TZ", "America/Los_Angeles");
|
||||
tzset();
|
||||
|
||||
let time = ::time::Timespec::new(1234567890, 54321);
|
||||
let time = Timespec::new(1234567890, 54321);
|
||||
let local = at(time);
|
||||
|
||||
error!("time_at: %?", local);
|
||||
@ -950,7 +954,7 @@ mod tests {
|
||||
os::setenv("TZ", "America/Los_Angeles");
|
||||
tzset();
|
||||
|
||||
let time = ::time::Timespec::new(1234567890, 54321);
|
||||
let time = Timespec::new(1234567890, 54321);
|
||||
let utc = at_utc(time);
|
||||
|
||||
assert_eq!(utc.to_timespec(), time);
|
||||
@ -961,7 +965,7 @@ mod tests {
|
||||
os::setenv("TZ", "America/Los_Angeles");
|
||||
tzset();
|
||||
|
||||
let time = ::time::Timespec::new(1234567890, 54321);
|
||||
let time = Timespec::new(1234567890, 54321);
|
||||
let utc = at_utc(time);
|
||||
let local = at(time);
|
||||
|
||||
@ -1142,7 +1146,7 @@ mod tests {
|
||||
os::setenv("TZ", "America/Los_Angeles");
|
||||
tzset();
|
||||
|
||||
let time = ::time::Timespec::new(1234567890, 54321);
|
||||
let time = Timespec::new(1234567890, 54321);
|
||||
let utc = at_utc(time);
|
||||
let local = at(time);
|
||||
|
||||
@ -1156,7 +1160,7 @@ mod tests {
|
||||
os::setenv("TZ", "America/Los_Angeles");
|
||||
tzset();
|
||||
|
||||
let time = ::time::Timespec::new(1234567890, 54321);
|
||||
let time = Timespec::new(1234567890, 54321);
|
||||
let utc = at_utc(time);
|
||||
let local = at(time);
|
||||
|
||||
|
@ -22,6 +22,7 @@ use middle::trans::common::gensym_name;
|
||||
use middle::ty;
|
||||
use util::ppaux;
|
||||
|
||||
use std::c_str::ToCStr;
|
||||
use std::char;
|
||||
use std::hash::Streaming;
|
||||
use std::hash;
|
||||
@ -76,9 +77,9 @@ pub fn WriteOutputFile(sess: Session,
|
||||
OptLevel: c_int,
|
||||
EnableSegmentedStacks: bool) {
|
||||
unsafe {
|
||||
do Triple.as_c_str |Triple| {
|
||||
do Feature.as_c_str |Feature| {
|
||||
do Output.as_c_str |Output| {
|
||||
do Triple.to_c_str().with_ref |Triple| {
|
||||
do Feature.to_c_str().with_ref |Feature| {
|
||||
do Output.to_c_str().with_ref |Output| {
|
||||
let result = llvm::LLVMRustWriteOutputFile(
|
||||
PM,
|
||||
M,
|
||||
@ -105,6 +106,7 @@ pub mod jit {
|
||||
use lib::llvm::{ModuleRef, ContextRef, ExecutionEngineRef};
|
||||
use metadata::cstore;
|
||||
|
||||
use std::c_str::ToCStr;
|
||||
use std::cast;
|
||||
use std::local_data;
|
||||
use std::unstable::intrinsics;
|
||||
@ -146,7 +148,7 @@ pub mod jit {
|
||||
|
||||
debug!("linking: %s", path);
|
||||
|
||||
do path.as_c_str |buf_t| {
|
||||
do path.to_c_str().with_ref |buf_t| {
|
||||
if !llvm::LLVMRustLoadCrate(manager, buf_t) {
|
||||
llvm_err(sess, ~"Could not link");
|
||||
}
|
||||
@ -165,7 +167,7 @@ pub mod jit {
|
||||
// Next, we need to get a handle on the _rust_main function by
|
||||
// looking up it's corresponding ValueRef and then requesting that
|
||||
// the execution engine compiles the function.
|
||||
let fun = do "_rust_main".as_c_str |entry| {
|
||||
let fun = do "_rust_main".to_c_str().with_ref |entry| {
|
||||
llvm::LLVMGetNamedFunction(m, entry)
|
||||
};
|
||||
if fun.is_null() {
|
||||
@ -230,6 +232,7 @@ pub mod write {
|
||||
|
||||
use back::passes;
|
||||
|
||||
use std::c_str::ToCStr;
|
||||
use std::libc::{c_int, c_uint};
|
||||
use std::path::Path;
|
||||
use std::run;
|
||||
@ -263,14 +266,14 @@ pub mod write {
|
||||
output_type_bitcode => {
|
||||
if opts.optimize != session::No {
|
||||
let filename = output.with_filetype("no-opt.bc");
|
||||
do filename.to_str().as_c_str |buf| {
|
||||
do filename.to_c_str().with_ref |buf| {
|
||||
llvm::LLVMWriteBitcodeToFile(llmod, buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
let filename = output.with_filetype("bc");
|
||||
do filename.to_str().as_c_str |buf| {
|
||||
do filename.to_c_str().with_ref |buf| {
|
||||
llvm::LLVMWriteBitcodeToFile(llmod, buf);
|
||||
}
|
||||
}
|
||||
@ -333,7 +336,7 @@ pub mod write {
|
||||
// Always output the bitcode file with --save-temps
|
||||
|
||||
let filename = output.with_filetype("opt.bc");
|
||||
do filename.to_str().as_c_str |buf| {
|
||||
do filename.to_c_str().with_ref |buf| {
|
||||
llvm::LLVMWriteBitcodeToFile(llmod, buf)
|
||||
};
|
||||
// Save the assembly file if -S is used
|
||||
@ -391,13 +394,13 @@ pub mod write {
|
||||
|
||||
if output_type == output_type_llvm_assembly {
|
||||
// Given options "-S --emit-llvm": output LLVM assembly
|
||||
do output.to_str().as_c_str |buf_o| {
|
||||
do output.to_c_str().with_ref |buf_o| {
|
||||
llvm::LLVMRustAddPrintModulePass(pm.llpm, llmod, buf_o);
|
||||
}
|
||||
} else {
|
||||
// If only a bitcode file is asked for by using the
|
||||
// '--emit-llvm' flag, then output it here
|
||||
do output.to_str().as_c_str |buf| {
|
||||
do output.to_c_str().with_ref |buf| {
|
||||
llvm::LLVMWriteBitcodeToFile(llmod, buf);
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,7 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use std::c_str::ToCStr;
|
||||
use std::io;
|
||||
|
||||
use driver::session::{OptLevel, No, Less, Aggressive};
|
||||
@ -172,7 +173,7 @@ pub fn populate_pass_manager(sess: Session, pm: &mut PassManager, pass_list:&[~s
|
||||
}
|
||||
|
||||
pub fn create_pass(name:&str) -> Option<PassRef> {
|
||||
do name.as_c_str |s| {
|
||||
do name.to_c_str().with_ref |s| {
|
||||
unsafe {
|
||||
let p = llvm::LLVMCreatePass(s);
|
||||
if p.is_null() {
|
||||
|
@ -8,7 +8,7 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
|
||||
use std::c_str::ToCStr;
|
||||
use std::hashmap::HashMap;
|
||||
use std::libc::{c_uint, c_ushort};
|
||||
use std::option;
|
||||
@ -2259,7 +2259,7 @@ pub struct TargetData {
|
||||
}
|
||||
|
||||
pub fn mk_target_data(string_rep: &str) -> TargetData {
|
||||
let lltd = do string_rep.as_c_str |buf| {
|
||||
let lltd = do string_rep.to_c_str().with_ref |buf| {
|
||||
unsafe { llvm::LLVMCreateTargetData(buf) }
|
||||
};
|
||||
|
||||
|
@ -23,6 +23,7 @@ use syntax::print::pprust;
|
||||
use syntax::{ast, attr};
|
||||
use syntax::attr::AttrMetaMethods;
|
||||
|
||||
use std::c_str::ToCStr;
|
||||
use std::cast;
|
||||
use std::io;
|
||||
use std::num;
|
||||
@ -198,7 +199,7 @@ pub fn metadata_matches(extern_metas: &[@ast::MetaItem],
|
||||
fn get_metadata_section(os: os,
|
||||
filename: &Path) -> Option<@~[u8]> {
|
||||
unsafe {
|
||||
let mb = do filename.to_str().as_c_str |buf| {
|
||||
let mb = do filename.to_c_str().with_ref |buf| {
|
||||
llvm::LLVMRustCreateMemoryBufferWithContentsOfFile(buf)
|
||||
};
|
||||
if mb as int == 0 { return option::None::<@~[u8]>; }
|
||||
|
@ -12,6 +12,7 @@
|
||||
# Translation of inline assembly.
|
||||
*/
|
||||
|
||||
use std::c_str::ToCStr;
|
||||
|
||||
use lib;
|
||||
use middle::trans::build::*;
|
||||
@ -119,8 +120,8 @@ pub fn trans_inline_asm(bcx: @mut Block, ia: &ast::inline_asm) -> @mut Block {
|
||||
ast::asm_intel => lib::llvm::AD_Intel
|
||||
};
|
||||
|
||||
let r = do ia.asm.as_c_str |a| {
|
||||
do constraints.as_c_str |c| {
|
||||
let r = do ia.asm.to_c_str().with_ref |a| {
|
||||
do constraints.to_c_str().with_ref |c| {
|
||||
InlineAsmCall(bcx, a, c, inputs, output, ia.volatile, ia.alignstack, dialect)
|
||||
}
|
||||
};
|
||||
|
@ -65,6 +65,7 @@ use util::ppaux::{Repr, ty_to_str};
|
||||
|
||||
use middle::trans::type_::Type;
|
||||
|
||||
use std::c_str::ToCStr;
|
||||
use std::hash;
|
||||
use std::hashmap::HashMap;
|
||||
use std::io;
|
||||
@ -179,7 +180,7 @@ impl<'self> Drop for StatRecorder<'self> {
|
||||
}
|
||||
|
||||
pub fn decl_fn(llmod: ModuleRef, name: &str, cc: lib::llvm::CallConv, ty: Type) -> ValueRef {
|
||||
let llfn: ValueRef = do name.as_c_str |buf| {
|
||||
let llfn: ValueRef = do name.to_c_str().with_ref |buf| {
|
||||
unsafe {
|
||||
llvm::LLVMGetOrInsertFunction(llmod, buf, ty.to_ref())
|
||||
}
|
||||
@ -219,7 +220,7 @@ pub fn get_extern_const(externs: &mut ExternMap, llmod: ModuleRef,
|
||||
None => ()
|
||||
}
|
||||
unsafe {
|
||||
let c = do name.as_c_str |buf| {
|
||||
let c = do name.to_c_str().with_ref |buf| {
|
||||
llvm::LLVMAddGlobal(llmod, ty.to_ref(), buf)
|
||||
};
|
||||
externs.insert(name, c);
|
||||
@ -521,7 +522,7 @@ pub fn get_res_dtor(ccx: @mut CrateContext,
|
||||
// Structural comparison: a rather involved form of glue.
|
||||
pub fn maybe_name_value(cx: &CrateContext, v: ValueRef, s: &str) {
|
||||
if cx.sess.opts.save_temps {
|
||||
do s.as_c_str |buf| {
|
||||
do s.to_c_str().with_ref |buf| {
|
||||
unsafe {
|
||||
llvm::LLVMSetValueName(v, buf)
|
||||
}
|
||||
@ -1135,7 +1136,7 @@ pub fn new_block(cx: @mut FunctionContext,
|
||||
opt_node_info: Option<NodeInfo>)
|
||||
-> @mut Block {
|
||||
unsafe {
|
||||
let llbb = do name.as_c_str |buf| {
|
||||
let llbb = do name.to_c_str().with_ref |buf| {
|
||||
llvm::LLVMAppendBasicBlockInContext(cx.ccx.llcx, cx.llfn, buf)
|
||||
};
|
||||
let bcx = @mut Block::new(llbb,
|
||||
@ -1552,7 +1553,7 @@ pub struct BasicBlocks {
|
||||
pub fn mk_staticallocas_basic_block(llfn: ValueRef) -> BasicBlockRef {
|
||||
unsafe {
|
||||
let cx = task_llcx();
|
||||
do "static_allocas".as_c_str | buf| {
|
||||
do "static_allocas".to_c_str().with_ref | buf| {
|
||||
llvm::LLVMAppendBasicBlockInContext(cx, llfn, buf)
|
||||
}
|
||||
}
|
||||
@ -1561,7 +1562,7 @@ pub fn mk_staticallocas_basic_block(llfn: ValueRef) -> BasicBlockRef {
|
||||
pub fn mk_return_basic_block(llfn: ValueRef) -> BasicBlockRef {
|
||||
unsafe {
|
||||
let cx = task_llcx();
|
||||
do "return".as_c_str |buf| {
|
||||
do "return".to_c_str().with_ref |buf| {
|
||||
llvm::LLVMAppendBasicBlockInContext(cx, llfn, buf)
|
||||
}
|
||||
}
|
||||
@ -2312,7 +2313,7 @@ pub fn create_entry_wrapper(ccx: @mut CrateContext,
|
||||
};
|
||||
decl_cdecl_fn(ccx.llmod, main_name, llfty)
|
||||
};
|
||||
let llbb = do "top".as_c_str |buf| {
|
||||
let llbb = do "top".to_c_str().with_ref |buf| {
|
||||
unsafe {
|
||||
llvm::LLVMAppendBasicBlockInContext(ccx.llcx, llfn, buf)
|
||||
}
|
||||
@ -2322,7 +2323,7 @@ pub fn create_entry_wrapper(ccx: @mut CrateContext,
|
||||
llvm::LLVMPositionBuilderAtEnd(bld, llbb);
|
||||
|
||||
let crate_map = ccx.crate_map;
|
||||
let opaque_crate_map = do "crate_map".as_c_str |buf| {
|
||||
let opaque_crate_map = do "crate_map".to_c_str().with_ref |buf| {
|
||||
llvm::LLVMBuildPointerCast(bld, crate_map, Type::i8p().to_ref(), buf)
|
||||
};
|
||||
|
||||
@ -2340,7 +2341,7 @@ pub fn create_entry_wrapper(ccx: @mut CrateContext,
|
||||
};
|
||||
|
||||
let args = {
|
||||
let opaque_rust_main = do "rust_main".as_c_str |buf| {
|
||||
let opaque_rust_main = do "rust_main".to_c_str().with_ref |buf| {
|
||||
llvm::LLVMBuildPointerCast(bld, rust_main, Type::i8p().to_ref(), buf)
|
||||
};
|
||||
|
||||
@ -2365,11 +2366,10 @@ pub fn create_entry_wrapper(ccx: @mut CrateContext,
|
||||
(rust_main, args)
|
||||
};
|
||||
|
||||
let result = llvm::LLVMBuildCall(bld,
|
||||
start_fn,
|
||||
&args[0],
|
||||
args.len() as c_uint,
|
||||
noname());
|
||||
let result = do args.as_imm_buf |buf, len| {
|
||||
llvm::LLVMBuildCall(bld, start_fn, buf, len as c_uint, noname())
|
||||
};
|
||||
|
||||
llvm::LLVMBuildRet(bld, result);
|
||||
}
|
||||
}
|
||||
@ -2428,7 +2428,7 @@ pub fn get_item_val(ccx: @mut CrateContext, id: ast::NodeId) -> ValueRef {
|
||||
|
||||
unsafe {
|
||||
let llty = llvm::LLVMTypeOf(v);
|
||||
let g = do sym.as_c_str |buf| {
|
||||
let g = do sym.to_c_str().with_ref |buf| {
|
||||
llvm::LLVMAddGlobal(ccx.llmod, llty, buf)
|
||||
};
|
||||
|
||||
@ -2452,7 +2452,7 @@ pub fn get_item_val(ccx: @mut CrateContext, id: ast::NodeId) -> ValueRef {
|
||||
|
||||
match (attr::first_attr_value_str_by_name(i.attrs, "link_section")) {
|
||||
Some(sect) => unsafe {
|
||||
do sect.as_c_str |buf| {
|
||||
do sect.to_c_str().with_ref |buf| {
|
||||
llvm::LLVMSetSection(v, buf);
|
||||
}
|
||||
},
|
||||
@ -2493,7 +2493,7 @@ pub fn get_item_val(ccx: @mut CrateContext, id: ast::NodeId) -> ValueRef {
|
||||
}
|
||||
ast::foreign_item_static(*) => {
|
||||
let ident = token::ident_to_str(&ni.ident);
|
||||
let g = do ident.as_c_str |buf| {
|
||||
let g = do ident.to_c_str().with_ref |buf| {
|
||||
unsafe {
|
||||
let ty = type_of(ccx, ty);
|
||||
llvm::LLVMAddGlobal(ccx.llmod, ty.to_ref(), buf)
|
||||
@ -2600,7 +2600,7 @@ pub fn trans_constant(ccx: &mut CrateContext, it: @ast::item) {
|
||||
let s = mangle_exported_name(ccx, p, ty::mk_int()).to_managed();
|
||||
let disr_val = vi[i].disr_val;
|
||||
note_unique_llvm_symbol(ccx, s);
|
||||
let discrim_gvar = do s.as_c_str |buf| {
|
||||
let discrim_gvar = do s.to_c_str().with_ref |buf| {
|
||||
unsafe {
|
||||
llvm::LLVMAddGlobal(ccx.llmod, ccx.int_type.to_ref(), buf)
|
||||
}
|
||||
@ -2741,7 +2741,7 @@ pub fn decl_gc_metadata(ccx: &mut CrateContext, llmod_id: &str) {
|
||||
}
|
||||
|
||||
let gc_metadata_name = ~"_gc_module_metadata_" + llmod_id;
|
||||
let gc_metadata = do gc_metadata_name.as_c_str |buf| {
|
||||
let gc_metadata = do gc_metadata_name.to_c_str().with_ref |buf| {
|
||||
unsafe {
|
||||
llvm::LLVMAddGlobal(ccx.llmod, Type::i32().to_ref(), buf)
|
||||
}
|
||||
@ -2756,7 +2756,7 @@ pub fn decl_gc_metadata(ccx: &mut CrateContext, llmod_id: &str) {
|
||||
pub fn create_module_map(ccx: &mut CrateContext) -> ValueRef {
|
||||
let elttype = Type::struct_([ccx.int_type, ccx.int_type], false);
|
||||
let maptype = Type::array(&elttype, (ccx.module_data.len() + 1) as u64);
|
||||
let map = do "_rust_mod_map".as_c_str |buf| {
|
||||
let map = do "_rust_mod_map".to_c_str().with_ref |buf| {
|
||||
unsafe {
|
||||
llvm::LLVMAddGlobal(ccx.llmod, maptype.to_ref(), buf)
|
||||
}
|
||||
@ -2804,7 +2804,7 @@ pub fn decl_crate_map(sess: session::Session, mapmeta: LinkMeta,
|
||||
let sym_name = ~"_rust_crate_map_" + mapname;
|
||||
let arrtype = Type::array(&int_type, n_subcrates as u64);
|
||||
let maptype = Type::struct_([Type::i32(), Type::i8p(), int_type, arrtype], false);
|
||||
let map = do sym_name.as_c_str |buf| {
|
||||
let map = do sym_name.to_c_str().with_ref |buf| {
|
||||
unsafe {
|
||||
llvm::LLVMAddGlobal(llmod, maptype.to_ref(), buf)
|
||||
}
|
||||
@ -2823,7 +2823,7 @@ pub fn fill_crate_map(ccx: @mut CrateContext, map: ValueRef) {
|
||||
cdata.name,
|
||||
cstore::get_crate_vers(cstore, i),
|
||||
cstore::get_crate_hash(cstore, i));
|
||||
let cr = do nm.as_c_str |buf| {
|
||||
let cr = do nm.to_c_str().with_ref |buf| {
|
||||
unsafe {
|
||||
llvm::LLVMAddGlobal(ccx.llmod, ccx.int_type.to_ref(), buf)
|
||||
}
|
||||
@ -2886,21 +2886,21 @@ pub fn write_metadata(cx: &mut CrateContext, crate: &ast::Crate) {
|
||||
let encode_parms = crate_ctxt_to_encode_parms(cx, encode_inlined_item);
|
||||
let llmeta = C_bytes(encoder::encode_metadata(encode_parms, crate));
|
||||
let llconst = C_struct([llmeta]);
|
||||
let mut llglobal = do "rust_metadata".as_c_str |buf| {
|
||||
let mut llglobal = do "rust_metadata".to_c_str().with_ref |buf| {
|
||||
unsafe {
|
||||
llvm::LLVMAddGlobal(cx.llmod, val_ty(llconst).to_ref(), buf)
|
||||
}
|
||||
};
|
||||
unsafe {
|
||||
llvm::LLVMSetInitializer(llglobal, llconst);
|
||||
do cx.sess.targ_cfg.target_strs.meta_sect_name.as_c_str |buf| {
|
||||
do cx.sess.targ_cfg.target_strs.meta_sect_name.to_c_str().with_ref |buf| {
|
||||
llvm::LLVMSetSection(llglobal, buf)
|
||||
};
|
||||
lib::llvm::SetLinkage(llglobal, lib::llvm::InternalLinkage);
|
||||
|
||||
let t_ptr_i8 = Type::i8p();
|
||||
llglobal = llvm::LLVMConstBitCast(llglobal, t_ptr_i8.to_ref());
|
||||
let llvm_used = do "llvm.used".as_c_str |buf| {
|
||||
let llvm_used = do "llvm.used".to_c_str().with_ref |buf| {
|
||||
llvm::LLVMAddGlobal(cx.llmod, Type::array(&t_ptr_i8, 1).to_ref(), buf)
|
||||
};
|
||||
lib::llvm::SetLinkage(llvm_used, lib::llvm::AppendingLinkage);
|
||||
@ -2914,7 +2914,7 @@ fn mk_global(ccx: &CrateContext,
|
||||
internal: bool)
|
||||
-> ValueRef {
|
||||
unsafe {
|
||||
let llglobal = do name.as_c_str |buf| {
|
||||
let llglobal = do name.to_c_str().with_ref |buf| {
|
||||
llvm::LLVMAddGlobal(ccx.llmod, val_ty(llval).to_ref(), buf)
|
||||
};
|
||||
llvm::LLVMSetInitializer(llglobal, llval);
|
||||
|
@ -423,7 +423,7 @@ impl Builder {
|
||||
if name.is_empty() {
|
||||
llvm::LLVMBuildAlloca(self.llbuilder, ty.to_ref(), noname())
|
||||
} else {
|
||||
do name.as_c_str |c| {
|
||||
do name.to_c_str().with_ref |c| {
|
||||
llvm::LLVMBuildAlloca(self.llbuilder, ty.to_ref(), c)
|
||||
}
|
||||
}
|
||||
@ -739,7 +739,7 @@ impl Builder {
|
||||
let sanitized = text.replace("$", "");
|
||||
let comment_text = fmt!("# %s", sanitized.replace("\n", "\n\t# "));
|
||||
self.count_insn("inlineasm");
|
||||
let asm = do comment_text.as_c_str |c| {
|
||||
let asm = do comment_text.to_c_str().with_ref |c| {
|
||||
unsafe {
|
||||
llvm::LLVMConstInlineAsm(Type::func([], &Type::void()).to_ref(),
|
||||
c, noname(), False, False)
|
||||
@ -895,7 +895,7 @@ impl Builder {
|
||||
let BB: BasicBlockRef = llvm::LLVMGetInsertBlock(self.llbuilder);
|
||||
let FN: ValueRef = llvm::LLVMGetBasicBlockParent(BB);
|
||||
let M: ModuleRef = llvm::LLVMGetGlobalParent(FN);
|
||||
let T: ValueRef = do "llvm.trap".as_c_str |buf| {
|
||||
let T: ValueRef = do "llvm.trap".to_c_str().with_ref |buf| {
|
||||
llvm::LLVMGetNamedFunction(M, buf)
|
||||
};
|
||||
assert!((T as int != 0));
|
||||
|
@ -31,6 +31,7 @@ use util::ppaux::{Repr};
|
||||
|
||||
use middle::trans::type_::Type;
|
||||
|
||||
use std::c_str::ToCStr;
|
||||
use std::cast::transmute;
|
||||
use std::cast;
|
||||
use std::hashmap::{HashMap};
|
||||
@ -707,7 +708,7 @@ pub fn C_integral(t: Type, u: u64, sign_extend: bool) -> ValueRef {
|
||||
|
||||
pub fn C_floating(s: &str, t: Type) -> ValueRef {
|
||||
unsafe {
|
||||
do s.as_c_str |buf| {
|
||||
do s.to_c_str().with_ref |buf| {
|
||||
llvm::LLVMConstRealOfString(t.to_ref(), buf)
|
||||
}
|
||||
}
|
||||
@ -755,12 +756,12 @@ pub fn C_cstr(cx: &mut CrateContext, s: @str) -> ValueRef {
|
||||
None => ()
|
||||
}
|
||||
|
||||
let sc = do s.as_c_str |buf| {
|
||||
let sc = do s.to_c_str().with_ref |buf| {
|
||||
llvm::LLVMConstStringInContext(cx.llcx, buf, s.len() as c_uint, False)
|
||||
};
|
||||
|
||||
let gsym = token::gensym("str");
|
||||
let g = do fmt!("str%u", gsym).as_c_str |buf| {
|
||||
let g = do fmt!("str%u", gsym).to_c_str().with_ref |buf| {
|
||||
llvm::LLVMAddGlobal(cx.llmod, val_ty(sc).to_ref(), buf)
|
||||
};
|
||||
llvm::LLVMSetInitializer(g, sc);
|
||||
@ -779,7 +780,7 @@ pub fn C_estr_slice(cx: &mut CrateContext, s: @str) -> ValueRef {
|
||||
unsafe {
|
||||
let len = s.len();
|
||||
let cs = llvm::LLVMConstPointerCast(C_cstr(cx, s), Type::i8p().to_ref());
|
||||
C_struct([cs, C_uint(cx, len + 1u /* +1 for null */)])
|
||||
C_struct([cs, C_uint(cx, len)])
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -30,6 +30,7 @@ use util::ppaux::{Repr, ty_to_str};
|
||||
|
||||
use middle::trans::type_::Type;
|
||||
|
||||
use std::c_str::ToCStr;
|
||||
use std::libc::c_uint;
|
||||
use syntax::{ast, ast_util, ast_map};
|
||||
|
||||
@ -101,7 +102,7 @@ pub fn const_vec(cx: @mut CrateContext, e: &ast::expr, es: &[@ast::expr])
|
||||
|
||||
fn const_addr_of(cx: &mut CrateContext, cv: ValueRef) -> ValueRef {
|
||||
unsafe {
|
||||
let gv = do "const".as_c_str |name| {
|
||||
let gv = do "const".to_c_str().with_ref |name| {
|
||||
llvm::LLVMAddGlobal(cx.llmod, val_ty(cv).to_ref(), name)
|
||||
};
|
||||
llvm::LLVMSetInitializer(gv, cv);
|
||||
@ -527,7 +528,7 @@ fn const_expr_unadjusted(cx: @mut CrateContext, e: &ast::expr) -> ValueRef {
|
||||
ast::expr_vec(ref es, ast::m_imm) => {
|
||||
let (cv, sz, llunitty) = const_vec(cx, e, *es);
|
||||
let llty = val_ty(cv);
|
||||
let gv = do "const".as_c_str |name| {
|
||||
let gv = do "const".to_c_str().with_ref |name| {
|
||||
llvm::LLVMAddGlobal(cx.llmod, llty.to_ref(), name)
|
||||
};
|
||||
llvm::LLVMSetInitializer(gv, cv);
|
||||
|
@ -26,6 +26,7 @@ use middle::ty;
|
||||
|
||||
use middle::trans::type_::Type;
|
||||
|
||||
use std::c_str::ToCStr;
|
||||
use std::hash;
|
||||
use std::hashmap::{HashMap, HashSet};
|
||||
use std::local_data;
|
||||
@ -124,11 +125,17 @@ impl CrateContext {
|
||||
unsafe {
|
||||
let llcx = llvm::LLVMContextCreate();
|
||||
set_task_llcx(llcx);
|
||||
let llmod = name.as_c_str(|buf| llvm::LLVMModuleCreateWithNameInContext(buf, llcx));
|
||||
let llmod = do name.to_c_str().with_ref |buf| {
|
||||
llvm::LLVMModuleCreateWithNameInContext(buf, llcx)
|
||||
};
|
||||
let data_layout: &str = sess.targ_cfg.target_strs.data_layout;
|
||||
let targ_triple: &str = sess.targ_cfg.target_strs.target_triple;
|
||||
data_layout.as_c_str(|buf| llvm::LLVMSetDataLayout(llmod, buf));
|
||||
targ_triple.as_c_str(|buf| llvm::LLVMSetTarget(llmod, buf));
|
||||
do data_layout.to_c_str().with_ref |buf| {
|
||||
llvm::LLVMSetDataLayout(llmod, buf)
|
||||
};
|
||||
do targ_triple.to_c_str().with_ref |buf| {
|
||||
llvm::LLVMSetTarget(llmod, buf)
|
||||
};
|
||||
let targ_cfg = sess.targ_cfg;
|
||||
|
||||
let td = mk_target_data(sess.targ_cfg.target_strs.data_layout);
|
||||
|
@ -8,6 +8,7 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use std::c_str::ToCStr;
|
||||
|
||||
use back::link;
|
||||
use lib;
|
||||
@ -240,7 +241,7 @@ pub fn trans_log(log_ex: &ast::expr,
|
||||
ccx, modpath, "loglevel");
|
||||
let global;
|
||||
unsafe {
|
||||
global = do s.as_c_str |buf| {
|
||||
global = do s.to_c_str().with_ref |buf| {
|
||||
llvm::LLVMAddGlobal(ccx.llmod, Type::i32().to_ref(), buf)
|
||||
};
|
||||
llvm::LLVMSetGlobalConstant(global, False);
|
||||
|
@ -63,6 +63,7 @@ use middle::ty;
|
||||
use middle::pat_util;
|
||||
use util::ppaux::ty_to_str;
|
||||
|
||||
use std::c_str::ToCStr;
|
||||
use std::hashmap::HashMap;
|
||||
use std::libc::{c_uint, c_ulonglong, c_longlong};
|
||||
use std::ptr;
|
||||
@ -159,7 +160,7 @@ pub fn create_local_var_metadata(bcx: @mut Block, local: &ast::Local) {
|
||||
let ty = node_id_type(bcx, node_id);
|
||||
let type_metadata = type_metadata(cx, ty, span);
|
||||
|
||||
let var_metadata = do name.as_c_str |name| {
|
||||
let var_metadata = do name.to_c_str().with_ref |name| {
|
||||
unsafe {
|
||||
llvm::LLVMDIBuilderCreateLocalVariable(
|
||||
DIB(cx),
|
||||
@ -246,7 +247,7 @@ pub fn create_argument_metadata(bcx: @mut Block,
|
||||
argument_index as c_uint
|
||||
};
|
||||
|
||||
let arg_metadata = do name.as_c_str |name| {
|
||||
let arg_metadata = do name.to_c_str().with_ref |name| {
|
||||
unsafe {
|
||||
llvm::LLVMDIBuilderCreateLocalVariable(
|
||||
DIB(cx),
|
||||
@ -382,8 +383,8 @@ pub fn create_function_metadata(fcx: &FunctionContext) -> DISubprogram {
|
||||
};
|
||||
|
||||
let fn_metadata =
|
||||
do cx.sess.str_of(ident).as_c_str |name| {
|
||||
do cx.sess.str_of(ident).as_c_str |linkage| {
|
||||
do cx.sess.str_of(ident).to_c_str().with_ref |name| {
|
||||
do cx.sess.str_of(ident).to_c_str().with_ref |linkage| {
|
||||
unsafe {
|
||||
llvm::LLVMDIBuilderCreateFunction(
|
||||
DIB(cx),
|
||||
@ -430,11 +431,11 @@ fn compile_unit_metadata(cx: @mut CrateContext) {
|
||||
let work_dir = cx.sess.working_dir.to_str();
|
||||
let producer = fmt!("rustc version %s", env!("CFG_VERSION"));
|
||||
|
||||
do crate_name.as_c_str |crate_name| {
|
||||
do work_dir.as_c_str |work_dir| {
|
||||
do producer.as_c_str |producer| {
|
||||
do "".as_c_str |flags| {
|
||||
do "".as_c_str |split_name| {
|
||||
do crate_name.to_c_str().with_ref |crate_name| {
|
||||
do work_dir.to_c_str().with_ref |work_dir| {
|
||||
do producer.to_c_str().with_ref |producer| {
|
||||
do "".to_c_str().with_ref |flags| {
|
||||
do "".to_c_str().with_ref |split_name| {
|
||||
unsafe {
|
||||
llvm::LLVMDIBuilderCreateCompileUnit(dcx.builder,
|
||||
DW_LANG_RUST as c_uint, crate_name, work_dir, producer,
|
||||
@ -461,8 +462,8 @@ fn file_metadata(cx: &mut CrateContext, full_path: &str) -> DIFile {
|
||||
};
|
||||
|
||||
let file_metadata =
|
||||
do file_name.as_c_str |file_name| {
|
||||
do work_dir.as_c_str |work_dir| {
|
||||
do file_name.to_c_str().with_ref |file_name| {
|
||||
do work_dir.to_c_str().with_ref |work_dir| {
|
||||
unsafe {
|
||||
llvm::LLVMDIBuilderCreateFile(DIB(cx), file_name, work_dir)
|
||||
}
|
||||
@ -550,7 +551,7 @@ fn basic_type_metadata(cx: &mut CrateContext, t: ty::t) -> DIType {
|
||||
|
||||
let llvm_type = type_of::type_of(cx, t);
|
||||
let (size, align) = size_and_align_of(cx, llvm_type);
|
||||
let ty_metadata = do name.as_c_str |name| {
|
||||
let ty_metadata = do name.to_c_str().with_ref |name| {
|
||||
unsafe {
|
||||
llvm::LLVMDIBuilderCreateBasicType(
|
||||
DIB(cx),
|
||||
@ -571,7 +572,7 @@ fn pointer_type_metadata(cx: &mut CrateContext,
|
||||
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 = ty_to_str(cx.tcx, pointer_type);
|
||||
let ptr_metadata = do name.as_c_str |name| {
|
||||
let ptr_metadata = do name.to_c_str().with_ref |name| {
|
||||
unsafe {
|
||||
llvm::LLVMDIBuilderCreatePointerType(
|
||||
DIB(cx),
|
||||
@ -665,7 +666,7 @@ fn enum_metadata(cx: &mut CrateContext,
|
||||
let name: &str = cx.sess.str_of(v.name);
|
||||
let discriminant_value = v.disr_val as c_ulonglong;
|
||||
|
||||
do name.as_c_str |name| {
|
||||
do name.to_c_str().with_ref |name| {
|
||||
unsafe {
|
||||
llvm::LLVMDIBuilderCreateEnumerator(
|
||||
DIB(cx),
|
||||
@ -679,7 +680,7 @@ fn enum_metadata(cx: &mut CrateContext,
|
||||
let loc = span_start(cx, span);
|
||||
let file_metadata = file_metadata(cx, loc.file.name);
|
||||
|
||||
let discriminant_type_metadata = do enum_name.as_c_str |enum_name| {
|
||||
let discriminant_type_metadata = do enum_name.to_c_str().with_ref |enum_name| {
|
||||
unsafe {
|
||||
llvm::LLVMDIBuilderCreateEnumerationType(
|
||||
DIB(cx),
|
||||
@ -716,7 +717,7 @@ fn enum_metadata(cx: &mut CrateContext,
|
||||
Some(discriminant_type_metadata),
|
||||
span);
|
||||
|
||||
do "".as_c_str |name| {
|
||||
do "".to_c_str().with_ref |name| {
|
||||
unsafe {
|
||||
llvm::LLVMDIBuilderCreateMemberType(
|
||||
DIB(cx),
|
||||
@ -736,7 +737,7 @@ fn enum_metadata(cx: &mut CrateContext,
|
||||
let enum_llvm_type = type_of::type_of(cx, enum_type);
|
||||
let (enum_type_size, enum_type_align) = size_and_align_of(cx, enum_llvm_type);
|
||||
|
||||
return do enum_name.as_c_str |enum_name| {
|
||||
return do enum_name.to_c_str().with_ref |enum_name| {
|
||||
unsafe {
|
||||
llvm::LLVMDIBuilderCreateUnionType(
|
||||
DIB(cx),
|
||||
@ -820,7 +821,7 @@ fn composite_type_metadata(cx: &mut CrateContext,
|
||||
let member_offset = machine::llelement_offset(cx, composite_llvm_type, i);
|
||||
let member_name: &str = member_names[i];
|
||||
|
||||
do member_name.as_c_str |member_name| {
|
||||
do member_name.to_c_str().with_ref |member_name| {
|
||||
unsafe {
|
||||
llvm::LLVMDIBuilderCreateMemberType(
|
||||
DIB(cx),
|
||||
@ -838,7 +839,7 @@ fn composite_type_metadata(cx: &mut CrateContext,
|
||||
})
|
||||
.collect();
|
||||
|
||||
return do composite_type_name.as_c_str |name| {
|
||||
return do composite_type_name.to_c_str().with_ref |name| {
|
||||
unsafe {
|
||||
llvm::LLVMDIBuilderCreateStructType(
|
||||
DIB(cx),
|
||||
@ -1064,7 +1065,7 @@ fn unimplemented_type_metadata(cx: &mut CrateContext, t: ty::t) -> DIType {
|
||||
debug!("unimplemented_type_metadata: %?", ty::get(t));
|
||||
|
||||
let name = ty_to_str(cx.tcx, t);
|
||||
let metadata = do fmt!("NYI<%s>", name).as_c_str |name| {
|
||||
let metadata = do fmt!("NYI<%s>", name).to_c_str().with_ref |name| {
|
||||
unsafe {
|
||||
llvm::LLVMDIBuilderCreateBasicType(
|
||||
DIB(cx),
|
||||
|
@ -849,7 +849,6 @@ fn trans_lvalue_unadjusted(bcx: @mut Block, expr: @ast::expr) -> DatumBlock {
|
||||
|
||||
let _icx = push_ctxt("trans_index");
|
||||
let ccx = bcx.ccx();
|
||||
let base_ty = expr_ty(bcx, base);
|
||||
let mut bcx = bcx;
|
||||
|
||||
let base_datum = unpack_datum!(bcx, trans_to_datum(bcx, base));
|
||||
@ -879,12 +878,6 @@ fn trans_lvalue_unadjusted(bcx: @mut Block, expr: @ast::expr) -> DatumBlock {
|
||||
let (bcx, base, len) =
|
||||
base_datum.get_vec_base_and_len(bcx, index_expr.span,
|
||||
index_expr.id, 0);
|
||||
let mut len = len;
|
||||
|
||||
if ty::type_is_str(base_ty) {
|
||||
// acccount for null terminator in the case of string
|
||||
len = Sub(bcx, len, C_uint(bcx.ccx(), 1u));
|
||||
}
|
||||
|
||||
debug!("trans_index: base %s", bcx.val_to_str(base));
|
||||
debug!("trans_index: len %s", bcx.val_to_str(len));
|
||||
@ -943,7 +936,7 @@ fn trans_lvalue_unadjusted(bcx: @mut Block, expr: @ast::expr) -> DatumBlock {
|
||||
let symbol = csearch::get_symbol(
|
||||
bcx.ccx().sess.cstore,
|
||||
did);
|
||||
let llval = do symbol.as_c_str |buf| {
|
||||
let llval = do symbol.to_c_str().with_ref |buf| {
|
||||
llvm::LLVMAddGlobal(bcx.ccx().llmod,
|
||||
llty.to_ref(),
|
||||
buf)
|
||||
|
@ -37,6 +37,7 @@ use util::ppaux::ty_to_short_str;
|
||||
|
||||
use middle::trans::type_::Type;
|
||||
|
||||
use std::c_str::ToCStr;
|
||||
use std::libc::c_uint;
|
||||
use syntax::ast;
|
||||
|
||||
@ -659,7 +660,7 @@ pub fn declare_tydesc(ccx: &mut CrateContext, t: ty::t) -> @mut tydesc_info {
|
||||
let name = mangle_internal_name_by_type_and_seq(ccx, t, "tydesc").to_managed();
|
||||
note_unique_llvm_symbol(ccx, name);
|
||||
debug!("+++ declare_tydesc %s %s", ppaux::ty_to_str(ccx.tcx, t), name);
|
||||
let gvar = do name.as_c_str |buf| {
|
||||
let gvar = do name.to_c_str().with_ref |buf| {
|
||||
unsafe {
|
||||
llvm::LLVMAddGlobal(ccx.llmod, ccx.tydesc_type.to_ref(), buf)
|
||||
}
|
||||
|
@ -32,6 +32,7 @@ use util::ppaux::Repr;
|
||||
|
||||
use middle::trans::type_::Type;
|
||||
|
||||
use std::c_str::ToCStr;
|
||||
use std::vec;
|
||||
use syntax::ast_map::{path, path_mod, path_name};
|
||||
use syntax::ast_util;
|
||||
@ -604,7 +605,7 @@ pub fn make_vtable(ccx: &mut CrateContext,
|
||||
|
||||
let tbl = C_struct(components);
|
||||
let vtable = ccx.sess.str_of(gensym_name("vtable"));
|
||||
let vt_gvar = do vtable.as_c_str |buf| {
|
||||
let vt_gvar = do vtable.to_c_str().with_ref |buf| {
|
||||
llvm::LLVMAddGlobal(ccx.llmod, val_ty(tbl).to_ref(), buf)
|
||||
};
|
||||
llvm::LLVMSetInitializer(vt_gvar, tbl);
|
||||
|
@ -58,7 +58,7 @@ impl Reflector {
|
||||
let str_vstore = ty::vstore_slice(ty::re_static);
|
||||
let str_ty = ty::mk_estr(bcx.tcx(), str_vstore);
|
||||
let scratch = scratch_datum(bcx, str_ty, "", false);
|
||||
let len = C_uint(bcx.ccx(), s.len() + 1);
|
||||
let len = C_uint(bcx.ccx(), s.len());
|
||||
let c_str = PointerCast(bcx, C_cstr(bcx.ccx(), s), Type::i8p());
|
||||
Store(bcx, c_str, GEPi(bcx, scratch.val, [ 0, 0 ]));
|
||||
Store(bcx, len, GEPi(bcx, scratch.val, [ 0, 1 ]));
|
||||
|
@ -265,7 +265,7 @@ pub fn trans_lit_str(bcx: @mut Block,
|
||||
Ignore => bcx,
|
||||
SaveIn(lldest) => {
|
||||
unsafe {
|
||||
let bytes = str_lit.len() + 1; // count null-terminator too
|
||||
let bytes = str_lit.len(); // count null-terminator too
|
||||
let llbytes = C_uint(bcx.ccx(), bytes);
|
||||
let llcstr = C_cstr(bcx.ccx(), str_lit);
|
||||
let llcstr = llvm::LLVMConstPointerCast(llcstr, Type::i8p().to_ref());
|
||||
@ -363,7 +363,7 @@ pub fn write_content(bcx: @mut Block,
|
||||
return bcx;
|
||||
}
|
||||
SaveIn(lldest) => {
|
||||
let bytes = s.len() + 1; // copy null-terminator too
|
||||
let bytes = s.len();
|
||||
let llbytes = C_uint(bcx.ccx(), bytes);
|
||||
let llcstr = C_cstr(bcx.ccx(), s);
|
||||
base::call_memcpy(bcx, lldest, llcstr, llbytes, 1);
|
||||
@ -491,7 +491,7 @@ pub fn elements_required(bcx: @mut Block, content_expr: &ast::expr) -> uint {
|
||||
|
||||
match content_expr.node {
|
||||
ast::expr_lit(@codemap::spanned { node: ast::lit_str(s), _ }) => {
|
||||
s.len() + 1
|
||||
s.len()
|
||||
},
|
||||
ast::expr_vec(ref es, _) => es.len(),
|
||||
ast::expr_repeat(_, count_expr, _) => {
|
||||
@ -524,7 +524,6 @@ pub fn get_base_and_len(bcx: @mut Block,
|
||||
match vstore {
|
||||
ty::vstore_fixed(n) => {
|
||||
let base = GEPi(bcx, llval, [0u, 0u]);
|
||||
let n = if ty::type_is_str(vec_ty) { n + 1u } else { n };
|
||||
let len = Mul(bcx, C_uint(ccx, n), vt.llunit_size);
|
||||
(base, len)
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ use middle::trans::base;
|
||||
use syntax::ast;
|
||||
use syntax::abi::{Architecture, X86, X86_64, Arm, Mips};
|
||||
|
||||
use std::c_str::ToCStr;
|
||||
use std::vec;
|
||||
use std::cast;
|
||||
|
||||
@ -170,7 +171,7 @@ impl Type {
|
||||
|
||||
pub fn named_struct(name: &str) -> Type {
|
||||
let ctx = base::task_llcx();
|
||||
ty!(name.as_c_str(|s| llvm::LLVMStructCreateNamed(ctx, s)))
|
||||
ty!(name.to_c_str().with_ref(|s| llvm::LLVMStructCreateNamed(ctx, s)))
|
||||
}
|
||||
|
||||
pub fn empty_struct() -> Type {
|
||||
|
@ -394,10 +394,12 @@ pub fn link_exe(_src: &Path, _dest: &Path) -> bool {
|
||||
#[cfg(target_os = "freebsd")]
|
||||
#[cfg(target_os = "macos")]
|
||||
pub fn link_exe(src: &Path, dest: &Path) -> bool {
|
||||
use std::c_str::ToCStr;
|
||||
use std::libc;
|
||||
|
||||
unsafe {
|
||||
do src.to_str().as_c_str |src_buf| {
|
||||
do dest.to_str().as_c_str |dest_buf| {
|
||||
do src.to_c_str().with_ref |src_buf| {
|
||||
do dest.to_c_str().with_ref |dest_buf| {
|
||||
libc::link(src_buf, dest_buf) == 0 as libc::c_int &&
|
||||
libc::chmod(dest_buf, 755) == 0 as libc::c_int
|
||||
}
|
||||
|
233
src/libstd/c_str.rs
Normal file
233
src/libstd/c_str.rs
Normal file
@ -0,0 +1,233 @@
|
||||
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use cast;
|
||||
use iterator::Iterator;
|
||||
use libc;
|
||||
use ops::Drop;
|
||||
use option::{Option, Some, None};
|
||||
use ptr::RawPtr;
|
||||
use ptr;
|
||||
use str::StrSlice;
|
||||
use vec::ImmutableVector;
|
||||
|
||||
/// The representation of a C String.
|
||||
///
|
||||
/// This structure wraps a `*libc::c_char`, and will automatically free the
|
||||
/// memory it is pointing to when it goes out of scope.
|
||||
pub struct CString {
|
||||
priv buf: *libc::c_char,
|
||||
priv owns_buffer_: bool,
|
||||
}
|
||||
|
||||
impl CString {
|
||||
/// Create a C String from a pointer.
|
||||
pub unsafe fn new(buf: *libc::c_char, owns_buffer: bool) -> CString {
|
||||
CString { buf: buf, owns_buffer_: owns_buffer }
|
||||
}
|
||||
|
||||
/// Unwraps the wrapped `*libc::c_char` from the `CString` wrapper.
|
||||
pub unsafe fn unwrap(self) -> *libc::c_char {
|
||||
let mut c_str = self;
|
||||
c_str.owns_buffer_ = false;
|
||||
c_str.buf
|
||||
}
|
||||
|
||||
/// Calls a closure with a reference to the underlying `*libc::c_char`.
|
||||
///
|
||||
/// # Failure
|
||||
///
|
||||
/// Fails if the CString is null.
|
||||
pub fn with_ref<T>(&self, f: &fn(*libc::c_char) -> T) -> T {
|
||||
if self.buf.is_null() { fail!("CString is null!"); }
|
||||
f(self.buf)
|
||||
}
|
||||
|
||||
/// Calls a closure with a mutable reference to the underlying `*libc::c_char`.
|
||||
///
|
||||
/// # Failure
|
||||
///
|
||||
/// Fails if the CString is null.
|
||||
pub fn with_mut_ref<T>(&mut self, f: &fn(*mut libc::c_char) -> T) -> T {
|
||||
if self.buf.is_null() { fail!("CString is null!"); }
|
||||
f(unsafe { cast::transmute_mut_unsafe(self.buf) })
|
||||
}
|
||||
|
||||
/// Returns true if the CString is a null.
|
||||
pub fn is_null(&self) -> bool {
|
||||
self.buf.is_null()
|
||||
}
|
||||
|
||||
/// Returns true if the CString is not null.
|
||||
pub fn is_not_null(&self) -> bool {
|
||||
self.buf.is_not_null()
|
||||
}
|
||||
|
||||
/// 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.
|
||||
///
|
||||
/// # Failure
|
||||
///
|
||||
/// Fails if the CString is null.
|
||||
pub fn as_bytes<'a>(&'a self) -> &'a [u8] {
|
||||
if self.buf.is_null() { fail!("CString is null!"); }
|
||||
unsafe {
|
||||
let len = libc::strlen(self.buf) as uint;
|
||||
cast::transmute((self.buf, len + 1))
|
||||
}
|
||||
}
|
||||
|
||||
/// Return a CString iterator.
|
||||
fn iter<'a>(&'a self) -> CStringIterator<'a> {
|
||||
CStringIterator {
|
||||
ptr: self.buf,
|
||||
lifetime: unsafe { cast::transmute(self.buf) },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for CString {
|
||||
fn drop(&self) {
|
||||
if self.owns_buffer_ {
|
||||
unsafe {
|
||||
libc::free(self.buf as *libc::c_void)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A generic trait for converting a value to a CString.
|
||||
pub trait ToCStr {
|
||||
/// Create a C String.
|
||||
fn to_c_str(&self) -> CString;
|
||||
}
|
||||
|
||||
impl<'self> ToCStr for &'self str {
|
||||
#[inline]
|
||||
fn to_c_str(&self) -> CString {
|
||||
self.as_bytes().to_c_str()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'self> ToCStr for &'self [u8] {
|
||||
fn to_c_str(&self) -> CString {
|
||||
do self.as_imm_buf |self_buf, self_len| {
|
||||
unsafe {
|
||||
let buf = libc::malloc(self_len as libc::size_t + 1) as *mut u8;
|
||||
if buf.is_null() {
|
||||
fail!("failed to allocate memory!");
|
||||
}
|
||||
|
||||
ptr::copy_memory(buf, self_buf, self_len);
|
||||
*ptr::mut_offset(buf, self_len as int) = 0;
|
||||
|
||||
CString::new(buf as *libc::c_char, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// External iterator for a CString's bytes.
|
||||
///
|
||||
/// Use with the `std::iterator` module.
|
||||
pub struct CStringIterator<'self> {
|
||||
priv ptr: *libc::c_char,
|
||||
priv lifetime: &'self libc::c_char, // FIXME: #5922
|
||||
}
|
||||
|
||||
impl<'self> Iterator<libc::c_char> for CStringIterator<'self> {
|
||||
fn next(&mut self) -> Option<libc::c_char> {
|
||||
let ch = unsafe { *self.ptr };
|
||||
if ch == 0 {
|
||||
None
|
||||
} else {
|
||||
self.ptr = ptr::offset(self.ptr, 1);
|
||||
Some(ch)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use libc;
|
||||
use ptr;
|
||||
use option::{Some, None};
|
||||
|
||||
#[test]
|
||||
fn test_to_c_str() {
|
||||
do "".to_c_str().with_ref |buf| {
|
||||
unsafe {
|
||||
assert_eq!(*ptr::offset(buf, 0), 0);
|
||||
}
|
||||
}
|
||||
|
||||
do "hello".to_c_str().with_ref |buf| {
|
||||
unsafe {
|
||||
assert_eq!(*ptr::offset(buf, 0), 'h' as libc::c_char);
|
||||
assert_eq!(*ptr::offset(buf, 1), 'e' as libc::c_char);
|
||||
assert_eq!(*ptr::offset(buf, 2), 'l' as libc::c_char);
|
||||
assert_eq!(*ptr::offset(buf, 3), 'l' as libc::c_char);
|
||||
assert_eq!(*ptr::offset(buf, 4), 'o' as libc::c_char);
|
||||
assert_eq!(*ptr::offset(buf, 5), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_is_null() {
|
||||
let c_str = unsafe { CString::new(ptr::null(), false) };
|
||||
assert!(c_str.is_null());
|
||||
assert!(!c_str.is_not_null());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_unwrap() {
|
||||
let c_str = "hello".to_c_str();
|
||||
unsafe { libc::free(c_str.unwrap() as *libc::c_void) }
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_with_ref() {
|
||||
let c_str = "hello".to_c_str();
|
||||
let len = unsafe { c_str.with_ref(|buf| libc::strlen(buf)) };
|
||||
assert!(!c_str.is_null());
|
||||
assert!(c_str.is_not_null());
|
||||
assert_eq!(len, 5);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_fail]
|
||||
#[ignore(cfg(windows))]
|
||||
fn test_with_ref_empty_fail() {
|
||||
let c_str = unsafe { CString::new(ptr::null(), false) };
|
||||
c_str.with_ref(|_| ());
|
||||
}
|
||||
|
||||
#[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);
|
||||
}
|
||||
}
|
@ -165,10 +165,20 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(stage0)]
|
||||
#[test]
|
||||
fn test_transmute2() {
|
||||
unsafe {
|
||||
assert_eq!(~[76u8, 0u8], transmute(~"L"));
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(stage0))]
|
||||
#[test]
|
||||
fn test_transmute2() {
|
||||
unsafe {
|
||||
assert_eq!(~[76u8], transmute(~"L"));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -48,6 +48,7 @@ implement `Reader` and `Writer`, where appropriate.
|
||||
|
||||
use cast;
|
||||
use clone::Clone;
|
||||
use c_str::ToCStr;
|
||||
use container::Container;
|
||||
use int;
|
||||
use iterator::Iterator;
|
||||
@ -1040,8 +1041,8 @@ pub fn stdin() -> @Reader {
|
||||
}
|
||||
|
||||
pub fn file_reader(path: &Path) -> Result<@Reader, ~str> {
|
||||
let f = do path.to_str().as_c_str |pathbuf| {
|
||||
do "rb".as_c_str |modebuf| {
|
||||
let f = do path.to_c_str().with_ref |pathbuf| {
|
||||
do "rb".to_c_str().with_ref |modebuf| {
|
||||
unsafe { libc::fopen(pathbuf, modebuf as *libc::c_char) }
|
||||
}
|
||||
};
|
||||
@ -1290,9 +1291,8 @@ pub fn mk_file_writer(path: &Path, flags: &[FileFlag])
|
||||
}
|
||||
}
|
||||
let fd = unsafe {
|
||||
do path.to_str().as_c_str |pathbuf| {
|
||||
libc::open(pathbuf, fflags,
|
||||
(S_IRUSR | S_IWUSR) as c_int)
|
||||
do path.to_c_str().with_ref |pathbuf| {
|
||||
libc::open(pathbuf, fflags, (S_IRUSR | S_IWUSR) as c_int)
|
||||
}
|
||||
};
|
||||
if fd < (0 as c_int) {
|
||||
@ -1574,8 +1574,8 @@ pub fn file_writer(path: &Path, flags: &[FileFlag]) -> Result<@Writer, ~str> {
|
||||
// FIXME: fileflags // #2004
|
||||
pub fn buffered_file_writer(path: &Path) -> Result<@Writer, ~str> {
|
||||
unsafe {
|
||||
let f = do path.to_str().as_c_str |pathbuf| {
|
||||
do "w".as_c_str |modebuf| {
|
||||
let f = do path.to_c_str().with_ref |pathbuf| {
|
||||
do "w".to_c_str().with_ref |modebuf| {
|
||||
libc::fopen(pathbuf, modebuf)
|
||||
}
|
||||
};
|
||||
@ -1707,6 +1707,7 @@ pub fn with_bytes_writer(f: &fn(@Writer)) -> ~[u8] {
|
||||
(*bytes).clone()
|
||||
}
|
||||
|
||||
#[cfg(stage0)]
|
||||
pub fn with_str_writer(f: &fn(@Writer)) -> ~str {
|
||||
let mut v = with_bytes_writer(f);
|
||||
|
||||
@ -1719,6 +1720,11 @@ pub fn with_str_writer(f: &fn(@Writer)) -> ~str {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(stage0))]
|
||||
pub fn with_str_writer(f: &fn(@Writer)) -> ~str {
|
||||
str::from_bytes(with_bytes_writer(f))
|
||||
}
|
||||
|
||||
// Utility functions
|
||||
pub fn seek_in_buf(offset: int, pos: uint, len: uint, whence: SeekStyle) ->
|
||||
uint {
|
||||
|
@ -2652,7 +2652,7 @@ pub mod funcs {
|
||||
pub fn execvpe(c: *c_char, argv: **c_char, envp: **c_char)
|
||||
-> c_int;
|
||||
#[link_name = "_getcwd"]
|
||||
pub fn getcwd(buf: *c_char, size: size_t) -> *c_char;
|
||||
pub fn getcwd(buf: *mut c_char, size: size_t) -> *c_char;
|
||||
#[link_name = "_getpid"]
|
||||
pub fn getpid() -> c_int;
|
||||
#[link_name = "_isatty"]
|
||||
@ -2804,7 +2804,7 @@ pub mod funcs {
|
||||
pub fn execvp(c: *c_char, argv: **c_char) -> c_int;
|
||||
pub fn fork() -> pid_t;
|
||||
pub fn fpathconf(filedes: c_int, name: c_int) -> c_long;
|
||||
pub fn getcwd(buf: *c_char, size: size_t) -> *c_char;
|
||||
pub fn getcwd(buf: *mut c_char, size: size_t) -> *c_char;
|
||||
pub fn getegid() -> gid_t;
|
||||
pub fn geteuid() -> uid_t;
|
||||
pub fn getgid() -> gid_t ;
|
||||
|
216
src/libstd/os.rs
216
src/libstd/os.rs
@ -28,7 +28,7 @@
|
||||
|
||||
#[allow(missing_doc)];
|
||||
|
||||
use cast;
|
||||
use c_str::ToCStr;
|
||||
use clone::Clone;
|
||||
use container::Container;
|
||||
use io;
|
||||
@ -70,14 +70,15 @@ pub static TMPBUF_SZ : uint = 1000u;
|
||||
static BUF_BYTES : uint = 2048u;
|
||||
|
||||
pub fn getcwd() -> Path {
|
||||
let buf = [0 as libc::c_char, ..BUF_BYTES];
|
||||
unsafe {
|
||||
if(0 as *libc::c_char == libc::getcwd(
|
||||
&buf[0],
|
||||
BUF_BYTES as libc::size_t)) {
|
||||
fail!();
|
||||
let mut buf = [0 as libc::c_char, ..BUF_BYTES];
|
||||
do buf.as_mut_buf |buf, len| {
|
||||
unsafe {
|
||||
if libc::getcwd(buf, len as size_t).is_null() {
|
||||
fail!()
|
||||
}
|
||||
|
||||
Path(str::raw::from_c_str(buf as *c_char))
|
||||
}
|
||||
Path(str::raw::from_c_str(&buf[0]))
|
||||
}
|
||||
}
|
||||
|
||||
@ -88,7 +89,7 @@ pub fn fill_charp_buf(f: &fn(*mut c_char, size_t) -> bool) -> Option<~str> {
|
||||
do buf.as_mut_buf |b, sz| {
|
||||
if f(b, sz as size_t) {
|
||||
unsafe {
|
||||
Some(str::raw::from_buf(b as *u8))
|
||||
Some(str::raw::from_c_str(b as *c_char))
|
||||
}
|
||||
} else {
|
||||
None
|
||||
@ -238,11 +239,13 @@ pub fn env() -> ~[(~str,~str)] {
|
||||
pub fn getenv(n: &str) -> Option<~str> {
|
||||
unsafe {
|
||||
do with_env_lock {
|
||||
let s = n.as_c_str(|s| libc::getenv(s as *libc::c_char));
|
||||
if ptr::null::<u8>() == cast::transmute(s) {
|
||||
let s = do n.to_c_str().with_ref |buf| {
|
||||
libc::getenv(buf)
|
||||
};
|
||||
if s.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(str::raw::from_buf(cast::transmute(s)))
|
||||
Some(str::raw::from_c_str(s))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -271,8 +274,8 @@ pub fn getenv(n: &str) -> Option<~str> {
|
||||
pub fn setenv(n: &str, v: &str) {
|
||||
unsafe {
|
||||
do with_env_lock {
|
||||
do n.to_str().as_c_str |nbuf| {
|
||||
do v.to_str().as_c_str |vbuf| {
|
||||
do n.to_c_str().with_ref |nbuf| {
|
||||
do v.to_c_str().with_ref |vbuf| {
|
||||
libc::funcs::posix01::unistd::setenv(nbuf, vbuf, 1);
|
||||
}
|
||||
}
|
||||
@ -303,7 +306,7 @@ pub fn unsetenv(n: &str) {
|
||||
fn _unsetenv(n: &str) {
|
||||
unsafe {
|
||||
do with_env_lock {
|
||||
do n.to_str().as_c_str |nbuf| {
|
||||
do n.to_c_str().with_ref |nbuf| {
|
||||
libc::funcs::posix01::unistd::unsetenv(nbuf);
|
||||
}
|
||||
}
|
||||
@ -325,7 +328,7 @@ pub fn unsetenv(n: &str) {
|
||||
}
|
||||
|
||||
pub fn fdopen(fd: c_int) -> *FILE {
|
||||
do "r".as_c_str |modebuf| {
|
||||
do "r".to_c_str().with_ref |modebuf| {
|
||||
unsafe {
|
||||
libc::fdopen(fd, modebuf)
|
||||
}
|
||||
@ -458,18 +461,18 @@ pub fn self_exe_path() -> Option<Path> {
|
||||
unsafe {
|
||||
use libc::funcs::posix01::unistd::readlink;
|
||||
|
||||
let mut path_str = str::with_capacity(TMPBUF_SZ);
|
||||
let len = do path_str.as_c_str |buf| {
|
||||
let buf = buf as *mut c_char;
|
||||
do "/proc/self/exe".as_c_str |proc_self_buf| {
|
||||
readlink(proc_self_buf, buf, TMPBUF_SZ as size_t)
|
||||
let mut path = [0 as c_char, .. TMPBUF_SZ];
|
||||
|
||||
do path.as_mut_buf |buf, len| {
|
||||
let len = do "/proc/self/exe".to_c_str().with_ref |proc_self_buf| {
|
||||
readlink(proc_self_buf, buf, len as size_t) as uint
|
||||
};
|
||||
|
||||
if len == -1 {
|
||||
None
|
||||
} else {
|
||||
Some(str::raw::from_buf_len(buf as *u8, len))
|
||||
}
|
||||
};
|
||||
if len == -1 {
|
||||
None
|
||||
} else {
|
||||
str::raw::set_len(&mut path_str, len as uint);
|
||||
Some(path_str)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -590,7 +593,7 @@ pub fn walk_dir(p: &Path, f: &fn(&Path) -> bool) -> bool {
|
||||
/// Indicates whether a path represents a directory
|
||||
pub fn path_is_dir(p: &Path) -> bool {
|
||||
unsafe {
|
||||
do p.to_str().as_c_str |buf| {
|
||||
do p.to_c_str().with_ref |buf| {
|
||||
rustrt::rust_path_is_dir(buf) != 0 as c_int
|
||||
}
|
||||
}
|
||||
@ -599,7 +602,7 @@ pub fn path_is_dir(p: &Path) -> bool {
|
||||
/// Indicates whether a path exists
|
||||
pub fn path_exists(p: &Path) -> bool {
|
||||
unsafe {
|
||||
do p.to_str().as_c_str |buf| {
|
||||
do p.to_c_str().with_ref |buf| {
|
||||
rustrt::rust_path_exists(buf) != 0 as c_int
|
||||
}
|
||||
}
|
||||
@ -634,7 +637,7 @@ pub fn make_dir(p: &Path, mode: c_int) -> bool {
|
||||
use os::win32::as_utf16_p;
|
||||
// FIXME: turn mode into something useful? #2623
|
||||
do as_utf16_p(p.to_str()) |buf| {
|
||||
libc::CreateDirectoryW(buf, cast::transmute(0))
|
||||
libc::CreateDirectoryW(buf, ptr::mut_null())
|
||||
!= (0 as libc::BOOL)
|
||||
}
|
||||
}
|
||||
@ -642,7 +645,7 @@ pub fn make_dir(p: &Path, mode: c_int) -> bool {
|
||||
|
||||
#[cfg(unix)]
|
||||
fn mkdir(p: &Path, mode: c_int) -> bool {
|
||||
do p.to_str().as_c_str |buf| {
|
||||
do p.to_c_str().with_ref |buf| {
|
||||
unsafe {
|
||||
libc::mkdir(buf, mode as libc::mode_t) == (0 as c_int)
|
||||
}
|
||||
@ -691,13 +694,15 @@ pub fn list_dir(p: &Path) -> ~[~str] {
|
||||
extern {
|
||||
fn rust_list_dir_val(ptr: *dirent_t) -> *libc::c_char;
|
||||
}
|
||||
let input = p.to_str();
|
||||
let mut strings = ~[];
|
||||
let input_ptr = ::cast::transmute(&input[0]);
|
||||
debug!("os::list_dir -- BEFORE OPENDIR");
|
||||
let dir_ptr = opendir(input_ptr);
|
||||
|
||||
let dir_ptr = do p.to_c_str().with_ref |buf| {
|
||||
opendir(buf)
|
||||
};
|
||||
|
||||
if (dir_ptr as uint != 0) {
|
||||
debug!("os::list_dir -- opendir() SUCCESS");
|
||||
debug!("os::list_dir -- opendir() SUCCESS");
|
||||
let mut entry_ptr = readdir(dir_ptr);
|
||||
while (entry_ptr as uint != 0) {
|
||||
strings.push(str::raw::from_c_str(rust_list_dir_val(
|
||||
@ -707,7 +712,7 @@ pub fn list_dir(p: &Path) -> ~[~str] {
|
||||
closedir(dir_ptr);
|
||||
}
|
||||
else {
|
||||
debug!("os::list_dir -- opendir() FAILURE");
|
||||
debug!("os::list_dir -- opendir() FAILURE");
|
||||
}
|
||||
debug!(
|
||||
"os::list_dir -- AFTER -- #: %?",
|
||||
@ -723,6 +728,7 @@ pub fn list_dir(p: &Path) -> ~[~str] {
|
||||
FindNextFileW,
|
||||
FindClose,
|
||||
};
|
||||
use libc::types::os::arch::extra::HANDLE;
|
||||
use os::win32::{
|
||||
as_utf16_p
|
||||
};
|
||||
@ -737,10 +743,7 @@ pub fn list_dir(p: &Path) -> ~[~str] {
|
||||
do as_utf16_p(star(p).to_str()) |path_ptr| {
|
||||
let mut strings = ~[];
|
||||
let wfd_ptr = malloc_raw(rust_list_dir_wfd_size() as uint);
|
||||
let find_handle =
|
||||
FindFirstFileW(
|
||||
path_ptr,
|
||||
::cast::transmute(wfd_ptr));
|
||||
let find_handle = FindFirstFileW(path_ptr, wfd_ptr as HANDLE);
|
||||
if find_handle as libc::c_int != INVALID_HANDLE_VALUE {
|
||||
let mut more_files = 1 as libc::c_int;
|
||||
while more_files != 0 {
|
||||
@ -754,9 +757,7 @@ pub fn list_dir(p: &Path) -> ~[~str] {
|
||||
let fp_str = str::from_utf16(fp_vec);
|
||||
strings.push(fp_str);
|
||||
}
|
||||
more_files = FindNextFileW(
|
||||
find_handle,
|
||||
::cast::transmute(wfd_ptr));
|
||||
more_files = FindNextFileW(find_handle, wfd_ptr as HANDLE);
|
||||
}
|
||||
FindClose(find_handle);
|
||||
free(wfd_ptr)
|
||||
@ -818,7 +819,7 @@ pub fn remove_dir(p: &Path) -> bool {
|
||||
|
||||
#[cfg(unix)]
|
||||
fn rmdir(p: &Path) -> bool {
|
||||
do p.to_str().as_c_str |buf| {
|
||||
do p.to_c_str().with_ref |buf| {
|
||||
unsafe {
|
||||
libc::rmdir(buf) == (0 as c_int)
|
||||
}
|
||||
@ -843,7 +844,7 @@ pub fn change_dir(p: &Path) -> bool {
|
||||
|
||||
#[cfg(unix)]
|
||||
fn chdir(p: &Path) -> bool {
|
||||
do p.to_str().as_c_str |buf| {
|
||||
do p.to_c_str().with_ref |buf| {
|
||||
unsafe {
|
||||
libc::chdir(buf) == (0 as c_int)
|
||||
}
|
||||
@ -871,8 +872,8 @@ pub fn copy_file(from: &Path, to: &Path) -> bool {
|
||||
#[cfg(unix)]
|
||||
fn do_copy_file(from: &Path, to: &Path) -> bool {
|
||||
unsafe {
|
||||
let istream = do from.to_str().as_c_str |fromp| {
|
||||
do "rb".as_c_str |modebuf| {
|
||||
let istream = do from.to_c_str().with_ref |fromp| {
|
||||
do "rb".to_c_str().with_ref |modebuf| {
|
||||
libc::fopen(fromp, modebuf)
|
||||
}
|
||||
};
|
||||
@ -883,8 +884,8 @@ pub fn copy_file(from: &Path, to: &Path) -> bool {
|
||||
let from_mode = from.get_mode().expect("copy_file: couldn't get permissions \
|
||||
for source file");
|
||||
|
||||
let ostream = do to.to_str().as_c_str |top| {
|
||||
do "w+b".as_c_str |modebuf| {
|
||||
let ostream = do to.to_c_str().with_ref |top| {
|
||||
do "w+b".to_c_str().with_ref |modebuf| {
|
||||
libc::fopen(top, modebuf)
|
||||
}
|
||||
};
|
||||
@ -916,7 +917,7 @@ pub fn copy_file(from: &Path, to: &Path) -> bool {
|
||||
fclose(ostream);
|
||||
|
||||
// Give the new file the old file's permissions
|
||||
if do to.to_str().as_c_str |to_buf| {
|
||||
if do to.to_c_str().with_ref |to_buf| {
|
||||
libc::chmod(to_buf, from_mode as libc::mode_t)
|
||||
} != 0 {
|
||||
return false; // should be a condition...
|
||||
@ -943,7 +944,7 @@ pub fn remove_file(p: &Path) -> bool {
|
||||
#[cfg(unix)]
|
||||
fn unlink(p: &Path) -> bool {
|
||||
unsafe {
|
||||
do p.to_str().as_c_str |buf| {
|
||||
do p.to_c_str().with_ref |buf| {
|
||||
libc::unlink(buf) == (0 as c_int)
|
||||
}
|
||||
}
|
||||
@ -1035,14 +1036,15 @@ pub fn last_os_error() -> ~str {
|
||||
}
|
||||
|
||||
let mut buf = [0 as c_char, ..TMPBUF_SZ];
|
||||
unsafe {
|
||||
let err = strerror_r(errno() as c_int, &mut buf[0],
|
||||
TMPBUF_SZ as size_t);
|
||||
if err < 0 {
|
||||
fail!("strerror_r failure");
|
||||
}
|
||||
|
||||
str::raw::from_c_str(&buf[0])
|
||||
do buf.as_mut_buf |buf, len| {
|
||||
unsafe {
|
||||
if strerror_r(errno() as c_int, buf, len as size_t) < 0 {
|
||||
fail!("strerror_r failure");
|
||||
}
|
||||
|
||||
str::raw::from_c_str(buf as *c_char)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1068,23 +1070,31 @@ pub fn last_os_error() -> ~str {
|
||||
static FORMAT_MESSAGE_FROM_SYSTEM: DWORD = 0x00001000;
|
||||
static FORMAT_MESSAGE_IGNORE_INSERTS: DWORD = 0x00000200;
|
||||
|
||||
let mut buf = [0 as c_char, ..TMPBUF_SZ];
|
||||
|
||||
// This value is calculated from the macro
|
||||
// MAKELANGID(LANG_SYSTEM_DEFAULT, SUBLANG_SYS_DEFAULT)
|
||||
let langId = 0x0800 as DWORD;
|
||||
let err = errno() as DWORD;
|
||||
|
||||
let mut buf = [0 as c_char, ..TMPBUF_SZ];
|
||||
|
||||
unsafe {
|
||||
let res = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
ptr::mut_null(), err, langId,
|
||||
&mut buf[0], TMPBUF_SZ as DWORD,
|
||||
ptr::null());
|
||||
if res == 0 {
|
||||
fail!("[%?] FormatMessage failure", errno());
|
||||
do buf.as_mut_buf |buf, len| {
|
||||
let res = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
ptr::mut_null(),
|
||||
err,
|
||||
langId,
|
||||
buf,
|
||||
len as DWORD,
|
||||
ptr::null());
|
||||
if res == 0 {
|
||||
fail!("[%?] FormatMessage failure", errno());
|
||||
}
|
||||
}
|
||||
|
||||
str::raw::from_c_str(&buf[0])
|
||||
do buf.as_imm_buf |buf, _len| {
|
||||
str::raw::from_c_str(buf)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1160,7 +1170,7 @@ pub fn real_args() -> ~[~str] {
|
||||
}
|
||||
|
||||
unsafe {
|
||||
LocalFree(cast::transmute(szArgList));
|
||||
LocalFree(szArgList as *c_void);
|
||||
}
|
||||
|
||||
return args;
|
||||
@ -1272,7 +1282,7 @@ pub fn glob(pattern: &str) -> ~[Path] {
|
||||
}
|
||||
|
||||
let mut g = default_glob_t();
|
||||
do pattern.as_c_str |c_pattern| {
|
||||
do pattern.to_c_str().with_ref |c_pattern| {
|
||||
unsafe { libc::glob(c_pattern, 0, ptr::null(), &mut g) }
|
||||
};
|
||||
do(|| {
|
||||
@ -1677,6 +1687,7 @@ pub mod consts {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use c_str::ToCStr;
|
||||
use libc::{c_int, c_void, size_t};
|
||||
use libc;
|
||||
use option::Some;
|
||||
@ -1689,7 +1700,6 @@ mod tests {
|
||||
use rand;
|
||||
use run;
|
||||
use str::StrSlice;
|
||||
use vec::CopyableVector;
|
||||
use libc::consts::os::posix88::{S_IRUSR, S_IWUSR, S_IXUSR};
|
||||
|
||||
|
||||
@ -1912,39 +1922,39 @@ mod tests {
|
||||
#[test]
|
||||
fn copy_file_ok() {
|
||||
unsafe {
|
||||
let tempdir = getcwd(); // would like to use $TMPDIR,
|
||||
// doesn't seem to work on Linux
|
||||
assert!((tempdir.to_str().len() > 0u));
|
||||
let input = tempdir.push("in.txt");
|
||||
let out = tempdir.push("out.txt");
|
||||
let tempdir = getcwd(); // would like to use $TMPDIR,
|
||||
// doesn't seem to work on Linux
|
||||
assert!((tempdir.to_str().len() > 0u));
|
||||
let input = tempdir.push("in.txt");
|
||||
let out = tempdir.push("out.txt");
|
||||
|
||||
/* Write the temp input file */
|
||||
let ostream = do input.to_str().as_c_str |fromp| {
|
||||
do "w+b".as_c_str |modebuf| {
|
||||
/* Write the temp input file */
|
||||
let ostream = do input.to_c_str().with_ref |fromp| {
|
||||
do "w+b".to_c_str().with_ref |modebuf| {
|
||||
libc::fopen(fromp, modebuf)
|
||||
}
|
||||
};
|
||||
assert!((ostream as uint != 0u));
|
||||
let s = ~"hello";
|
||||
let mut buf = s.as_bytes_with_null().to_owned();
|
||||
let len = buf.len();
|
||||
do buf.as_mut_buf |b, _len| {
|
||||
assert_eq!(libc::fwrite(b as *c_void, 1u as size_t,
|
||||
(s.len() + 1u) as size_t, ostream),
|
||||
len as size_t)
|
||||
}
|
||||
assert_eq!(libc::fclose(ostream), (0u as c_int));
|
||||
let in_mode = input.get_mode();
|
||||
let rs = os::copy_file(&input, &out);
|
||||
if (!os::path_exists(&input)) {
|
||||
fail!("%s doesn't exist", input.to_str());
|
||||
}
|
||||
assert!((rs));
|
||||
let rslt = run::process_status("diff", [input.to_str(), out.to_str()]);
|
||||
assert_eq!(rslt, 0);
|
||||
assert_eq!(out.get_mode(), in_mode);
|
||||
assert!((remove_file(&input)));
|
||||
assert!((remove_file(&out)));
|
||||
};
|
||||
assert!((ostream as uint != 0u));
|
||||
let s = ~"hello";
|
||||
do "hello".to_c_str().with_ref |buf| {
|
||||
let write_len = libc::fwrite(buf as *c_void,
|
||||
1u as size_t,
|
||||
(s.len() + 1u) as size_t,
|
||||
ostream);
|
||||
assert_eq!(write_len, (s.len() + 1) as size_t)
|
||||
}
|
||||
assert_eq!(libc::fclose(ostream), (0u as c_int));
|
||||
let in_mode = input.get_mode();
|
||||
let rs = os::copy_file(&input, &out);
|
||||
if (!os::path_exists(&input)) {
|
||||
fail!("%s doesn't exist", input.to_str());
|
||||
}
|
||||
assert!((rs));
|
||||
let rslt = run::process_status("diff", [input.to_str(), out.to_str()]);
|
||||
assert_eq!(rslt, 0);
|
||||
assert_eq!(out.get_mode(), in_mode);
|
||||
assert!((remove_file(&input)));
|
||||
assert!((remove_file(&out)));
|
||||
}
|
||||
}
|
||||
|
||||
@ -2003,11 +2013,11 @@ mod tests {
|
||||
remove_file(&path);
|
||||
|
||||
let fd = unsafe {
|
||||
let fd = do path.to_str().as_c_str |path| {
|
||||
let fd = do path.to_c_str().with_ref |path| {
|
||||
open(path, O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR)
|
||||
};
|
||||
lseek_(fd, size);
|
||||
do "x".as_c_str |x| {
|
||||
do "x".to_c_str().with_ref |x| {
|
||||
assert!(write(fd, x as *c_void, 1) == 1);
|
||||
}
|
||||
fd
|
||||
|
@ -16,9 +16,11 @@ Cross-platform file path handling
|
||||
|
||||
#[allow(missing_doc)];
|
||||
|
||||
use c_str::ToCStr;
|
||||
use c_str;
|
||||
use clone::Clone;
|
||||
use container::Container;
|
||||
use cmp::Eq;
|
||||
use container::Container;
|
||||
use iterator::{Iterator, IteratorUtil, range};
|
||||
use libc;
|
||||
use num;
|
||||
@ -379,7 +381,7 @@ mod stat {
|
||||
#[cfg(target_os = "win32")]
|
||||
impl WindowsPath {
|
||||
pub fn stat(&self) -> Option<libc::stat> {
|
||||
do self.to_str().as_c_str |buf| {
|
||||
do self.to_c_str().with_ref |buf| {
|
||||
let mut st = stat::arch::default_stat();
|
||||
match unsafe { libc::stat(buf, &mut st) } {
|
||||
0 => Some(st),
|
||||
@ -413,7 +415,7 @@ impl WindowsPath {
|
||||
#[cfg(not(target_os = "win32"))]
|
||||
impl PosixPath {
|
||||
pub fn stat(&self) -> Option<libc::stat> {
|
||||
do self.to_str().as_c_str |buf| {
|
||||
do self.to_c_str().with_ref |buf| {
|
||||
let mut st = stat::arch::default_stat();
|
||||
match unsafe { libc::stat(buf as *libc::c_char, &mut st) } {
|
||||
0 => Some(st),
|
||||
@ -491,7 +493,7 @@ impl PosixPath {
|
||||
#[cfg(unix)]
|
||||
impl PosixPath {
|
||||
pub fn lstat(&self) -> Option<libc::stat> {
|
||||
do self.to_str().as_c_str |buf| {
|
||||
do self.to_c_str().with_ref |buf| {
|
||||
let mut st = stat::arch::default_stat();
|
||||
match unsafe { libc::lstat(buf, &mut st) } {
|
||||
0 => Some(st),
|
||||
@ -563,6 +565,12 @@ impl ToStr for PosixPath {
|
||||
}
|
||||
}
|
||||
|
||||
impl ToCStr for PosixPath {
|
||||
fn to_c_str(&self) -> c_str::CString {
|
||||
self.to_str().to_c_str()
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME (#3227): when default methods in traits are working, de-duplicate
|
||||
// PosixPath and WindowsPath, most of their methods are common.
|
||||
impl GenericPath for PosixPath {
|
||||
@ -769,6 +777,11 @@ impl ToStr for WindowsPath {
|
||||
}
|
||||
}
|
||||
|
||||
impl c_str::ToCStr for WindowsPath {
|
||||
fn to_c_str(&self) -> c_str::CString {
|
||||
self.to_str().to_c_str()
|
||||
}
|
||||
}
|
||||
|
||||
impl GenericPath for WindowsPath {
|
||||
fn from_str(s: &str) -> WindowsPath {
|
||||
|
@ -43,6 +43,7 @@ pub use io::{print, println};
|
||||
pub use iterator::range;
|
||||
|
||||
// Reexported types and traits
|
||||
pub use c_str::ToCStr;
|
||||
pub use clone::{Clone, DeepClone};
|
||||
pub use cmp::{Eq, ApproxEq, Ord, TotalEq, TotalOrd, Ordering, Less, Equal, Greater, Equiv};
|
||||
pub use char::Char;
|
||||
@ -64,7 +65,7 @@ pub use path::PosixPath;
|
||||
pub use path::WindowsPath;
|
||||
pub use ptr::RawPtr;
|
||||
pub use ascii::{Ascii, AsciiCast, OwnedAsciiCast, AsciiStr, ToBytesConsume};
|
||||
pub use str::{Str, StrVector, StrSlice, OwnedStr, NullTerminatedStr};
|
||||
pub use str::{Str, StrVector, StrSlice, OwnedStr};
|
||||
pub use from_str::FromStr;
|
||||
pub use to_bytes::IterBytes;
|
||||
pub use to_str::{ToStr, ToStrConsume};
|
||||
|
@ -456,6 +456,7 @@ pub mod ptr_tests {
|
||||
use super::*;
|
||||
use prelude::*;
|
||||
|
||||
use c_str::ToCStr;
|
||||
use cast;
|
||||
use libc;
|
||||
use str;
|
||||
@ -502,22 +503,20 @@ pub mod ptr_tests {
|
||||
fn test_position() {
|
||||
use libc::c_char;
|
||||
|
||||
let s = ~"hello";
|
||||
unsafe {
|
||||
assert!(2u == s.as_c_str(|p| position(p, |c| *c == 'l' as c_char)));
|
||||
assert!(4u == s.as_c_str(|p| position(p, |c| *c == 'o' as c_char)));
|
||||
assert!(5u == s.as_c_str(|p| position(p, |c| *c == 0 as c_char)));
|
||||
do "hello".to_c_str().with_ref |p| {
|
||||
unsafe {
|
||||
assert!(2u == position(p, |c| *c == 'l' as c_char));
|
||||
assert!(4u == position(p, |c| *c == 'o' as c_char));
|
||||
assert!(5u == position(p, |c| *c == 0 as c_char));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_buf_len() {
|
||||
let s0 = ~"hello";
|
||||
let s1 = ~"there";
|
||||
let s2 = ~"thing";
|
||||
do s0.as_c_str |p0| {
|
||||
do s1.as_c_str |p1| {
|
||||
do s2.as_c_str |p2| {
|
||||
do "hello".to_c_str().with_ref |p0| {
|
||||
do "there".to_c_str().with_ref |p1| {
|
||||
do "thing".to_c_str().with_ref |p2| {
|
||||
let v = ~[p0, p1, p2, null()];
|
||||
do v.as_imm_buf |vp, len| {
|
||||
assert_eq!(unsafe { buf_len(vp) }, 3u);
|
||||
@ -621,66 +620,75 @@ pub mod ptr_tests {
|
||||
#[test]
|
||||
fn test_ptr_array_each_with_len() {
|
||||
unsafe {
|
||||
let one = ~"oneOne";
|
||||
let two = ~"twoTwo";
|
||||
let three = ~"threeThree";
|
||||
let arr: ~[*i8] = ~[
|
||||
::cast::transmute(&one[0]),
|
||||
::cast::transmute(&two[0]),
|
||||
::cast::transmute(&three[0]),
|
||||
let one = "oneOne".to_c_str();
|
||||
let two = "twoTwo".to_c_str();
|
||||
let three = "threeThree".to_c_str();
|
||||
let arr = ~[
|
||||
one.with_ref(|buf| buf),
|
||||
two.with_ref(|buf| buf),
|
||||
three.with_ref(|buf| buf),
|
||||
];
|
||||
let expected_arr = [
|
||||
one, two, three
|
||||
];
|
||||
let arr_ptr = &arr[0];
|
||||
let mut ctr = 0;
|
||||
let mut iteration_count = 0;
|
||||
array_each_with_len(arr_ptr, arr.len(),
|
||||
|e| {
|
||||
let actual = str::raw::from_c_str(e);
|
||||
let expected = expected_arr[ctr].clone();
|
||||
debug!(
|
||||
"test_ptr_array_each e: %s, a: %s",
|
||||
expected, actual);
|
||||
assert_eq!(actual, expected);
|
||||
ctr += 1;
|
||||
iteration_count += 1;
|
||||
});
|
||||
assert_eq!(iteration_count, 3u);
|
||||
|
||||
do arr.as_imm_buf |arr_ptr, arr_len| {
|
||||
let mut ctr = 0;
|
||||
let mut iteration_count = 0;
|
||||
do array_each_with_len(arr_ptr, arr_len) |e| {
|
||||
let actual = str::raw::from_c_str(e);
|
||||
let expected = do expected_arr[ctr].with_ref |buf| {
|
||||
str::raw::from_c_str(buf)
|
||||
};
|
||||
debug!(
|
||||
"test_ptr_array_each_with_len e: %s, a: %s",
|
||||
expected, actual);
|
||||
assert_eq!(actual, expected);
|
||||
ctr += 1;
|
||||
iteration_count += 1;
|
||||
}
|
||||
assert_eq!(iteration_count, 3u);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ptr_array_each() {
|
||||
unsafe {
|
||||
let one = ~"oneOne";
|
||||
let two = ~"twoTwo";
|
||||
let three = ~"threeThree";
|
||||
let arr: ~[*i8] = ~[
|
||||
::cast::transmute(&one[0]),
|
||||
::cast::transmute(&two[0]),
|
||||
::cast::transmute(&three[0]),
|
||||
let one = "oneOne".to_c_str();
|
||||
let two = "twoTwo".to_c_str();
|
||||
let three = "threeThree".to_c_str();
|
||||
let arr = ~[
|
||||
one.with_ref(|buf| buf),
|
||||
two.with_ref(|buf| buf),
|
||||
three.with_ref(|buf| buf),
|
||||
// fake a null terminator
|
||||
0 as *i8
|
||||
null(),
|
||||
];
|
||||
let expected_arr = [
|
||||
one, two, three
|
||||
];
|
||||
let arr_ptr = &arr[0];
|
||||
let mut ctr = 0;
|
||||
let mut iteration_count = 0;
|
||||
array_each(arr_ptr, |e| {
|
||||
let actual = str::raw::from_c_str(e);
|
||||
let expected = expected_arr[ctr].clone();
|
||||
debug!(
|
||||
"test_ptr_array_each e: %s, a: %s",
|
||||
expected, actual);
|
||||
assert_eq!(actual, expected);
|
||||
ctr += 1;
|
||||
iteration_count += 1;
|
||||
});
|
||||
assert_eq!(iteration_count, 3);
|
||||
|
||||
do arr.as_imm_buf |arr_ptr, arr_len| {
|
||||
let mut ctr = 0;
|
||||
let mut iteration_count = 0;
|
||||
do array_each(arr_ptr) |e| {
|
||||
let actual = str::raw::from_c_str(e);
|
||||
let expected = do expected_arr[ctr].with_ref |buf| {
|
||||
str::raw::from_c_str(buf)
|
||||
};
|
||||
debug!(
|
||||
"test_ptr_array_each e: %s, a: %s",
|
||||
expected, actual);
|
||||
assert_eq!(actual, expected);
|
||||
ctr += 1;
|
||||
iteration_count += 1;
|
||||
}
|
||||
assert_eq!(iteration_count, 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_fail]
|
||||
#[ignore(cfg(windows))]
|
||||
|
@ -8,6 +8,7 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use c_str::ToCStr;
|
||||
use cast::transmute;
|
||||
use libc::{c_char, size_t, STDERR_FILENO};
|
||||
use io;
|
||||
@ -51,8 +52,8 @@ unsafe fn fail_borrowed(box: *mut raw::Box<()>, file: *c_char, line: size_t) {
|
||||
match try_take_task_borrow_list() {
|
||||
None => { // not recording borrows
|
||||
let msg = "borrowed";
|
||||
do msg.as_c_str |msg_p| {
|
||||
sys::begin_unwind_(msg_p as *c_char, file, line);
|
||||
do msg.to_c_str().with_ref |msg_p| {
|
||||
sys::begin_unwind_(msg_p, file, line);
|
||||
}
|
||||
}
|
||||
Some(borrow_list) => { // recording borrows
|
||||
@ -67,8 +68,8 @@ unsafe fn fail_borrowed(box: *mut raw::Box<()>, file: *c_char, line: size_t) {
|
||||
sep = " and at ";
|
||||
}
|
||||
}
|
||||
do msg.as_c_str |msg_p| {
|
||||
sys::begin_unwind_(msg_p as *c_char, file, line)
|
||||
do msg.to_c_str().with_ref |msg_p| {
|
||||
sys::begin_unwind_(msg_p, file, line)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -207,8 +208,8 @@ pub unsafe fn unrecord_borrow(a: *u8, old_ref_count: uint,
|
||||
let br = borrow_list.pop();
|
||||
if br.box != a || br.file != file || br.line != line {
|
||||
let err = fmt!("wrong borrow found, br=%?", br);
|
||||
do err.as_c_str |msg_p| {
|
||||
sys::begin_unwind_(msg_p as *c_char, file, line)
|
||||
do err.to_c_str().with_ref |msg_p| {
|
||||
sys::begin_unwind_(msg_p, file, line)
|
||||
}
|
||||
}
|
||||
borrow_list
|
||||
|
@ -58,15 +58,15 @@ impl Logger for StdErrLogger {
|
||||
/// Configure logging by traversing the crate map and setting the
|
||||
/// per-module global logging flags based on the logging spec
|
||||
pub fn init(crate_map: *u8) {
|
||||
use c_str::ToCStr;
|
||||
use os;
|
||||
use str::StrSlice;
|
||||
use ptr;
|
||||
use option::{Some, None};
|
||||
|
||||
let log_spec = os::getenv("RUST_LOG");
|
||||
match log_spec {
|
||||
Some(spec) => {
|
||||
do spec.as_c_str |buf| {
|
||||
do spec.to_c_str().with_ref |buf| {
|
||||
unsafe { rust_update_log_settings(crate_map, buf) }
|
||||
}
|
||||
}
|
||||
|
@ -8,26 +8,26 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use option::*;
|
||||
use result::*;
|
||||
use ops::Drop;
|
||||
use cell::Cell;
|
||||
use cast;
|
||||
use c_str::ToCStr;
|
||||
use cast::transmute;
|
||||
use cast;
|
||||
use cell::Cell;
|
||||
use clone::Clone;
|
||||
use libc::{c_int, c_uint, c_void};
|
||||
use ops::Drop;
|
||||
use option::*;
|
||||
use ptr;
|
||||
use result::*;
|
||||
use rt::io::IoError;
|
||||
use rt::io::net::ip::{SocketAddr, IpAddr};
|
||||
use rt::io::{standard_error, OtherIoError};
|
||||
use rt::local::Local;
|
||||
use rt::rtio::*;
|
||||
use rt::sched::Scheduler;
|
||||
use rt::tube::Tube;
|
||||
use rt::uv::*;
|
||||
use rt::uv::idle::IdleWatcher;
|
||||
use rt::uv::net::{UvIpv4SocketAddr, UvIpv6SocketAddr};
|
||||
use rt::rtio::*;
|
||||
use rt::sched::Scheduler;
|
||||
use rt::io::{standard_error, OtherIoError};
|
||||
use rt::tube::Tube;
|
||||
use rt::local::Local;
|
||||
use str::StrSlice;
|
||||
use unstable::sync::Exclusive;
|
||||
|
||||
#[cfg(test)] use container::Container;
|
||||
@ -654,7 +654,7 @@ impl RtioUdpSocket for UvUdpSocket {
|
||||
|
||||
fn join_multicast(&mut self, multi: IpAddr) -> Result<(), IoError> {
|
||||
let r = unsafe {
|
||||
do multi.to_str().as_c_str |m_addr| {
|
||||
do multi.to_str().to_c_str().with_ref |m_addr| {
|
||||
uvll::udp_set_membership(self.native_handle(), m_addr,
|
||||
ptr::null(), uvll::UV_JOIN_GROUP)
|
||||
}
|
||||
@ -668,7 +668,7 @@ impl RtioUdpSocket for UvUdpSocket {
|
||||
|
||||
fn leave_multicast(&mut self, multi: IpAddr) -> Result<(), IoError> {
|
||||
let r = unsafe {
|
||||
do multi.to_str().as_c_str |m_addr| {
|
||||
do multi.to_str().to_c_str().with_ref |m_addr| {
|
||||
uvll::udp_set_membership(self.native_handle(), m_addr,
|
||||
ptr::null(), uvll::UV_LEAVE_GROUP)
|
||||
}
|
||||
|
@ -29,6 +29,7 @@
|
||||
|
||||
#[allow(non_camel_case_types)]; // C types
|
||||
|
||||
use c_str::ToCStr;
|
||||
use libc::{size_t, c_int, c_uint, c_void, c_char, uintptr_t};
|
||||
use libc::{malloc, free};
|
||||
use libc;
|
||||
@ -372,12 +373,12 @@ pub unsafe fn is_ip6_addr(addr: *sockaddr) -> bool {
|
||||
}
|
||||
|
||||
pub unsafe fn malloc_ip4_addr(ip: &str, port: int) -> *sockaddr_in {
|
||||
do ip.as_c_str |ip_buf| {
|
||||
do ip.to_c_str().with_ref |ip_buf| {
|
||||
rust_uv_ip4_addrp(ip_buf as *u8, port as libc::c_int)
|
||||
}
|
||||
}
|
||||
pub unsafe fn malloc_ip6_addr(ip: &str, port: int) -> *sockaddr_in6 {
|
||||
do ip.as_c_str |ip_buf| {
|
||||
do ip.to_c_str().with_ref |ip_buf| {
|
||||
rust_uv_ip6_addrp(ip_buf as *u8, port as libc::c_int)
|
||||
}
|
||||
}
|
||||
|
@ -12,6 +12,7 @@
|
||||
|
||||
#[allow(missing_doc)];
|
||||
|
||||
use c_str::ToCStr;
|
||||
use cast;
|
||||
use clone::Clone;
|
||||
use comm::{stream, SharedChan, GenericChan, GenericPort};
|
||||
@ -505,7 +506,7 @@ fn spawn_process_os(prog: &str, args: &[~str],
|
||||
|
||||
do with_envp(env) |envp| {
|
||||
do with_dirp(dir) |dirp| {
|
||||
do cmd.as_c_str |cmdp| {
|
||||
do cmd.to_c_str().with_ref |cmdp| {
|
||||
let created = CreateProcessA(ptr::null(), cast::transmute(cmdp),
|
||||
ptr::mut_null(), ptr::mut_null(), TRUE,
|
||||
0, envp, dirp, &mut si, &mut pi);
|
||||
@ -688,46 +689,62 @@ fn spawn_process_os(prog: &str, args: &[~str],
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
fn with_argv<T>(prog: &str, args: &[~str],
|
||||
cb: &fn(**libc::c_char) -> T) -> T {
|
||||
let mut argptrs = ~[prog.as_c_str(|b| b)];
|
||||
let mut tmps = ~[];
|
||||
fn with_argv<T>(prog: &str, args: &[~str], cb: &fn(**libc::c_char) -> T) -> T {
|
||||
use vec;
|
||||
|
||||
// We can't directly convert `str`s into `*char`s, as someone needs to hold
|
||||
// a reference to the intermediary byte buffers. So first build an array to
|
||||
// hold all the ~[u8] byte strings.
|
||||
let mut tmps = vec::with_capacity(args.len() + 1);
|
||||
|
||||
tmps.push(prog.to_c_str());
|
||||
|
||||
for arg in args.iter() {
|
||||
let t = @(*arg).clone();
|
||||
tmps.push(t);
|
||||
argptrs.push(t.as_c_str(|b| b));
|
||||
tmps.push(arg.to_c_str());
|
||||
}
|
||||
argptrs.push(ptr::null());
|
||||
argptrs.as_imm_buf(|buf, _len| cb(buf))
|
||||
|
||||
// Next, convert each of the byte strings into a pointer. This is
|
||||
// technically unsafe as the caller could leak these pointers out of our
|
||||
// scope.
|
||||
let mut ptrs = do tmps.map |tmp| {
|
||||
tmp.with_ref(|buf| buf)
|
||||
};
|
||||
|
||||
// Finally, make sure we add a null pointer.
|
||||
ptrs.push(ptr::null());
|
||||
|
||||
ptrs.as_imm_buf(|buf, _| cb(buf))
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
fn with_envp<T>(env: Option<&[(~str, ~str)]>, cb: &fn(*c_void) -> T) -> T {
|
||||
// On posixy systems we can pass a char** for envp, which is
|
||||
// a null-terminated array of "k=v\n" strings.
|
||||
match env {
|
||||
Some(es) => {
|
||||
let mut tmps = ~[];
|
||||
let mut ptrs = ~[];
|
||||
use vec;
|
||||
|
||||
for pair in es.iter() {
|
||||
// Use of match here is just to workaround limitations
|
||||
// in the stage0 irrefutable pattern impl.
|
||||
match pair {
|
||||
&(ref k, ref v) => {
|
||||
let kv = @fmt!("%s=%s", *k, *v);
|
||||
tmps.push(kv);
|
||||
ptrs.push(kv.as_c_str(|b| b));
|
||||
}
|
||||
// On posixy systems we can pass a char** for envp, which is a
|
||||
// null-terminated array of "k=v\n" strings. Like `with_argv`, we have to
|
||||
// have a temporary buffer to hold the intermediary `~[u8]` byte strings.
|
||||
match env {
|
||||
Some(env) => {
|
||||
let mut tmps = vec::with_capacity(env.len());
|
||||
|
||||
for pair in env.iter() {
|
||||
// Use of match here is just to workaround limitations
|
||||
// in the stage0 irrefutable pattern impl.
|
||||
let kv = fmt!("%s=%s", pair.first(), pair.second());
|
||||
tmps.push(kv.to_c_str());
|
||||
}
|
||||
|
||||
// Once again, this is unsafe.
|
||||
let mut ptrs = do tmps.map |tmp| {
|
||||
tmp.with_ref(|buf| buf)
|
||||
};
|
||||
ptrs.push(ptr::null());
|
||||
|
||||
do ptrs.as_imm_buf |buf, _| {
|
||||
unsafe { cb(cast::transmute(buf)) }
|
||||
}
|
||||
}
|
||||
|
||||
ptrs.push(ptr::null());
|
||||
ptrs.as_imm_buf(|p, _len|
|
||||
unsafe { cb(::cast::transmute(p)) }
|
||||
)
|
||||
}
|
||||
_ => cb(ptr::null())
|
||||
_ => cb(ptr::null())
|
||||
}
|
||||
}
|
||||
|
||||
@ -737,25 +754,28 @@ fn with_envp<T>(env: Option<&[(~str, ~str)]>, cb: &fn(*mut c_void) -> T) -> T {
|
||||
// rather a concatenation of null-terminated k=v\0 sequences, with a final
|
||||
// \0 to terminate.
|
||||
match env {
|
||||
Some(es) => {
|
||||
let mut blk = ~[];
|
||||
for pair in es.iter() {
|
||||
let kv = fmt!("%s=%s", pair.first(), pair.second());
|
||||
blk.push_all(kv.to_bytes_with_null());
|
||||
Some(env) => {
|
||||
let mut blk = ~[];
|
||||
|
||||
for pair in env.iter() {
|
||||
let kv = fmt!("%s=%s", pair.first(), pair.second());
|
||||
blk.push_all(kv.as_bytes());
|
||||
blk.push(0);
|
||||
}
|
||||
|
||||
blk.push(0);
|
||||
|
||||
do blk.as_imm_buf |p, _len| {
|
||||
unsafe { cb(cast::transmute(p)) }
|
||||
}
|
||||
}
|
||||
blk.push(0);
|
||||
blk.as_imm_buf(|p, _len|
|
||||
unsafe { cb(::cast::transmute(p)) }
|
||||
)
|
||||
}
|
||||
_ => cb(ptr::mut_null())
|
||||
_ => cb(ptr::mut_null())
|
||||
}
|
||||
}
|
||||
|
||||
fn with_dirp<T>(d: Option<&Path>,
|
||||
cb: &fn(*libc::c_char) -> T) -> T {
|
||||
fn with_dirp<T>(d: Option<&Path>, cb: &fn(*libc::c_char) -> T) -> T {
|
||||
match d {
|
||||
Some(dir) => dir.to_str().as_c_str(cb),
|
||||
Some(dir) => dir.to_c_str().with_ref(|buf| cb(buf)),
|
||||
None => cb(ptr::null())
|
||||
}
|
||||
}
|
||||
|
@ -170,6 +170,7 @@ pub mod local_data;
|
||||
/* Runtime and platform support */
|
||||
|
||||
pub mod libc;
|
||||
pub mod c_str;
|
||||
pub mod os;
|
||||
pub mod path;
|
||||
pub mod rand;
|
||||
|
@ -33,6 +33,7 @@ use ptr;
|
||||
use ptr::RawPtr;
|
||||
use to_str::ToStr;
|
||||
use uint;
|
||||
#[cfg(stage0)]
|
||||
use unstable::raw::Repr;
|
||||
use vec;
|
||||
use vec::{OwnedVector, OwnedCopyableVector, ImmutableVector, MutableVector};
|
||||
@ -83,19 +84,22 @@ pub fn from_bytes_owned(vv: ~[u8]) -> ~str {
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert a vector of bytes to a UTF-8 string.
|
||||
/// The vector needs to be one byte longer than the string, and end with a 0 byte.
|
||||
/// Converts a vector to a string slice without performing any allocations.
|
||||
///
|
||||
/// Compared to `from_bytes()`, this fn doesn't need to allocate a new owned str.
|
||||
/// Once the slice has been validated as utf-8, it is transmuted in-place and
|
||||
/// returned as a '&str' instead of a '&[u8]'
|
||||
///
|
||||
/// # Failure
|
||||
///
|
||||
/// Fails if invalid UTF-8
|
||||
/// Fails if not null terminated
|
||||
pub fn from_bytes_with_null<'a>(vv: &'a [u8]) -> &'a str {
|
||||
assert_eq!(vv[vv.len() - 1], 0);
|
||||
assert!(is_utf8(vv));
|
||||
return unsafe { raw::from_bytes_with_null(vv) };
|
||||
#[cfg(stage0)]
|
||||
pub fn from_bytes_slice<'a>(vector: &'a [u8]) -> &'a str {
|
||||
unsafe {
|
||||
assert!(is_utf8(vector));
|
||||
let mut s = vector.repr();
|
||||
s.len += 1;
|
||||
cast::transmute(s)
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts a vector to a string slice without performing any allocations.
|
||||
@ -106,13 +110,10 @@ pub fn from_bytes_with_null<'a>(vv: &'a [u8]) -> &'a str {
|
||||
/// # Failure
|
||||
///
|
||||
/// Fails if invalid UTF-8
|
||||
pub fn from_bytes_slice<'a>(vector: &'a [u8]) -> &'a str {
|
||||
unsafe {
|
||||
assert!(is_utf8(vector));
|
||||
let mut s = vector.repr();
|
||||
s.len += 1;
|
||||
cast::transmute(s)
|
||||
}
|
||||
#[cfg(not(stage0))]
|
||||
pub fn from_bytes_slice<'a>(v: &'a [u8]) -> &'a str {
|
||||
assert!(is_utf8(v));
|
||||
unsafe { cast::transmute(v) }
|
||||
}
|
||||
|
||||
impl ToStr for ~str {
|
||||
@ -133,11 +134,23 @@ impl ToStr for @str {
|
||||
/// # Failure
|
||||
///
|
||||
/// Fails if invalid UTF-8
|
||||
#[cfg(stage0)]
|
||||
pub fn from_byte(b: u8) -> ~str {
|
||||
assert!(b < 128u8);
|
||||
unsafe { cast::transmute(~[b, 0u8]) }
|
||||
}
|
||||
|
||||
/// Convert a byte to a UTF-8 string
|
||||
///
|
||||
/// # Failure
|
||||
///
|
||||
/// Fails if invalid UTF-8
|
||||
#[cfg(not(stage0))]
|
||||
pub fn from_byte(b: u8) -> ~str {
|
||||
assert!(b < 128u8);
|
||||
unsafe { ::cast::transmute(~[b]) }
|
||||
}
|
||||
|
||||
/// Convert a char to a string
|
||||
pub fn from_char(ch: char) -> ~str {
|
||||
let mut buf = ~"";
|
||||
@ -168,6 +181,7 @@ pub trait StrVector {
|
||||
|
||||
impl<'self, S: Str> StrVector for &'self [S] {
|
||||
/// Concatenate a vector of strings.
|
||||
#[cfg(stage0)]
|
||||
pub fn concat(&self) -> ~str {
|
||||
if self.is_empty() { return ~""; }
|
||||
|
||||
@ -191,7 +205,32 @@ impl<'self, S: Str> StrVector for &'self [S] {
|
||||
s
|
||||
}
|
||||
|
||||
/// Concatenate a vector of strings.
|
||||
#[cfg(not(stage0))]
|
||||
pub fn concat(&self) -> ~str {
|
||||
if self.is_empty() { return ~""; }
|
||||
|
||||
let len = self.iter().transform(|s| s.as_slice().len()).sum();
|
||||
|
||||
let mut s = with_capacity(len);
|
||||
|
||||
unsafe {
|
||||
do s.as_mut_buf |buf, _| {
|
||||
let mut buf = buf;
|
||||
for ss in self.iter() {
|
||||
do ss.as_slice().as_imm_buf |ssbuf, sslen| {
|
||||
ptr::copy_memory(buf, ssbuf, sslen);
|
||||
buf = buf.offset(sslen as int);
|
||||
}
|
||||
}
|
||||
}
|
||||
raw::set_len(&mut s, len);
|
||||
}
|
||||
s
|
||||
}
|
||||
|
||||
/// Concatenate a vector of strings, placing a given separator between each.
|
||||
#[cfg(stage0)]
|
||||
pub fn connect(&self, sep: &str) -> ~str {
|
||||
if self.is_empty() { return ~""; }
|
||||
|
||||
@ -230,6 +269,45 @@ impl<'self, S: Str> StrVector for &'self [S] {
|
||||
}
|
||||
s
|
||||
}
|
||||
|
||||
/// Concatenate a vector of strings, placing a given separator between each.
|
||||
#[cfg(not(stage0))]
|
||||
pub fn connect(&self, sep: &str) -> ~str {
|
||||
if self.is_empty() { return ~""; }
|
||||
|
||||
// concat is faster
|
||||
if sep.is_empty() { return self.concat(); }
|
||||
|
||||
// this is wrong without the guarantee that `self` is non-empty
|
||||
let len = sep.len() * (self.len() - 1)
|
||||
+ self.iter().transform(|s| s.as_slice().len()).sum();
|
||||
let mut s = ~"";
|
||||
let mut first = true;
|
||||
|
||||
s.reserve(len);
|
||||
|
||||
unsafe {
|
||||
do s.as_mut_buf |buf, _| {
|
||||
do sep.as_imm_buf |sepbuf, seplen| {
|
||||
let mut buf = buf;
|
||||
for ss in self.iter() {
|
||||
do ss.as_slice().as_imm_buf |ssbuf, sslen| {
|
||||
if first {
|
||||
first = false;
|
||||
} else {
|
||||
ptr::copy_memory(buf, sepbuf, seplen);
|
||||
buf = buf.offset(seplen as int);
|
||||
}
|
||||
ptr::copy_memory(buf, ssbuf, sslen);
|
||||
buf = buf.offset(sslen as int);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
raw::set_len(&mut s, len);
|
||||
}
|
||||
s
|
||||
}
|
||||
}
|
||||
|
||||
/// Something that can be used to compare against a character
|
||||
@ -500,7 +578,7 @@ Section: Comparing strings
|
||||
*/
|
||||
|
||||
/// Bytewise slice equality
|
||||
#[cfg(not(test))]
|
||||
#[cfg(not(test), stage0)]
|
||||
#[lang="str_eq"]
|
||||
#[inline]
|
||||
pub fn eq_slice(a: &str, b: &str) -> bool {
|
||||
@ -518,7 +596,28 @@ pub fn eq_slice(a: &str, b: &str) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
/// Bytewise slice equality
|
||||
#[cfg(not(test), not(stage0))]
|
||||
#[lang="str_eq"]
|
||||
#[inline]
|
||||
pub fn eq_slice(a: &str, b: &str) -> bool {
|
||||
do a.as_imm_buf |ap, alen| {
|
||||
do b.as_imm_buf |bp, blen| {
|
||||
if (alen != blen) { false }
|
||||
else {
|
||||
unsafe {
|
||||
libc::memcmp(ap as *libc::c_void,
|
||||
bp as *libc::c_void,
|
||||
alen as libc::size_t) == 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Bytewise slice equality
|
||||
#[cfg(test, stage0)]
|
||||
#[lang="str_eq"]
|
||||
#[inline]
|
||||
pub fn eq_slice(a: &str, b: &str) -> bool {
|
||||
do a.as_imm_buf |ap, alen| {
|
||||
@ -535,6 +634,24 @@ pub fn eq_slice(a: &str, b: &str) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
/// Bytewise slice equality
|
||||
#[cfg(test, not(stage0))]
|
||||
#[inline]
|
||||
pub fn eq_slice(a: &str, b: &str) -> bool {
|
||||
do a.as_imm_buf |ap, alen| {
|
||||
do b.as_imm_buf |bp, blen| {
|
||||
if (alen != blen) { false }
|
||||
else {
|
||||
unsafe {
|
||||
libc::memcmp(ap as *libc::c_void,
|
||||
bp as *libc::c_void,
|
||||
alen as libc::size_t) == 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Bytewise string equality
|
||||
#[cfg(not(test))]
|
||||
#[lang="uniq_str_eq"]
|
||||
@ -800,20 +917,12 @@ pub mod raw {
|
||||
use str::is_utf8;
|
||||
use vec;
|
||||
use vec::MutableVector;
|
||||
use unstable::raw::{Slice, String};
|
||||
|
||||
/// Create a Rust string from a null-terminated *u8 buffer
|
||||
pub unsafe fn from_buf(buf: *u8) -> ~str {
|
||||
let mut curr = buf;
|
||||
let mut i = 0u;
|
||||
while *curr != 0u8 {
|
||||
i += 1u;
|
||||
curr = ptr::offset(buf, i as int);
|
||||
}
|
||||
return from_buf_len(buf, i);
|
||||
}
|
||||
use unstable::raw::Slice;
|
||||
#[cfg(stage0)]
|
||||
use unstable::raw::String;
|
||||
|
||||
/// Create a Rust string from a *u8 buffer of the given length
|
||||
#[cfg(stage0)]
|
||||
pub unsafe fn from_buf_len(buf: *u8, len: uint) -> ~str {
|
||||
let mut v: ~[u8] = vec::with_capacity(len + 1);
|
||||
v.as_mut_buf(|vbuf, _len| {
|
||||
@ -823,17 +932,31 @@ pub mod raw {
|
||||
v.push(0u8);
|
||||
|
||||
assert!(is_utf8(v));
|
||||
return cast::transmute(v);
|
||||
cast::transmute(v)
|
||||
}
|
||||
|
||||
/// Create a Rust string from a *u8 buffer of the given length
|
||||
#[cfg(not(stage0))]
|
||||
pub unsafe fn from_buf_len(buf: *u8, len: uint) -> ~str {
|
||||
let mut v: ~[u8] = vec::with_capacity(len);
|
||||
do v.as_mut_buf |vbuf, _len| {
|
||||
ptr::copy_memory(vbuf, buf as *u8, len)
|
||||
};
|
||||
vec::raw::set_len(&mut v, len);
|
||||
|
||||
assert!(is_utf8(v));
|
||||
::cast::transmute(v)
|
||||
}
|
||||
|
||||
/// Create a Rust string from a null-terminated C string
|
||||
pub unsafe fn from_c_str(c_str: *libc::c_char) -> ~str {
|
||||
from_buf(c_str as *u8)
|
||||
}
|
||||
|
||||
/// Create a Rust string from a `*c_char` buffer of the given length
|
||||
pub unsafe fn from_c_str_len(c_str: *libc::c_char, len: uint) -> ~str {
|
||||
from_buf_len(c_str as *u8, len)
|
||||
pub unsafe fn from_c_str(buf: *libc::c_char) -> ~str {
|
||||
let mut curr = buf;
|
||||
let mut i = 0;
|
||||
while *curr != 0 {
|
||||
i += 1;
|
||||
curr = ptr::offset(buf, i);
|
||||
}
|
||||
from_buf_len(buf as *u8, i as uint)
|
||||
}
|
||||
|
||||
/// Converts a vector of bytes to a new owned string.
|
||||
@ -845,15 +968,17 @@ pub mod raw {
|
||||
|
||||
/// Converts an owned vector of bytes to a new owned string. This assumes
|
||||
/// that the utf-8-ness of the vector has already been validated
|
||||
#[cfg(stage0)]
|
||||
pub unsafe fn from_bytes_owned(mut v: ~[u8]) -> ~str {
|
||||
v.push(0u8);
|
||||
cast::transmute(v)
|
||||
}
|
||||
|
||||
/// Converts a vector of bytes to a string.
|
||||
/// The byte slice needs to contain valid utf8 and needs to be one byte longer than
|
||||
/// the string, if possible ending in a 0 byte.
|
||||
pub unsafe fn from_bytes_with_null<'a>(v: &'a [u8]) -> &'a str {
|
||||
/// Converts an owned vector of bytes to a new owned string. This assumes
|
||||
/// that the utf-8-ness of the vector has already been validated
|
||||
#[cfg(not(stage0))]
|
||||
#[inline]
|
||||
pub unsafe fn from_bytes_owned(v: ~[u8]) -> ~str {
|
||||
cast::transmute(v)
|
||||
}
|
||||
|
||||
@ -863,6 +988,7 @@ pub mod raw {
|
||||
/// Form a slice from a C string. Unsafe because the caller must ensure the
|
||||
/// C string has the static lifetime, or else the return value may be
|
||||
/// invalidated later.
|
||||
#[cfg(stage0)]
|
||||
pub unsafe fn c_str_to_static_slice(s: *libc::c_char) -> &'static str {
|
||||
let s = s as *u8;
|
||||
let mut curr = s;
|
||||
@ -876,6 +1002,23 @@ pub mod raw {
|
||||
cast::transmute(v)
|
||||
}
|
||||
|
||||
/// Form a slice from a C string. Unsafe because the caller must ensure the
|
||||
/// C string has the static lifetime, or else the return value may be
|
||||
/// invalidated later.
|
||||
#[cfg(not(stage0))]
|
||||
pub unsafe fn c_str_to_static_slice(s: *libc::c_char) -> &'static str {
|
||||
let s = s as *u8;
|
||||
let mut curr = s;
|
||||
let mut len = 0u;
|
||||
while *curr != 0u8 {
|
||||
len += 1u;
|
||||
curr = ptr::offset(s, len as int);
|
||||
}
|
||||
let v = Slice { data: s, len: len };
|
||||
assert!(is_utf8(::cast::transmute(v)));
|
||||
::cast::transmute(v)
|
||||
}
|
||||
|
||||
/// Takes a bytewise (not UTF-8) slice from a string.
|
||||
///
|
||||
/// Returns the substring from [`begin`..`end`).
|
||||
@ -884,6 +1027,7 @@ pub mod raw {
|
||||
///
|
||||
/// If begin is greater than end.
|
||||
/// If end is greater than the length of the string.
|
||||
#[cfg(stage0)]
|
||||
#[inline]
|
||||
pub unsafe fn slice_bytes<'a>(s: &'a str, begin: uint, end: uint) -> &'a str {
|
||||
do s.as_imm_buf |sbuf, n| {
|
||||
@ -897,16 +1041,47 @@ pub mod raw {
|
||||
}
|
||||
}
|
||||
|
||||
/// Takes a bytewise (not UTF-8) slice from a string.
|
||||
///
|
||||
/// Returns the substring from [`begin`..`end`).
|
||||
///
|
||||
/// # Failure
|
||||
///
|
||||
/// If begin is greater than end.
|
||||
/// If end is greater than the length of the string.
|
||||
#[cfg(not(stage0))]
|
||||
#[inline]
|
||||
pub unsafe fn slice_bytes(s: &str, begin: uint, end: uint) -> &str {
|
||||
do s.as_imm_buf |sbuf, n| {
|
||||
assert!((begin <= end));
|
||||
assert!((end <= n));
|
||||
|
||||
cast::transmute(Slice {
|
||||
data: ptr::offset(sbuf, begin as int),
|
||||
len: end - begin,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Appends a byte to a string. (Not UTF-8 safe).
|
||||
#[cfg(stage0)]
|
||||
pub unsafe fn push_byte(s: &mut ~str, b: u8) {
|
||||
let new_len = s.len() + 1;
|
||||
s.reserve_at_least(new_len);
|
||||
do s.as_mut_buf |buf, len| {
|
||||
*ptr::mut_offset(buf, (len-1) as int) = b;
|
||||
*ptr::mut_offset(buf, len as int) = b;
|
||||
}
|
||||
set_len(&mut *s, new_len);
|
||||
}
|
||||
|
||||
/// Appends a byte to a string. (Not UTF-8 safe).
|
||||
#[cfg(not(stage0))]
|
||||
#[inline]
|
||||
pub unsafe fn push_byte(s: &mut ~str, b: u8) {
|
||||
let v: &mut ~[u8] = cast::transmute(s);
|
||||
v.push(b);
|
||||
}
|
||||
|
||||
/// Appends a vector of bytes to a string. (Not UTF-8 safe).
|
||||
unsafe fn push_bytes(s: &mut ~str, bytes: &[u8]) {
|
||||
let new_len = s.len() + bytes.len();
|
||||
@ -933,6 +1108,7 @@ pub mod raw {
|
||||
}
|
||||
|
||||
/// Sets the length of the string and adds the null terminator
|
||||
#[cfg(stage0)]
|
||||
#[inline]
|
||||
pub unsafe fn set_len(v: &mut ~str, new_len: uint) {
|
||||
let v: **mut String = cast::transmute(v);
|
||||
@ -942,6 +1118,23 @@ pub mod raw {
|
||||
*null = 0u8;
|
||||
}
|
||||
|
||||
/// Sets the length of a string
|
||||
///
|
||||
/// This will explicitly set the size of the string, without actually
|
||||
/// modifing its buffers, so it is up to the caller to ensure that
|
||||
/// the string is actually the specified size.
|
||||
#[cfg(not(stage0))]
|
||||
#[inline]
|
||||
pub unsafe fn set_len(s: &mut ~str, new_len: uint) {
|
||||
let v: &mut ~[u8] = cast::transmute(s);
|
||||
vec::raw::set_len(v, new_len)
|
||||
}
|
||||
|
||||
/// Sets the length of a string
|
||||
///
|
||||
/// This will explicitly set the size of the string, without actually
|
||||
/// modifing its buffers, so it is up to the caller to ensure that
|
||||
/// the string is actually the specified size.
|
||||
#[test]
|
||||
fn test_from_buf_len() {
|
||||
unsafe {
|
||||
@ -1119,10 +1312,17 @@ impl<'self> Str for @str {
|
||||
}
|
||||
|
||||
impl<'self> Container for &'self str {
|
||||
#[cfg(stage0)]
|
||||
#[inline]
|
||||
fn len(&self) -> uint {
|
||||
do self.as_imm_buf |_p, n| { n - 1u }
|
||||
}
|
||||
|
||||
#[cfg(not(stage0))]
|
||||
#[inline]
|
||||
fn len(&self) -> uint {
|
||||
do self.as_imm_buf |_p, n| { n }
|
||||
}
|
||||
}
|
||||
|
||||
impl Container for ~str {
|
||||
@ -1210,7 +1410,6 @@ pub trait StrSlice<'self> {
|
||||
fn subslice_offset(&self, inner: &str) -> uint;
|
||||
|
||||
fn as_imm_buf<T>(&self, f: &fn(*u8, uint) -> T) -> T;
|
||||
fn as_c_str<T>(&self, f: &fn(*libc::c_char) -> T) -> T;
|
||||
}
|
||||
|
||||
/// Extension methods for strings
|
||||
@ -1597,6 +1796,7 @@ impl<'self> StrSlice<'self> for &'self str {
|
||||
}
|
||||
|
||||
/// Copy a slice into a new unique str
|
||||
#[cfg(stage0)]
|
||||
#[inline]
|
||||
fn to_owned(&self) -> ~str {
|
||||
do self.as_imm_buf |src, len| {
|
||||
@ -1614,6 +1814,24 @@ impl<'self> StrSlice<'self> for &'self str {
|
||||
}
|
||||
}
|
||||
|
||||
/// Copy a slice into a new unique str
|
||||
#[cfg(not(stage0))]
|
||||
#[inline]
|
||||
fn to_owned(&self) -> ~str {
|
||||
do self.as_imm_buf |src, len| {
|
||||
unsafe {
|
||||
let mut v = vec::with_capacity(len);
|
||||
|
||||
do v.as_mut_buf |dst, _| {
|
||||
ptr::copy_memory(dst, src, len);
|
||||
}
|
||||
vec::raw::set_len(&mut v, len);
|
||||
::cast::transmute(v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(stage0)]
|
||||
#[inline]
|
||||
fn to_managed(&self) -> @str {
|
||||
let v = at_vec::from_fn(self.len() + 1, |i| {
|
||||
@ -1622,6 +1840,15 @@ impl<'self> StrSlice<'self> for &'self str {
|
||||
unsafe { cast::transmute(v) }
|
||||
}
|
||||
|
||||
#[cfg(not(stage0))]
|
||||
#[inline]
|
||||
fn to_managed(&self) -> @str {
|
||||
unsafe {
|
||||
let v: *&[u8] = cast::transmute(self);
|
||||
cast::transmute(at_vec::to_managed(*v))
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts to a vector of `u16` encoded as UTF-16.
|
||||
fn to_utf16(&self) -> ~[u16] {
|
||||
let mut u = ~[];
|
||||
@ -1762,6 +1989,7 @@ impl<'self> StrSlice<'self> for &'self str {
|
||||
/// Work with the byte buffer of a string as a byte slice.
|
||||
///
|
||||
/// The byte slice does not include the null terminator.
|
||||
#[cfg(stage0)]
|
||||
fn as_bytes(&self) -> &'self [u8] {
|
||||
unsafe {
|
||||
let mut slice = self.repr();
|
||||
@ -1770,6 +1998,14 @@ impl<'self> StrSlice<'self> for &'self str {
|
||||
}
|
||||
}
|
||||
|
||||
/// Work with the byte buffer of a string as a byte slice.
|
||||
///
|
||||
/// The byte slice does not include the null terminator.
|
||||
#[cfg(not(stage0))]
|
||||
fn as_bytes(&self) -> &'self [u8] {
|
||||
unsafe { cast::transmute(*self) }
|
||||
}
|
||||
|
||||
/// Returns the byte index of the first character of `self` that matches `search`
|
||||
///
|
||||
/// # Return value
|
||||
@ -1836,6 +2072,7 @@ impl<'self> StrSlice<'self> for &'self str {
|
||||
}
|
||||
|
||||
/// Given a string, make a new string with repeated copies of it.
|
||||
#[cfg(stage0)]
|
||||
fn repeat(&self, nn: uint) -> ~str {
|
||||
do self.as_imm_buf |buf, len| {
|
||||
// ignore the NULL terminator
|
||||
@ -1857,6 +2094,27 @@ impl<'self> StrSlice<'self> for &'self str {
|
||||
}
|
||||
}
|
||||
|
||||
/// Given a string, make a new string with repeated copies of it.
|
||||
#[cfg(not(stage0))]
|
||||
fn repeat(&self, nn: uint) -> ~str {
|
||||
do self.as_imm_buf |buf, len| {
|
||||
let mut ret = with_capacity(nn * len);
|
||||
|
||||
unsafe {
|
||||
do ret.as_mut_buf |rbuf, _len| {
|
||||
let mut rbuf = rbuf;
|
||||
|
||||
do nn.times {
|
||||
ptr::copy_memory(rbuf, buf, len);
|
||||
rbuf = rbuf.offset(len as int);
|
||||
}
|
||||
}
|
||||
raw::set_len(&mut ret, nn * len);
|
||||
}
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
/// Retrieves the first character from a string slice and returns
|
||||
/// it. This does not allocate a new string; instead, it returns a
|
||||
/// slice that point one character beyond the character that was
|
||||
@ -1959,61 +2217,6 @@ impl<'self> StrSlice<'self> for &'self str {
|
||||
let v: &[u8] = unsafe { cast::transmute(*self) };
|
||||
v.as_imm_buf(f)
|
||||
}
|
||||
|
||||
/// Work with the byte buffer of a string as a null-terminated C string.
|
||||
///
|
||||
/// Allows for unsafe manipulation of strings, which is useful for foreign
|
||||
/// interop. This is similar to `str::as_buf`, but guarantees null-termination.
|
||||
/// If the given slice is not already null-terminated, this function will
|
||||
/// allocate a temporary, copy the slice, null terminate it, and pass
|
||||
/// that instead.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ~~~ {.rust}
|
||||
/// let s = "PATH".as_c_str(|path| libc::getenv(path));
|
||||
/// ~~~
|
||||
#[inline]
|
||||
fn as_c_str<T>(&self, f: &fn(*libc::c_char) -> T) -> T {
|
||||
do self.as_imm_buf |buf, len| {
|
||||
// NB: len includes the trailing null.
|
||||
assert!(len > 0);
|
||||
if unsafe { *(ptr::offset(buf, (len - 1) as int)) != 0 } {
|
||||
self.to_owned().as_c_str(|s| f(s))
|
||||
} else {
|
||||
f(buf as *libc::c_char)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(missing_doc)]
|
||||
pub trait NullTerminatedStr {
|
||||
fn as_bytes_with_null<'a>(&'a self) -> &'a [u8];
|
||||
}
|
||||
|
||||
impl NullTerminatedStr for ~str {
|
||||
/// Work with the byte buffer of a string as a byte slice.
|
||||
///
|
||||
/// The byte slice does include the null terminator.
|
||||
#[inline]
|
||||
fn as_bytes_with_null<'a>(&'a self) -> &'a [u8] {
|
||||
let ptr: &'a ~[u8] = unsafe { cast::transmute(self) };
|
||||
let slice: &'a [u8] = *ptr;
|
||||
slice
|
||||
}
|
||||
}
|
||||
|
||||
impl NullTerminatedStr for @str {
|
||||
/// Work with the byte buffer of a string as a byte slice.
|
||||
///
|
||||
/// The byte slice does include the null terminator.
|
||||
#[inline]
|
||||
fn as_bytes_with_null<'a>(&'a self) -> &'a [u8] {
|
||||
let ptr: &'a @[u8] = unsafe { cast::transmute(self) };
|
||||
let slice: &'a [u8] = *ptr;
|
||||
slice
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(missing_doc)]
|
||||
@ -2028,6 +2231,7 @@ pub trait OwnedStr {
|
||||
fn reserve(&mut self, n: uint);
|
||||
fn reserve_at_least(&mut self, n: uint);
|
||||
fn capacity(&self) -> uint;
|
||||
#[cfg(stage0)]
|
||||
fn to_bytes_with_null(self) -> ~[u8];
|
||||
|
||||
/// Work with the mutable byte buffer and length of a slice.
|
||||
@ -2174,6 +2378,7 @@ impl OwnedStr for ~str {
|
||||
///
|
||||
/// * s - A string
|
||||
/// * n - The number of bytes to reserve space for
|
||||
#[cfg(stage0)]
|
||||
#[inline]
|
||||
pub fn reserve(&mut self, n: uint) {
|
||||
unsafe {
|
||||
@ -2182,6 +2387,29 @@ impl OwnedStr for ~str {
|
||||
}
|
||||
}
|
||||
|
||||
/// Reserves capacity for exactly `n` bytes in the given string, not including
|
||||
/// the null terminator.
|
||||
///
|
||||
/// Assuming single-byte characters, the resulting string will be large
|
||||
/// enough to hold a string of length `n`. To account for the null terminator,
|
||||
/// the underlying buffer will have the size `n` + 1.
|
||||
///
|
||||
/// If the capacity for `s` is already equal to or greater than the requested
|
||||
/// capacity, then no action is taken.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * s - A string
|
||||
/// * n - The number of bytes to reserve space for
|
||||
#[cfg(not(stage0))]
|
||||
#[inline]
|
||||
pub fn reserve(&mut self, n: uint) {
|
||||
unsafe {
|
||||
let v: &mut ~[u8] = cast::transmute(self);
|
||||
(*v).reserve(n);
|
||||
}
|
||||
}
|
||||
|
||||
/// Reserves capacity for at least `n` bytes in the given string, not including
|
||||
/// the null terminator.
|
||||
///
|
||||
@ -2200,13 +2428,38 @@ impl OwnedStr for ~str {
|
||||
///
|
||||
/// * s - A string
|
||||
/// * n - The number of bytes to reserve space for
|
||||
#[cfg(stage0)]
|
||||
#[inline]
|
||||
fn reserve_at_least(&mut self, n: uint) {
|
||||
self.reserve(uint::next_power_of_two(n + 1u) - 1u)
|
||||
}
|
||||
|
||||
/// Reserves capacity for at least `n` bytes in the given string.
|
||||
///
|
||||
/// Assuming single-byte characters, the resulting string will be large
|
||||
/// enough to hold a string of length `n`. To account for the null terminator,
|
||||
/// the underlying buffer will have the size `n` + 1.
|
||||
///
|
||||
/// This function will over-allocate in order to amortize the allocation costs
|
||||
/// in scenarios where the caller may need to repeatedly reserve additional
|
||||
/// space.
|
||||
///
|
||||
/// If the capacity for `s` is already equal to or greater than the requested
|
||||
/// capacity, then no action is taken.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * s - A string
|
||||
/// * n - The number of bytes to reserve space for
|
||||
#[cfg(not(stage0))]
|
||||
#[inline]
|
||||
fn reserve_at_least(&mut self, n: uint) {
|
||||
self.reserve(uint::next_power_of_two(n))
|
||||
}
|
||||
|
||||
/// Returns the number of single-byte characters the string can hold without
|
||||
/// reallocating
|
||||
#[cfg(stage0)]
|
||||
fn capacity(&self) -> uint {
|
||||
let buf: &~[u8] = unsafe { cast::transmute(self) };
|
||||
let vcap = buf.capacity();
|
||||
@ -2214,8 +2467,19 @@ impl OwnedStr for ~str {
|
||||
vcap - 1u
|
||||
}
|
||||
|
||||
/// Returns the number of single-byte characters the string can hold without
|
||||
/// reallocating
|
||||
#[cfg(not(stage0))]
|
||||
fn capacity(&self) -> uint {
|
||||
unsafe {
|
||||
let buf: &~[u8] = cast::transmute(self);
|
||||
buf.capacity()
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert to a vector of bytes. This does not allocate a new
|
||||
/// string, and includes the null terminator.
|
||||
#[cfg(stage0)]
|
||||
#[inline]
|
||||
fn to_bytes_with_null(self) -> ~[u8] {
|
||||
unsafe { cast::transmute(self) }
|
||||
@ -2904,71 +3168,11 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_unsafe_from_bytes_with_null() {
|
||||
let a = [65u8, 65u8, 65u8, 65u8, 65u8, 65u8, 65u8, 0u8];
|
||||
let b = unsafe { raw::from_bytes_with_null(a) };
|
||||
assert_eq!(b, "AAAAAAA");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_from_bytes_with_null() {
|
||||
let ss = "ศไทย中华Việt Nam";
|
||||
let bb = [0xe0_u8, 0xb8_u8, 0xa8_u8,
|
||||
0xe0_u8, 0xb9_u8, 0x84_u8,
|
||||
0xe0_u8, 0xb8_u8, 0x97_u8,
|
||||
0xe0_u8, 0xb8_u8, 0xa2_u8,
|
||||
0xe4_u8, 0xb8_u8, 0xad_u8,
|
||||
0xe5_u8, 0x8d_u8, 0x8e_u8,
|
||||
0x56_u8, 0x69_u8, 0xe1_u8,
|
||||
0xbb_u8, 0x87_u8, 0x74_u8,
|
||||
0x20_u8, 0x4e_u8, 0x61_u8,
|
||||
0x6d_u8, 0x0_u8];
|
||||
|
||||
assert_eq!(ss, from_bytes_with_null(bb));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_fail]
|
||||
#[ignore(cfg(windows))]
|
||||
fn test_from_bytes_with_null_fail() {
|
||||
let bb = [0xff_u8, 0xb8_u8, 0xa8_u8,
|
||||
0xe0_u8, 0xb9_u8, 0x84_u8,
|
||||
0xe0_u8, 0xb8_u8, 0x97_u8,
|
||||
0xe0_u8, 0xb8_u8, 0xa2_u8,
|
||||
0xe4_u8, 0xb8_u8, 0xad_u8,
|
||||
0xe5_u8, 0x8d_u8, 0x8e_u8,
|
||||
0x56_u8, 0x69_u8, 0xe1_u8,
|
||||
0xbb_u8, 0x87_u8, 0x74_u8,
|
||||
0x20_u8, 0x4e_u8, 0x61_u8,
|
||||
0x6d_u8, 0x0_u8];
|
||||
|
||||
let _x = from_bytes_with_null(bb);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_fail]
|
||||
#[ignore(cfg(windows))]
|
||||
fn test_from_bytes_with_null_fail_2() {
|
||||
let bb = [0xff_u8, 0xb8_u8, 0xa8_u8,
|
||||
0xe0_u8, 0xb9_u8, 0x84_u8,
|
||||
0xe0_u8, 0xb8_u8, 0x97_u8,
|
||||
0xe0_u8, 0xb8_u8, 0xa2_u8,
|
||||
0xe4_u8, 0xb8_u8, 0xad_u8,
|
||||
0xe5_u8, 0x8d_u8, 0x8e_u8,
|
||||
0x56_u8, 0x69_u8, 0xe1_u8,
|
||||
0xbb_u8, 0x87_u8, 0x74_u8,
|
||||
0x20_u8, 0x4e_u8, 0x61_u8,
|
||||
0x6d_u8, 0x60_u8];
|
||||
|
||||
let _x = from_bytes_with_null(bb);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_from_buf() {
|
||||
fn test_raw_from_c_str() {
|
||||
unsafe {
|
||||
let a = ~[65u8, 65u8, 65u8, 65u8, 65u8, 65u8, 65u8, 0u8];
|
||||
let a = ~[65, 65, 65, 65, 65, 65, 65, 0];
|
||||
let b = vec::raw::to_ptr(a);
|
||||
let c = raw::from_buf(b);
|
||||
let c = raw::from_c_str(b);
|
||||
assert_eq!(c, ~"AAAAAAA");
|
||||
}
|
||||
}
|
||||
@ -2986,30 +3190,31 @@ mod tests {
|
||||
assert_eq!("ศไทย中华Việt Nam".as_bytes(), v);
|
||||
}
|
||||
|
||||
#[cfg(stage0)]
|
||||
#[test]
|
||||
fn test_as_bytes_with_null() {
|
||||
// has null
|
||||
let v = [
|
||||
224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
|
||||
184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
|
||||
109, 0
|
||||
];
|
||||
|
||||
let s1 = @"";
|
||||
let s2 = @"abc";
|
||||
let s3 = @"ศไทย中华Việt Nam";
|
||||
assert_eq!(s1.as_bytes_with_null(), &[0]);
|
||||
assert_eq!(s2.as_bytes_with_null(), &['a' as u8, 'b' as u8, 'c' as u8, 0]);
|
||||
assert_eq!(s3.as_bytes_with_null(), v);
|
||||
|
||||
let s1 = ~"";
|
||||
let s2 = ~"abc";
|
||||
let s3 = ~"ศไทย中华Việt Nam";
|
||||
assert_eq!(s1.as_bytes_with_null(), &[0]);
|
||||
assert_eq!(s2.as_bytes_with_null(), &['a' as u8, 'b' as u8, 'c' as u8, 0]);
|
||||
assert_eq!(s3.as_bytes_with_null(), v);
|
||||
#[ignore(cfg(windows))]
|
||||
#[should_fail]
|
||||
fn test_as_bytes_fail() {
|
||||
// Don't double free. (I'm not sure if this exercises the
|
||||
// original problem code path anymore.)
|
||||
let s = ~"";
|
||||
let _bytes = s.as_bytes();
|
||||
fail!();
|
||||
}
|
||||
|
||||
#[cfg(stage0)]
|
||||
#[test]
|
||||
#[ignore(cfg(windows))]
|
||||
#[should_fail]
|
||||
fn test_as_bytes_fail() {
|
||||
// Don't double free. (I'm not sure if this exercises the
|
||||
// original problem code path anymore.)
|
||||
let s = ~"";
|
||||
let _bytes = s.as_bytes_with_null();
|
||||
fail!();
|
||||
}
|
||||
|
||||
#[cfg(stage0)]
|
||||
#[test]
|
||||
fn test_to_bytes_with_null() {
|
||||
let s = ~"ศไทย中华Việt Nam";
|
||||
@ -3031,50 +3236,24 @@ mod tests {
|
||||
// Don't double free. (I'm not sure if this exercises the
|
||||
// original problem code path anymore.)
|
||||
let s = ~"";
|
||||
let _bytes = s.as_bytes_with_null();
|
||||
let _bytes = s.as_bytes();
|
||||
fail!();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_as_imm_buf() {
|
||||
do "".as_imm_buf |buf, len| {
|
||||
assert_eq!(len, 1);
|
||||
unsafe {
|
||||
assert_eq!(*ptr::offset(buf, 0), 0);
|
||||
}
|
||||
do "".as_imm_buf |_, len| {
|
||||
assert_eq!(len, 0);
|
||||
}
|
||||
|
||||
do "hello".as_imm_buf |buf, len| {
|
||||
assert_eq!(len, 6);
|
||||
assert_eq!(len, 5);
|
||||
unsafe {
|
||||
assert_eq!(*ptr::offset(buf, 0), 'h' as u8);
|
||||
assert_eq!(*ptr::offset(buf, 1), 'e' as u8);
|
||||
assert_eq!(*ptr::offset(buf, 2), 'l' as u8);
|
||||
assert_eq!(*ptr::offset(buf, 3), 'l' as u8);
|
||||
assert_eq!(*ptr::offset(buf, 4), 'o' as u8);
|
||||
assert_eq!(*ptr::offset(buf, 5), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_as_c_str() {
|
||||
let a = ~"";
|
||||
do a.as_c_str |buf| {
|
||||
unsafe {
|
||||
assert_eq!(*ptr::offset(buf, 0), 0);
|
||||
}
|
||||
}
|
||||
|
||||
let a = ~"hello";
|
||||
do a.as_c_str |buf| {
|
||||
unsafe {
|
||||
assert_eq!(*ptr::offset(buf, 0), 'h' as libc::c_char);
|
||||
assert_eq!(*ptr::offset(buf, 1), 'e' as libc::c_char);
|
||||
assert_eq!(*ptr::offset(buf, 2), 'l' as libc::c_char);
|
||||
assert_eq!(*ptr::offset(buf, 3), 'l' as libc::c_char);
|
||||
assert_eq!(*ptr::offset(buf, 4), 'o' as libc::c_char);
|
||||
assert_eq!(*ptr::offset(buf, 5), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -18,7 +18,9 @@ use container::Container;
|
||||
use cast;
|
||||
use ptr;
|
||||
use iterator::{Iterator, IteratorUtil};
|
||||
use vec::{CopyableVector, ImmutableVector, OwnedVector};
|
||||
use vec::{CopyableVector, ImmutableVector};
|
||||
#[cfg(stage0)]
|
||||
use vec::OwnedVector;
|
||||
use to_bytes::IterBytes;
|
||||
use option::{Some, None};
|
||||
|
||||
@ -96,19 +98,26 @@ impl<'self> AsciiCast<&'self[Ascii]> for &'self [u8] {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'self> AsciiCast<&'self[Ascii]> for &'self str {
|
||||
impl<'self> AsciiCast<&'self [Ascii]> for &'self str {
|
||||
#[inline]
|
||||
fn to_ascii(&self) -> &'self[Ascii] {
|
||||
fn to_ascii(&self) -> &'self [Ascii] {
|
||||
assert!(self.is_ascii());
|
||||
unsafe {self.to_ascii_nocheck()}
|
||||
unsafe { self.to_ascii_nocheck() }
|
||||
}
|
||||
|
||||
#[cfg(stage0)]
|
||||
#[inline]
|
||||
unsafe fn to_ascii_nocheck(&self) -> &'self[Ascii] {
|
||||
unsafe fn to_ascii_nocheck(&self) -> &'self [Ascii] {
|
||||
let (p,len): (*u8, uint) = cast::transmute(*self);
|
||||
cast::transmute((p, len - 1))
|
||||
}
|
||||
|
||||
#[cfg(not(stage0))]
|
||||
#[inline]
|
||||
unsafe fn to_ascii_nocheck(&self) -> &'self [Ascii] {
|
||||
cast::transmute(*self)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_ascii(&self) -> bool {
|
||||
self.byte_iter().all(|b| b.is_ascii())
|
||||
@ -181,12 +190,19 @@ impl OwnedAsciiCast for ~str {
|
||||
unsafe {self.into_ascii_nocheck()}
|
||||
}
|
||||
|
||||
#[cfg(stage0)]
|
||||
#[inline]
|
||||
unsafe fn into_ascii_nocheck(self) -> ~[Ascii] {
|
||||
let mut r: ~[Ascii] = cast::transmute(self);
|
||||
r.pop();
|
||||
r
|
||||
}
|
||||
|
||||
#[cfg(not(stage0))]
|
||||
#[inline]
|
||||
unsafe fn into_ascii_nocheck(self) -> ~[Ascii] {
|
||||
cast::transmute(self)
|
||||
}
|
||||
}
|
||||
|
||||
/// Trait for converting an ascii type to a string. Needed to convert `&[Ascii]` to `~str`
|
||||
@ -205,11 +221,19 @@ pub trait AsciiStr {
|
||||
}
|
||||
|
||||
impl<'self> AsciiStr for &'self [Ascii] {
|
||||
#[cfg(stage0)]
|
||||
#[inline]
|
||||
fn to_str_ascii(&self) -> ~str {
|
||||
let mut cpy = self.to_owned();
|
||||
cpy.push(0u8.to_ascii());
|
||||
unsafe {cast::transmute(cpy)}
|
||||
unsafe { cast::transmute(cpy) }
|
||||
}
|
||||
|
||||
#[cfg(not(stage0))]
|
||||
#[inline]
|
||||
fn to_str_ascii(&self) -> ~str {
|
||||
let cpy = self.to_owned();
|
||||
unsafe { cast::transmute(cpy) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -229,11 +253,18 @@ impl<'self> AsciiStr for &'self [Ascii] {
|
||||
}
|
||||
|
||||
impl ToStrConsume for ~[Ascii] {
|
||||
#[cfg(stage0)]
|
||||
#[inline]
|
||||
fn into_str(self) -> ~str {
|
||||
let mut cpy = self;
|
||||
cpy.push(0u8.to_ascii());
|
||||
unsafe {cast::transmute(cpy)}
|
||||
unsafe { cast::transmute(cpy) }
|
||||
}
|
||||
|
||||
#[cfg(not(stage0))]
|
||||
#[inline]
|
||||
fn into_str(self) -> ~str {
|
||||
unsafe { cast::transmute(self) }
|
||||
}
|
||||
}
|
||||
|
||||
@ -252,7 +283,7 @@ pub trait ToBytesConsume {
|
||||
|
||||
impl ToBytesConsume for ~[Ascii] {
|
||||
fn into_bytes(self) -> ~[u8] {
|
||||
unsafe {cast::transmute(self)}
|
||||
unsafe { cast::transmute(self) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -12,12 +12,12 @@
|
||||
|
||||
#[allow(missing_doc)];
|
||||
|
||||
use c_str::ToCStr;
|
||||
use cast;
|
||||
use io;
|
||||
use libc;
|
||||
use libc::{c_char, size_t};
|
||||
use repr;
|
||||
use str::StrSlice;
|
||||
use str;
|
||||
use unstable::intrinsics;
|
||||
|
||||
@ -105,8 +105,8 @@ pub trait FailWithCause {
|
||||
|
||||
impl FailWithCause for ~str {
|
||||
fn fail_with(cause: ~str, file: &'static str, line: uint) -> ! {
|
||||
do cause.as_c_str |msg_buf| {
|
||||
do file.as_c_str |file_buf| {
|
||||
do cause.to_c_str().with_ref |msg_buf| {
|
||||
do file.to_c_str().with_ref |file_buf| {
|
||||
begin_unwind_(msg_buf, file_buf, line as libc::size_t)
|
||||
}
|
||||
}
|
||||
@ -115,8 +115,8 @@ impl FailWithCause for ~str {
|
||||
|
||||
impl FailWithCause for &'static str {
|
||||
fn fail_with(cause: &'static str, file: &'static str, line: uint) -> ! {
|
||||
do cause.as_c_str |msg_buf| {
|
||||
do file.as_c_str |file_buf| {
|
||||
do cause.to_c_str().with_ref |msg_buf| {
|
||||
do file.to_c_str().with_ref |file_buf| {
|
||||
begin_unwind_(msg_buf, file_buf, line as libc::size_t)
|
||||
}
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ Dynamic library facilities.
|
||||
A simple wrapper over the platforms dynamic library facilities
|
||||
|
||||
*/
|
||||
use c_str::ToCStr;
|
||||
use cast;
|
||||
use path;
|
||||
use libc;
|
||||
@ -65,7 +66,7 @@ impl DynamicLibrary {
|
||||
// T but that feature is still unimplemented
|
||||
|
||||
let maybe_symbol_value = do dl::check_for_errors_in {
|
||||
do symbol.as_c_str |raw_string| {
|
||||
do symbol.to_c_str().with_ref |raw_string| {
|
||||
dl::symbol(self.handle, raw_string)
|
||||
}
|
||||
};
|
||||
@ -135,6 +136,7 @@ mod test {
|
||||
#[cfg(target_os = "macos")]
|
||||
#[cfg(target_os = "freebsd")]
|
||||
mod dl {
|
||||
use c_str::ToCStr;
|
||||
use libc;
|
||||
use path;
|
||||
use ptr;
|
||||
@ -143,7 +145,7 @@ mod dl {
|
||||
use result::*;
|
||||
|
||||
pub unsafe fn open_external(filename: &path::Path) -> *libc::c_void {
|
||||
do filename.to_str().as_c_str |raw_name| {
|
||||
do filename.to_c_str().with_ref |raw_name| {
|
||||
dlopen(raw_name, Lazy as libc::c_int)
|
||||
}
|
||||
}
|
||||
|
@ -549,12 +549,14 @@ pub mod rt {
|
||||
// For strings, precision is the maximum characters
|
||||
// displayed
|
||||
let unpadded = match cv.precision {
|
||||
CountImplied => s,
|
||||
CountIs(max) => if (max as uint) < s.char_len() {
|
||||
s.slice(0, max as uint)
|
||||
} else {
|
||||
s
|
||||
}
|
||||
CountImplied => s,
|
||||
CountIs(max) => {
|
||||
if (max as uint) < s.char_len() {
|
||||
s.slice(0, max as uint)
|
||||
} else {
|
||||
s
|
||||
}
|
||||
}
|
||||
};
|
||||
pad(cv, unpadded, None, PadNozero, buf);
|
||||
}
|
||||
|
@ -10,6 +10,7 @@
|
||||
|
||||
//! Runtime calls emitted by the compiler.
|
||||
|
||||
use c_str::ToCStr;
|
||||
use cast::transmute;
|
||||
use libc::{c_char, c_uchar, c_void, size_t, uintptr_t};
|
||||
use str;
|
||||
@ -28,7 +29,7 @@ pub fn fail_bounds_check(file: *c_char, line: size_t,
|
||||
index: size_t, len: size_t) {
|
||||
let msg = fmt!("index out of bounds: the len is %d but the index is %d",
|
||||
len as int, index as int);
|
||||
do msg.as_c_str |buf| {
|
||||
do msg.to_c_str().with_ref |buf| {
|
||||
fail_(buf, file, line);
|
||||
}
|
||||
}
|
||||
|
@ -292,10 +292,9 @@ void tm_to_rust_tm(tm* in_tm, rust_tm* out_tm, int32_t gmtoff,
|
||||
|
||||
if (zone != NULL) {
|
||||
size_t size = strlen(zone);
|
||||
reserve_vec_exact(&out_tm->tm_zone, size + 1);
|
||||
reserve_vec_exact(&out_tm->tm_zone, size);
|
||||
memcpy(out_tm->tm_zone->data, zone, size);
|
||||
out_tm->tm_zone->fill = size + 1;
|
||||
out_tm->tm_zone->data[size] = '\0';
|
||||
out_tm->tm_zone->fill = size;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,21 +0,0 @@
|
||||
// Copyright 2013 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.
|
||||
|
||||
fn main() {
|
||||
let _ = (~"foo").as_bytes_with_null();
|
||||
let _ = (@"foo").as_bytes_with_null();
|
||||
|
||||
// a plain static slice is null terminated, but such a slice can
|
||||
// be sliced shorter (i.e. become non-null terminated) and still
|
||||
// have the static lifetime
|
||||
let foo: &'static str = "foo";
|
||||
let _ = foo.as_bytes_with_null();
|
||||
//~^ ERROR does not implement any method in scope named `as_bytes_with_null`
|
||||
}
|
@ -20,11 +20,11 @@ mod libc {
|
||||
}
|
||||
|
||||
fn atol(s: ~str) -> int {
|
||||
s.as_imm_buf(|x, _len| unsafe { libc::atol(x) })
|
||||
s.to_c_str().with_ref(|x| unsafe { libc::atol(x as *u8) })
|
||||
}
|
||||
|
||||
fn atoll(s: ~str) -> i64 {
|
||||
s.as_imm_buf(|x, _len| unsafe { libc::atoll(x) })
|
||||
s.to_c_str().with_ref(|x| unsafe { libc::atoll(x as *u8) })
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
|
@ -10,15 +10,20 @@
|
||||
|
||||
use std::str;
|
||||
|
||||
static a: [u8, ..3] = ['h' as u8, 'i' as u8, 0 as u8];
|
||||
static c: &'static [u8, ..3] = &a;
|
||||
static b: *u8 = c as *u8;
|
||||
static A: [u8, ..2] = ['h' as u8, 'i' as u8];
|
||||
static B: &'static [u8, ..2] = &A;
|
||||
static C: *u8 = B as *u8;
|
||||
|
||||
pub fn main() {
|
||||
let foo = &a as *u8;
|
||||
assert_eq!(unsafe { str::raw::from_bytes(a) }, ~"hi\x00");
|
||||
assert_eq!(unsafe { str::raw::from_buf(foo) }, ~"hi");
|
||||
assert_eq!(unsafe { str::raw::from_buf(b) }, ~"hi");
|
||||
assert!(unsafe { *b == a[0] });
|
||||
assert!(unsafe { *(&c[0] as *u8) == a[0] });
|
||||
unsafe {
|
||||
let foo = &A as *u8;
|
||||
assert_eq!(str::raw::from_bytes(A), ~"hi");
|
||||
assert_eq!(str::raw::from_buf_len(foo, A.len()), ~"hi");
|
||||
assert_eq!(str::raw::from_buf_len(C, B.len()), ~"hi");
|
||||
assert!(*C == A[0]);
|
||||
assert!(*(&B[0] as *u8) == A[0]);
|
||||
|
||||
let bar = str::raw::from_bytes(A).to_c_str();
|
||||
assert_eq!(bar.with_ref(|buf| str::raw::from_c_str(buf)), ~"hi");
|
||||
}
|
||||
}
|
||||
|
@ -26,8 +26,9 @@ mod libc {
|
||||
fn strlen(str: ~str) -> uint {
|
||||
unsafe {
|
||||
// C string is terminated with a zero
|
||||
let bytes = str.to_bytes_with_null();
|
||||
return libc::my_strlen(vec::raw::to_ptr(bytes));
|
||||
do str.to_c_str().with_ref |buf| {
|
||||
libc::my_strlen(buf as *u8)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user