parent
6d042c0f2d
commit
06ac0c2b1d
|
@ -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 <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; }
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue