repa-array-4.2.2.1: Data/Repa/Array/Auto/IO.hs
-- | Raw Array IO.
module Data.Repa.Array.Auto.IO
( -- * Via File Names
readFile
, writeFile
, appendFile
-- * Via File Handles
, hGetArray, hGetArrayPre
, hPutArray)
where
import Data.Repa.Array.Auto.Base
import Data.Repa.Array.Generic.Convert
import Data.Word
import qualified Data.Repa.Array.Material.Foreign as A
import qualified Foreign.Ptr as F
import qualified Foreign.ForeignPtr as F
import qualified Foreign.Marshal.Alloc as F
import qualified Foreign.Marshal.Utils as F
import qualified System.IO as S
import qualified System.FileLock as S
import Prelude hiding (readFile, writeFile, appendFile)
---------------------------------------------------------------------------------------------------
-- | Read an entire file as an array of bytes.
readFile :: FilePath -> IO (Array Word8)
readFile path
= S.withFileLock path S.Shared
$ \_lock -> do
h <- S.openFile path S.ReadMode
S.hSeek h S.SeekFromEnd 0
len <- S.hTell h
S.hSeek h S.AbsoluteSeek 0
!arr <- hGetArray h (fromIntegral len)
S.hClose h
return arr
{-# NOINLINE readFile #-}
-- | Write an array of bytes to a file.
writeFile :: FilePath -> Array Word8 -> IO ()
writeFile path arr
= S.withFileLock path S.Exclusive
$ \_lock -> do
h <- S.openFile path S.WriteMode
hPutArray h arr
S.hClose h
{-# NOINLINE writeFile #-}
-- | Append an array of bytes to a file.
appendFile :: FilePath -> Array Word8 -> IO ()
appendFile path arr
= S.withFileLock path S.Exclusive
$ \_lock -> do
h <- S.openFile path S.AppendMode
hPutArray h arr
S.hClose h
{-# NOINLINE appendFile #-}
---------------------------------------------------------------------------------------------------
-- | Get data from a file handle, up to the given number of bytes.
hGetArray :: S.Handle -> Int -> IO (Array Word8)
hGetArray h len
= do buf :: F.Ptr Word8 <- F.mallocBytes len
bytesRead <- S.hGetBuf h buf len
fptr <- F.newForeignPtr F.finalizerFree buf
return $! convert $! A.fromForeignPtr bytesRead fptr
{-# NOINLINE hGetArray #-}
-- | Get data from a file handle, up to the given number of bytes, also
-- copying the given data to the front of the new buffer.
hGetArrayPre :: S.Handle -> Int -> Array Word8 -> IO (Array Word8)
hGetArrayPre h len arr
| (offset, lenPre, fptrPre :: F.ForeignPtr Word8)
<- A.toForeignPtr $ convert arr
= F.withForeignPtr fptrPre
$ \ptrPre' -> do
let ptrPre = F.plusPtr ptrPre' offset
ptrBuf :: F.Ptr Word8 <- F.mallocBytes (lenPre + len)
F.copyBytes ptrBuf ptrPre lenPre
lenRead <- S.hGetBuf h (F.plusPtr ptrBuf lenPre) len
let bytesTotal = lenPre + lenRead
fptrBuf <- F.newForeignPtr F.finalizerFree ptrBuf
return $ convert $! A.fromForeignPtr bytesTotal fptrBuf
{-# NOINLINE hGetArrayPre #-}
-- | Write data into a file.
hPutArray :: S.Handle -> Array Word8 -> IO ()
hPutArray h arr
| (offset, lenPre, fptrPre :: F.ForeignPtr Word8)
<- A.toForeignPtr $ convert arr
= F.withForeignPtr fptrPre
$ \ptr' -> do
let ptr = F.plusPtr ptr' offset
S.hPutBuf h ptr lenPre
{-# NOINLINE hPutArray #-}