aboutsummaryrefslogtreecommitdiff
path: root/src/lib/io.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/io.rs')
-rw-r--r--src/lib/io.rs99
1 files changed, 87 insertions, 12 deletions
diff --git a/src/lib/io.rs b/src/lib/io.rs
index 165fe030..23a503ab 100644
--- a/src/lib/io.rs
+++ b/src/lib/io.rs
@@ -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);
}