2 % (c) The AQUA Project, Glasgow University, 1994-1996
5 \section[IO]{Module @IO@}
8 {-# OPTIONS -fno-implicit-prelude #-}
13 IOMode(ReadMode,WriteMode,AppendMode,ReadWriteMode),
14 BufferMode(NoBuffering,LineBuffering,BlockBuffering),
15 SeekMode(AbsoluteSeek,RelativeSeek,SeekFromEnd),
17 stdin, stdout, stderr,
18 openFile, hClose, hFileSize, hIsEOF, isEOF,
19 hSetBuffering, hGetBuffering, hFlush, hGetPosn, hSetPosn, hSeek,
20 hIsOpen, hIsClosed, hIsReadable, hIsWritable, hIsSeekable, hReady,
21 hGetChar, hLookAhead, hGetContents, hPutChar, hPutStr, hPrint,
23 isAlreadyExistsError, isAlreadyInUseError, isFullError, isEOFError,
24 isIllegalOperation, isPermissionError, isUserError,
25 ioeGetHandle, ioeGetFileName
31 import ArrBase ( MutableByteArray(..), newCharArray )
32 import IOHandle -- much of the real stuff is in here
33 import PackedString ( nilPS, packCBytesST, unpackPS )
38 %*********************************************************
40 \subsection{Signatures}
42 %*********************************************************
45 --IOHandle:hClose :: Handle -> IO ()
46 --IOHandle:hFileSize :: Handle -> IO Integer
47 --IOHandle:hFlush :: Handle -> IO ()
48 --IOHandle:hGetBuffering :: Handle -> IO BufferMode
49 hGetChar :: Handle -> IO Char
50 hGetContents :: Handle -> IO String
51 --IOHandle:hGetPosn :: Handle -> IO HandlePosn
52 --IOHandle:hIsClosed :: Handle -> IO Bool
53 --IOHandle:hIsEOF :: Handle -> IO Bool
54 --IOHandle:hIsOpen :: Handle -> IO Bool
55 --IOHandle:hIsReadable :: Handle -> IO Bool
56 --IOHandle:hIsSeekable :: Handle -> IO Bool
57 --IOHandle:hIsWritable :: Handle -> IO Bool
58 hLookAhead :: Handle -> IO Char
59 hPrint :: Show a => Handle -> a -> IO ()
60 hPutChar :: Handle -> Char -> IO ()
61 hPutStr :: Handle -> String -> IO ()
62 hReady :: Handle -> IO Bool
63 --IOHandle:hSeek :: Handle -> SeekMode -> Integer -> IO ()
64 --IOHandle:hSetBuffering :: Handle -> BufferMode -> IO ()
65 --IOHandle:hSetPosn :: HandlePosn -> IO ()
66 -- ioeGetFileName :: IOError -> Maybe FilePath
67 -- ioeGetHandle :: IOError -> Maybe Handle
68 -- isAlreadyExistsError :: IOError -> Bool
69 -- isAlreadyInUseError :: IOError -> Bool
70 --IOHandle:isEOF :: IO Bool
71 -- isEOFError :: IOError -> Bool
72 -- isFullError :: IOError -> Bool
73 -- isIllegalOperation :: IOError -> Bool
74 -- isPermissionError :: IOError -> Bool
75 -- isUserError :: IOError -> Maybe String
76 --IOHandle:openFile :: FilePath -> IOMode -> IO Handle
77 --IOHandle:stdin, stdout, stderr :: Handle
80 %*********************************************************
82 \subsection{Simple input operations}
84 %*********************************************************
86 Computation $hReady hdl$ indicates whether at least
87 one item is available for input from handle {\em hdl}.
90 --hReady :: Handle -> IO Bool
92 readHandle handle >>= \ htype ->
94 ErrorHandle ioError ->
95 writeHandle handle htype >>
98 writeHandle handle htype >>
99 fail (IllegalOperation "handle is closed")
100 SemiClosedHandle _ _ ->
101 writeHandle handle htype >>
102 fail (IllegalOperation "handle is closed")
103 AppendHandle _ _ _ ->
104 writeHandle handle htype >>
105 fail (IllegalOperation "handle is not open for reading")
107 writeHandle handle htype >>
108 fail (IllegalOperation "handle is not open for reading")
110 _ccall_ inputReady (filePtr other) `thenIO_Prim` \ rc ->
111 writeHandle handle (markHandle htype) >>
115 _ -> constructErrorAndFail "hReady"
118 Computation $hGetChar hdl$ reads the next character from handle
119 {\em hdl}, blocking until a character is available.
122 --hGetChar :: Handle -> IO Char
125 readHandle handle >>= \ htype ->
127 ErrorHandle ioError ->
128 writeHandle handle htype >>
131 writeHandle handle htype >>
132 fail (IllegalOperation "handle is closed")
133 SemiClosedHandle _ _ ->
134 writeHandle handle htype >>
135 fail (IllegalOperation "handle is closed")
136 AppendHandle _ _ _ ->
137 writeHandle handle htype >>
138 fail (IllegalOperation "handle is not open for reading")
140 writeHandle handle htype >>
141 fail (IllegalOperation "handle is not open for reading")
143 _ccall_ fileGetc (filePtr other) `thenIO_Prim` \ intc ->
144 writeHandle handle (markHandle htype) >>
145 if intc /= ``EOF'' then
148 constructErrorAndFail "hGetChar"
151 Computation $hLookahead hdl$ returns the next character from handle
152 {\em hdl} without removing it from the input buffer, blocking until a
153 character is available.
156 --hLookAhead :: Handle -> IO Char
159 readHandle handle >>= \ htype ->
161 ErrorHandle ioError ->
162 writeHandle handle htype >>
165 writeHandle handle htype >>
166 fail (IllegalOperation "handle is closed")
167 SemiClosedHandle _ _ ->
168 writeHandle handle htype >>
169 fail (IllegalOperation "handle is closed")
170 AppendHandle _ _ _ ->
171 writeHandle handle htype >>
172 fail (IllegalOperation "handle is not open for reading")
174 writeHandle handle htype >>
175 fail (IllegalOperation "handle is not open for reading")
177 _ccall_ fileLookAhead (filePtr other) `thenIO_Prim` \ intc ->
178 writeHandle handle (markHandle htype) >>
179 if intc /= ``EOF'' then
182 constructErrorAndFail "hLookAhead"
186 %*********************************************************
188 \subsection{Getting the entire contents of a handle}
190 %*********************************************************
192 Computation $hGetContents hdl$ returns the list of characters
193 corresponding to the unread portion of the channel or file managed by
194 {\em hdl}, which is made semi-closed.
197 --hGetContents :: Handle -> IO String
199 hGetContents handle =
200 readHandle handle >>= \ htype ->
202 ErrorHandle ioError ->
203 writeHandle handle htype >>
206 writeHandle handle htype >>
207 fail (IllegalOperation "handle is closed")
208 SemiClosedHandle _ _ ->
209 writeHandle handle htype >>
210 fail (IllegalOperation "handle is closed")
211 AppendHandle _ _ _ ->
212 writeHandle handle htype >>
213 fail (IllegalOperation "handle is not open for reading")
215 writeHandle handle htype >>
216 fail (IllegalOperation "handle is not open for reading")
219 To avoid introducing an extra layer of buffering here,
220 we provide three lazy read methods, based on character,
221 line, and block buffering.
223 stToIO (getBufferMode other) >>= \ other ->
224 case (bufferMode other) of
225 Just LineBuffering ->
226 allocBuf Nothing >>= \ buf_info ->
227 writeHandle handle (SemiClosedHandle (filePtr other) buf_info)
229 unsafeInterleavePrimIO (lazyReadLine handle)
230 `thenIO_Prim` \ contents ->
233 Just (BlockBuffering size) ->
234 allocBuf size >>= \ buf_info ->
235 writeHandle handle (SemiClosedHandle (filePtr other) buf_info)
237 unsafeInterleavePrimIO (lazyReadBlock handle)
238 `thenIO_Prim` \ contents ->
240 _ -> -- Nothing is treated pessimistically as NoBuffering
241 writeHandle handle (SemiClosedHandle (filePtr other) (``NULL'', 0))
243 unsafeInterleavePrimIO (lazyReadChar handle)
244 `thenIO_Prim` \ contents ->
247 allocBuf :: Maybe Int -> IO (Addr, Int)
249 _ccall_ malloc size `thenIO_Prim` \ buf ->
250 if buf /= ``NULL'' then
253 fail (ResourceExhausted "not enough virtual memory")
258 Nothing -> ``BUFSIZ''
261 Note that someone may yank our handle out from under us, and then re-use
262 the same FILE * for something else. Therefore, we have to re-examine the
263 handle every time through.
266 lazyReadBlock :: Handle -> PrimIO String
267 lazyReadLine :: Handle -> PrimIO String
268 lazyReadChar :: Handle -> PrimIO String
270 lazyReadBlock handle =
271 ioToST (readHandle handle) >>= \ htype ->
273 -- There cannae be an ErrorHandle here
275 ioToST (writeHandle handle htype) >>
277 SemiClosedHandle fp (buf, size) ->
278 _ccall_ readBlock buf fp size >>= \ bytes ->
281 else packCBytesST bytes buf) >>= \ some ->
283 ioToST (writeHandle handle (SemiClosedHandle ``NULL'' (``NULL'', 0)))
285 _ccall_ free buf >>= \ () ->
286 _ccall_ closeFile fp >>
287 returnPrimIO (unpackPS some)
289 ioToST (writeHandle handle htype) >>
290 unsafeInterleavePrimIO (lazyReadBlock handle)
292 returnPrimIO (unpackPS some ++ more)
294 lazyReadLine handle =
295 ioToST (readHandle handle) >>= \ htype ->
297 -- There cannae be an ErrorHandle here
299 ioToST (writeHandle handle htype) >>
301 SemiClosedHandle fp (buf, size) ->
302 _ccall_ readLine buf fp size >>= \ bytes ->
305 else packCBytesST bytes buf) >>= \ some ->
307 ioToST (writeHandle handle (SemiClosedHandle ``NULL'' (``NULL'', 0)))
309 _ccall_ free buf >>= \ () ->
310 _ccall_ closeFile fp >>
311 returnPrimIO (unpackPS some)
313 ioToST (writeHandle handle htype) >>
314 unsafeInterleavePrimIO (lazyReadLine handle)
316 returnPrimIO (unpackPS some ++ more)
318 lazyReadChar handle =
319 ioToST (readHandle handle) >>= \ htype ->
321 -- There cannae be an ErrorHandle here
323 ioToST (writeHandle handle htype) >>
325 SemiClosedHandle fp buf_info ->
326 _ccall_ readChar fp >>= \ char ->
327 if char == ``EOF'' then
328 ioToST (writeHandle handle (SemiClosedHandle ``NULL'' buf_info))
330 _ccall_ closeFile fp >>
333 ioToST (writeHandle handle htype) >>
334 unsafeInterleavePrimIO (lazyReadChar handle)
336 returnPrimIO (chr char : more)
340 %*********************************************************
342 \subsection{Simple output functions}
344 %*********************************************************
346 Computation $hPutChar hdl c$ writes the character {\em c} to the file
347 or channel managed by {\em hdl}. Characters may be buffered if
348 buffering is enabled for {\em hdl}.
351 --hPutChar :: Handle -> Char -> IO ()
354 readHandle handle >>= \ htype ->
356 ErrorHandle ioError ->
357 writeHandle handle htype >>
360 writeHandle handle htype >>
361 fail (IllegalOperation "handle is closed")
362 SemiClosedHandle _ _ ->
363 writeHandle handle htype >>
364 fail (IllegalOperation "handle is closed")
366 writeHandle handle htype >>
367 fail (IllegalOperation "handle is not open for writing")
369 _ccall_ filePutc (filePtr other) (ord c) `thenIO_Prim` \ rc ->
370 writeHandle handle (markHandle htype) >>
374 constructErrorAndFail "hPutChar"
377 Computation $hPutStr hdl s$ writes the string {\em s} to the file or
378 channel managed by {\em hdl}.
381 --hPutStr :: Handle -> String -> IO ()
384 readHandle handle >>= \ htype ->
386 ErrorHandle ioError ->
387 writeHandle handle htype >>
390 writeHandle handle htype >>
391 fail (IllegalOperation "handle is closed")
392 SemiClosedHandle _ _ ->
393 writeHandle handle htype >>
394 fail (IllegalOperation "handle is closed")
396 writeHandle handle htype >>
397 fail (IllegalOperation "handle is not open for writing")
399 getBufferMode other `thenIO_Prim` \ other ->
400 (case bufferMode other of
401 Just LineBuffering ->
402 writeLines (filePtr other) str
403 Just (BlockBuffering (Just size)) ->
404 writeBlocks (filePtr other) size str
405 Just (BlockBuffering Nothing) ->
406 writeBlocks (filePtr other) ``BUFSIZ'' str
407 _ -> -- Nothing is treated pessimistically as NoBuffering
408 writeChars (filePtr other) str
409 ) `thenIO_Prim` \ success ->
410 writeHandle handle (markHandle other) >>
414 constructErrorAndFail "hPutStr"
416 writeLines :: Addr -> String -> PrimIO Bool
417 writeLines = writeChunks ``BUFSIZ'' True
419 writeBlocks :: Addr -> Int -> String -> PrimIO Bool
420 writeBlocks fp size s = writeChunks size False fp s
423 The breaking up of output into lines along \n boundaries
424 works fine as long as there are newlines to split by.
425 Avoid the splitting up into lines alltogether (doesn't work
426 for overly long lines like the stuff that showsPrec instances
427 normally return). Instead, we split them up into fixed size
428 chunks before blasting them off to the Real World.
430 Hacked to avoid multiple passes over the strings - unsightly, but
431 a whole lot quicker. -- SOF 3/96
434 writeChunks :: Int -> Bool -> Addr -> String -> PrimIO Bool
436 writeChunks (I# bufLen) chopOnNewLine fp s =
437 newCharArray (0,I# bufLen) >>= \ arr@(MutableByteArray _ arr#) ->
439 write_char :: MutableByteArray# RealWorld -> Int# -> Char# -> PrimIO ()
440 write_char arr# n x = ST $ \ (S# s#) ->
441 case (writeCharArray# arr# n x s#) of { s1# ->
444 shoveString :: Int# -> [Char] -> PrimIO Bool
451 _ccall_ writeFile arr fp (I# n) >>= \rc ->
455 write_char arr# n x >>
457 {- Flushing lines - should we bother? -}
458 if n ==# bufLen {- || (chopOnNewLine && (x `eqChar#` '\n'#)) -} then
459 _ccall_ writeFile arr fp (I# (n +# 1#)) >>= \ rc ->
465 shoveString (n +# 1#) xs
469 writeChars :: Addr -> String -> PrimIO Bool
470 writeChars fp "" = returnPrimIO True
471 writeChars fp (c:cs) =
472 _ccall_ filePutc fp (ord c) >>= \ rc ->
479 Computation $hPrint hdl t$ writes the string representation of {\em t}
480 given by the $shows$ function to the file or channel managed by {\em
484 --hPrint :: Show a => Handle -> a -> IO ()
485 hPrint hdl = hPutStr hdl . show