module Data.Repa.Array.Auto.Unpack
( module Data.Repa.Convert.Format
, packForeign
, unpackForeign)
where
import Data.Repa.Array.Auto.Base as A
import Data.Repa.Array.Generic.Convert as A
import qualified Data.Repa.Array.Material.Auto as A
import qualified Data.Repa.Array.Material.Foreign as A
import qualified Data.Repa.Array.Internals.Target as A
import qualified Data.Repa.Array.Internals.Bulk as A
import Data.Repa.Convert.Format
import Foreign.ForeignPtr
import Foreign.Ptr
import System.IO.Unsafe
import Control.Monad
import Data.Word
import qualified Data.Vector.Storable.Mutable as SM
#include "repa-array.h"
packForeign
:: (Packable format, A.Bulk A.A (Value format))
=> format
-> Array (Value format)
-> Maybe (Array Word8)
packForeign !format !arrElems
| Just rowSize <- fixedSize format
, lenElems <- A.length arrElems
, lenBytes <- rowSize * lenElems
= unsafePerformIO
$ do
buf@(A.FBuffer mvec) :: A.Buffer A.F Word8
<- A.unsafeNewBuffer (A.Foreign lenBytes)
let (fptr, oStart, _) = SM.unsafeToForeignPtr mvec
withForeignPtr fptr $ \ptr_
-> do let ptr = plusPtr ptr_ oStart
let loop !ixSrc !ixDst
| ixSrc >= lenElems
= return $ Just ()
| otherwise
= Data.Repa.Convert.Format.pack
(plusPtr ptr ixDst) format (A.index arrElems ixSrc)
$ \oElem -> loop (ixSrc + 1) (ixDst + oElem)
mFinal <- loop 0 0
case mFinal of
Nothing -> return Nothing
Just _ -> liftM (Just . A.convert) $ A.unsafeFreezeBuffer buf
| otherwise
= Nothing
unpackForeign
:: (Packable format, A.Target A.A (Value format))
=> format
-> Array Word8
-> Maybe (Array (Value format))
unpackForeign !format !arrBytes
| Just rowSize <- fixedSize format
, lenBytes <- A.length arrBytes
, lenBytes `mod` rowSize == 0
, lenElems <- lenBytes `div` rowSize
= unsafePerformIO
$ do
let (oStart, _, fptr :: ForeignPtr Word8)
= A.toForeignPtr $ A.convert arrBytes
withForeignPtr fptr $ \ptr_
-> do let ptr = plusPtr ptr_ oStart
buf <- A.unsafeNewBuffer (A.Auto lenElems)
let loop !ixSrc !ixDst
| ixDst >= lenElems
= return $ Just ixSrc
| otherwise
= Data.Repa.Convert.Format.unpack
(plusPtr ptr ixSrc) format
$ \(value, oElem) -> do
A.unsafeWriteBuffer buf ixDst value
loop (ixSrc + oElem) (ixDst + 1)
mFinal <- loop 0 0
case mFinal of
Nothing -> return Nothing
Just _ -> liftM Just $ A.unsafeFreezeBuffer buf
| otherwise
= Nothing