import GHC.Num
import GHC.Show
import GHC.List
-import GHC.Exception ( ioError, catch, throw )
+import GHC.Exception ( ioError, catch )
import GHC.Conc
-- ---------------------------------------------------------------------------
NoBuffering -> do
-- make use of the minimal buffer we already have
let raw = bufBuf buf
- r <- throwErrnoIfMinus1RetryMayBlock "hGetChar"
- (read_off_ba (fromIntegral fd) (haIsStream handle_) raw 0 1)
- (threadWaitRead fd)
+ r <- readRawBuffer "hGetChar" (fromIntegral fd) (haIsStream handle_) raw 0 1
if r == 0
then ioe_EOF
else do (c,_) <- readCharFromBuffer raw 0
#endif
xs <- unpack raw r off
+
+ -- if eol == True, then off is the offset of the '\n'
+ -- otherwise off == w and the buffer is now empty.
if eol
- then do if w == off + 1
- then writeIORef ref buf{ bufRPtr=0, bufWPtr=0 }
- else writeIORef ref buf{ bufRPtr = off + 1 }
+ then do if (w == off + 1)
+ then writeIORef ref buf{ bufRPtr=0, bufWPtr=0 }
+ else writeIORef ref buf{ bufRPtr = off + 1 }
return (concat (reverse (xs:xss)))
else do
maybe_buf <- maybeFillReadBuffer (haFD handle_) True (haIsStream handle_)
case maybe_buf of
-- Nothing indicates we caught an EOF, and we may have a
-- partial line to return.
- Nothing -> let str = concat (reverse (xs:xss)) in
- if not (null str)
- then return str
- else ioe_EOF
+ Nothing -> do
+ writeIORef ref buf{ bufRPtr=0, bufWPtr=0 }
+ let str = concat (reverse (xs:xss))
+ if not (null str)
+ then return str
+ else ioe_EOF
Just new_buf ->
hGetLineBufferedLoop handle_ ref new_buf (xs:xss)
)
(\e -> do if isEOFError e
then return Nothing
- else throw e)
+ else ioError e)
unpack :: RawBuffer -> Int -> Int -> IO [Char]
NoBuffering -> do
-- make use of the minimal buffer we already have
let raw = bufBuf buf
- r <- throwErrnoIfMinus1RetryMayBlock "lazyRead"
- (read_off_ba (fromIntegral fd) (haIsStream handle_) raw 0 1)
- (threadWaitRead fd)
+ r <- readRawBuffer "lazyRead" (fromIntegral fd) (haIsStream handle_) raw 0 1
if r == 0
then do handle_ <- hClose_help handle_
return (handle_, "")
LineBuffering -> hPutcBuffered handle_ True c
BlockBuffering _ -> hPutcBuffered handle_ False c
NoBuffering ->
- withObject (castCharToCChar c) $ \buf ->
- throwErrnoIfMinus1RetryMayBlock_ "hPutChar"
- (write_off (fromIntegral fd) (haIsStream handle_) buf 0 1)
- (threadWaitWrite fd)
-
+ withObject (castCharToCChar c) $ \buf -> do
+ writeRawBufferPtr "hPutChar" (fromIntegral fd) (haIsStream handle_) buf 0 1
+ return ()
hPutcBuffered handle_ is_line c = do
let ref = haBuffer handle_
-> Int -- number of bytes of data in buffer
-> IO ()
hPutBuf handle ptr count
- | count <= 0 = illegalBufferSize handle "hPutBuf" count
+ | count == 0 = return ()
+ | count < 0 = illegalBufferSize handle "hPutBuf" count
| otherwise =
wantWritableHandle "hPutBuf" handle $
\ handle_@Handle__{ haFD=fd, haBuffer=ref, haIsStream=is_stream } -> do
else do flushed_buf <- flushWriteBuffer fd is_stream old_buf
writeIORef ref flushed_buf
-- ToDo: should just memcpy instead of writing if possible
- writeChunk fd ptr count
+ writeChunk fd is_stream (castPtr ptr) count
-writeChunk :: FD -> Ptr a -> Int -> IO ()
-writeChunk fd ptr bytes = loop 0 bytes
+writeChunk :: FD -> Bool -> Ptr CChar -> Int -> IO ()
+writeChunk fd is_stream ptr bytes = loop 0 bytes
where
loop :: Int -> Int -> IO ()
loop _ bytes | bytes <= 0 = return ()
loop off bytes = do
r <- fromIntegral `liftM`
- throwErrnoIfMinus1RetryMayBlock "writeChunk"
- (c_write (fromIntegral fd) (ptr `plusPtr` off) (fromIntegral bytes))
- (threadWaitWrite fd)
+ writeRawBufferPtr "writeChunk" (fromIntegral fd) is_stream ptr
+ off (fromIntegral bytes)
-- write can't return 0
loop (off + r) (bytes - r)
hGetBuf :: Handle -> Ptr a -> Int -> IO Int
hGetBuf handle ptr count
- | count <= 0 = illegalBufferSize handle "hGetBuf" count
+ | count == 0 = return 0
+ | count < 0 = illegalBufferSize handle "hGetBuf" count
| otherwise =
wantReadableHandle "hGetBuf" handle $
- \ handle_@Handle__{ haFD=fd, haBuffer=ref } -> do
+ \ handle_@Handle__{ haFD=fd, haBuffer=ref, haIsStream=is_stream } -> do
buf@Buffer{ bufBuf=raw, bufWPtr=w, bufRPtr=r } <- readIORef ref
if bufferEmpty buf
- then readChunk fd ptr count
+ then readChunk fd is_stream ptr count
else do
let avail = w - r
copied <- if (count >= avail)
let remaining = count - copied
if remaining > 0
- then do rest <- readChunk fd (ptr `plusPtr` copied) remaining
+ then do rest <- readChunk fd is_stream (ptr `plusPtr` copied) remaining
return (rest + copied)
else return count
-readChunk :: FD -> Ptr a -> Int -> IO Int
-readChunk fd ptr bytes = loop 0 bytes
+readChunk :: FD -> Bool -> Ptr a -> Int -> IO Int
+readChunk fd is_stream ptr bytes = loop 0 bytes
where
loop :: Int -> Int -> IO Int
loop off bytes | bytes <= 0 = return off
loop off bytes = do
r <- fromIntegral `liftM`
- throwErrnoIfMinus1RetryMayBlock "readChunk"
- (c_read (fromIntegral fd) (ptr `plusPtr` off) (fromIntegral bytes))
- (threadWaitRead fd)
+ readRawBufferPtr "readChunk" (fromIntegral fd) is_stream
+ (castPtr ptr) off (fromIntegral bytes)
if r == 0
then return off
else loop (off + r) (bytes - r)
ioError (userError "slurpFile: file too big")
else do
let sz_i = fromIntegral sz
+ if sz_i == 0 then return (nullPtr, 0) else do
chunk <- mallocBytes sz_i
r <- hGetBuf handle chunk sz_i
hClose handle