module Data.Repa.Array.Auto.Format
( module Data.Repa.Convert.Format
, module Data.Repa.Convert.Formats
, packFormat
, packsFormat
, packsFormatLn
, unpackFormat
, unpacksFormatLn
, UnpackableRow
, A.Unpackables)
where
import Data.Repa.Array.Auto.Base as A
import Data.Repa.Array.Generic.Convert as A
import qualified Data.Repa.Array.Generic as AG
import qualified Data.Repa.Array.Material.Auto as A
import qualified Data.Repa.Array.Material.Auto.Operator.Lines as A
import qualified Data.Repa.Array.Material.Auto.Operator.Unpackables as A
import qualified Data.Repa.Array.Material.Foreign as AF
import qualified Data.Repa.Array.Internals.Target as A
import qualified Data.Repa.Array.Internals.Layout as A
import qualified Data.Repa.Array.Internals.Bulk as A
import qualified Data.Repa.Convert.Format as C
import Data.Repa.Convert.Format
import Data.Repa.Convert.Formats
import Foreign.ForeignPtr as F
import Foreign.Ptr as F
import System.IO.Unsafe
import Data.Word
import Data.Char
import qualified Data.Vector.Storable.Mutable as SM
#include "repa-array.h"
packFormat
:: C.Packable format
=> format
-> Value format
-> Maybe (Array Word8)
packFormat !format !v
| Just lenBytes <- packedSize format v
= unsafePerformIO
$ do
buf@(AF.FBuffer mvec) :: A.Buffer AF.F Word8
<- A.unsafeNewBuffer (AF.Foreign lenBytes)
let (fptr, oStart, _) = SM.unsafeToForeignPtr mvec
withForeignPtr fptr $ \ptr
-> do Just ptr' <- C.unsafeRunPacker (C.pack format v)
(plusPtr ptr oStart)
let len = minusPtr ptr' ptr
buf' <- A.unsafeSliceBuffer 0 len buf
arr <- A.unsafeFreezeBuffer buf'
return $ Just $ A.convert arr
| otherwise = Nothing
packsFormat
:: (C.Packable format, Show format, A.Bulk A.A (Value format))
=> format
-> Array (Value format)
-> Maybe (Array Word8)
packsFormat !format !arr
= let
packRow v
= case packFormat format v of
Nothing
-> error $ unlines
[ "repa-array.packsFormat: conversion failed"]
Just arr8 -> arr8
in Just $ AG.concat A.A $ AG.mapS A.N packRow arr
packsFormatLn
:: (C.Packable format, A.Bulk A.A (Value format))
=> format
-> Array (Value format)
-> Maybe (Array Word8)
packsFormatLn !format !arr
= let
!arrNL
= A.fromList A.A [fromIntegral $ ord '\n']
packRow v
= case packFormat format v of
Nothing
-> error $ unlines
[ "repa-array.packsFormat: conversion failed"]
Just arr8 -> AG.concat A.A $ A.fromList A.A [ arr8, arrNL ]
in Just $ AG.concat A.A $ AG.mapS A.N packRow arr
unpackFormat
:: C.Unpackable format
=> format
-> Array Word8
-> Maybe (C.Value format)
unpackFormat !format !arrBytes
| lenBytes <- A.length arrBytes
= unsafePerformIO
$ let (oStart, _, fptr :: ForeignPtr Word8)
= AF.toForeignPtr $ A.convert arrBytes
in withForeignPtr fptr $ \ptr_
-> do r <- C.unsafeRunUnpacker
(C.unpack format)
(plusPtr ptr_ oStart)
lenBytes (const False)
case r of
Just (v, _) -> return $ Just v
_ -> return Nothing
| otherwise = Nothing
unpacksFormatLn
:: UnpackableRow format
=> Sep format
-> Array Word8
-> Array (Value (Sep format))
unpacksFormatLn format arrSrc@(A.AArray_Word8 arrSrcF)
= unsafePerformIO
$ do
let !wSepRow
= fromIntegral $ ord '\n'
let !wSepField
= case takeSepChar format of
Nothing -> fromIntegral $ ord ' '
Just c -> fromIntegral $ ord c
let (ixsStarts, ixsEnds)
= A.findRowsStartEnd wSepRow arrSrc
let len = A.extent $ A.bufferLayout ixsStarts
buf <- A.unsafeNewBuffer (A.Auto len)
mErr <- A.unpacksToBuffer
format
wSepField
arrSrcF
ixsStarts ixsEnds buf
case mErr of
Nothing
-> A.unsafeFreezeBuffer buf
Just err
-> error $ "unsafeFormatLn: parse error " ++ show err
type UnpackableRow format
= ( SepFormat format
, A.Unpackables (Sep format)
, A.Target A.A (Value (Sep format)))