mohws-0.2: src/Network/MoHWS/ByteString.hs
module Network.MoHWS.ByteString where
import qualified Data.ByteString.Char8 as S
import qualified Data.ByteString.Lazy.Char8 as L
import qualified System.IO as IO
import Control.Monad (liftM2, )
import System.IO.Unsafe (unsafeInterleaveIO, )
{- |
Like 'L.hGetContents' but it does not try to close the file when reaching the end.
Since you may abort reading before reaching the end,
or the run-time system reads more than necessary
(you don't know how unsafeInterleaveIO works),
you never know, whether 'L.hGetContents' has already closed the file or not.
With this function however it is always sure,
that the file is not closed and you are responsible for closing it.
-}
hGetContentsN :: Int -> IO.Handle -> IO L.ByteString
hGetContentsN k h =
let loop = unsafeInterleaveIO $ do
eof <- IO.hIsEOF h
if eof
then return L.empty
else
do liftM2
(\c -> L.append (L.fromChunks [c]))
(S.hGet h k) loop
in loop
{- |
Variant of 'hGetContentsN' that may choose smaller chunks
when currently no more data is available.
The chunk size may however become arbitrarily small,
making the whole process inefficient.
But when real-time fetching counts, it is the better choice.
-}
hGetContentsNonBlockingN :: Int -> IO.Handle -> IO L.ByteString
hGetContentsNonBlockingN k h =
let lazyRead = unsafeInterleaveIO loop
loop = do
c <- S.hGetNonBlocking h k
if S.null c
then do eof <- IO.hIsEOF h
if eof
then return L.empty
else IO.hWaitForInput h (-1) >> loop
else fmap (L.append $ L.fromChunks [c]) lazyRead
in lazyRead
-- | Read the given number of bytes from a Handle
hGetChars :: IO.Handle -> Int -> IO String
hGetChars h n = fmap L.unpack $ L.hGet h n