module Data.Iteratee.IO.Fd(
#if defined(USE_POSIX)
enumFd
,enumFdRandom
,fileDriverFd
,fileDriverRandomFd
#endif
)
where
#if defined(USE_POSIX)
import Data.Iteratee.Base.StreamChunk (ReadableChunk (..))
import Data.Iteratee.Base
import Data.Iteratee.Binary()
import Data.Iteratee.IO.Base
import Foreign.Ptr
import Foreign.Marshal.Alloc
import System.IO (SeekMode(..))
import System.Posix hiding (FileOffset)
enumFd :: ReadableChunk s el => Fd -> EnumeratorGM s el IO a
enumFd fd iter' = allocaBytes (fromIntegral buffer_size) $ loop iter'
where
buffer_size = 4096
loop iter p = do
n <- myfdRead fd (castPtr p) buffer_size
case n of
Left _errno -> enumErr "IO error" iter
Right 0 -> return iter
Right n' -> do
s <- readFromPtr p (fromIntegral n')
igv <- runIter iter (Chunk s)
check p igv
check _p (Done x _) = return . return $ x
check p (Cont i Nothing) = loop i p
check _p (Cont _ (Just e)) = return $ throwErr e
enumFdRandom :: ReadableChunk s el => Fd -> EnumeratorGM s el IO a
enumFdRandom fd iter =
allocaBytes (fromIntegral buffer_size) (loop (0,0) iter)
where
buffer_size = 4096
loop (off,len) _iter' _p | off `seq` len `seq` False = undefined
loop (off,len) iter' p = do
n <- myfdRead fd (castPtr p) buffer_size
case n of
Left _errno -> enumErr "IO error" iter'
Right 0 -> return iter'
Right n' -> do
s <- readFromPtr p (fromIntegral n')
igv <- runIter iter' (Chunk s)
check (off + fromIntegral len, fromIntegral n') p igv
seekTo pos@(off, len) off' iter' p
| off <= off' && off' < off + fromIntegral len =
do
let local_off = fromIntegral $ off' off
s <- readFromPtr (p `plusPtr` local_off) (len local_off)
igv <- runIter iter' (Chunk s)
check pos p igv
seekTo _pos off iter' p = do
off' <- myfdSeek fd AbsoluteSeek (fromIntegral off)
case off' of
Left _errno -> enumErr "IO error" iter'
Right off'' -> loop (off'',0) iter' p
check _ _p (Done x _) = return . return $ x
check o p (Cont i Nothing) = loop o i p
check o p (Cont i (Just (Seek off))) = seekTo o off i p
check _ _p (Cont _ (Just e)) = return $ throwErr e
fileDriverFd :: ReadableChunk s el => IterateeG s el IO a ->
FilePath ->
IO a
fileDriverFd iter filepath = do
fd <- openFd filepath ReadOnly Nothing defaultFileFlags
result <- enumFd fd iter >>= run
closeFd fd
return result
fileDriverRandomFd :: ReadableChunk s el =>
IterateeG s el IO a ->
FilePath ->
IO a
fileDriverRandomFd iter filepath = do
fd <- openFd filepath ReadOnly Nothing defaultFileFlags
result <- enumFdRandom fd iter >>= run
closeFd fd
return result
#endif