module Bio.Iteratee.IO.Fd(
enumFd
,enumFdCatch
,enumFdRandom
,enumFile
,enumFileRandom
,fileDriverFd
,fileDriverRandomFd
)
where
import Bio.Iteratee.Binary ()
import Bio.Iteratee.IO.Base
import Bio.Iteratee.Iteratee
import Bio.Iteratee.ReadableChunk
import Bio.Prelude
import Control.Monad.Catch as CIO
import Control.Monad.IO.Class
import Foreign.Marshal.Alloc
import Foreign.Ptr
import Foreign.Storable
import System.IO (SeekMode(..))
makefdCallback ::
(MonadIO m, NullPoint s, ReadableChunk s el) =>
Ptr el
-> ByteCount
-> Fd
-> st
-> m (Either SomeException ((Bool, st), s))
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')
enumFd
:: forall s el m a.(NullPoint s, ReadableChunk s el, MonadIO m, MonadMask m) =>
Int
-> Fd
-> Enumerator s m a
enumFd bs fd iter =
let bufsize = bs * (sizeOf (undefined :: el))
in CIO.bracket (liftIO $ mallocBytes bufsize)
(liftIO . free)
(\p -> enumFromCallback (makefdCallback p (fromIntegral bufsize) fd) () iter)
enumFdCatch
:: forall e s el m a.(IException e, NullPoint s, ReadableChunk s el, MonadIO m, MonadMask m)
=> Int
-> Fd
-> (e -> m (Maybe EnumException))
-> Enumerator s m a
enumFdCatch bs fd handler iter =
let bufsize = bs * (sizeOf (undefined :: el))
in CIO.bracket (liftIO $ mallocBytes bufsize)
(liftIO . free)
(\p -> enumFromCallbackCatch (makefdCallback p (fromIntegral bufsize) fd) handler () iter)
enumFdRandom
:: forall s el m a.(NullPoint s, ReadableChunk s el, MonadIO m, MonadMask m) =>
Int
-> Fd
-> Enumerator s 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
:: (NullPoint s, MonadIO m, MonadMask m, ReadableChunk s el) =>
Int
-> Iteratee s m a
-> FilePath
-> m a
fileDriverFd = fileDriver enumFd
fileDriverRandomFd
:: (NullPoint s, MonadIO m, MonadMask m, ReadableChunk s el) =>
Int
-> Iteratee s 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 ::
(NullPoint s, MonadIO m, MonadMask m, ReadableChunk s el)
=> Int
-> FilePath
-> Enumerator s m a
enumFile = enumFile' enumFd
enumFileRandom ::
(NullPoint s, MonadIO m, MonadMask m, ReadableChunk s el)
=> Int
-> FilePath
-> Enumerator s m a
enumFileRandom = enumFile' enumFdRandom