[project @ 2001-01-26 17:51:40 by rrt]
[ghc-hetmet.git] / ghc / lib / std / cbits / readFile.c
index 8c3be14..8393d07 100644 (file)
@@ -1,7 +1,7 @@
 /* 
  * (c) The GRASP/AQUA Project, Glasgow University, 1994-1998
  *
- * $Id: readFile.c,v 1.9 1999/12/08 15:47:08 simonmar Exp $
+ * $Id: readFile.c,v 1.15 2000/04/12 17:33:16 simonmar Exp $
  *
  * hGetContents Runtime Support
  */
@@ -22,8 +22,7 @@
 /* Filling up a (block-buffered) buffer, that
    is completely empty. */
 StgInt
-readBlock(ptr)
-StgForeignPtr ptr;
+readBlock(StgForeignPtr ptr)
 {
     IOFileObject* fo = (IOFileObject*)ptr;
     int count,rc=0;
@@ -106,14 +105,23 @@ StgForeignPtr ptr;
 }
 
 /* Filling up a (block-buffered) buffer of length len */
+
+/* readChunk(FileObjet *, void *, int)
+ * returns:
+ *  -1                             error
+ *  -2                             object closed
+ *  FILEOBJ_BLOCKED_CONN_WRITE     blocking while flushing
+ *                                 buffer of connected handle.
+ *  FILEOBJ_BLOCKED_READ           didn't read anything; would block
+ *  n, where n > 0                 read n bytes into buffer.
+ *  0                             EOF has been reached
+ */
+
 StgInt
-readChunk(ptr,buf,len)
-StgForeignPtr ptr;
-StgAddr buf;
-StgInt len;
+readChunk(StgForeignPtr ptr, StgAddr buf, StgInt off, StgInt len)
 {
     IOFileObject* fo = (IOFileObject*)ptr;
-    int count=0,rc=0, total_count;
+    int count, rc=0, total_count=0;
     int fd;
     char* p;
 
@@ -127,9 +135,7 @@ StgInt len;
        return -2;
 
     if ( FILEOBJ_IS_EOF(fo) ) {
-       ghc_errtype = ERR_EOF;
-       ghc_errstr = "";
-       return -1;
+        return 0;
     }
 
     /* if input stream is connect to an output stream, flush it first */
@@ -148,24 +154,29 @@ StgInt len;
     }
     fo->flags = (fo->flags & ~FILEOBJ_RW_WRITE) | FILEOBJ_RW_READ;
 
+    p = buf+off;
+
     /* copy the unread parts of the file buffer..*/
     if ( FILEOBJ_READABLE(fo) && 
         fo->bufRPtr > 0      &&
         fo->bufWPtr >= fo->bufRPtr ) {
-       count = ( len < (fo->bufWPtr - fo->bufRPtr)) ? len : (fo->bufWPtr - fo->bufRPtr);
-       memcpy(buf,fo->buf, count);
-       fo->bufWPtr=0;
-       fo->bufRPtr=0;
-       
-    }
 
-    if (len - count <= 0)
-       return count;
-
-    len -= count;
-    p = buf;
-    p += count;
-    total_count = count;
+        if (fo->bufWPtr - fo->bufRPtr >= len) {
+            /* buffer has enough data to fulfill the request */
+           memcpy(buf, fo->buf + fo->bufRPtr, len);
+            fo->bufRPtr += len;
+            return len;
+        } else {
+            /* can only partially fulfill the request from the buffer */
+            count = fo->bufWPtr - fo->bufRPtr;
+           memcpy(buf, fo->buf + fo->bufRPtr, count);
+            fo->bufWPtr=0;
+           fo->bufRPtr=0;
+            len -= count;
+            p += count;
+            total_count = count;
+        }
+    }
 
     while ((count =
              (
@@ -176,24 +187,30 @@ StgInt len;
 #else
                 read(fd, p, len))) <= 0 ) {
 #endif
-       if ( count == 0 ) { /* EOF */
-           break;
-       } else if ( count == -1 && errno == EAGAIN) {
+        /* EOF */
+       if ( count == 0 ) {
+            FILEOBJ_SET_EOF(fo);
+            return total_count;
+       }
+
+        /* Blocking */
+       else if ( count == -1 && errno == EAGAIN) {
            errno = 0;
-           return FILEOBJ_BLOCKED_READ;
-       } else if ( count == -1 && errno != EINTR) {
+            if (total_count > 0) 
+               return total_count; /* partial read */
+           else
+              return FILEOBJ_BLOCKED_READ;
+       }
+
+        /* Error */
+       else if ( count == -1 && errno != EINTR) {
            cvtErrno();
            stdErrno();
            return -1;
-       }
-        total_count += count;
-       len -= count;
-       p += count;
+        }
     }
 
     total_count += count;
-    fo->bufWPtr = total_count;
-    fo->bufRPtr = 0;
     return total_count;
 }
 
@@ -207,8 +224,7 @@ StgInt len;
 */
 
 StgInt
-readLine(ptr)
-StgForeignPtr ptr;
+readLine(StgForeignPtr ptr)
 {
     IOFileObject* fo = (IOFileObject*)ptr;
     int rc=0, count;
@@ -247,9 +263,10 @@ StgForeignPtr ptr;
     fo->flags = (fo->flags & ~FILEOBJ_RW_WRITE) | FILEOBJ_RW_READ;
 
     if ( fo->bufRPtr < 0 || fo->bufRPtr >= fo->bufWPtr ) { /* Buffer is empty */
-       fo->bufRPtr=0; fo->bufWPtr=0;
-       rc = fill_up_line_buffer(fo);
-       if (rc < 0) return rc;
+        fo->bufRPtr=0; 
+       fo->bufWPtr=0;
+        rc = fill_up_line_buffer(fo);
+        if (rc < 0) return rc;
     }
 
     while (1) {
@@ -270,8 +287,7 @@ StgForeignPtr ptr;
 }
 
 StgInt
-readChar(ptr)
-StgForeignPtr ptr;
+readChar(StgForeignPtr ptr)
 {
     IOFileObject* fo= (IOFileObject*)ptr;
     int count,rc=0;