From: Erick Tryzelaar Date: Sun, 4 Aug 2013 23:23:41 +0000 (-0700) Subject: Merge remote-tracking branch 'remotes/origin/master' into str-remove-null X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=3c94b5044c2e589292def83e9cce187407c9328a;p=rust.git Merge remote-tracking branch 'remotes/origin/master' into str-remove-null --- 3c94b5044c2e589292def83e9cce187407c9328a diff --cc src/libstd/rt/uv/uvio.rs index 071a90f4a83,85cf660a5f1..01d01de54ef --- a/src/libstd/rt/uv/uvio.rs +++ b/src/libstd/rt/uv/uvio.rs @@@ -8,26 -8,26 +8,26 @@@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use option::*; -use result::*; -use ops::Drop; -use cell::Cell; -use cast; +use c_str::ToCStr; use cast::transmute; +use cast; +use cell::Cell; use clone::Clone; use libc::{c_int, c_uint, c_void}; +use ops::Drop; +use option::*; use ptr; +use result::*; use rt::io::IoError; - use rt::io::net::ip::{IpAddr, Ipv4, Ipv6}; + use rt::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::{UvIpv4, UvIpv6}; ++use rt::uv::net::{UvIpv4SocketAddr, UvIpv6SocketAddr}; use unstable::sync::Exclusive; #[cfg(test)] use container::Container; @@@ -653,17 -653,8 +653,8 @@@ impl RtioUdpSocket for UvUdpSocket } fn join_multicast(&mut self, multi: IpAddr) -> Result<(), IoError> { - let ip_str = match multi { - Ipv4(x1, x2, x3, x4, _) => - fmt!("%u.%u.%u.%u", x1 as uint, x2 as uint, x3 as uint, x4 as uint), - Ipv6(x1, x2, x3, x4, x5, x6, x7, x8, _) => - fmt!("%x:%x:%x:%x:%x:%x:%x:%x", - x1 as uint, x2 as uint, x3 as uint, x4 as uint, - x5 as uint, x6 as uint, x7 as uint, x8 as uint), - }; - let r = unsafe { - do ip_str.to_c_str().with_ref |m_addr| { - 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) } @@@ -676,17 -667,8 +667,8 @@@ } fn leave_multicast(&mut self, multi: IpAddr) -> Result<(), IoError> { - let ip_str = match multi { - Ipv4(x1, x2, x3, x4, _) => - fmt!("%u.%u.%u.%u", x1 as uint, x2 as uint, x3 as uint, x4 as uint), - Ipv6(x1, x2, x3, x4, x5, x6, x7, x8, _) => - fmt!("%x:%x:%x:%x:%x:%x:%x:%x", - x1 as uint, x2 as uint, x3 as uint, x4 as uint, - x5 as uint, x6 as uint, x7 as uint, x8 as uint), - }; - let r = unsafe { - do ip_str.to_c_str().with_ref |m_addr| { - 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) } diff --cc src/libstd/run.rs index d0f7f307088,ef3d881c5fe..72b3399c404 --- a/src/libstd/run.rs +++ b/src/libstd/run.rs @@@ -692,58 -690,46 +692,58 @@@ fn spawn_process_os(prog: &str, args: & } #[cfg(unix)] -fn with_argv(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(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()); + - foreach arg in args.iter() { + 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(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()); + - foreach pair in env.iter() { ++ 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()) } } @@@ -753,22 -739,18 +753,22 @@@ fn with_envp(env: Option<&[(~str, ~s // 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()); - } - blk.push(0); - blk.as_imm_buf(|p, _len| - unsafe { cb(::cast::transmute(p)) } - ) - } - _ => cb(ptr::mut_null()) + Some(env) => { + let mut blk = ~[]; + - foreach pair in env.iter() { ++ 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)) } + } + } + _ => cb(ptr::mut_null()) } } diff --cc src/libstd/str.rs index 5796b541186,5c6895fea43..4a5fa82a226 --- a/src/libstd/str.rs +++ b/src/libstd/str.rs @@@ -205,32 -191,7 +205,32 @@@ impl<'self, S: Str> StrVector for &'sel 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; - foreach ss in self.iter() { ++ 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 ~""; } @@@ -269,45 -230,6 +269,45 @@@ } 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; - foreach ss in self.iter() { ++ 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