about summary refs log tree commit diff
path: root/src/lib
diff options
context:
space:
mode:
authorPatrick Walton <pcwalton@mimiga.net>2011-03-22 16:38:47 -0700
committerPatrick Walton <pcwalton@mimiga.net>2011-03-22 16:40:22 -0700
commitb33f0df152fd2242a1ea88d0961065caecd228ac (patch)
treeeaf1ef79e516e842b1c16f2e955a2bfc3964740c /src/lib
parentdcf122ede03af71d8a1d892a077a9e2435b64ef3 (diff)
downloadrust-b33f0df152fd2242a1ea88d0961065caecd228ac.tar.gz
rust-b33f0df152fd2242a1ea88d0961065caecd228ac.zip
stdlib: Make writers seekable; switch file writers to the C FILE interface to make this work
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/_str.rs13
-rw-r--r--src/lib/io.rs99
-rw-r--r--src/lib/linux_os.rs1
-rw-r--r--src/lib/macos_os.rs1
-rw-r--r--src/lib/win32_os.rs1
5 files changed, 101 insertions, 14 deletions
diff --git a/src/lib/_str.rs b/src/lib/_str.rs
index e73fd1150dc..87eef514127 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 165fe0302d6..23a503ab728 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 bce859567e3..51f2943dfb3 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 f9734de3caa..9633c14c433 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 3ca76e77d77..7f113b2725c 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;