diff options
Diffstat (limited to 'src/lib')
| -rw-r--r-- | src/lib/_str.rs | 13 | ||||
| -rw-r--r-- | src/lib/io.rs | 99 | ||||
| -rw-r--r-- | src/lib/linux_os.rs | 1 | ||||
| -rw-r--r-- | src/lib/macos_os.rs | 1 | ||||
| -rw-r--r-- | src/lib/win32_os.rs | 1 |
5 files changed, 101 insertions, 14 deletions
diff --git a/src/lib/_str.rs b/src/lib/_str.rs index e73fd115..87eef514 100644 --- a/src/lib/_str.rs +++ b/src/lib/_str.rs @@ -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); } 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); } diff --git a/src/lib/linux_os.rs b/src/lib/linux_os.rs index bce85956..51f2943d 100644 --- a/src/lib/linux_os.rs +++ b/src/lib/linux_os.rs @@ -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; diff --git a/src/lib/macos_os.rs b/src/lib/macos_os.rs index f9734de3..9633c14c 100644 --- a/src/lib/macos_os.rs +++ b/src/lib/macos_os.rs @@ -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; diff --git a/src/lib/win32_os.rs b/src/lib/win32_os.rs index 3ca76e77..7f113b27 100644 --- a/src/lib/win32_os.rs +++ b/src/lib/win32_os.rs @@ -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; |