hWaitForInput :: Handle -> Int -> IO Bool
hWaitForInput h msecs = do
wantReadableHandle_ "hWaitForInput" h $ \ handle_@Handle__{..} -> do
- buf <- readIORef haCharBuffer
+ cbuf <- readIORef haCharBuffer
- if not (isEmptyBuffer buf)
- then return True
- else do
+ if not (isEmptyBuffer cbuf) then return True else do
if msecs < 0
- then do buf' <- readTextDevice handle_ buf
- writeIORef haCharBuffer buf'
+ then do cbuf' <- readTextDevice handle_ cbuf
+ writeIORef haCharBuffer cbuf'
return True
- else do r <- IODevice.ready haDevice False{-read-} msecs
+ else do
+ -- there might be bytes in the byte buffer waiting to be decoded
+ cbuf' <- readTextDeviceNonBlocking handle_ cbuf
+ writeIORef haCharBuffer cbuf'
+
+ if not (isEmptyBuffer cbuf') then return True else do
+
+ r <- IODevice.ready haDevice False{-read-} msecs
if r then do -- Call hLookAhead' to throw an EOF
- -- exception if appropriate
- hLookAhead_ handle_
- return True
- else return False
+ -- exception if appropriate
+ _ <- hLookAhead_ handle_
+ return True
+ else return False
+ -- XXX we should only return when there are full characters
+ -- not when there are only bytes. That would mean looping
+ -- and re-running IODevice.ready if we don't have any full
+ -- characters; but we don't know how long we've waited
+ -- so far.
-- ---------------------------------------------------------------------------
-- hGetChar
-- if we're about to call readTextDevice, otherwise it
-- would mess up flushCharBuffer.
-- See [note Buffer Flushing], GHC.IO.Handle.Types
- writeCharBuf bufRaw 0 '\r'
+ _ <- writeCharBuf bufRaw 0 '\r'
let buf' = buf{ bufL=0, bufR=1 }
readTextDevice handle_ buf'
else do
let
shoveString :: Int -> [Char] -> IO ()
shoveString !n [] = do
- commitBuffer hdl raw len n False{-no flush-} True{-release-}
+ _ <- commitBuffer hdl raw len n False{-no flush-} True{-release-}
return ()
shoveString !n (c:cs)
-- n+1 so we have enough room to write '\r\n' if necessary
-- otherwise, we have to flush the new data too,
-- and start with a fresh buffer
else do
- flushWriteBuffer_ handle_ this_buf
+ -- We're aren't going to use this buffer again
+ -- so we ignore the result of flushWriteBuffer_
+ _ <- flushWriteBuffer_ handle_ this_buf
writeIORef ref flushed_buf
-- if the sizes were different, then allocate
-- a new buffer of the correct size.
-- 'hPutBuf' ignores any text encoding that applies to the 'Handle',
-- writing the bytes directly to the underlying file or device.
--
+-- 'hPutBuf' ignores the prevailing 'TextEncoding' and
+-- 'NewlineMode' on the 'Handle', and writes bytes directly.
+--
-- This operation may fail with:
--
-- * 'ResourceVanished' if the handle is a pipe or socket, and the
-> Ptr a -- address of buffer
-> Int -- number of bytes of data in buffer
-> IO ()
-hPutBuf h ptr count = do hPutBuf' h ptr count True; return ()
+hPutBuf h ptr count = do _ <- hPutBuf' h ptr count True
+ return ()
hPutBufNonBlocking
:: Handle -- handle to write to
-- else, we have to flush
else do debugIO "hPutBuf: flushing first"
- Buffered.flushWriteBuffer haDevice old_buf
+ old_buf' <- Buffered.flushWriteBuffer haDevice old_buf
-- TODO: we should do a non-blocking flush here
- writeIORef haByteBuffer old_buf{bufL=0,bufR=0}
+ writeIORef haByteBuffer old_buf'
-- if we can fit in the buffer, then just loop
if count < size
then bufWrite h_ ptr count can_block
-- If the handle is a pipe or socket, and the writing end
-- is closed, 'hGetBuf' will behave as if EOF was reached.
--
+-- 'hGetBuf' ignores the prevailing 'TextEncoding' and 'NewlineMode'
+-- on the 'Handle', and reads bytes directly.
hGetBuf :: Handle -> Ptr a -> Int -> IO Int
hGetBuf h ptr count
-- If the handle is a pipe or socket, and the writing end
-- is closed, 'hGetBufNonBlocking' will behave as if EOF was reached.
--
+-- 'hGetBufNonBlocking' ignores the prevailing 'TextEncoding' and
+-- 'NewlineMode' on the 'Handle', and reads bytes directly.
+
hGetBufNonBlocking :: Handle -> Ptr a -> Int -> IO Int
hGetBufNonBlocking h ptr count
| count == 0 = return 0
-- memcpy wrappers
copyToRawBuffer :: RawBuffer e -> Int -> Ptr e -> Int -> IO ()
-copyToRawBuffer raw off ptr bytes = do
+copyToRawBuffer raw off ptr bytes =
withRawBuffer raw $ \praw ->
- memcpy (praw `plusPtr` off) ptr (fromIntegral bytes)
- return ()
+ do _ <- memcpy (praw `plusPtr` off) ptr (fromIntegral bytes)
+ return ()
copyFromRawBuffer :: Ptr e -> RawBuffer e -> Int -> Int -> IO ()
-copyFromRawBuffer ptr raw off bytes = do
+copyFromRawBuffer ptr raw off bytes =
withRawBuffer raw $ \praw ->
- memcpy ptr (praw `plusPtr` off) (fromIntegral bytes)
- return ()
+ do _ <- memcpy ptr (praw `plusPtr` off) (fromIntegral bytes)
+ return ()
foreign import ccall unsafe "memcpy"
memcpy :: Ptr a -> Ptr a -> CSize -> IO (Ptr ())