diff --git a/src/libcore/io.rs b/src/libcore/io.rs index 659fdbc6d7e81..4da7044e48b13 100644 --- a/src/libcore/io.rs +++ b/src/libcore/io.rs @@ -30,7 +30,9 @@ enum seek_style { seek_set, seek_end, seek_cur, } // The raw underlying reader iface. All readers must implement this. iface reader { // FIXME (#2004): Seekable really should be orthogonal. - fn read_bytes(uint) -> ~[u8]; + + // FIXME (#2982): This should probably return an error. + fn read(buf: &[mut u8], len: uint) -> uint; fn read_byte() -> int; fn unread_byte(int); fn eof() -> bool; @@ -41,6 +43,16 @@ iface reader { // Generic utility functions defined on readers impl reader_util for reader { + fn read_bytes(len: uint) -> ~[u8] { + let mut buf = ~[mut]; + vec::reserve(buf, len); + unsafe { vec::unsafe::set_len(buf, len); } + + let count = self.read(buf, len); + + unsafe { vec::unsafe::set_len(buf, count); } + vec::from_mut(buf) + } fn read_chars(n: uint) -> ~[char] { // returns the (consumed offset, n_req), appends characters to &chars fn chars_from_buf(buf: ~[u8], &chars: ~[char]) -> (uint, uint) { @@ -192,15 +204,15 @@ fn convert_whence(whence: seek_style) -> i32 { } impl of reader for *libc::FILE { - fn read_bytes(len: uint) -> ~[u8] { - let mut buf : ~[mut u8] = ~[mut]; - vec::reserve(buf, len); - do vec::as_mut_buf(buf) |b| { - let read = libc::fread(b as *mut c_void, 1u as size_t, - len as size_t, self); - unsafe { vec::unsafe::set_len(buf, read as uint) }; + fn read(buf: &[mut u8], len: uint) -> uint { + do vec::unpack_slice(buf) |buf_p, buf_len| { + assert buf_len <= len; + + let count = libc::fread(buf_p as *mut c_void, 1u as size_t, + len as size_t, self); + + count as uint } - ret vec::from_mut(buf); } fn read_byte() -> int { ret libc::fgetc(self) as int; } fn unread_byte(byte: int) { libc::ungetc(byte as c_int, self); } @@ -216,7 +228,7 @@ impl of reader for *libc::FILE { // duration of its lifetime. // FIXME there really should be a better way to do this // #2004 impl of reader for {base: T, cleanup: C} { - fn read_bytes(len: uint) -> ~[u8] { self.base.read_bytes(len) } + fn read(buf: &[mut u8], len: uint) -> uint { self.base.read(buf, len) } fn read_byte() -> int { self.base.read_byte() } fn unread_byte(byte: int) { self.base.unread_byte(byte); } fn eof() -> bool { self.base.eof() } @@ -262,13 +274,15 @@ fn file_reader(path: ~str) -> result { type byte_buf = {buf: ~[const u8], mut pos: uint, len: uint}; impl of reader for byte_buf { - fn read_bytes(len: uint) -> ~[u8] { - let rest = self.len - self.pos; - let mut to_read = len; - if rest < to_read { to_read = rest; } - let range = vec::slice(self.buf, self.pos, self.pos + to_read); - self.pos += to_read; - ret range; + fn read(buf: &[mut u8], len: uint) -> uint { + let count = uint::min(len, self.len - self.pos); + + vec::u8::memcpy(buf, vec::const_view(self.buf, self.pos, self.len), + count); + + self.pos += count; + + count } fn read_byte() -> int { if self.pos == self.len { ret -1; } diff --git a/src/libcore/run.rs b/src/libcore/run.rs index a466971b9bdf2..1229d0724de79 100644 --- a/src/libcore/run.rs +++ b/src/libcore/run.rs @@ -1,6 +1,7 @@ //! Process spawning import option::{some, none}; import libc::{pid_t, c_void, c_int}; +import io::reader_util; export program; export run_program; diff --git a/src/libcore/vec.rs b/src/libcore/vec.rs index c4e8ad6425cd7..a5d535e62f24e 100644 --- a/src/libcore/vec.rs +++ b/src/libcore/vec.rs @@ -27,7 +27,7 @@ export init; export last; export last_opt; export slice; -export view; +export view, mut_view, const_view; export split; export splitn; export rsplit; @@ -313,7 +313,7 @@ pure fn slice(v: &[const T], start: uint, end: uint) -> ~[T] { ret result; } -#[doc = "Return a slice that points into another slice."] +/// Return a slice that points into another slice. pure fn view(v: &[T], start: uint, end: uint) -> &[T] { assert (start <= end); assert (end <= len(v)); @@ -325,6 +325,30 @@ pure fn view(v: &[T], start: uint, end: uint) -> &[T] { } } +/// Return a slice that points into another slice. +pure fn mut_view(v: &[mut T], start: uint, end: uint) -> &[mut T] { + assert (start <= end); + assert (end <= len(v)); + do unpack_slice(v) |p, _len| { + unsafe { + ::unsafe::reinterpret_cast( + (ptr::offset(p, start), (end - start) * sys::size_of::())) + } + } +} + +/// Return a slice that points into another slice. +pure fn const_view(v: &[const T], start: uint, end: uint) -> &[const T] { + assert (start <= end); + assert (end <= len(v)); + do unpack_slice(v) |p, _len| { + unsafe { + ::unsafe::reinterpret_cast( + (ptr::offset(p, start), (end - start) * sys::size_of::())) + } + } +} + /// Split the vector `v` by applying each element against the predicate `f`. fn split(v: &[T], f: fn(T) -> bool) -> ~[~[T]] { let ln = len(v); @@ -627,7 +651,6 @@ fn grow_set(&v: ~[mut T], index: uint, initval: T, val: T) { v[index] = val; } - // Functional utilities /// Apply a function to each element of a vector and return the results @@ -1574,6 +1597,34 @@ mod unsafe { ::unsafe::reinterpret_cast(ptr::addr_of(pair)); f(*v) } + + /** + * Copies data from one vector to another. + * + * Copies `count` bytes from `src` to `dst`. The source and destination + * may overlap. + */ + unsafe fn memcpy(dst: &[mut T], src: &[const T], count: uint) { + do unpack_slice(dst) |p_dst, _len_dst| { + do unpack_slice(src) |p_src, _len_src| { + ptr::memcpy(p_dst, p_src, count) + } + } + } + + /** + * Copies data from one vector to another. + * + * Copies `count` bytes from `src` to `dst`. The source and destination + * may overlap. + */ + unsafe fn memmove(dst: &[mut T], src: &[const T], count: uint) { + do unpack_slice(dst) |p_dst, _len_dst| { + do unpack_slice(src) |p_src, _len_src| { + ptr::memmove(p_dst, p_src, count) + } + } + } } /// Operations on `[u8]` @@ -1581,6 +1632,7 @@ mod u8 { export cmp; export lt, le, eq, ne, ge, gt; export hash; + export memcpy, memmove; /// Bytewise string comparison pure fn cmp(&&a: ~[u8], &&b: ~[u8]) -> int { @@ -1631,6 +1683,32 @@ mod u8 { vec::iter(s, |c| {u *= 33u; u += c as uint;}); ret u; } + + /** + * Copies data from one vector to another. + * + * Copies `count` bytes from `src` to `dst`. The source and destination + * may not overlap. + */ + fn memcpy(dst: &[mut u8], src: &[const u8], count: uint) { + assert dst.len() >= count; + assert src.len() >= count; + + unsafe { vec::unsafe::memcpy(dst, src, count) } + } + + /** + * Copies data from one vector to another. + * + * Copies `count` bytes from `src` to `dst`. The source and destination + * may overlap. + */ + fn memmove(dst: &[mut u8], src: &[const u8], count: uint) { + assert dst.len() >= count; + assert src.len() >= count; + + unsafe { vec::unsafe::memmove(dst, src, count) } + } } // ___________________________________________________________________________ diff --git a/src/libstd/net_tcp.rs b/src/libstd/net_tcp.rs index c7dc2d0cdab48..4826bc760c237 100644 --- a/src/libstd/net_tcp.rs +++ b/src/libstd/net_tcp.rs @@ -11,7 +11,7 @@ import future::extensions; import result::*; import libc::size_t; import str::extensions; -import io::{reader, writer}; +import io::{reader, reader_util, writer}; // tcp interfaces export tcp_socket; @@ -766,34 +766,41 @@ impl tcp_socket for tcp_socket { /// Implementation of `io::reader` iface for a buffered `net::tcp::tcp_socket` impl tcp_socket_buf of io::reader for @tcp_socket_buf { - fn read_bytes(amt: uint) -> ~[u8] { - let has_amt_available = - vec::len((*(self.data)).buf) >= amt; - if has_amt_available { - // no arbitrary-length shift in vec::? - let mut ret_buf = ~[]; - while vec::len(ret_buf) < amt { - ret_buf += ~[vec::shift((*(self.data)).buf)]; - } - ret_buf - } - else { - let read_result = read((*(self.data)).sock, 0u); + fn read(buf: &[mut u8], len: uint) -> uint { + // Loop until our buffer has enough data in it for us to read from. + while self.data.buf.len() < len { + let read_result = read(self.data.sock, 0u); if read_result.is_err() { let err_data = read_result.get_err(); - log(debug, #fmt("ERROR sock_buf as io::reader.read err %? %?", - err_data.err_name, err_data.err_msg)); - ~[] + + if err_data.err_name == ~"EOF" { + break; + } else { + #debug("ERROR sock_buf as io::reader.read err %? %?", + err_data.err_name, err_data.err_msg); + + ret 0; + } } else { - let new_chunk = result::unwrap(read_result); - (*(self.data)).buf += new_chunk; - self.read_bytes(amt) + vec::push_all(self.data.buf, result::unwrap(read_result)); } } + + let count = uint::min(len, self.data.buf.len()); + + let mut data = ~[]; + self.data.buf <-> data; + + vec::u8::memcpy(buf, vec::view(data, 0, data.len()), count); + + vec::push_all(self.data.buf, vec::view(data, count, data.len())); + + count } fn read_byte() -> int { - self.read_bytes(1u)[0] as int + let bytes = ~[0]; + if self.read(bytes, 1u) == 0 { fail } else { bytes[0] as int } } fn unread_byte(amt: int) { vec::unshift((*(self.data)).buf, amt as u8); diff --git a/src/test/auxiliary/issue-2526.rs b/src/test/auxiliary/issue-2526.rs index 700c5468e6191..9504ec576c40e 100644 --- a/src/test/auxiliary/issue-2526.rs +++ b/src/test/auxiliary/issue-2526.rs @@ -1,4 +1,4 @@ -#[link(name = "zmq", +#[link(name = "issue_2526", vers = "0.2", uuid = "54cc1bc9-02b8-447c-a227-75ebc923bc29")]; #[crate_type = "lib"]; diff --git a/src/test/run-pass/issue-2526-a.rs b/src/test/run-pass/issue-2526-a.rs index fdbcc005ae2b4..f364439740e11 100644 --- a/src/test/run-pass/issue-2526-a.rs +++ b/src/test/run-pass/issue-2526-a.rs @@ -1,8 +1,8 @@ // xfail-fast // aux-build:issue-2526.rs -use zmq; -import zmq::*; +use issue_2526; +import issue_2526::*; fn main() {}