module Data.Iteratee.IO.Handle(
enumHandle
,enumHandleCatch
,enumHandleRandom
,enumFile
,enumFileRandom
,fileDriverHandle
,fileDriverRandomHandle
)
where
import Data.Iteratee.Base.ReadableChunk
import Data.Iteratee.Iteratee
import Data.Iteratee.Binary()
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
#if MIN_VERSION_exceptions(0,6,0)
#else
type MonadMask = MonadCatch
#endif
makeHandleCallback ::
(MonadIO m, MonadCatch m, NullPoint s, ReadableChunk s el) =>
Ptr el
-> Int
-> Handle
-> st
-> m (Either SomeException ((Bool, st), s))
makeHandleCallback p bsize h st = do
n' <- liftIO (CIO.try $ hGetBuf h p bsize :: IO (Either SomeException Int))
case n' of
Left e -> return $ Left e
Right 0 -> return $ Right ((False, st), empty)
Right n -> liftM (\s -> Right ((True, st), s)) $
readFromPtr p (fromIntegral n)
enumHandle ::
forall s el m a.(NullPoint s, ReadableChunk s el, MonadIO m, MonadMask m) =>
Int
-> Handle
-> Enumerator s m a
enumHandle bs h i =
let bufsize = bs * sizeOf (undefined :: el)
in CIO.bracket (liftIO $ mallocBytes bufsize)
(liftIO . free)
(\p -> enumFromCallback (makeHandleCallback p bufsize h) () i)
enumHandleCatch
::
forall e s el m a.(IException e,
NullPoint s,
ReadableChunk s el,
MonadIO m, MonadMask m) =>
Int
-> Handle
-> (e -> m (Maybe EnumException))
-> Enumerator s m a
enumHandleCatch bs h handler i =
let bufsize = bs * sizeOf (undefined :: el)
in CIO.bracket (liftIO $ mallocBytes bufsize)
(liftIO . free)
(\p -> enumFromCallbackCatch (makeHandleCallback p bufsize h) handler () i)
enumHandleRandom ::
forall s el m a.(NullPoint s, ReadableChunk s el, MonadIO m, MonadMask m) =>
Int
-> Handle
-> Enumerator s m a
enumHandleRandom bs h i = enumHandleCatch bs h handler i
where
handler (SeekException off) =
liftM (either
(Just . EnumException :: IOException -> Maybe EnumException)
(const Nothing))
. liftIO . CIO.try $ hSeek h AbsoluteSeek $ fromIntegral off
enumFile' :: (NullPoint s, MonadIO m, MonadMask m, ReadableChunk s el) =>
(Int -> Handle -> Enumerator s m a)
-> Int
-> FilePath
-> Enumerator s m a
enumFile' enumf bufsize filepath iter = CIO.bracket
(liftIO $ openBinaryFile filepath ReadMode)
(liftIO . hClose)
(flip (enumf bufsize) iter)
enumFile ::
(NullPoint s, MonadIO m, MonadMask m, ReadableChunk s el)
=> Int
-> FilePath
-> Enumerator s m a
enumFile = enumFile' enumHandle
enumFileRandom ::
(NullPoint s, MonadIO m, MonadMask m, ReadableChunk s el)
=> Int
-> FilePath
-> Enumerator s m a
enumFileRandom = enumFile' enumHandleRandom
fileDriverHandle
:: (NullPoint s, MonadIO m, MonadMask m, ReadableChunk s el) =>
Int
-> Iteratee s m a
-> FilePath
-> m a
fileDriverHandle bufsize iter filepath =
enumFile bufsize filepath iter >>= run
fileDriverRandomHandle
:: (NullPoint s, MonadIO m, MonadMask m, ReadableChunk s el) =>
Int
-> Iteratee s m a
-> FilePath
-> m a
fileDriverRandomHandle bufsize iter filepath =
enumFileRandom bufsize filepath iter >>= run