storablevector-0.2.7.2: Data/StorableVector/Pointer.hs
{- |
In principle you can traverse through a storable vector
using repeated calls to @viewL@ or using @index@.
However this needs a bit of pointer arrangement and allocation.
This data structure should make loops optimally fast.
-}
module Data.StorableVector.Pointer where
-- import qualified Data.StorableVector as V
import qualified Data.StorableVector.Base as VB
import qualified Foreign.ForeignPtr as FPtr
import Foreign.Marshal.Array (advancePtr, )
import Foreign.Storable (Storable, peek, )
import Foreign (Ptr, )
-- import System.IO.Unsafe (unsafePerformIO, )
{-
The reference to the ForeignPtr asserts,
that the array is maintained and thus is not garbage collected.
The Ptr we use for traversing would not achieve this.
-}
{- |
We might have name the data type iterator.
-}
data Pointer a =
Pointer {
fptr :: {-# UNPACK #-} !(FPtr.ForeignPtr a),
ptr :: {-# UNPACK #-} !(Ptr a),
left :: {-# UNPACK #-} !Int
}
{-# INLINE cons #-}
cons :: Storable a => VB.Vector a -> Pointer a
cons (VB.SV fp s l) =
Pointer fp (advancePtr (FPtr.unsafeForeignPtrToPtr fp) s) l
{-# INLINE viewL #-}
viewL :: Storable a => Pointer a -> Maybe (a, Pointer a)
viewL = switchL Nothing (curry Just)
{-# INLINE switchL #-}
switchL :: Storable a =>
b -> (a -> Pointer a -> b) -> Pointer a -> b
switchL n j (Pointer fp p l) =
if l<=0
then n
else j (VB.inlinePerformIO (peek p)) (Pointer fp (advancePtr p 1) (l-1))
-- unsafePerformIO at this place would make SpeedPointer test 0.5 s slower