Revision
4480
Author
lsansonetti@apple.com
Date
2010-08-30 22:02:24 -0700 (Mon, 30 Aug 2010)

Log Message

when reading all, try to determine the input's remaining data length before actually reading it in chunks

Modified Paths

Diff

Modified: MacRuby/trunk/io.c (4479 => 4480)


--- MacRuby/trunk/io.c	2010-08-31 02:04:11 UTC (rev 4479)
+++ MacRuby/trunk/io.c	2010-08-31 05:02:24 UTC (rev 4480)
@@ -1011,16 +1011,26 @@
 static VALUE 
 rb_io_read_all(rb_io_t *io_struct, VALUE outbuf) 
 {
+    struct stat st;
+    long bufsize = 512;
+    if (fstat(io_struct->read_fd, &st) == 0 && S_ISREG(st.st_mode)) {
+	const off_t pos = lseek(io_struct->read_fd, 0, SEEK_CUR);
+	if (st.st_size >= pos && pos >= 0) {
+	    bufsize = st.st_size - pos;
+	    if (bufsize > LONG_MAX) {
+		rb_raise(rb_eIOError, "file too big for single read");
+	    }
+	}
+    }
+
     outbuf = rb_str_bstr(outbuf);
-
-    const long BUFSIZE = 512;
     long bytes_read = 0;
     const long original_position = rb_bstr_length(outbuf);
 
     while (true) {
-	rb_bstr_resize(outbuf, original_position + bytes_read + BUFSIZE);
+	rb_bstr_resize(outbuf, original_position + bytes_read + bufsize);
 	uint8_t *bytes = rb_bstr_bytes(outbuf) + original_position + bytes_read;
-        const long last_read = rb_io_read_internal(io_struct, bytes, BUFSIZE);
+        const long last_read = rb_io_read_internal(io_struct, bytes, bufsize);
         bytes_read += last_read;
 	if (last_read == 0) {
 	    break;