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