[project @ 1998-08-14 12:42:01 by sof]
[ghc-hetmet.git] / ghc / lib / std / cbits / writeFile.lc
1 %
2 % (c) The GRASP/AQUA Project, Glasgow University, 1994
3 %
4 \subsection[writeFile.lc]{hPutStr Runtime Support}
5
6 \begin{code}
7
8 #include "rtsdefs.h"
9 #include "stgio.h"
10
11 StgInt
12 writeFileObject(ptr, bytes)
13 StgForeignObj ptr;
14 StgInt bytes;
15 {
16     int rc=0;
17     IOFileObject* fo = (IOFileObject*)ptr;
18
19     char *p = (char *) fo->buf;
20
21     /* If we've got a r/w file object in our hand, flush the
22        (input) buffer contents first.
23     */
24     if ( FILEOBJ_READABLE(fo) && FILEOBJ_JUST_READ(fo) ) {
25        fo->flags = (fo->flags & ~FILEOBJ_RW_READ) | FILEOBJ_RW_WRITE;
26        rc = flushReadBuffer(ptr);
27        if (rc < 0) return rc;
28     }
29
30     return (writeBuffer(ptr, bytes));
31 }
32
33 StgInt
34 writeBuffer(ptr, bytes)
35 StgForeignObj ptr;
36 StgInt bytes;
37 {
38     int count, rc=0;
39     IOFileObject* fo = (IOFileObject*)ptr;
40
41     char *p = (char *) fo->buf;
42
43     /* Disallow short writes */
44     if (bytes == 0  || fo->buf == NULL)
45         return 0;
46
47     if ( fo->flags & FILEOBJ_NONBLOCKING_IO && inputReady(ptr,0) != 1 )
48        return FILEOBJ_BLOCKED_WRITE;
49
50     while ((count = write(fo->fd, fo->buf, bytes)) < bytes) {
51         if (errno != EINTR) {
52             cvtErrno();
53             stdErrno();
54             return -1;
55         }
56         bytes -= count;
57         p += count;
58     }
59     /* Signal that we've emptied the buffer */
60     fo->bufWPtr=0;
61     return 0;
62 }
63
64
65 StgInt
66 writeBuf(ptr, buf, len)
67 StgForeignObj ptr;
68 StgAddr buf;
69 StgInt  len;
70 {
71     IOFileObject* fo = (IOFileObject*)ptr;
72     int count;
73     int rc = 0;
74     char *p = (char *) buf;
75
76     if (len == 0 )
77         return 0;
78
79     /* First of all, check if we do need to flush the buffer .. */
80     /* Note - in the case of line buffering, we do not currently check
81        whether we need to flush buffer due to line terminators in the
82        buffer we're outputting */
83     if ( fo->buf != NULL                     &&   /* buffered and */
84          (fo->bufWPtr + len < (fo->bufSize))      /* there's room */
85        ) {
86        /* Block copying is likely to be cheaper than, flush, followed by write */
87        memcpy(((char*)fo->buf + fo->bufWPtr), buf, len);
88        fo->bufWPtr += len;
89        return 0;
90     }
91     /* If we do overflow, flush current contents of the buffer and
92        directly output the chunk.
93        (no attempt at splitting up the chunk is currently made)
94     */       
95     if ( fo->buf != NULL                     &&    /* buffered and */
96          (fo->bufWPtr + len >= (fo->bufSize))       /* there's not room */
97        ) {
98        /* Flush buffer */
99        rc = writeFileObject(ptr, fo->bufWPtr);
100        /* ToDo: undo buffer fill if we're blocking.. */
101     }
102
103     if (rc != 0) { 
104        return rc;
105     }
106
107     if ( fo->flags & FILEOBJ_NONBLOCKING_IO && inputReady(ptr,0) != 1 )
108        return FILEOBJ_BLOCKED_WRITE;
109
110     /* Disallow short writes */
111     while ((count = write(fo->fd, (char *)buf, (int)len)) < len) {
112         if (errno != EINTR) {
113             cvtErrno();
114             stdErrno();
115             return -1;
116         }
117         len -= count;
118         p += count;
119     }
120
121     return 0;
122 }
123
124 StgInt
125 writeBufBA(ptr, buf, len)
126 StgForeignObj ptr;
127 StgByteArray buf;
128 StgInt  len;
129 { return (writeBuf(ptr,(StgAddr)buf, len)); }
130
131
132 \end{code}