// 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;
/// 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
}
}
/// 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 }
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);
}
}
}
}
+#[cfg(stage0)]
priv fn format(val: Param, op: FormatOp, flags: Flags) -> Result<~[u8],~str> {
let mut s = match val {
Number(d) => {
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))]
+priv 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);
}
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;
#[cfg(test)]
mod tests {
- use time::*;
+ use super::*;
use std::float;
use std::os;
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);
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);
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);
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);
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);
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);
use middle::ty;
use util::ppaux;
+use std::c_str::ToCStr;
use std::char;
use std::hash::Streaming;
use std::hash;
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,
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;
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");
}
// 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() {
use back::passes;
+ use std::c_str::ToCStr;
use std::libc::{c_int, c_uint};
use std::path::Path;
use std::run;
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);
}
}
// 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
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);
}
}
// 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};
}
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() {
// 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;
}
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) }
};
use syntax::{ast, attr};
use syntax::attr::AttrMetaMethods;
+use std::c_str::ToCStr;
use std::cast;
use std::io;
use std::num;
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]>; }
# Translation of inline assembly.
*/
+use std::c_str::ToCStr;
use lib;
use middle::trans::build::*;
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)
}
};
use middle::trans::type_::Type;
+use std::c_str::ToCStr;
use std::hash;
use std::hashmap::HashMap;
use std::io;
}
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())
}
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);
// 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)
}
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,
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)
}
}
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)
}
}
};
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)
}
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)
};
};
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)
};
(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);
}
}
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)
};
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);
}
},
}
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)
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)
}
}
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)
}
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)
}
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)
}
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)
}
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);
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);
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)
}
}
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)
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));
use middle::trans::type_::Type;
+use std::c_str::ToCStr;
use std::cast::transmute;
use std::cast;
use std::hashmap::{HashMap};
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)
}
}
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);
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)])
}
}
use middle::trans::type_::Type;
+use std::c_str::ToCStr;
use std::libc::c_uint;
use syntax::{ast, ast_util, ast_map};
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);
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);
use middle::trans::type_::Type;
+use std::c_str::ToCStr;
use std::hash;
use std::hashmap::{HashMap, HashSet};
use std::local_data;
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);
// 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;
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);
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;
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),
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),
};
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),
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,
};
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)
}
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),
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),
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),
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),
Some(discriminant_type_metadata),
span);
- do "".as_c_str |name| {
+ do "".to_c_str().with_ref |name| {
unsafe {
llvm::LLVMDIBuilderCreateMemberType(
DIB(cx),
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),
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),
})
.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),
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),
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));
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));
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)
use middle::trans::type_::Type;
+use std::c_str::ToCStr;
use std::libc::c_uint;
use syntax::ast;
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)
}
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;
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);
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 ]));
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());
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);
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, _) => {
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)
}
use syntax::ast;
use syntax::abi::{Architecture, X86, X86_64, Arm, Mips};
+use std::c_str::ToCStr;
use std::vec;
use std::cast;
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 {
// except according to those terms.
use std::{os, result};
+use std::c_str::ToCStr;
use rustc::driver::{driver, session};
use rustc::metadata::filesearch;
use extra::getopts::groups::getopts;
pub fn link_exe(src: &Path, dest: &Path) -> bool {
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
}
--- /dev/null
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use cast;
+use iterator::Iterator;
+use libc;
+use ops::Drop;
+use option::{Option, Some, None};
+use ptr::RawPtr;
+use ptr;
+use str::StrSlice;
+use vec::ImmutableVector;
+
+/**
+ * The representation of a C String.
+ *
+ * This structure wraps a `*libc::c_char`, and will automatically free the
+ * memory it is pointing to when it goes out of scope.
+ */
+pub struct CString {
+ priv buf: *libc::c_char,
+}
+
+impl<'self> CString {
+ /**
+ * Create a C String from a str.
+ */
+ pub fn from_str(s: &str) -> CString {
+ s.to_c_str()
+ }
+
+ /**
+ * Take the wrapped `*libc::c_char` from the `CString` wrapper.
+ *
+ * # Failure
+ *
+ * If the wrapper is empty.
+ */
+ pub unsafe fn take(&mut self) -> *libc::c_char {
+ if self.buf.is_null() {
+ fail!("CString has no wrapped `*libc::c_char`");
+ }
+ let buf = self.buf;
+ self.buf = ptr::null();
+ buf
+ }
+
+ /**
+ * Puts a `*libc::c_char` into the `CString` wrapper.
+ *
+ * # Failure
+ *
+ * If the `*libc::c_char` is null.
+ * If the wrapper is not empty.
+ */
+ pub fn put_back(&mut self, buf: *libc::c_char) {
+ if buf.is_null() {
+ fail!("attempt to put a null pointer into a CString");
+ }
+ if self.buf.is_not_null() {
+ fail!("CString already wraps a `*libc::c_char`");
+ }
+ self.buf = buf;
+ }
+
+ /**
+ * Calls a closure with a reference to the underlying `*libc::c_char`.
+ */
+ pub fn with_ref<T>(&self, f: &fn(*libc::c_char) -> T) -> T {
+ if self.buf.is_null() {
+ fail!("CString already wraps a `*libc::c_char`");
+ }
+ f(self.buf)
+ }
+
+ /**
+ * Calls a closure with a mutable reference to the underlying `*libc::c_char`.
+ */
+ pub fn with_mut_ref<T>(&mut self, f: &fn(*mut libc::c_char) -> T) -> T {
+ if self.buf.is_not_null() {
+ fail!("CString already wraps a `*libc::c_char`");
+ }
+ f(unsafe { cast::transmute(self.buf) })
+ }
+
+ /**
+ * Returns true if the CString does not wrap a `*libc::c_char`.
+ */
+ pub fn is_empty(&self) -> bool {
+ self.buf.is_null()
+ }
+
+ /**
+ * Returns true if the CString wraps a `*libc::c_char`.
+ */
+ pub fn is_not_empty(&self) -> bool {
+ self.buf.is_not_null()
+ }
+
+ /**
+ * Converts the CString into a `&[u8]` without copying.
+ */
+ pub fn as_bytes(&self) -> &'self [u8] {
+ unsafe {
+ let len = libc::strlen(self.buf) as uint;
+ cast::transmute((self.buf, len + 1))
+ }
+ }
+
+ /**
+ * Return a CString iterator.
+ */
+ fn iter(&self) -> CStringIterator<'self> {
+ CStringIterator {
+ ptr: self.buf,
+ lifetime: unsafe { cast::transmute(self.buf) },
+ }
+ }
+}
+
+impl Drop for CString {
+ fn drop(&self) {
+ if self.buf.is_not_null() {
+ unsafe {
+ libc::free(self.buf as *libc::c_void)
+ };
+ }
+ }
+}
+
+/**
+ * A generic trait for converting a value to a CString.
+ */
+pub trait ToCStr {
+ /**
+ * Create a C String.
+ */
+ fn to_c_str(&self) -> CString;
+}
+
+impl<'self> ToCStr for &'self str {
+ /**
+ * Create a C String from a `&str`.
+ */
+ fn to_c_str(&self) -> CString {
+ self.as_bytes().to_c_str()
+ }
+}
+
+impl<'self> ToCStr for &'self [u8] {
+ /**
+ * Create a C String from a `&[u8]`.
+ */
+ fn to_c_str(&self) -> CString {
+ do self.as_imm_buf |self_buf, self_len| {
+ unsafe {
+ let buf = libc::malloc(self_len as u64 + 1) as *mut u8;
+ if buf.is_null() {
+ fail!("failed to allocate memory!");
+ }
+
+ ptr::copy_memory(buf, self_buf, self_len);
+ *ptr::mut_offset(buf, self_len as int) = 0;
+ CString { buf: buf as *libc::c_char }
+ }
+ }
+ }
+}
+
+/**
+ * External iterator for a CString's bytes.
+ *
+ * Use with the `std::iterator` module.
+ */
+pub struct CStringIterator<'self> {
+ priv ptr: *libc::c_char,
+ priv lifetime: &'self libc::c_char, // FIXME: #5922
+}
+
+impl<'self> Iterator<libc::c_char> for CStringIterator<'self> {
+ /**
+ * Advance the iterator.
+ */
+ fn next(&mut self) -> Option<libc::c_char> {
+ if self.ptr.is_null() {
+ None
+ } else {
+ let ch = unsafe { *self.ptr };
+ self.ptr = ptr::offset(self.ptr, 1);
+ Some(ch)
+ }
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use libc;
+ use ptr;
+
+ #[test]
+ fn test_to_c_str() {
+ do "".to_c_str().with_ref |buf| {
+ unsafe {
+ assert_eq!(*ptr::offset(buf, 0), 0);
+ }
+ }
+
+ do "hello".to_c_str().with_ref |buf| {
+ unsafe {
+ assert_eq!(*ptr::offset(buf, 0), 'h' as libc::c_char);
+ assert_eq!(*ptr::offset(buf, 1), 'e' as libc::c_char);
+ assert_eq!(*ptr::offset(buf, 2), 'l' as libc::c_char);
+ assert_eq!(*ptr::offset(buf, 3), 'l' as libc::c_char);
+ assert_eq!(*ptr::offset(buf, 4), 'o' as libc::c_char);
+ assert_eq!(*ptr::offset(buf, 5), 0);
+ }
+ }
+ }
+
+ #[test]
+ fn test_take() {
+ let mut c_str = "hello".to_c_str();
+ unsafe { libc::free(c_str.take() as *libc::c_void) }
+ assert!(c_str.is_empty());
+ }
+
+ #[test]
+ fn test_take_and_put_back() {
+ let mut c_str = "hello".to_c_str();
+ assert!(c_str.is_not_empty());
+
+ let buf = unsafe { c_str.take() };
+
+ assert!(c_str.is_empty());
+
+ c_str.put_back(buf);
+
+ assert!(c_str.is_not_empty());
+ }
+
+ #[test]
+ #[should_fail]
+ #[ignore(cfg(windows))]
+ fn test_take_empty_fail() {
+ let mut c_str = "hello".to_c_str();
+ unsafe {
+ libc::free(c_str.take() as *libc::c_void);
+ c_str.take();
+ }
+ }
+
+ #[test]
+ #[should_fail]
+ #[ignore(cfg(windows))]
+ fn test_put_back_null_fail() {
+ let mut c_str = "hello".to_c_str();
+ c_str.put_back(ptr::null());
+ }
+
+ #[test]
+ #[should_fail]
+ #[ignore(cfg(windows))]
+ fn test_put_back_full_fail() {
+ let mut c_str = "hello".to_c_str();
+ c_str.put_back(0xdeadbeef as *libc::c_char);
+ }
+
+ fn test_with() {
+ let c_str = "hello".to_c_str();
+ let len = unsafe { c_str.with_ref(|buf| libc::strlen(buf)) };
+ assert!(c_str.is_not_empty());
+ assert_eq!(len, 5);
+ }
+
+ #[test]
+ #[should_fail]
+ #[ignore(cfg(windows))]
+ fn test_with_empty_fail() {
+ let mut c_str = "hello".to_c_str();
+ unsafe { libc::free(c_str.take() as *libc::c_void) }
+ c_str.with_ref(|_| ());
+ }
+}
}
}
+ #[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"));
+ }
+ }
+
}
use cast;
use clone::Clone;
+use c_str::ToCStr;
use container::Container;
use int;
use iterator::Iterator;
}
pub fn file_reader(path: &Path) -> Result<@Reader, ~str> {
- let f = do path.to_str().as_c_str |pathbuf| {
- do "r".as_c_str |modebuf| {
+ let f = do path.to_c_str().with_ref |pathbuf| {
+ do "r".to_c_str().with_ref |modebuf| {
unsafe { libc::fopen(pathbuf, modebuf as *libc::c_char) }
}
};
}
}
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) {
// 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)
}
};
(*bytes).clone()
}
+#[cfg(stage0)]
pub fn with_str_writer(f: &fn(@Writer)) -> ~str {
let mut v = with_bytes_writer(f);
}
}
+#[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 {
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"]
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 ;
#[allow(missing_doc)];
-use cast;
+use c_str::ToCStr;
use clone::Clone;
use container::Container;
use io;
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]))
}
}
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
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))
}
}
}
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);
}
}
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);
}
}
}
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)
}
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)
}
}
}
/// 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
}
}
/// 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
}
}
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))
- != (0 as libc::BOOL)
+ libc::CreateDirectoryW(buf, ptr::null()) != (0 as libc::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)
}
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(
closedir(dir_ptr);
}
else {
- debug!("os::list_dir -- opendir() FAILURE");
+ debug!("os::list_dir -- opendir() FAILURE");
}
debug!(
"os::list_dir -- AFTER -- #: %?",
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 {
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)
#[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)
}
#[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)
}
#[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)
}
};
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)
}
};
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...
#[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)
}
}
}
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)
+ }
}
}
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;
- 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());
- }
- str::raw::from_c_str(&buf[0])
+ let mut buf = [0 as c_char, ..TMPBUF_SZ];
+
+ do buf.as_imm_buf |buf, len| {
+ unsafe {
+ 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)
+ }
}
}
}
unsafe {
- LocalFree(cast::transmute(szArgList));
+ LocalFree(szArgList as *c_void);
}
return args;
}
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(|| {
#[cfg(test)]
mod tests {
+ use c_str::ToCStr;
use libc::{c_int, c_void, size_t};
use libc;
use option::Some;
use rand;
use run;
use str::StrSlice;
- use vec::CopyableVector;
use libc::consts::os::posix88::{S_IRUSR, S_IWUSR, S_IXUSR};
#[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");
-
- /* Write the temp input file */
- let ostream = do input.to_str().as_c_str |fromp| {
- do "w+b".as_c_str |modebuf| {
+ 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_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)));
}
}
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
#[allow(missing_doc)];
+use c_str::ToCStr;
+use c_str;
use clone::Clone;
-use container::Container;
use cmp::Eq;
+use container::Container;
use iterator::{Iterator, IteratorUtil};
use libc;
use option::{None, Option, Some};
#[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),
#[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),
#[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),
}
}
+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 {
}
}
+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 {
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;
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};
use super::*;
use prelude::*;
+ use c_str::ToCStr;
use cast;
use libc;
use str;
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);
#[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))]
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use c_str::ToCStr;
use cast::transmute;
use libc::{c_char, c_void, size_t, STDERR_FILENO};
use io;
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
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)
}
}
}
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
/// 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) }
}
}
// 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::uv::*;
-use rt::uv::idle::IdleWatcher;
-use rt::uv::net::{UvIpv4SocketAddr, UvIpv6SocketAddr};
+use rt::io::{standard_error, OtherIoError};
+use rt::local::Local;
use rt::rtio::*;
use rt::sched::Scheduler;
-use rt::io::{standard_error, OtherIoError};
use rt::tube::Tube;
-use rt::local::Local;
-use str::StrSlice;
+use rt::uv::*;
+use rt::uv::idle::IdleWatcher;
+use rt::uv::net::{UvIpv4SocketAddr, UvIpv6SocketAddr};
use unstable::sync::Exclusive;
#[cfg(test)] use container::Container;
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)
}
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)
}
#[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;
}
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)
}
}
#[allow(missing_doc)];
+use c_str::ToCStr;
use cast;
use clone::Clone;
use comm::{stream, SharedChan, GenericChan, GenericPort};
use ptr;
use task;
use vec::ImmutableVector;
+use vec;
/**
* A value representing a child process.
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);
}
#[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 {
+ // 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.
+ // 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(es) => {
- let mut tmps = ~[];
- let mut ptrs = ~[];
-
- 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));
- }
+ 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());
}
- }
- ptrs.push(ptr::null());
- ptrs.as_imm_buf(|p, _len|
- unsafe { cb(::cast::transmute(p)) }
- )
- }
- _ => cb(ptr::null())
+ // 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)) }
+ }
+ }
+ _ => cb(ptr::null())
}
}
// 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())
}
}
pub mod gc;
pub mod libc;
+pub mod c_str;
pub mod os;
pub mod path;
pub mod rand;
use ptr::RawPtr;
use to_str::ToStr;
use uint;
+#[cfg(stage0)]
use unstable::raw::Repr;
use vec;
use vec::{OwnedVector, OwnedCopyableVector, ImmutableVector, MutableVector};
}
}
-/// 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.
-///
-/// Compared to `from_bytes()`, this fn doesn't need to allocate a new owned str.
-///
-/// # 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) };
-}
-
/// Converts a vector to a string slice without performing any allocations.
///
/// Once the slice has been validated as utf-8, it is transmuted in-place and
/// # Failure
///
/// Fails if invalid UTF-8
+#[cfg(stage0)]
pub fn from_bytes_slice<'a>(vector: &'a [u8]) -> &'a str {
unsafe {
assert!(is_utf8(vector));
}
}
+/// Converts a vector to a string slice without performing any allocations.
+///
+/// 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
+#[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 {
#[inline]
fn to_str(&self) -> ~str { self.to_owned() }
/// # 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 = ~"";
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 ~""; }
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 ~""; }
}
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
*/
/// Bytewise slice equality
-#[cfg(not(test))]
+#[cfg(not(test), stage0)]
#[lang="str_eq"]
#[inline]
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| {
}
}
+/// 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"]
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| {
v.push(0u8);
assert!(is_utf8(v));
- return cast::transmute(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 *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 `*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)
+ /// Create a Rust string from a null-terminated C string
+ 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.
/// 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)
}
/// 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;
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`).
///
/// If begin is greater than end.
/// If end is greater than the length of the string.
+ #[cfg(stage0)]
#[inline]
pub unsafe fn slice_bytes(s: &str, begin: uint, end: uint) -> &str {
do s.as_imm_buf |sbuf, n| {
}
}
+ /// 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).
pub unsafe fn push_byte(s: &mut ~str, b: u8) {
let new_len = s.len() + 1;
}
/// 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);
*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 {
}
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 {
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
}
/// Copy a slice into a new unique str
+ #[cfg(stage0)]
#[inline]
fn to_owned(&self) -> ~str {
do self.as_imm_buf |src, len| {
}
}
+ /// 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| {
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 = ~[];
/// 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();
}
}
+ /// 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
}
/// 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
}
}
+ /// 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
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)]
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.
///
/// * s - A string
/// * n - The number of bytes to reserve space for
+ #[cfg(stage0)]
#[inline]
pub fn reserve(&mut self, n: uint) {
unsafe {
}
}
+ /// 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.
///
///
/// * 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();
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) }
}
#[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");
}
}
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);
+ #[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!();
+ }
- 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);
+ #[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";
// 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);
}
}
}
use str::StrSlice;
use cast;
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};
}
}
-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())
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`
}
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]
}
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) }
}
}
impl ToBytesConsume for ~[Ascii] {
fn into_bytes(self) -> ~[u8] {
- unsafe {cast::transmute(self)}
+ unsafe { cast::transmute(self) }
}
}
#[allow(missing_doc)];
+use c_str::ToCStr;
use cast;
use gc;
use io;
use libc;
use libc::{c_char, size_t};
use repr;
-use str::StrSlice;
use str;
use unstable::intrinsics;
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)
}
}
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)
}
}
A simple wrapper over the platforms dynamic library facilities
*/
+use c_str::ToCStr;
use cast;
use path;
use libc;
// 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)
}
};
#[cfg(target_os = "macos")]
#[cfg(target_os = "freebsd")]
mod dl {
+ use c_str::ToCStr;
use libc;
use path;
use ptr;
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)
}
}
// 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);
}
//! Runtime calls emitted by the compiler.
+use c_str::ToCStr;
use cast::transmute;
use libc::{c_char, c_uchar, c_void, size_t, uintptr_t, c_int};
use str;
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);
}
}
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;
}
}
+++ /dev/null
-// 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`
-}
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");
+ }
}
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)
+ }
}
}