module Bio.Iteratee.IO.Fd(
enumFd
,enumFdCatch
,enumFdRandom
,enumFile
,enumFileRandom
,fileDriverFd
,fileDriverRandomFd
)
where
import Bio.Iteratee.IO.Base
import Bio.Iteratee.Iteratee
import Bio.Prelude
import Control.Monad.Catch as CIO
import Control.Monad.IO.Class
import Data.ByteString (packCStringLen)
import Foreign.Marshal.Alloc
import System.IO (SeekMode(..))
makefdCallback ::
MonadIO m =>
Ptr el
-> ByteCount
-> Fd
-> st
-> m (Either SomeException ((Bool, st), Bytes))
makefdCallback p bufsize fd st = do
n <- liftIO $ myfdRead fd (castPtr p) bufsize
case n of
Left _ -> return $ Left (error "myfdRead failed")
Right 0 -> liftIO yield >> return (Right ((False, st), emptyP))
Right n' -> liftM (\s -> Right ((True, st), s)) $
readFromPtr p (fromIntegral n')
where
readFromPtr buf l = liftIO $ packCStringLen (castPtr buf, l)
enumFd
:: (MonadIO m, MonadMask m) =>
Int
-> Fd
-> Enumerator Bytes m a
enumFd bufsize fd iter =
CIO.bracket (liftIO $ mallocBytes bufsize)
(liftIO . free)
(\p -> enumFromCallback (makefdCallback p (fromIntegral bufsize) fd) () iter)
enumFdCatch
:: (IException e, MonadIO m, MonadMask m)
=> Int
-> Fd
-> (e -> m (Maybe EnumException))
-> Enumerator Bytes m a
enumFdCatch bufsize fd handler iter =
CIO.bracket (liftIO $ mallocBytes bufsize)
(liftIO . free)
(\p -> enumFromCallbackCatch (makefdCallback p (fromIntegral bufsize) fd) handler () iter)
enumFdRandom
:: (MonadIO m, MonadMask m) =>
Int
-> Fd
-> Enumerator Bytes m a
enumFdRandom bs fd iter = enumFdCatch bs fd handler iter
where
handler (SeekException off) =
liftM (either
(const . Just $ enStrExc "Error seeking within file descriptor")
(const Nothing))
. liftIO . myfdSeek fd AbsoluteSeek $ fromIntegral off
fileDriver
:: (MonadIO m, MonadMask m) =>
(Int -> Fd -> Enumerator s m a)
-> Int
-> Iteratee s m a
-> FilePath
-> m a
fileDriver enumf bufsize iter filepath = CIO.bracket
(liftIO $ openFd filepath ReadOnly Nothing defaultFileFlags)
(liftIO . closeFd)
(run <=< flip (enumf bufsize) iter)
fileDriverFd
:: (MonadIO m, MonadMask m) =>
Int
-> Iteratee Bytes m a
-> FilePath
-> m a
fileDriverFd = fileDriver enumFd
fileDriverRandomFd
:: (MonadIO m, MonadMask m) =>
Int
-> Iteratee Bytes m a
-> FilePath
-> m a
fileDriverRandomFd = fileDriver enumFdRandom
enumFile' :: (MonadIO m, MonadMask m) =>
(Int -> Fd -> Enumerator s m a)
-> Int
-> FilePath
-> Enumerator s m a
enumFile' enumf bufsize filepath iter = CIO.bracket
(liftIO $ openFd filepath ReadOnly Nothing defaultFileFlags)
(liftIO . closeFd)
(flip (enumf bufsize) iter)
enumFile ::
(MonadIO m, MonadMask m)
=> Int
-> FilePath
-> Enumerator Bytes m a
enumFile = enumFile' enumFd
enumFileRandom ::
(MonadIO m, MonadMask m)
=> Int
-> FilePath
-> Enumerator Bytes m a
enumFileRandom = enumFile' enumFdRandom