1 {-# OPTIONS -fno-implicit-prelude -#include "HsCore.h" #-}
5 -- -----------------------------------------------------------------------------
6 -- $Id: IO.hs,v 1.2 2002/01/02 14:40:10 simonmar Exp $
8 -- (c) The University of Glasgow, 1992-2001
12 hWaitForInput, hGetChar, hGetLine, hGetContents, hPutChar, hPutStr,
13 commitBuffer', -- hack, see below
14 hGetcBuffered, -- needed by ghc/compiler/utils/StringBuffer.lhs
15 hGetBuf, hPutBuf, slurpFile
28 import GHC.Handle -- much of the real stuff is in here
33 import GHC.Exception ( ioError, catch, throw )
36 -- ---------------------------------------------------------------------------
37 -- Simple input operations
39 -- Computation "hReady hdl" indicates whether at least
40 -- one item is available for input from handle "hdl".
42 -- If hWaitForInput finds anything in the Handle's buffer, it
43 -- immediately returns. If not, it tries to read from the underlying
44 -- OS handle. Notice that for buffered Handles connected to terminals
45 -- this means waiting until a complete line is available.
47 hWaitForInput :: Handle -> Int -> IO Bool
48 hWaitForInput h msecs = do
49 wantReadableHandle "hWaitForInput" h $ \ handle_ -> do
50 let ref = haBuffer handle_
53 if not (bufferEmpty buf)
57 r <- throwErrnoIfMinus1Retry "hWaitForInput"
58 (inputReady (fromIntegral (haFD handle_)) (fromIntegral msecs) (haIsStream handle_))
61 foreign import "inputReady" unsafe
62 inputReady :: CInt -> CInt -> Bool -> IO CInt
64 -- ---------------------------------------------------------------------------
67 -- hGetChar reads the next character from a handle,
68 -- blocking until a character is available.
70 hGetChar :: Handle -> IO Char
72 wantReadableHandle "hGetChar" handle $ \handle_ -> do
75 ref = haBuffer handle_
78 if not (bufferEmpty buf)
79 then hGetcBuffered fd ref buf
83 case haBufferMode handle_ of
85 new_buf <- fillReadBuffer fd True (haIsStream handle_) buf
86 hGetcBuffered fd ref new_buf
87 BlockBuffering _ -> do
88 new_buf <- fillReadBuffer fd False (haIsStream handle_) buf
89 hGetcBuffered fd ref new_buf
91 -- make use of the minimal buffer we already have
93 r <- throwErrnoIfMinus1RetryMayBlock "hGetChar"
94 (read_off (fromIntegral fd) (haIsStream handle_) raw 0 1)
98 else do (c,_) <- readCharFromBuffer raw 0
101 hGetcBuffered fd ref buf@Buffer{ bufBuf=b, bufRPtr=r, bufWPtr=w }
102 = do (c,r) <- readCharFromBuffer b r
103 let new_buf | r == w = buf{ bufRPtr=0, bufWPtr=0 }
104 | otherwise = buf{ bufRPtr=r }
105 writeIORef ref new_buf
108 -- ---------------------------------------------------------------------------
111 -- If EOF is reached before EOL is encountered, ignore the EOF and
112 -- return the partial line. Next attempt at calling hGetLine on the
113 -- handle will yield an EOF IO exception though.
115 -- ToDo: the unbuffered case is wrong: it doesn't lock the handle for
117 hGetLine :: Handle -> IO String
119 m <- wantReadableHandle "hGetLine" h $ \ handle_ -> do
120 case haBufferMode handle_ of
121 NoBuffering -> return Nothing
123 l <- hGetLineBuffered handle_
125 BlockBuffering _ -> do
126 l <- hGetLineBuffered handle_
129 Nothing -> hGetLineUnBuffered h
133 hGetLineBuffered handle_ = do
134 let ref = haBuffer handle_
136 hGetLineBufferedLoop handle_ ref buf []
139 hGetLineBufferedLoop handle_ ref
140 buf@Buffer{ bufRPtr=r, bufWPtr=w, bufBuf=raw } xss =
142 -- find the end-of-line character, if there is one
144 | r == w = return (False, w)
146 (c,r') <- readCharFromBuffer raw r
148 then return (True, r) -- NB. not r': don't include the '\n'
151 (eol, off) <- loop raw r
154 puts ("hGetLineBufferedLoop: r=" ++ show r ++ ", w=" ++ show w ++ ", off=" ++ show off ++ "\n")
157 xs <- unpack raw r off
159 then do if w == off + 1
160 then writeIORef ref buf{ bufRPtr=0, bufWPtr=0 }
161 else writeIORef ref buf{ bufRPtr = off + 1 }
162 return (concat (reverse (xs:xss)))
164 maybe_buf <- maybeFillReadBuffer (haFD handle_) True (haIsStream handle_)
165 buf{ bufWPtr=0, bufRPtr=0 }
167 -- Nothing indicates we caught an EOF, and we may have a
168 -- partial line to return.
169 Nothing -> let str = concat (reverse (xs:xss)) in
174 hGetLineBufferedLoop handle_ ref new_buf (xs:xss)
177 maybeFillReadBuffer fd is_line is_stream buf
179 (do buf <- fillReadBuffer fd is_line is_stream buf
182 (\e -> do if isEOFError e
187 unpack :: RawBuffer -> Int -> Int -> IO [Char]
188 unpack buf r 0 = return ""
189 unpack buf (I# r) (I# len) = IO $ \s -> unpack [] (len -# 1#) s
192 | i <# r = (# s, acc #)
194 case readCharArray# buf i s of
195 (# s, ch #) -> unpack (C# ch : acc) (i -# 1#) s
198 hGetLineUnBuffered :: Handle -> IO String
199 hGetLineUnBuffered h = do
212 if isEOFError err then
222 -- -----------------------------------------------------------------------------
225 -- hGetContents returns the list of characters corresponding to the
226 -- unread portion of the channel or file managed by the handle, which
227 -- is made semi-closed.
229 -- hGetContents on a DuplexHandle only affects the read side: you can
230 -- carry on writing to it afterwards.
232 hGetContents :: Handle -> IO String
233 hGetContents handle =
234 withHandle "hGetContents" handle $ \handle_ ->
235 case haType handle_ of
236 ClosedHandle -> ioe_closedHandle
237 SemiClosedHandle -> ioe_closedHandle
238 AppendHandle -> ioe_notReadable
239 WriteHandle -> ioe_notReadable
240 _ -> do xs <- lazyRead handle
241 return (handle_{ haType=SemiClosedHandle}, xs )
243 -- Note that someone may close the semi-closed handle (or change its
244 -- buffering), so each time these lazy read functions are pulled on,
245 -- they have to check whether the handle has indeed been closed.
247 lazyRead :: Handle -> IO String
250 withHandle "lazyRead" handle $ \ handle_ -> do
251 case haType handle_ of
252 ClosedHandle -> return (handle_, "")
253 SemiClosedHandle -> lazyRead' handle handle_
255 (IOError (Just handle) IllegalOperation "lazyRead"
256 "illegal handle type" Nothing)
258 lazyRead' h handle_ = do
259 let ref = haBuffer handle_
262 -- even a NoBuffering handle can have a char in the buffer...
265 if not (bufferEmpty buf)
266 then lazyReadHaveBuffer h handle_ fd ref buf
269 case haBufferMode handle_ of
271 -- make use of the minimal buffer we already have
273 r <- throwErrnoIfMinus1RetryMayBlock "lazyRead"
274 (read_off (fromIntegral fd) (haIsStream handle_) raw 0 1)
277 then do handle_ <- hClose_help handle_
279 else do (c,_) <- readCharFromBuffer raw 0
281 return (handle_, c : rest)
283 LineBuffering -> lazyReadBuffered h handle_ fd ref buf
284 BlockBuffering _ -> lazyReadBuffered h handle_ fd ref buf
286 -- we never want to block during the read, so we call fillReadBuffer with
287 -- is_line==True, which tells it to "just read what there is".
288 lazyReadBuffered h handle_ fd ref buf = do
290 (do buf <- fillReadBuffer fd True{-is_line-} (haIsStream handle_) buf
291 lazyReadHaveBuffer h handle_ fd ref buf
293 -- all I/O errors are discarded. Additionally, we close the handle.
294 (\e -> do handle_ <- hClose_help handle_
298 lazyReadHaveBuffer h handle_ fd ref buf = do
300 writeIORef ref buf{ bufRPtr=0, bufWPtr=0 }
301 s <- unpackAcc (bufBuf buf) (bufRPtr buf) (bufWPtr buf) more
305 unpackAcc :: RawBuffer -> Int -> Int -> [Char] -> IO [Char]
306 unpackAcc buf r 0 acc = return ""
307 unpackAcc buf (I# r) (I# len) acc = IO $ \s -> unpack acc (len -# 1#) s
310 | i <# r = (# s, acc #)
312 case readCharArray# buf i s of
313 (# s, ch #) -> unpack (C# ch : acc) (i -# 1#) s
315 -- ---------------------------------------------------------------------------
318 -- `hPutChar hdl ch' writes the character `ch' to the file or channel
319 -- managed by `hdl'. Characters may be buffered if buffering is
320 -- enabled for `hdl'.
322 hPutChar :: Handle -> Char -> IO ()
324 c `seq` do -- must evaluate c before grabbing the handle lock
325 wantWritableHandle "hPutChar" handle $ \ handle_ -> do
326 let fd = haFD handle_
327 case haBufferMode handle_ of
328 LineBuffering -> hPutcBuffered handle_ True c
329 BlockBuffering _ -> hPutcBuffered handle_ False c
331 withObject (castCharToCChar c) $ \buf ->
332 throwErrnoIfMinus1RetryMayBlock_ "hPutChar"
333 (c_write (fromIntegral fd) buf 1)
337 hPutcBuffered handle_ is_line c = do
338 let ref = haBuffer handle_
341 w' <- writeCharIntoBuffer (bufBuf buf) w c
342 let new_buf = buf{ bufWPtr = w' }
343 if bufferFull new_buf || is_line && c == '\n'
345 flushed_buf <- flushWriteBuffer (haFD handle_) (haIsStream handle_) new_buf
346 writeIORef ref flushed_buf
348 writeIORef ref new_buf
351 hPutChars :: Handle -> [Char] -> IO ()
352 hPutChars handle [] = return ()
353 hPutChars handle (c:cs) = hPutChar handle c >> hPutChars handle cs
355 -- ---------------------------------------------------------------------------
358 -- `hPutStr hdl s' writes the string `s' to the file or
359 -- hannel managed by `hdl', buffering the output if needs be.
361 -- We go to some trouble to avoid keeping the handle locked while we're
362 -- evaluating the string argument to hPutStr, in case doing so triggers another
363 -- I/O operation on the same handle which would lead to deadlock. The classic
366 -- putStr (trace "hello" "world")
368 -- so the basic scheme is this:
370 -- * copy the string into a fresh buffer,
371 -- * "commit" the buffer to the handle.
373 -- Committing may involve simply copying the contents of the new
374 -- buffer into the handle's buffer, flushing one or both buffers, or
375 -- maybe just swapping the buffers over (if the handle's buffer was
376 -- empty). See commitBuffer below.
378 hPutStr :: Handle -> String -> IO ()
379 hPutStr handle str = do
380 buffer_mode <- wantWritableHandle "hPutStr" handle
381 (\ handle_ -> do getSpareBuffer handle_)
383 (NoBuffering, _) -> do
384 hPutChars handle str -- v. slow, but we don't care
385 (LineBuffering, buf) -> do
386 writeLines handle buf str
387 (BlockBuffering _, buf) -> do
388 writeBlocks handle buf str
391 getSpareBuffer :: Handle__ -> IO (BufferMode, Buffer)
392 getSpareBuffer Handle__{haBuffer=ref,
397 NoBuffering -> return (mode, error "no buffer!")
399 bufs <- readIORef spare_ref
402 BufferListCons b rest -> do
403 writeIORef spare_ref rest
404 return ( mode, newEmptyBuffer b WriteBuffer (bufSize buf))
406 new_buf <- allocateBuffer (bufSize buf) WriteBuffer
407 return (mode, new_buf)
410 writeLines :: Handle -> Buffer -> String -> IO ()
411 writeLines hdl Buffer{ bufBuf=raw, bufSize=len } s =
413 shoveString :: Int -> [Char] -> IO ()
414 -- check n == len first, to ensure that shoveString is strict in n.
415 shoveString n cs | n == len = do
416 new_buf <- commitBuffer hdl raw len n True{-needs flush-} False
417 writeLines hdl new_buf cs
418 shoveString n [] = do
419 commitBuffer hdl raw len n False{-no flush-} True{-release-}
421 shoveString n (c:cs) = do
422 n' <- writeCharIntoBuffer raw n c
425 new_buf <- commitBuffer hdl raw len n' True{-needs flush-} False
426 writeLines hdl new_buf cs
432 writeBlocks :: Handle -> Buffer -> String -> IO ()
433 writeBlocks hdl Buffer{ bufBuf=raw, bufSize=len } s =
435 shoveString :: Int -> [Char] -> IO ()
436 -- check n == len first, to ensure that shoveString is strict in n.
437 shoveString n cs | n == len = do
438 new_buf <- commitBuffer hdl raw len n True{-needs flush-} False
439 writeBlocks hdl new_buf cs
440 shoveString n [] = do
441 commitBuffer hdl raw len n False{-no flush-} True{-release-}
443 shoveString n (c:cs) = do
444 n' <- writeCharIntoBuffer raw n c
449 -- -----------------------------------------------------------------------------
450 -- commitBuffer handle buf sz count flush release
452 -- Write the contents of the buffer 'buf' ('sz' bytes long, containing
453 -- 'count' bytes of data) to handle (handle must be block or line buffered).
457 -- for block/line buffering,
458 -- 1. If there isn't room in the handle buffer, flush the handle
461 -- 2. If the handle buffer is empty,
463 -- then write buf directly to the device.
464 -- else swap the handle buffer with buf.
466 -- 3. If the handle buffer is non-empty, copy buf into the
467 -- handle buffer. Then, if flush != 0, flush
471 :: Handle -- handle to commit to
472 -> RawBuffer -> Int -- address and size (in bytes) of buffer
473 -> Int -- number of bytes of data in buffer
474 -> Bool -- True <=> flush the handle afterward
475 -> Bool -- release the buffer?
478 commitBuffer hdl raw sz@(I# _) count@(I# _) flush release = do
479 wantWritableHandle "commitAndReleaseBuffer" hdl $
480 commitBuffer' hdl raw sz count flush release
482 -- Explicitly lambda-lift this function to subvert GHC's full laziness
483 -- optimisations, which otherwise tends to float out subexpressions
484 -- past the \handle, which is really a pessimisation in this case because
485 -- that lambda is a one-shot lambda.
487 -- Don't forget to export the function, to stop it being inlined too
488 -- (this appears to be better than NOINLINE, because the strictness
489 -- analyser still gets to worker-wrapper it).
491 -- This hack is a fairly big win for hPutStr performance. --SDM 18/9/2001
493 commitBuffer' hdl raw sz@(I# _) count@(I# _) flush release
494 handle_@Handle__{ haFD=fd, haBuffer=ref, haBuffers=spare_buf_ref } = do
497 puts ("commitBuffer: sz=" ++ show sz ++ ", count=" ++ show count
498 ++ ", flush=" ++ show flush ++ ", release=" ++ show release ++"\n")
501 old_buf@Buffer{ bufBuf=old_raw, bufRPtr=r, bufWPtr=w, bufSize=size }
505 -- enough room in handle buffer?
506 if (not flush && (size - w > count))
507 -- The > is to be sure that we never exactly fill
508 -- up the buffer, which would require a flush. So
509 -- if copying the new data into the buffer would
510 -- make the buffer full, we just flush the existing
511 -- buffer and the new data immediately, rather than
512 -- copying before flushing.
514 -- not flushing, and there's enough room in the buffer:
515 -- just copy the data in and update bufWPtr.
516 then do memcpy_baoff_ba old_raw w raw (fromIntegral count)
517 writeIORef ref old_buf{ bufWPtr = w + count }
518 return (newEmptyBuffer raw WriteBuffer sz)
520 -- else, we have to flush
521 else do flushed_buf <- flushWriteBuffer fd (haIsStream handle_) old_buf
524 Buffer{ bufBuf=raw, bufState=WriteBuffer,
525 bufRPtr=0, bufWPtr=count, bufSize=sz }
527 -- if: (a) we don't have to flush, and
528 -- (b) size(new buffer) == size(old buffer), and
529 -- (c) new buffer is not full,
530 -- we can just just swap them over...
531 if (not flush && sz == size && count /= sz)
533 writeIORef ref this_buf
536 -- otherwise, we have to flush the new data too,
537 -- and start with a fresh buffer
539 flushWriteBuffer fd (haIsStream handle_) this_buf
540 writeIORef ref flushed_buf
541 -- if the sizes were different, then allocate
542 -- a new buffer of the correct size.
544 then return (newEmptyBuffer raw WriteBuffer sz)
545 else allocateBuffer size WriteBuffer
547 -- release the buffer if necessary
549 Buffer{ bufSize=buf_ret_sz, bufBuf=buf_ret_raw } -> do
550 if release && buf_ret_sz == size
552 spare_bufs <- readIORef spare_buf_ref
553 writeIORef spare_buf_ref
554 (BufferListCons buf_ret_raw spare_bufs)
559 -- ---------------------------------------------------------------------------
560 -- Reading/writing sequences of bytes.
563 Semantics of hGetBuf:
565 - hGetBuf reads data into the buffer until either
568 (b) the buffer is full
570 It returns the amount of data actually read. This may
571 be zero in case (a). hGetBuf never raises
572 an EOF exception, it always returns zero instead.
574 If the handle is a pipe or socket, and the writing end
575 is closed, hGetBuf will behave as for condition (a).
577 Semantics of hPutBuf:
579 - hPutBuf writes data from the buffer to the handle
580 until the buffer is empty. It returns ().
582 If the handle is a pipe or socket, and the reading end is
583 closed, hPutBuf will raise a ResourceVanished exception.
584 (If this is a POSIX system, and the program has not
585 asked to ignore SIGPIPE, then a SIGPIPE may be delivered
586 instead, whose default action is to terminate the program).
589 -- ---------------------------------------------------------------------------
592 hPutBuf :: Handle -- handle to write to
593 -> Ptr a -- address of buffer
594 -> Int -- number of bytes of data in buffer
596 hPutBuf handle ptr count
597 | count <= 0 = illegalBufferSize handle "hPutBuf" count
599 wantWritableHandle "hPutBuf" handle $
600 \ handle_@Handle__{ haFD=fd, haBuffer=ref, haIsStream=is_stream } -> do
602 old_buf@Buffer{ bufBuf=old_raw, bufRPtr=r, bufWPtr=w, bufSize=size }
605 -- enough room in handle buffer?
606 if (size - w > count)
607 -- There's enough room in the buffer:
608 -- just copy the data in and update bufWPtr.
609 then do memcpy_baoff_ptr old_raw w ptr (fromIntegral count)
610 writeIORef ref old_buf{ bufWPtr = w + count }
613 -- else, we have to flush
614 else do flushed_buf <- flushWriteBuffer fd is_stream old_buf
615 writeIORef ref flushed_buf
616 -- ToDo: should just memcpy instead of writing if possible
617 writeChunk fd ptr count
619 writeChunk :: FD -> Ptr a -> Int -> IO ()
620 writeChunk fd ptr bytes = loop 0 bytes
622 loop :: Int -> Int -> IO ()
623 loop _ bytes | bytes <= 0 = return ()
625 r <- fromIntegral `liftM`
626 throwErrnoIfMinus1RetryMayBlock "writeChunk"
627 (c_write (fromIntegral fd) (ptr `plusPtr` off) (fromIntegral bytes))
629 -- write can't return 0
630 loop (off + r) (bytes - r)
632 -- ---------------------------------------------------------------------------
635 hGetBuf :: Handle -> Ptr a -> Int -> IO Int
636 hGetBuf handle ptr count
637 | count <= 0 = illegalBufferSize handle "hGetBuf" count
639 wantReadableHandle "hGetBuf" handle $
640 \ handle_@Handle__{ haFD=fd, haBuffer=ref } -> do
641 buf@Buffer{ bufBuf=raw, bufWPtr=w, bufRPtr=r } <- readIORef ref
643 then readChunk fd ptr count
646 copied <- if (count >= avail)
648 memcpy_ptr_baoff ptr raw r (fromIntegral avail)
649 writeIORef ref buf{ bufWPtr=0, bufRPtr=0 }
652 memcpy_ptr_baoff ptr raw r (fromIntegral count)
653 writeIORef ref buf{ bufRPtr = r + count }
656 let remaining = count - copied
658 then do rest <- readChunk fd (ptr `plusPtr` copied) remaining
659 return (rest + copied)
662 readChunk :: FD -> Ptr a -> Int -> IO Int
663 readChunk fd ptr bytes = loop 0 bytes
665 loop :: Int -> Int -> IO Int
666 loop off bytes | bytes <= 0 = return off
668 r <- fromIntegral `liftM`
669 throwErrnoIfMinus1RetryMayBlock "readChunk"
670 (c_read (fromIntegral fd) (ptr `plusPtr` off) (fromIntegral bytes))
674 else loop (off + r) (bytes - r)
676 slurpFile :: FilePath -> IO (Ptr (), Int)
678 handle <- openFile fname ReadMode
679 sz <- hFileSize handle
680 if sz > fromIntegral (maxBound::Int) then
681 ioError (userError "slurpFile: file too big")
683 let sz_i = fromIntegral sz
684 chunk <- mallocBytes sz_i
685 r <- hGetBuf handle chunk sz_i
689 -- ---------------------------------------------------------------------------
692 foreign import "__hscore_memcpy_src_off" unsafe
693 memcpy_ba_baoff :: RawBuffer -> RawBuffer -> Int -> CSize -> IO (Ptr ())
694 foreign import "__hscore_memcpy_src_off" unsafe
695 memcpy_ptr_baoff :: Ptr a -> RawBuffer -> Int -> CSize -> IO (Ptr ())
696 foreign import "__hscore_memcpy_dst_off" unsafe
697 memcpy_baoff_ba :: RawBuffer -> Int -> RawBuffer -> CSize -> IO (Ptr ())
698 foreign import "__hscore_memcpy_dst_off" unsafe
699 memcpy_baoff_ptr :: RawBuffer -> Int -> Ptr a -> CSize -> IO (Ptr ())
701 -----------------------------------------------------------------------------
704 illegalBufferSize :: Handle -> String -> Int -> IO a
705 illegalBufferSize handle fn (sz :: Int) =
706 ioException (IOError (Just handle)
708 ("illegal buffer size " ++ showsPrec 9 sz [])