stdlib: Make writers seekable; switch file writers to the C FILE interface to make this work

This commit is contained in:
Patrick Walton 2011-03-22 16:38:47 -07:00
parent dcf122ede0
commit b33f0df152
5 changed files with 101 additions and 14 deletions

View File

@ -7,7 +7,7 @@ native "rust" mod rustrt {
fn str_buf(str s) -> sbuf;
fn str_byte_len(str s) -> uint;
fn str_alloc(uint n_bytes) -> str;
fn str_from_vec(vec[u8] b) -> str;
fn str_from_vec(vec[mutable? u8] b) -> str;
fn str_from_cstr(sbuf cstr) -> str;
fn str_from_buf(sbuf buf, uint len) -> str;
fn refcount[T](str s) -> uint;
@ -109,7 +109,16 @@ fn from_bytes(vec[u8] v) : is_utf8(v) -> str {
}
// FIXME temp thing
fn unsafe_from_bytes(vec[u8] v) -> str {
fn unsafe_from_bytes(vec[mutable? u8] v) -> str {
ret rustrt.str_from_vec(v);
}
// FIXME even temp-er thing; rustc can use "unsafe_from_bytes" above
fn unsafe_from_mutable_bytes(vec[mutable u8] mv) -> str {
let vec[u8] v = vec();
for (mutable u8 b in mv) {
v += vec(b);
}
ret rustrt.str_from_vec(v);
}

View File

@ -27,6 +27,14 @@ type reader =
impure fn tell() -> uint; // TODO: eventually u64
};
fn convert_whence(seek_style whence) -> int {
alt (whence) {
case (seek_set) {ret 0;}
case (seek_cur) {ret 1;}
case (seek_end) {ret 2;}
}
}
state obj FILE_reader(os.libc.FILE f, bool must_close) {
impure fn read_byte() -> u8 {
ret os.libc.fgetc(f) as u8;
@ -90,13 +98,7 @@ state obj FILE_reader(os.libc.FILE f, bool must_close) {
ret val as int; // TODO does that work?
}
impure fn seek(int offset, seek_style whence) {
auto wh;
alt (whence) {
case (seek_set) {wh = 0;}
case (seek_cur) {wh = 1;}
case (seek_end) {wh = 2;}
}
check(os.libc.fseek(f, offset, wh) == 0);
check(os.libc.fseek(f, offset, convert_whence(whence)) == 0);
}
impure fn tell() -> uint {
ret os.libc.ftell(f) as uint;
@ -132,8 +134,34 @@ tag fileflag {
type buf_writer = state obj {
fn write(vec[u8] v);
fn seek(int offset, seek_style whence);
fn tell() -> uint; // TODO: eventually u64
};
state obj FILE_writer(os.libc.FILE f, bool must_close) {
fn write(vec[u8] v) {
auto len = _vec.len[u8](v);
auto vbuf = _vec.buf[u8](v);
auto nout = os.libc.fwrite(vbuf, len, 1u, f);
if (nout < 1u) {
log "error dumping buffer";
}
}
fn seek(int offset, seek_style whence) {
check(os.libc.fseek(f, offset, convert_whence(whence)) == 0);
}
fn tell() -> uint {
ret os.libc.ftell(f) as uint;
}
drop {
if (must_close) {os.libc.fclose(f);}
}
}
state obj fd_buf_writer(int fd, bool must_close) {
fn write(vec[u8] v) {
auto len = _vec.len[u8](v);
@ -151,6 +179,16 @@ state obj fd_buf_writer(int fd, bool must_close) {
}
}
fn seek(int offset, seek_style whence) {
log "need 64-bit native calls for seek, sorry";
fail;
}
fn tell() -> uint {
log "need 64-bit native calls for tell, sorry";
fail;
}
drop {
if (must_close) {os.libc.close(fd);}
}
@ -239,19 +277,56 @@ type str_writer =
fn get_str() -> str;
};
type byte_buf = @rec(mutable vec[u8] buf);
type byte_buf = @rec(mutable vec[mutable u8] buf, mutable uint pos);
state obj byte_buf_writer(byte_buf buf) {
fn write(vec[u8] v) {buf.buf += v;}
fn write(vec[u8] v) {
// TODO: optimize
auto vlen = _vec.len[u8](v);
auto vpos = 0u;
while (vpos < vlen) {
auto b = v.(vpos);
if (buf.pos == _vec.len[mutable u8](buf.buf)) {
buf.buf += vec(mutable b);
} else {
buf.buf.(buf.pos) = b;
}
buf.pos += 1u;
vpos += 1u;
}
}
fn seek(int offset, seek_style whence) {
auto pos = buf.pos as int;
auto len = _vec.len[mutable u8](buf.buf) as int;
alt (whence) {
case (seek_set) { pos = offset; }
case (seek_cur) { pos += offset; }
case (seek_end) { pos = len + offset; }
}
if (pos < 0) {
pos = 0;
} else if (pos > len) {
pos = len;
}
buf.pos = pos as uint;
}
fn tell() -> uint { ret buf.pos; }
}
// TODO awkward! it's not possible to implement a writer with an extra method
fn string_writer() -> str_writer {
let vec[u8] b = vec();
let byte_buf buf = @rec(mutable buf = b);
// FIXME: yikes, this is bad. Needs fixing of mutable syntax.
let vec[mutable u8] b = vec(mutable 0u8);
_vec.pop[mutable u8](b);
let byte_buf buf = @rec(mutable buf = b, mutable pos = 0u);
state obj str_writer_wrap(writer wr, byte_buf buf) {
fn get_writer() -> writer {ret wr;}
fn get_str() -> str {ret _str.unsafe_from_bytes(buf.buf);}
fn get_str() -> str {ret _str.unsafe_from_mutable_bytes(buf.buf);}
}
ret str_writer_wrap(new_writer(byte_buf_writer(buf)), buf);
}

View File

@ -18,6 +18,7 @@ native mod libc = "libc.so.6" {
fn fgetc(FILE f) -> int;
fn ungetc(int c, FILE f);
fn fread(vbuf buf, uint size, uint n, FILE f) -> uint;
fn fwrite(vbuf buf, uint size, uint n, FILE f) -> uint;
fn fseek(FILE f, int offset, int whence) -> int;
fn ftell(FILE f) -> int;

View File

@ -15,6 +15,7 @@ native mod libc = "libc.dylib" {
fn fgetc(FILE f) -> int;
fn ungetc(int c, FILE f);
fn fread(vbuf buf, uint size, uint n, FILE f) -> uint;
fn fwrite(vbuf buf, uint size, uint n, FILE f) -> uint;
fn fseek(FILE f, int offset, int whence) -> int;
fn ftell(FILE f) -> int;

View File

@ -14,6 +14,7 @@ native mod libc = "msvcrt.dll" {
fn fgetc(FILE f) -> int;
fn ungetc(int c, FILE f);
fn fread(vbuf buf, uint size, uint n, FILE f) -> uint;
fn fwrite(vbuf buf, uint size, uint n, FILE f) -> uint;
fn fseek(FILE f, int offset, int whence) -> int;
fn ftell(FILE f) -> int;