2 % (c) The AQUA Project, Glasgow University, 1994-1996
5 \section[IO]{Module @IO@}
11 IOMode(ReadMode,WriteMode,AppendMode,ReadWriteMode),
12 BufferMode(NoBuffering,LineBuffering,BlockBuffering),
13 SeekMode(AbsoluteSeek,RelativeSeek,SeekFromEnd),
15 stdin, stdout, stderr,
16 openFile, hClose, hFileSize, hIsEOF, isEOF,
17 hSetBuffering, hGetBuffering, hFlush, hGetPosn, hSetPosn, hSeek,
18 hIsOpen, hIsClosed, hIsReadable, hIsWritable, hIsSeekable, hReady,
19 hGetChar, hLookAhead, hGetContents, hPutChar, hPutStr, hPrint,
21 isAlreadyExistsError, isAlreadyInUseError, isFullError, isEOFError,
22 isIllegalOperation, isPermissionError, isUserError,
23 ioeGetHandle, ioeGetFileName
30 import ArrBase ( MutableByteArray(..), newCharArray )
31 import IOHandle -- much of the real stuff is in here
32 import PackedString ( nilPS, packCBytesST, unpackPS )
37 %*********************************************************
39 \subsection{Signatures}
41 %*********************************************************
44 --IOHandle:hClose :: Handle -> IO ()
45 --IOHandle:hFileSize :: Handle -> IO Integer
46 --IOHandle:hFlush :: Handle -> IO ()
47 --IOHandle:hGetBuffering :: Handle -> IO BufferMode
48 hGetChar :: Handle -> IO Char
49 hGetContents :: Handle -> IO String
50 --IOHandle:hGetPosn :: Handle -> IO HandlePosn
51 --IOHandle:hIsClosed :: Handle -> IO Bool
52 --IOHandle:hIsEOF :: Handle -> IO Bool
53 --IOHandle:hIsOpen :: Handle -> IO Bool
54 --IOHandle:hIsReadable :: Handle -> IO Bool
55 --IOHandle:hIsSeekable :: Handle -> IO Bool
56 --IOHandle:hIsWritable :: Handle -> IO Bool
57 hLookAhead :: Handle -> IO Char
58 hPrint :: Show a => Handle -> a -> IO ()
59 hPutChar :: Handle -> Char -> IO ()
60 hPutStr :: Handle -> String -> IO ()
61 hReady :: Handle -> IO Bool
62 --IOHandle:hSeek :: Handle -> SeekMode -> Integer -> IO ()
63 --IOHandle:hSetBuffering :: Handle -> BufferMode -> IO ()
64 --IOHandle:hSetPosn :: HandlePosn -> IO ()
65 -- ioeGetFileName :: IOError -> Maybe FilePath
66 -- ioeGetHandle :: IOError -> Maybe Handle
67 -- isAlreadyExistsError :: IOError -> Bool
68 -- isAlreadyInUseError :: IOError -> Bool
69 --IOHandle:isEOF :: IO Bool
70 -- isEOFError :: IOError -> Bool
71 -- isFullError :: IOError -> Bool
72 -- isIllegalOperation :: IOError -> Bool
73 -- isPermissionError :: IOError -> Bool
74 -- isUserError :: IOError -> Maybe String
75 --IOHandle:openFile :: FilePath -> IOMode -> IO Handle
76 --IOHandle:stdin, stdout, stderr :: Handle
79 %*********************************************************
81 \subsection{Simple input operations}
83 %*********************************************************
85 Computation $hReady hdl$ indicates whether at least
86 one item is available for input from handle {\em hdl}.
89 --hReady :: Handle -> IO Bool
91 readHandle handle >>= \ htype ->
93 ErrorHandle ioError ->
94 writeHandle handle htype >>
97 writeHandle handle htype >>
98 fail (IllegalOperation "handle is closed")
99 SemiClosedHandle _ _ ->
100 writeHandle handle htype >>
101 fail (IllegalOperation "handle is closed")
102 AppendHandle _ _ _ ->
103 writeHandle handle htype >>
104 fail (IllegalOperation "handle is not open for reading")
106 writeHandle handle htype >>
107 fail (IllegalOperation "handle is not open for reading")
109 _ccall_ inputReady (filePtr other) `thenIO_Prim` \ rc ->
110 writeHandle handle (markHandle htype) >>
114 _ -> constructErrorAndFail "hReady"
117 Computation $hGetChar hdl$ reads the next character from handle
118 {\em hdl}, blocking until a character is available.
121 --hGetChar :: Handle -> IO Char
124 readHandle handle >>= \ htype ->
126 ErrorHandle ioError ->
127 writeHandle handle htype >>
130 writeHandle handle htype >>
131 fail (IllegalOperation "handle is closed")
132 SemiClosedHandle _ _ ->
133 writeHandle handle htype >>
134 fail (IllegalOperation "handle is closed")
135 AppendHandle _ _ _ ->
136 writeHandle handle htype >>
137 fail (IllegalOperation "handle is not open for reading")
139 writeHandle handle htype >>
140 fail (IllegalOperation "handle is not open for reading")
142 _ccall_ fileGetc (filePtr other) `thenIO_Prim` \ intc ->
143 writeHandle handle (markHandle htype) >>
144 if intc /= ``EOF'' then
147 constructErrorAndFail "hGetChar"
150 Computation $hLookahead hdl$ returns the next character from handle
151 {\em hdl} without removing it from the input buffer, blocking until a
152 character is available.
155 --hLookAhead :: Handle -> IO Char
158 readHandle handle >>= \ htype ->
160 ErrorHandle ioError ->
161 writeHandle handle htype >>
164 writeHandle handle htype >>
165 fail (IllegalOperation "handle is closed")
166 SemiClosedHandle _ _ ->
167 writeHandle handle htype >>
168 fail (IllegalOperation "handle is closed")
169 AppendHandle _ _ _ ->
170 writeHandle handle htype >>
171 fail (IllegalOperation "handle is not open for reading")
173 writeHandle handle htype >>
174 fail (IllegalOperation "handle is not open for reading")
176 _ccall_ fileLookAhead (filePtr other) `thenIO_Prim` \ intc ->
177 writeHandle handle (markHandle htype) >>
178 if intc /= ``EOF'' then
181 constructErrorAndFail "hLookAhead"
185 %*********************************************************
187 \subsection{Getting the entire contents of a handle}
189 %*********************************************************
191 Computation $hGetContents hdl$ returns the list of characters
192 corresponding to the unread portion of the channel or file managed by
193 {\em hdl}, which is made semi-closed.
196 --hGetContents :: Handle -> IO String
198 hGetContents handle =
199 readHandle handle >>= \ htype ->
201 ErrorHandle ioError ->
202 writeHandle handle htype >>
205 writeHandle handle htype >>
206 fail (IllegalOperation "handle is closed")
207 SemiClosedHandle _ _ ->
208 writeHandle handle htype >>
209 fail (IllegalOperation "handle is closed")
210 AppendHandle _ _ _ ->
211 writeHandle handle htype >>
212 fail (IllegalOperation "handle is not open for reading")
214 writeHandle handle htype >>
215 fail (IllegalOperation "handle is not open for reading")
218 To avoid introducing an extra layer of buffering here,
219 we provide three lazy read methods, based on character,
220 line, and block buffering.
222 stToIO (getBufferMode other) >>= \ other ->
223 case (bufferMode other) of
224 Just LineBuffering ->
225 allocBuf Nothing >>= \ buf_info ->
226 writeHandle handle (SemiClosedHandle (filePtr other) buf_info)
228 unsafeInterleavePrimIO (lazyReadLine handle)
229 `thenIO_Prim` \ contents ->
232 Just (BlockBuffering size) ->
233 allocBuf size >>= \ buf_info ->
234 writeHandle handle (SemiClosedHandle (filePtr other) buf_info)
236 unsafeInterleavePrimIO (lazyReadBlock handle)
237 `thenIO_Prim` \ contents ->
239 _ -> -- Nothing is treated pessimistically as NoBuffering
240 writeHandle handle (SemiClosedHandle (filePtr other) (``NULL'', 0))
242 unsafeInterleavePrimIO (lazyReadChar handle)
243 `thenIO_Prim` \ contents ->
246 allocBuf :: Maybe Int -> IO (Addr, Int)
248 _ccall_ malloc size `thenIO_Prim` \ buf ->
249 if buf /= ``NULL'' then
252 fail (ResourceExhausted "not enough virtual memory")
257 Nothing -> ``BUFSIZ''
260 Note that someone may yank our handle out from under us, and then re-use
261 the same FILE * for something else. Therefore, we have to re-examine the
262 handle every time through.
265 lazyReadBlock :: Handle -> PrimIO String
266 lazyReadLine :: Handle -> PrimIO String
267 lazyReadChar :: Handle -> PrimIO String
269 lazyReadBlock handle =
270 ioToST (readHandle handle) >>= \ htype ->
272 -- There cannae be an ErrorHandle here
274 ioToST (writeHandle handle htype) >>
276 SemiClosedHandle fp (buf, size) ->
277 _ccall_ readBlock buf fp size >>= \ bytes ->
280 else packCBytesST bytes buf) >>= \ some ->
282 ioToST (writeHandle handle (SemiClosedHandle ``NULL'' (``NULL'', 0)))
284 _ccall_ free buf >>= \ () ->
285 _ccall_ closeFile fp >>
286 returnPrimIO (unpackPS some)
288 ioToST (writeHandle handle htype) >>
289 unsafeInterleavePrimIO (lazyReadBlock handle)
291 returnPrimIO (unpackPS some ++ more)
293 lazyReadLine handle =
294 ioToST (readHandle handle) >>= \ htype ->
296 -- There cannae be an ErrorHandle here
298 ioToST (writeHandle handle htype) >>
300 SemiClosedHandle fp (buf, size) ->
301 _ccall_ readLine buf fp size >>= \ bytes ->
304 else packCBytesST bytes buf) >>= \ some ->
306 ioToST (writeHandle handle (SemiClosedHandle ``NULL'' (``NULL'', 0)))
308 _ccall_ free buf >>= \ () ->
309 _ccall_ closeFile fp >>
310 returnPrimIO (unpackPS some)
312 ioToST (writeHandle handle htype) >>
313 unsafeInterleavePrimIO (lazyReadLine handle)
315 returnPrimIO (unpackPS some ++ more)
317 lazyReadChar handle =
318 ioToST (readHandle handle) >>= \ htype ->
320 -- There cannae be an ErrorHandle here
322 ioToST (writeHandle handle htype) >>
324 SemiClosedHandle fp buf_info ->
325 _ccall_ readChar fp >>= \ char ->
326 if char == ``EOF'' then
327 ioToST (writeHandle handle (SemiClosedHandle ``NULL'' buf_info))
329 _ccall_ closeFile fp >>
332 ioToST (writeHandle handle htype) >>
333 unsafeInterleavePrimIO (lazyReadChar handle)
335 returnPrimIO (chr char : more)
339 %*********************************************************
341 \subsection{Simple output functions}
343 %*********************************************************
345 Computation $hPutChar hdl c$ writes the character {\em c} to the file
346 or channel managed by {\em hdl}. Characters may be buffered if
347 buffering is enabled for {\em hdl}.
350 --hPutChar :: Handle -> Char -> IO ()
353 readHandle handle >>= \ htype ->
355 ErrorHandle ioError ->
356 writeHandle handle htype >>
359 writeHandle handle htype >>
360 fail (IllegalOperation "handle is closed")
361 SemiClosedHandle _ _ ->
362 writeHandle handle htype >>
363 fail (IllegalOperation "handle is closed")
365 writeHandle handle htype >>
366 fail (IllegalOperation "handle is not open for writing")
368 _ccall_ filePutc (filePtr other) (ord c) `thenIO_Prim` \ rc ->
369 writeHandle handle (markHandle htype) >>
373 constructErrorAndFail "hPutChar"
376 Computation $hPutStr hdl s$ writes the string {\em s} to the file or
377 channel managed by {\em hdl}.
380 --hPutStr :: Handle -> String -> IO ()
383 readHandle handle >>= \ htype ->
385 ErrorHandle ioError ->
386 writeHandle handle htype >>
389 writeHandle handle htype >>
390 fail (IllegalOperation "handle is closed")
391 SemiClosedHandle _ _ ->
392 writeHandle handle htype >>
393 fail (IllegalOperation "handle is closed")
395 writeHandle handle htype >>
396 fail (IllegalOperation "handle is not open for writing")
398 getBufferMode other `thenIO_Prim` \ other ->
399 (case bufferMode other of
400 Just LineBuffering ->
401 writeLines (filePtr other) str
402 Just (BlockBuffering (Just size)) ->
403 writeBlocks (filePtr other) size str
404 Just (BlockBuffering Nothing) ->
405 writeBlocks (filePtr other) ``BUFSIZ'' str
406 _ -> -- Nothing is treated pessimistically as NoBuffering
407 writeChars (filePtr other) str
408 ) `thenIO_Prim` \ success ->
409 writeHandle handle (markHandle other) >>
413 constructErrorAndFail "hPutStr"
415 writeLines :: Addr -> String -> PrimIO Bool
416 writeLines = writeChunks ``BUFSIZ'' True
418 writeBlocks :: Addr -> Int -> String -> PrimIO Bool
419 writeBlocks fp size s = writeChunks size False fp s
422 The breaking up of output into lines along \n boundaries
423 works fine as long as there are newlines to split by.
424 Avoid the splitting up into lines alltogether (doesn't work
425 for overly long lines like the stuff that showsPrec instances
426 normally return). Instead, we split them up into fixed size
427 chunks before blasting them off to the Real World.
429 Hacked to avoid multiple passes over the strings - unsightly, but
430 a whole lot quicker. -- SOF 3/96
433 writeChunks :: Int -> Bool -> Addr -> String -> PrimIO Bool
435 writeChunks (I# bufLen) chopOnNewLine fp s =
436 newCharArray (0,I# bufLen) >>= \ arr@(MutableByteArray _ arr#) ->
438 write_char :: MutableByteArray# RealWorld -> Int# -> Char# -> PrimIO ()
439 write_char arr# n x = ST $ \ (S# s#) ->
440 case (writeCharArray# arr# n x s#) of { s1# ->
443 shoveString :: Int# -> [Char] -> PrimIO Bool
450 _ccall_ writeFile arr fp (I# n) >>= \rc ->
454 write_char arr# n x >>
456 {- Flushing lines - should we bother? -}
457 if n ==# bufLen {- || (chopOnNewLine && (x `eqChar#` '\n'#)) -} then
458 _ccall_ writeFile arr fp (I# (n +# 1#)) >>= \ rc ->
464 shoveString (n +# 1#) xs
468 writeChars :: Addr -> String -> PrimIO Bool
469 writeChars fp "" = returnPrimIO True
470 writeChars fp (c:cs) =
471 _ccall_ filePutc fp (ord c) >>= \ rc ->
478 Computation $hPrint hdl t$ writes the string representation of {\em t}
479 given by the $shows$ function to the file or channel managed by {\em
483 --hPrint :: Show a => Handle -> a -> IO ()
484 hPrint hdl = hPutStr hdl . show