summaryrefslogtreecommitdiff
path: root/ghc/lib/std/cbits/writeFile.lc
diff options
context:
space:
mode:
authorsof <unknown>1998-08-14 12:42:23 +0000
committersof <unknown>1998-08-14 12:42:23 +0000
commitbf64fa7057773902012e3cbea5186bc06b94be0b (patch)
treef7b8f34ac5604f7027a33a2d5901ffb97b32c35e /ghc/lib/std/cbits/writeFile.lc
parentfb49b1af911ded218b3b3a84c784be2542c53e86 (diff)
downloadhaskell-bf64fa7057773902012e3cbea5186bc06b94be0b.tar.gz
[project @ 1998-08-14 12:42:01 by sof]
Beefed up IO stub functions to not have to rely on stdio any longer
Diffstat (limited to 'ghc/lib/std/cbits/writeFile.lc')
-rw-r--r--ghc/lib/std/cbits/writeFile.lc99
1 files changed, 82 insertions, 17 deletions
diff --git a/ghc/lib/std/cbits/writeFile.lc b/ghc/lib/std/cbits/writeFile.lc
index 80b946f117..ca7bac63d4 100644
--- a/ghc/lib/std/cbits/writeFile.lc
+++ b/ghc/lib/std/cbits/writeFile.lc
@@ -9,19 +9,45 @@
#include "stgio.h"
StgInt
-writeFile(buf, fp, bytes)
-StgAddr buf;
-StgForeignObj fp;
+writeFileObject(ptr, bytes)
+StgForeignObj ptr;
StgInt bytes;
{
- int count;
- char *p = (char *) buf;
+ int rc=0;
+ IOFileObject* fo = (IOFileObject*)ptr;
- if (bytes == 0)
- return 0;
+ char *p = (char *) fo->buf;
+
+ /* If we've got a r/w file object in our hand, flush the
+ (input) buffer contents first.
+ */
+ if ( FILEOBJ_READABLE(fo) && FILEOBJ_JUST_READ(fo) ) {
+ fo->flags = (fo->flags & ~FILEOBJ_RW_READ) | FILEOBJ_RW_WRITE;
+ rc = flushReadBuffer(ptr);
+ if (rc < 0) return rc;
+ }
+
+ return (writeBuffer(ptr, bytes));
+}
+
+StgInt
+writeBuffer(ptr, bytes)
+StgForeignObj ptr;
+StgInt bytes;
+{
+ int count, rc=0;
+ IOFileObject* fo = (IOFileObject*)ptr;
+
+ char *p = (char *) fo->buf;
/* Disallow short writes */
- while ((count = fwrite(p, 1, bytes, (FILE *) fp)) < bytes) {
+ if (bytes == 0 || fo->buf == NULL)
+ return 0;
+
+ if ( fo->flags & FILEOBJ_NONBLOCKING_IO && inputReady(ptr,0) != 1 )
+ return FILEOBJ_BLOCKED_WRITE;
+
+ while ((count = write(fo->fd, fo->buf, bytes)) < bytes) {
if (errno != EINTR) {
cvtErrno();
stdErrno();
@@ -29,28 +55,60 @@ StgInt bytes;
}
bytes -= count;
p += count;
- clearerr((FILE *) fp);
}
-
+ /* Signal that we've emptied the buffer */
+ fo->bufWPtr=0;
return 0;
}
StgInt
-writeBuf(fp, elt_sz, len, buf)
-StgForeignObj fp;
-StgWord elt_sz;
-StgInt len;
+writeBuf(ptr, buf, len)
+StgForeignObj ptr;
StgAddr buf;
+StgInt len;
{
+ IOFileObject* fo = (IOFileObject*)ptr;
int count;
+ int rc = 0;
char *p = (char *) buf;
- if (len == 0 || elt_sz == 0)
+ if (len == 0 )
return 0;
+ /* First of all, check if we do need to flush the buffer .. */
+ /* Note - in the case of line buffering, we do not currently check
+ whether we need to flush buffer due to line terminators in the
+ buffer we're outputting */
+ if ( fo->buf != NULL && /* buffered and */
+ (fo->bufWPtr + len < (fo->bufSize)) /* there's room */
+ ) {
+ /* Block copying is likely to be cheaper than, flush, followed by write */
+ memcpy(((char*)fo->buf + fo->bufWPtr), buf, len);
+ fo->bufWPtr += len;
+ return 0;
+ }
+ /* If we do overflow, flush current contents of the buffer and
+ directly output the chunk.
+ (no attempt at splitting up the chunk is currently made)
+ */
+ if ( fo->buf != NULL && /* buffered and */
+ (fo->bufWPtr + len >= (fo->bufSize)) /* there's not room */
+ ) {
+ /* Flush buffer */
+ rc = writeFileObject(ptr, fo->bufWPtr);
+ /* ToDo: undo buffer fill if we're blocking.. */
+ }
+
+ if (rc != 0) {
+ return rc;
+ }
+
+ if ( fo->flags & FILEOBJ_NONBLOCKING_IO && inputReady(ptr,0) != 1 )
+ return FILEOBJ_BLOCKED_WRITE;
+
/* Disallow short writes */
- while ((count = fwrite((char *)buf, (unsigned)elt_sz, (int)len, (FILE *) fp)) < len) {
+ while ((count = write(fo->fd, (char *)buf, (int)len)) < len) {
if (errno != EINTR) {
cvtErrno();
stdErrno();
@@ -58,10 +116,17 @@ StgAddr buf;
}
len -= count;
p += count;
- clearerr((FILE *) fp);
}
return 0;
}
+StgInt
+writeBufBA(ptr, buf, len)
+StgForeignObj ptr;
+StgByteArray buf;
+StgInt len;
+{ return (writeBuf(ptr,(StgAddr)buf, len)); }
+
+
\end{code}