提交 06ac0c2b 编写于 作者: E Erick Tryzelaar 提交者: Graydon Hoare

Switch reader to work with preallocated vecs

This closes #2901.
上级 6d042c0f
......@@ -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 @@ enum seek_style { seek_set, seek_end, seek_cur, }
// 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 @@ fn seek(offset: int, whence: seek_style) {
// duration of its lifetime.
// FIXME there really should be a better way to do this // #2004
impl <T: reader, C> 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<reader, ~str> {
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; }
......
//! Process spawning
import option::{some, none};
import libc::{pid_t, c_void, c_int};
import io::reader_util;
export program;
export run_program;
......
......@@ -11,7 +11,7 @@
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 @@ fn write_future(raw_write_data: ~[u8])
/// 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);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册