module Data.Iteratee.IO.Fd(
#if defined(USE_POSIX)
enumFd
,enumFdCatch
,enumFdRandom
,enumFile
,enumFileRandom
,fileDriverFd
,fileDriverRandomFd
#endif
)
where
#if defined(USE_POSIX)
import Data.Iteratee.Base.ReadableChunk
import Data.Iteratee.Iteratee
import Data.Iteratee.Binary()
import Data.Iteratee.IO.Base
import Control.Concurrent (yield)
import Control.Exception
import Control.Monad
import Control.Monad.Catch as CIO
import Control.Monad.IO.Class
import Foreign.Ptr
import Foreign.Storable
import Foreign.Marshal.Alloc
import System.IO (SeekMode(..))
import System.Posix hiding (FileOffset)
#if MIN_VERSION_exceptions(0,6,0)
#else
type MonadMask = MonadCatch
#endif
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), empty))
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, ReadableChunk s el) =>
(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' :: (NullPoint s, MonadIO m, MonadMask m, ReadableChunk s el) =>
(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
#endif