]> git.lizzy.rs Git - rust.git/commitdiff
Merge remote-tracking branch 'remotes/origin/master' into str-remove-null
authorErick Tryzelaar <erick.tryzelaar@gmail.com>
Sun, 4 Aug 2013 23:23:41 +0000 (16:23 -0700)
committerErick Tryzelaar <erick.tryzelaar@gmail.com>
Sun, 4 Aug 2013 23:23:41 +0000 (16:23 -0700)
46 files changed:
src/libextra/rl.rs
src/libextra/terminfo/parm.rs
src/libextra/time.rs
src/librustc/back/link.rs
src/librustc/back/passes.rs
src/librustc/lib/llvm.rs
src/librustc/metadata/loader.rs
src/librustc/middle/trans/asm.rs
src/librustc/middle/trans/base.rs
src/librustc/middle/trans/builder.rs
src/librustc/middle/trans/common.rs
src/librustc/middle/trans/consts.rs
src/librustc/middle/trans/context.rs
src/librustc/middle/trans/controlflow.rs
src/librustc/middle/trans/debuginfo.rs
src/librustc/middle/trans/expr.rs
src/librustc/middle/trans/glue.rs
src/librustc/middle/trans/meth.rs
src/librustc/middle/trans/reflect.rs
src/librustc/middle/trans/tvec.rs
src/librustc/middle/trans/type_.rs
src/librustpkg/util.rs
src/libstd/c_str.rs [new file with mode: 0644]
src/libstd/cast.rs
src/libstd/io.rs
src/libstd/libc.rs
src/libstd/os.rs
src/libstd/path.rs
src/libstd/prelude.rs
src/libstd/ptr.rs
src/libstd/rt/borrowck.rs
src/libstd/rt/logging.rs
src/libstd/rt/uv/uvio.rs
src/libstd/rt/uv/uvll.rs
src/libstd/run.rs
src/libstd/std.rs
src/libstd/str.rs
src/libstd/str/ascii.rs
src/libstd/sys.rs
src/libstd/unstable/dynamic_lib.rs
src/libstd/unstable/extfmt.rs
src/libstd/unstable/lang.rs
src/rt/rust_builtin.cpp
src/test/compile-fail/static-slice-not-null-terminated.rs [deleted file]
src/test/run-pass/const-str-ptr.rs
src/test/run-pass/foreign-fn-linkname.rs

index 8aff8d388877f367e8e042cd4b23518b8b97c83b..9106d4cd684d916f5c6d58bcbb83dd87962cce90 100644 (file)
@@ -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);
                     }
                 }
index b619e0f33b644663bb43ba781c3688411f3f1679..a7cace2344643a0c08fd230a2e0bf0adb0f906a8 100644 (file)
@@ -476,6 +476,7 @@ impl FormatOp {
     }
 }
 
+#[cfg(stage0)]
 priv fn format(val: Param, op: FormatOp, flags: Flags) -> Result<~[u8],~str> {
     let mut s = match val {
         Number(d) => {
@@ -545,8 +546,103 @@ impl FormatOp {
         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);
                     }
index efc3dc87adc00f02887a3980fb20c7931cae69f6..52feb18c7581a4a8d846d5fdbb73c7b573fc95a0 100644 (file)
@@ -287,10 +287,14 @@ fn match_strs(ss: &str, pos: uint, strs: &[(~str, i32)])
     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;
 
@@ -856,7 +860,7 @@ fn parse_type(ch: char, tm: &Tm) -> ~str {
 
 #[cfg(test)]
 mod tests {
-    use time::*;
+    use super::*;
 
     use std::float;
     use std::os;
@@ -904,7 +908,7 @@ fn test_at_utc() {
         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);
@@ -925,7 +929,7 @@ fn test_at() {
         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);
@@ -953,7 +957,7 @@ fn test_to_timespec() {
         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);
@@ -964,7 +968,7 @@ fn test_conversions() {
         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);
 
@@ -1145,7 +1149,7 @@ fn test_ctime() {
         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);
 
@@ -1159,7 +1163,7 @@ fn test_strftime() {
         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);
 
index f066ede65f976c8af7de89fa5f2122230b9561c6..0f7e1413bc53ed711d0a49e92d23b8acc6d030ca 100644 (file)
@@ -22,6 +22,7 @@
 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 fn exec(sess: Session,
 
                 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 fn exec(sess: Session,
             // 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 fn run_passes(sess: Session,
                   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 fn run_passes(sess: Session,
                     // 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 fn run_passes(sess: Session,
 
             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);
                 }
             }
index b77ed10c21ba4e3b5abe4cefea307125ac0bc81c..c5b60c654daec15d514bd366b5c4c469e2d91106 100644 (file)
@@ -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() {
index 356cdaf754eebe7b199bf20870b46568e552d317..dfca804939e6d747018bbc28856a3c12572ac02c 100644 (file)
@@ -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) }
     };
 
index 9330cfc5c88b48fc4deade90b90c0298348955fd..058be7cc5581169459fe4988b0fbe999e62887d0 100644 (file)
@@ -24,6 +24,7 @@
 use syntax::{ast, attr};
 use syntax::attr::AttrMetaMethods;
 
+use std::c_str::ToCStr;
 use std::cast;
 use std::io;
 use std::num;
@@ -186,7 +187,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]>; }
index e54724b02ad40efd0225b389488ffb4b20c64e24..b6057199a280fbccddba02aefe60d7b20f42c5f7 100644 (file)
@@ -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)
         }
     };
index fc39af095b79c9a1dea95f31d789d7190ce4c2fb..edeca5e3e8cc5b189be767bd15a51a937601d2f3 100644 (file)
@@ -65,6 +65,7 @@
 
 use middle::trans::type_::Type;
 
+use std::c_str::ToCStr;
 use std::hash;
 use std::hashmap::HashMap;
 use std::io;
@@ -179,7 +180,7 @@ pub fn drop(&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)
         }
     }
@@ -2319,7 +2320,7 @@ fn create_entry_fn(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)
             }
@@ -2329,7 +2330,7 @@ fn create_entry_fn(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)
             };
 
@@ -2347,7 +2348,7 @@ fn create_entry_fn(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)
                     };
 
@@ -2372,11 +2373,10 @@ fn create_entry_fn(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);
         }
     }
@@ -2435,7 +2435,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)
                                 };
 
@@ -2459,7 +2459,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);
                             }
                         },
@@ -2500,7 +2500,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)
@@ -2606,7 +2606,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)
                 }
@@ -2747,7 +2747,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)
         }
@@ -2762,7 +2762,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)
         }
@@ -2810,7 +2810,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)
         }
@@ -2829,7 +2829,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)
             }
@@ -2892,21 +2892,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);
@@ -2920,7 +2920,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);
index 1d821e5af94bd3769c8477a846978c66564209e9..7d7fc9c087e64c97918e61af47bc87db2ba8771d 100644 (file)
@@ -423,7 +423,7 @@ pub fn alloca(&self, ty: Type, name: &str) -> ValueRef {
             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 @@ pub fn add_comment(&self, text: &str) {
             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 @@ pub fn trap(&self) {
             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));
index 527706be6c1f75a3e3a4960e72543f26437f3c19..b8fba9352a356b3736b072a68f7231fbdf67d8ac 100644 (file)
@@ -31,6 +31,7 @@
 
 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)])
     }
 }
 
index 40d0d77c16ecb11cfe39ddcc75bc86a059ba1823..0cb423d4921eb77a0ab654d279d5b6d2e892bc9d 100644 (file)
@@ -30,6 +30,7 @@
 
 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);
index 802163583d6a1dacb8ee552cbf392403f5d7ca27..54c957d115a4da811d9e4d7120ff2cf8d414e345 100644 (file)
@@ -26,6 +26,7 @@
 
 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 @@ pub fn new(sess: session::Session,
         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);
index 4fa64b4130aa9901fc39ece115e5443667814dd7..fe75ea390e693912f20573f0970fb7bd49e9e8f6 100644 (file)
@@ -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);
index e31a27a4c6ca0a035e2dcf9e2e158833e6bf13f8..c427c34e1d85dbed268a5f0179b2924429109ea7 100644 (file)
@@ -63,6 +63,7 @@
 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),
index a44f93214881b3b7e0898e19f70488f4148a701d..8c63be084fd55bfdb93af5e8ca8b8ee7bfa8ad68 100644 (file)
@@ -849,7 +849,6 @@ fn trans_index(bcx: @mut Block,
 
         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_index(bcx: @mut Block,
         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 get_val(bcx: @mut Block, did: ast::def_id, const_ty: ty::t)
                             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)
index 659f56b355e790c1bf81a1bdbaed02989842506f..925b3dd62db5c2a7bbed8ab8901490dec3bdb70c 100644 (file)
@@ -37,6 +37,7 @@
 
 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)
         }
index b67d88c07e1e6207dae5da20f96ed72150f33ff7..13f11d23c3bf3b6c899d80adeaa96a0094d6c1af 100644 (file)
@@ -32,6 +32,7 @@
 
 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);
index e4259c80720e672401c7e586755b537820b253a0..340964ff97b270cf79735d4057e3adba36aea862 100644 (file)
@@ -58,7 +58,7 @@ pub fn c_slice(&mut self, s: @str) -> ValueRef {
         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 ]));
index 34404e49317b6d396ef0919f2df47ca2e51b6394..5b0e2fa18f240af3716c6604a6ae391512b18d5e 100644 (file)
@@ -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)
         }
index 9bb7f9571f39f1775b5e3c9a32ba324a866edd83..110febfcc9f579b7080786fb98335b77c7f6a678 100644 (file)
@@ -20,6 +20,7 @@
 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 @@ pub fn struct_(els: &[Type], packed: bool) -> 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 {
index 361981289d3cef4c84be40d7304b17977d8e9d0b..7a5d8bca38a01ec617cc94fd295f49e9c3c28e69 100644 (file)
@@ -9,6 +9,7 @@
 // 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;
@@ -374,8 +375,8 @@ pub fn link_exe(_src: &Path, _dest: &Path) -> bool {
 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
             }
diff --git a/src/libstd/c_str.rs b/src/libstd/c_str.rs
new file mode 100644 (file)
index 0000000..29aa68b
--- /dev/null
@@ -0,0 +1,291 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use cast;
+use iterator::Iterator;
+use libc;
+use ops::Drop;
+use option::{Option, Some, None};
+use ptr::RawPtr;
+use ptr;
+use str::StrSlice;
+use vec::ImmutableVector;
+
+/**
+ * The representation of a C String.
+ *
+ * This structure wraps a `*libc::c_char`, and will automatically free the
+ * memory it is pointing to when it goes out of scope.
+ */
+pub struct CString {
+    priv buf: *libc::c_char,
+}
+
+impl<'self> CString {
+    /**
+     * Create a C String from a str.
+     */
+    pub fn from_str(s: &str) -> CString {
+        s.to_c_str()
+    }
+
+    /**
+     * Take the wrapped `*libc::c_char` from the `CString` wrapper.
+     *
+     * # Failure
+     *
+     * If the wrapper is empty.
+     */
+    pub unsafe fn take(&mut self) -> *libc::c_char {
+        if self.buf.is_null() {
+            fail!("CString has no wrapped `*libc::c_char`");
+        }
+        let buf = self.buf;
+        self.buf = ptr::null();
+        buf
+    }
+
+    /**
+     * Puts a `*libc::c_char` into the `CString` wrapper.
+     *
+     * # Failure
+     *
+     * If the `*libc::c_char` is null.
+     * If the wrapper is not empty.
+     */
+    pub fn put_back(&mut self, buf: *libc::c_char) {
+        if buf.is_null() {
+            fail!("attempt to put a null pointer into a CString");
+        }
+        if self.buf.is_not_null() {
+            fail!("CString already wraps a `*libc::c_char`");
+        }
+        self.buf = buf;
+    }
+
+    /**
+     * Calls a closure with a reference to the underlying `*libc::c_char`.
+     */
+    pub fn with_ref<T>(&self, f: &fn(*libc::c_char) -> T) -> T {
+        if self.buf.is_null() {
+            fail!("CString already wraps a `*libc::c_char`");
+        }
+        f(self.buf)
+    }
+
+    /**
+     * Calls a closure with a mutable reference to the underlying `*libc::c_char`.
+     */
+    pub fn with_mut_ref<T>(&mut self, f: &fn(*mut libc::c_char) -> T) -> T {
+        if self.buf.is_not_null() {
+            fail!("CString already wraps a `*libc::c_char`");
+        }
+        f(unsafe { cast::transmute(self.buf) })
+    }
+
+    /**
+     * Returns true if the CString does not wrap a `*libc::c_char`.
+     */
+    pub fn is_empty(&self) -> bool {
+        self.buf.is_null()
+    }
+
+    /**
+     * Returns true if the CString wraps a `*libc::c_char`.
+     */
+    pub fn is_not_empty(&self) -> bool {
+        self.buf.is_not_null()
+    }
+
+    /**
+     * Converts the CString into a `&[u8]` without copying.
+     */
+    pub fn as_bytes(&self) -> &'self [u8] {
+        unsafe {
+            let len = libc::strlen(self.buf) as uint;
+            cast::transmute((self.buf, len + 1))
+        }
+    }
+
+    /**
+     * Return a CString iterator.
+     */
+    fn iter(&self) -> CStringIterator<'self> {
+        CStringIterator {
+            ptr: self.buf,
+            lifetime: unsafe { cast::transmute(self.buf) },
+        }
+    }
+}
+
+impl Drop for CString {
+    fn drop(&self) {
+        if self.buf.is_not_null() {
+            unsafe {
+                libc::free(self.buf as *libc::c_void)
+            };
+        }
+    }
+}
+
+/**
+ * A generic trait for converting a value to a CString.
+ */
+pub trait ToCStr {
+    /**
+     * Create a C String.
+     */
+    fn to_c_str(&self) -> CString;
+}
+
+impl<'self> ToCStr for &'self str {
+    /**
+     * Create a C String from a `&str`.
+     */
+    fn to_c_str(&self) -> CString {
+        self.as_bytes().to_c_str()
+    }
+}
+
+impl<'self> ToCStr for &'self [u8] {
+    /**
+     * Create a C String from a `&[u8]`.
+     */
+    fn to_c_str(&self) -> CString {
+        do self.as_imm_buf |self_buf, self_len| {
+            unsafe {
+                let buf = libc::malloc(self_len as u64 + 1) as *mut u8;
+                if buf.is_null() {
+                    fail!("failed to allocate memory!");
+                }
+
+                ptr::copy_memory(buf, self_buf, self_len);
+                *ptr::mut_offset(buf, self_len as int) = 0;
+                CString { buf: buf as *libc::c_char }
+            }
+        }
+    }
+}
+
+/**
+ * External iterator for a CString's bytes.
+ *
+ * Use with the `std::iterator` module.
+ */
+pub struct CStringIterator<'self> {
+    priv ptr: *libc::c_char,
+    priv lifetime: &'self libc::c_char, // FIXME: #5922
+}
+
+impl<'self> Iterator<libc::c_char> for CStringIterator<'self> {
+    /**
+     * Advance the iterator.
+     */
+    fn next(&mut self) -> Option<libc::c_char> {
+        if self.ptr.is_null() {
+            None
+        } else {
+            let ch = unsafe { *self.ptr };
+            self.ptr = ptr::offset(self.ptr, 1);
+            Some(ch)
+        }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use libc;
+    use ptr;
+
+    #[test]
+    fn test_to_c_str() {
+        do "".to_c_str().with_ref |buf| {
+            unsafe {
+                assert_eq!(*ptr::offset(buf, 0), 0);
+            }
+        }
+
+        do "hello".to_c_str().with_ref |buf| {
+            unsafe {
+                assert_eq!(*ptr::offset(buf, 0), 'h' as libc::c_char);
+                assert_eq!(*ptr::offset(buf, 1), 'e' as libc::c_char);
+                assert_eq!(*ptr::offset(buf, 2), 'l' as libc::c_char);
+                assert_eq!(*ptr::offset(buf, 3), 'l' as libc::c_char);
+                assert_eq!(*ptr::offset(buf, 4), 'o' as libc::c_char);
+                assert_eq!(*ptr::offset(buf, 5), 0);
+            }
+        }
+    }
+
+    #[test]
+    fn test_take() {
+        let mut c_str = "hello".to_c_str();
+        unsafe { libc::free(c_str.take() as *libc::c_void) }
+        assert!(c_str.is_empty());
+    }
+
+    #[test]
+    fn test_take_and_put_back() {
+        let mut c_str = "hello".to_c_str();
+        assert!(c_str.is_not_empty());
+
+        let buf = unsafe { c_str.take() };
+
+        assert!(c_str.is_empty());
+
+        c_str.put_back(buf);
+
+        assert!(c_str.is_not_empty());
+    }
+
+    #[test]
+    #[should_fail]
+    #[ignore(cfg(windows))]
+    fn test_take_empty_fail() {
+        let mut c_str = "hello".to_c_str();
+        unsafe {
+            libc::free(c_str.take() as *libc::c_void);
+            c_str.take();
+        }
+    }
+
+    #[test]
+    #[should_fail]
+    #[ignore(cfg(windows))]
+    fn test_put_back_null_fail() {
+        let mut c_str = "hello".to_c_str();
+        c_str.put_back(ptr::null());
+    }
+
+    #[test]
+    #[should_fail]
+    #[ignore(cfg(windows))]
+    fn test_put_back_full_fail() {
+        let mut c_str = "hello".to_c_str();
+        c_str.put_back(0xdeadbeef as *libc::c_char);
+    }
+
+    fn test_with() {
+        let c_str = "hello".to_c_str();
+        let len = unsafe { c_str.with_ref(|buf| libc::strlen(buf)) };
+        assert!(c_str.is_not_empty());
+        assert_eq!(len, 5);
+    }
+
+    #[test]
+    #[should_fail]
+    #[ignore(cfg(windows))]
+    fn test_with_empty_fail() {
+        let mut c_str = "hello".to_c_str();
+        unsafe { libc::free(c_str.take() as *libc::c_void) }
+        c_str.with_ref(|_| ());
+    }
+}
index ee91d12790953214b49a0c25327a141e8cd03ee9..ff9057afb55fc47dfb1b10f88d8b7b958d757f34 100644 (file)
@@ -165,10 +165,20 @@ fn test_transmute() {
         }
     }
 
+    #[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"));
+        }
+    }
+
 }
index f750f3f3195e7157901ea67316de27da945b8352..1c2fc5db443f41a02a8d54c42def6491528f8cb8 100644 (file)
@@ -48,6 +48,7 @@
 
 use cast;
 use clone::Clone;
+use c_str::ToCStr;
 use container::Container;
 use int;
 use iterator::Iterator;
@@ -1040,8 +1041,8 @@ pub fn stdin() -> @Reader {
 }
 
 pub fn file_reader(path: &Path) -> Result<@Reader, ~str> {
-    let f = do path.to_str().as_c_str |pathbuf| {
-        do "r".as_c_str |modebuf| {
+    let f = do path.to_c_str().with_ref |pathbuf| {
+        do "r".to_c_str().with_ref |modebuf| {
             unsafe { libc::fopen(pathbuf, modebuf as *libc::c_char) }
         }
     };
@@ -1290,9 +1291,8 @@ fn wb() -> c_int { O_WRONLY as c_int }
         }
     }
     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 {
index f96d3ce263ec109aa5542f53c61ef184e9313099..678704fe0983308ee45bd5a6afbc051f76834721 100644 (file)
@@ -2652,7 +2652,7 @@ pub fn execve(prog: *c_char, argv: **c_char, envp: **c_char)
                 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 fn execve(prog: *c_char, argv: **c_char, envp: **c_char)
                 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 ;
index 2d0b7d4f849d7be254a0ece13fc60100ef12a548..6d109aac4ea6cfb40166736fe614d9845b563053 100644 (file)
@@ -28,7 +28,7 @@
 
 #[allow(missing_doc)];
 
-use cast;
+use c_str::ToCStr;
 use clone::Clone;
 use container::Container;
 use io;
@@ -73,14 +73,15 @@ pub mod rustrt {
 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]))
     }
 }
 
@@ -91,7 +92,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
@@ -241,11 +242,13 @@ fn env_convert(input: ~[~str]) -> ~[(~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))
             }
         }
     }
@@ -274,8 +277,8 @@ pub fn getenv(n: &str) -> Option<~str> {
 pub fn setenv(n: &str, v: &str) {
     unsafe {
         do with_env_lock {
-            do n.to_str().as_c_str |nbuf| {
-                do v.to_str().as_c_str |vbuf| {
+            do n.to_c_str().with_ref |nbuf| {
+                do v.to_c_str().with_ref |vbuf| {
                     libc::funcs::posix01::unistd::setenv(nbuf, vbuf, 1);
                 }
             }
@@ -306,7 +309,7 @@ pub fn unsetenv(n: &str) {
     fn _unsetenv(n: &str) {
         unsafe {
             do with_env_lock {
-                do n.to_str().as_c_str |nbuf| {
+                do n.to_c_str().with_ref |nbuf| {
                     libc::funcs::posix01::unistd::unsetenv(nbuf);
                 }
             }
@@ -328,7 +331,7 @@ 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)
         }
@@ -461,18 +464,18 @@ fn load_self() -> Option<~str> {
         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)
             }
         }
     }
@@ -595,7 +598,7 @@ pub fn walk_dir(p: &Path, f: &fn(&Path) -> bool) -> bool {
 /// Indicates whether a path represents a directory
 pub fn path_is_dir(p: &Path) -> bool {
     unsafe {
-        do p.to_str().as_c_str |buf| {
+        do p.to_c_str().with_ref |buf| {
             rustrt::rust_path_is_dir(buf) != 0 as c_int
         }
     }
@@ -604,7 +607,7 @@ pub fn path_is_dir(p: &Path) -> bool {
 /// Indicates whether a path exists
 pub fn path_exists(p: &Path) -> bool {
     unsafe {
-        do p.to_str().as_c_str |buf| {
+        do p.to_c_str().with_ref |buf| {
             rustrt::rust_path_exists(buf) != 0 as c_int
         }
     }
@@ -639,15 +642,14 @@ fn mkdir(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))
-                    != (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)
             }
@@ -696,13 +698,15 @@ unsafe fn get_list(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(
@@ -712,7 +716,7 @@ unsafe fn get_list(p: &Path) -> ~[~str] {
                 closedir(dir_ptr);
             }
             else {
-        debug!("os::list_dir -- opendir() FAILURE");
+                debug!("os::list_dir -- opendir() FAILURE");
             }
             debug!(
                 "os::list_dir -- AFTER -- #: %?",
@@ -742,10 +746,7 @@ fn star(p: &Path) -> Path { p.push("*") }
             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 {
@@ -759,9 +760,7 @@ fn star(p: &Path) -> Path { p.push("*") }
                             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)
@@ -823,7 +822,7 @@ fn rmdir(p: &Path) -> bool {
 
     #[cfg(unix)]
     fn rmdir(p: &Path) -> bool {
-        do p.to_str().as_c_str |buf| {
+        do p.to_c_str().with_ref |buf| {
             unsafe {
                 libc::rmdir(buf) == (0 as c_int)
             }
@@ -848,7 +847,7 @@ fn chdir(p: &Path) -> bool {
 
     #[cfg(unix)]
     fn chdir(p: &Path) -> bool {
-        do p.to_str().as_c_str |buf| {
+        do p.to_c_str().with_ref |buf| {
             unsafe {
                 libc::chdir(buf) == (0 as c_int)
             }
@@ -876,8 +875,8 @@ fn do_copy_file(from: &Path, to: &Path) -> bool {
     #[cfg(unix)]
     fn do_copy_file(from: &Path, to: &Path) -> bool {
         unsafe {
-            let istream = do from.to_str().as_c_str |fromp| {
-                do "rb".as_c_str |modebuf| {
+            let istream = do from.to_c_str().with_ref |fromp| {
+                do "rb".to_c_str().with_ref |modebuf| {
                     libc::fopen(fromp, modebuf)
                 }
             };
@@ -888,8 +887,8 @@ fn do_copy_file(from: &Path, to: &Path) -> bool {
             let from_mode = from.get_mode().expect("copy_file: couldn't get permissions \
                                                     for source file");
 
-            let ostream = do to.to_str().as_c_str |top| {
-                do "w+b".as_c_str |modebuf| {
+            let ostream = do to.to_c_str().with_ref |top| {
+                do "w+b".to_c_str().with_ref |modebuf| {
                     libc::fopen(top, modebuf)
                 }
             };
@@ -921,7 +920,7 @@ fn do_copy_file(from: &Path, to: &Path) -> bool {
             fclose(ostream);
 
             // Give the new file the old file's permissions
-            if do to.to_str().as_c_str |to_buf| {
+            if do to.to_c_str().with_ref |to_buf| {
                 libc::chmod(to_buf, from_mode as libc::mode_t)
             } != 0 {
                 return false; // should be a condition...
@@ -948,7 +947,7 @@ fn unlink(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)
             }
         }
@@ -1040,14 +1039,15 @@ fn __xpg_strerror_r(errnum: 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)
+            }
         }
     }
 
@@ -1073,23 +1073,29 @@ fn FormatMessageA(flags: DWORD,
         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)
+            }
         }
     }
 
@@ -1182,7 +1188,7 @@ pub fn real_args() -> ~[~str] {
     }
 
     unsafe {
-        LocalFree(cast::transmute(szArgList));
+        LocalFree(szArgList as *c_void);
     }
 
     return args;
@@ -1294,7 +1300,7 @@ fn default_glob_t () -> libc::glob_t {
     }
 
     let mut g = default_glob_t();
-    do pattern.as_c_str |c_pattern| {
+    do pattern.to_c_str().with_ref |c_pattern| {
         unsafe { libc::glob(c_pattern, 0, ptr::null(), &mut g) }
     };
     do(|| {
@@ -1699,6 +1705,7 @@ pub mod mips {
 
 #[cfg(test)]
 mod tests {
+    use c_str::ToCStr;
     use libc::{c_int, c_void, size_t};
     use libc;
     use option::Some;
@@ -1711,7 +1718,6 @@ mod tests {
     use rand;
     use run;
     use str::StrSlice;
-    use vec::CopyableVector;
     use libc::consts::os::posix88::{S_IRUSR, S_IWUSR, S_IXUSR};
 
 
@@ -1934,39 +1940,39 @@ fn copy_file_does_not_exist() {
     #[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)));
         }
     }
 
@@ -2025,11 +2031,11 @@ fn lseek_(fd: c_int, size: uint) {
         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
index 76001ae41887a8b19a53218b01a9d7de351d8808..de34ec4bed5e1cf1d7e986a6c6d572ab215a6e3d 100644 (file)
 
 #[allow(missing_doc)];
 
+use c_str::ToCStr;
+use c_str;
 use clone::Clone;
-use container::Container;
 use cmp::Eq;
+use container::Container;
 use iterator::{Iterator, IteratorUtil};
 use libc;
 use option::{None, Option, Some};
@@ -341,7 +343,7 @@ pub fn default_stat() -> libc::stat {
 #[cfg(target_os = "win32")]
 impl WindowsPath {
     pub fn stat(&self) -> Option<libc::stat> {
-        do self.to_str().as_c_str |buf| {
+        do self.to_c_str().with_ref |buf| {
             let mut st = stat::arch::default_stat();
             match unsafe { libc::stat(buf, &mut st) } {
                 0 => Some(st),
@@ -375,7 +377,7 @@ pub fn get_mode(&self) -> Option<uint> {
 #[cfg(not(target_os = "win32"))]
 impl PosixPath {
     pub fn stat(&self) -> Option<libc::stat> {
-        do self.to_str().as_c_str |buf| {
+        do self.to_c_str().with_ref |buf| {
             let mut st = stat::arch::default_stat();
             match unsafe { libc::stat(buf as *libc::c_char, &mut st) } {
                 0 => Some(st),
@@ -453,7 +455,7 @@ pub fn get_ctime(&self) -> Option<(i64, int)> {
 #[cfg(unix)]
 impl PosixPath {
     pub fn lstat(&self) -> Option<libc::stat> {
-        do self.to_str().as_c_str |buf| {
+        do self.to_c_str().with_ref |buf| {
             let mut st = stat::arch::default_stat();
             match unsafe { libc::lstat(buf, &mut st) } {
                 0 => Some(st),
@@ -525,6 +527,12 @@ fn to_str(&self) -> ~str {
     }
 }
 
+impl ToCStr for PosixPath {
+    fn to_c_str(&self) -> c_str::CString {
+        self.to_str().to_c_str()
+    }
+}
+
 // FIXME (#3227): when default methods in traits are working, de-duplicate
 // PosixPath and WindowsPath, most of their methods are common.
 impl GenericPath for PosixPath {
@@ -730,6 +738,11 @@ fn to_str(&self) -> ~str {
     }
 }
 
+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 {
index 517bc4a441a68df454edf042fe1209404c434abd..5b8833f3f361bdbff53f3a03a1fddad5a5b89044 100644 (file)
@@ -43,6 +43,7 @@
 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;
@@ -63,7 +64,7 @@
 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};
index 55c18faf83deeb5a9eed4044d551907ccfa36fe3..84d55c55c2ff390d12945a172e332f90bea9a9a1 100644 (file)
@@ -416,6 +416,7 @@ pub mod ptr_tests {
     use super::*;
     use prelude::*;
 
+    use c_str::ToCStr;
     use cast;
     use libc;
     use str;
@@ -462,22 +463,20 @@ struct Pair {
     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);
@@ -581,66 +580,75 @@ fn test_ptr_subtraction() {
     #[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))]
index dcfcc3a9fc67a401341ea845979201f8182cf22c..c18d0287bc801fc0cb1d2a8726b2cc8837de2887 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use c_str::ToCStr;
 use cast::transmute;
 use libc::{c_char, c_void, size_t, STDERR_FILENO};
 use io;
@@ -76,8 +77,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
@@ -92,8 +93,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)
             }
         }
     }
@@ -231,8 +232,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
index 11d11daebc254be912a0b2a25048db789b12874a..76619704bee43d3350d506675e86f27712550316 100644 (file)
@@ -45,15 +45,15 @@ fn log(&mut self, msg: Either<~str, &'static str>) {
 /// 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) }
             }
         }
index 85cf660a5f1aaded24bd731907a919dc6374ab0e..01d01de54ef20483baa230f55bdcf98079377e68 100644 (file)
@@ -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::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;
@@ -654,7 +654,7 @@ fn sendto(&mut self, buf: &[u8], dst: SocketAddr) -> Result<(), IoError> {
 
     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 @@ fn join_multicast(&mut self, multi: IpAddr) -> Result<(), IoError> {
 
     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)
             }
index 07264839c3555dda0107bdc085540cf2168d98b8..bd2d28f8642c44736552dfc9d400b066436df33e 100644 (file)
@@ -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)
     }
 }
index ef3d881c5fead58be610146747508263d37b2472..72b3399c404b9fef018432a436b2c4adaf2952ca 100644 (file)
@@ -12,6 +12,7 @@
 
 #[allow(missing_doc)];
 
+use c_str::ToCStr;
 use cast;
 use clone::Clone;
 use comm::{stream, SharedChan, GenericChan, GenericPort};
@@ -24,6 +25,7 @@
 use ptr;
 use task;
 use vec::ImmutableVector;
+use vec;
 
 /**
  * A value representing a child process.
@@ -505,7 +507,7 @@ fn spawn_process_os(prog: &str, args: &[~str],
 
         do with_envp(env) |envp| {
             do with_dirp(dir) |dirp| {
-                do cmd.as_c_str |cmdp| {
+                do cmd.to_c_str().with_ref |cmdp| {
                     let created = CreateProcessA(ptr::null(), cast::transmute(cmdp),
                                                  ptr::mut_null(), ptr::mut_null(), TRUE,
                                                  0, envp, dirp, &mut si, &mut pi);
@@ -690,46 +692,58 @@ mod rustrt {
 }
 
 #[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())
     }
 }
 
@@ -739,25 +753,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())
     }
 }
index 76d65192e01a98eb43b414e3ca57ad8fb50af7f8..d51f0de1d275b2bd84eaa273a7a6a123e9ec25b8 100644 (file)
@@ -172,6 +172,7 @@ pub mod linkhack {
 
 pub mod gc;
 pub mod libc;
+pub mod c_str;
 pub mod os;
 pub mod path;
 pub mod rand;
index 5c6895fea43c956e435948ed333596e6f57af8b2..4a5fa82a22695d5cc268fd9bd7eaf5b8c4132e41 100644 (file)
@@ -33,6 +33,7 @@
 use ptr::RawPtr;
 use to_str::ToStr;
 use uint;
+#[cfg(stage0)]
 use unstable::raw::Repr;
 use vec;
 use vec::{OwnedVector, OwnedCopyableVector, ImmutableVector, MutableVector};
@@ -83,21 +84,6 @@ 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.
-///
-/// 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
@@ -106,6 +92,7 @@ pub fn from_bytes_with_null<'a>(vv: &'a [u8]) -> &'a str {
 /// # Failure
 ///
 /// Fails if invalid UTF-8
+#[cfg(stage0)]
 pub fn from_bytes_slice<'a>(vector: &'a [u8]) -> &'a str {
     unsafe {
         assert!(is_utf8(vector));
@@ -115,6 +102,20 @@ pub fn from_bytes_slice<'a>(vector: &'a [u8]) -> &'a str {
     }
 }
 
+/// 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() }
@@ -133,11 +134,23 @@ 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 = ~"";
@@ -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 @@ pub fn concat(&self) -> ~str {
         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 @@ pub fn connect(&self, sep: &str) -> ~str {
         }
         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 @@ pub fn replace(s: &str, from: &str, to: &str) -> ~str {
 */
 
 /// 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 unsafe fn from_buf_len(buf: *u8, len: uint) -> ~str {
         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.
@@ -845,15 +968,17 @@ pub unsafe fn from_bytes(v: &[u8]) -> ~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(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 unsafe fn from_byte(u: u8) -> ~str { from_bytes([u]) }
     /// 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 unsafe fn c_str_to_static_slice(s: *libc::c_char) -> &'static 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(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 unsafe fn c_str_to_static_slice(s: *libc::c_char) -> &'static str {
     ///
     /// 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| {
@@ -897,6 +1041,28 @@ pub unsafe fn slice_bytes(s: &str, begin: uint, end: uint) -> &str {
         }
     }
 
+    /// 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;
@@ -933,6 +1099,7 @@ pub unsafe fn shift_byte(s: &mut ~str) -> u8 {
     }
 
     /// 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 +1109,23 @@ pub unsafe fn set_len(v: &mut ~str, new_len: uint) {
         *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 {
@@ -1137,10 +1321,17 @@ fn into_owned(self) -> ~str { self.to_owned() }
 }
 
 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 {
@@ -1228,7 +1419,6 @@ fn split_options_iter<Sep: CharEq>(&self, sep: Sep, count: uint, allow_trailing_
     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
@@ -1615,6 +1805,7 @@ pub fn replace(&self, from: &str, to: &str) -> ~str {
     }
 
     /// Copy a slice into a new unique str
+    #[cfg(stage0)]
     #[inline]
     fn to_owned(&self) -> ~str {
         do self.as_imm_buf |src, len| {
@@ -1632,6 +1823,24 @@ fn to_owned(&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| {
@@ -1640,6 +1849,15 @@ fn to_managed(&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 = ~[];
@@ -1780,6 +1998,7 @@ fn char_at_reverse(&self, i: uint) -> char {
     /// 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();
@@ -1788,6 +2007,14 @@ fn as_bytes(&self) -> &'self [u8] {
         }
     }
 
+    /// 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
@@ -1854,6 +2081,7 @@ fn find_str(&self, needle: &str) -> Option<uint> {
     }
 
     /// 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
@@ -1875,6 +2103,27 @@ fn repeat(&self, nn: uint) -> ~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
@@ -1977,61 +2226,6 @@ fn as_imm_buf<T>(&self, f: &fn(*u8, uint) -> T) -> T {
         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)]
@@ -2046,6 +2240,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.
@@ -2192,6 +2387,7 @@ fn append(self, rhs: &str) -> ~str {
     ///
     /// * s - A string
     /// * n - The number of bytes to reserve space for
+    #[cfg(stage0)]
     #[inline]
     pub fn reserve(&mut self, n: uint) {
         unsafe {
@@ -2200,6 +2396,29 @@ pub fn reserve(&mut self, n: uint) {
         }
     }
 
+    /// 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.
     ///
@@ -2218,13 +2437,38 @@ pub fn reserve(&mut self, n: uint) {
     ///
     /// * 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();
@@ -2232,8 +2476,19 @@ fn capacity(&self) -> uint {
         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) }
@@ -2915,71 +3170,11 @@ fn test_from_bytes_fail() {
     }
 
     #[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");
         }
     }
@@ -2997,30 +3192,31 @@ fn test_as_bytes() {
         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";
@@ -3042,50 +3238,24 @@ 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();
+        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);
             }
         }
     }
index dd730f2068973d67534586d69d03c4bacb99446e..5ffb7efab314e0563689fccea535f635853b36fa 100644 (file)
@@ -15,7 +15,9 @@
 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};
 
@@ -101,19 +103,26 @@ fn is_ascii(&self) -> bool {
     }
 }
 
-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())
@@ -186,12 +195,19 @@ fn into_ascii(self) -> ~[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`
@@ -210,11 +226,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]
@@ -234,11 +258,18 @@ fn eq_ignore_case(self, other: &[Ascii]) -> bool {
 }
 
 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) }
     }
 }
 
@@ -257,7 +288,7 @@ pub trait ToBytesConsume {
 
 impl ToBytesConsume for ~[Ascii] {
     fn into_bytes(self) -> ~[u8] {
-        unsafe {cast::transmute(self)}
+        unsafe { cast::transmute(self) }
     }
 }
 
index 51609709cdbcad3530e011856f96470982eca260..b40f87617a91411fa263d77bca0996e9cb0dc0b0 100644 (file)
 
 #[allow(missing_doc)];
 
+use c_str::ToCStr;
 use cast;
 use gc;
 use io;
 use libc;
 use libc::{c_char, size_t};
 use repr;
-use str::StrSlice;
 use str;
 use unstable::intrinsics;
 
@@ -115,8 +115,8 @@ pub trait FailWithCause {
 
 impl FailWithCause for ~str {
     fn fail_with(cause: ~str, file: &'static str, line: uint) -> ! {
-        do cause.as_c_str |msg_buf| {
-            do file.as_c_str |file_buf| {
+        do cause.to_c_str().with_ref |msg_buf| {
+            do file.to_c_str().with_ref |file_buf| {
                 begin_unwind_(msg_buf, file_buf, line as libc::size_t)
             }
         }
@@ -125,8 +125,8 @@ fn fail_with(cause: ~str, file: &'static str, line: uint) -> ! {
 
 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)
             }
         }
index 8d5654255f14a7264f50a9b3294dec4b49ffcc3c..49e3e0777df84e58356fe734fe07d3e37c36f34f 100644 (file)
@@ -15,6 +15,7 @@
 A simple wrapper over the platforms dynamic library facilities
 
 */
+use c_str::ToCStr;
 use cast;
 use path;
 use libc;
@@ -65,7 +66,7 @@ pub unsafe fn symbol<T>(&self, symbol: &str) -> Result<T, ~str> {
         // 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 @@ fn test_errors_do_not_crash() {
 #[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)
         }
     }
index 7b05515f74acb29bcf1f1a3d14ec66b33ce157d6..d63f914bc7386f215f98f86d5264f04ac601e0ff 100644 (file)
@@ -549,12 +549,14 @@ pub fn conv_str(cv: Conv, s: &str, buf: &mut ~str) {
         // 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);
     }
index e0c4950b38eaa8a0cb1d4cc742838b3493486bc2..1ea815f721cc1cb0d170c0c3cacbf11f9ef6ac38 100644 (file)
@@ -10,6 +10,7 @@
 
 //! Runtime calls emitted by the compiler.
 
+use c_str::ToCStr;
 use cast::transmute;
 use libc::{c_char, c_uchar, c_void, size_t, uintptr_t, c_int};
 use str;
@@ -49,7 +50,7 @@ pub fn fail_bounds_check(file: *c_char, line: size_t,
                          index: size_t, len: size_t) {
     let msg = fmt!("index out of bounds: the len is %d but the index is %d",
                     len as int, index as int);
-    do msg.as_c_str |buf| {
+    do msg.to_c_str().with_ref |buf| {
         fail_(buf, file, line);
     }
 }
index d77a9f58a38531f795d470a5523cb655c41350ed..dffa7232e348770fa7c5119e07a63bbd02c2f29d 100644 (file)
@@ -302,10 +302,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;
     }
 }
 
diff --git a/src/test/compile-fail/static-slice-not-null-terminated.rs b/src/test/compile-fail/static-slice-not-null-terminated.rs
deleted file mode 100644 (file)
index 3cfaa57..0000000
+++ /dev/null
@@ -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`
-}
index 2f0cd3c611f620afc8be3bb106e67be3e6b5ae9b..0e7d6d9f16a3c420f080df9a4115d7c09a1d49aa 100644 (file)
 
 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");
+    }
 }
index 38f36dd258b7acde112eb972d96eaebab173f3fc..b5a114ef22364e64dc2bea3f7ccf326b914afa50 100644 (file)
@@ -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)
+        }
     }
 }