Add facilities for accessing the memory of Storable vectors
authorRoman Leshchinskiy <rl@cse.unsw.edu.au>
Mon, 15 Feb 2010 03:53:10 +0000 (03:53 +0000)
committerRoman Leshchinskiy <rl@cse.unsw.edu.au>
Mon, 15 Feb 2010 03:53:10 +0000 (03:53 +0000)
Data/Vector/Storable.hs
Data/Vector/Storable/Mutable.hs

index 7bb9fc8..87ade87 100644 (file)
@@ -75,7 +75,10 @@ module Data.Vector.Storable (
   enumFromN, enumFromStepN, enumFromTo, enumFromThenTo,
 
   -- * Conversion to/from lists
-  toList, fromList
+  toList, fromList,
+
+  -- * Accessing the underlying memory
+  unsafeFromForeignPtr, unsafeToForeignPtr, unsafeWith
 ) where
 
 import qualified Data.Vector.Generic          as G
@@ -84,8 +87,8 @@ import Data.Vector.Storable.Internal
 
 import Foreign.Storable
 import Foreign.ForeignPtr
--- import Foreign.Ptr
--- import Foreign.C.Types
+import Foreign.Ptr
+import Foreign.Marshal.Array ( advancePtr )
 
 import Control.Monad.ST ( ST, runST )
 
@@ -838,3 +841,28 @@ fromList :: Storable a => [a] -> Vector a
 {-# INLINE fromList #-}
 fromList = G.fromList
 
+-- Accessing the underlying memory
+-- -------------------------------
+
+-- | Create a vector from a 'ForeignPtr' with an offset and a length. The data
+-- may not be modified through the 'ForeignPtr' afterwards.
+unsafeFromForeignPtr :: ForeignPtr a    -- ^ pointer
+                     -> Int             -- ^ offset
+                     -> Int             -- ^ length
+                     -> Vector a
+{-# INLINE unsafeFromForeignPtr #-}
+unsafeFromForeignPtr p i n = Vector i n p
+
+-- | Yield the underlying 'ForeignPtr' together with the offset to the data
+-- and its length. The data may not be modified through the 'ForeignPtr'.
+unsafeToForeignPtr :: Vector a -> (ForeignPtr a, Int, Int)
+{-# INLINE unsafeToForeignPtr #-}
+unsafeToForeignPtr (Vector i n p) = (p,i,n)
+
+-- | Pass a pointer to the vector's data to the IO action. The data may not be
+-- modified through the 'Ptr.
+unsafeWith :: Storable a => Vector a -> (Ptr a -> IO b) -> IO b
+{-# INLINE unsafeWith #-}
+unsafeWith (Vector i n fp) m
+  = withForeignPtr fp $ \p -> m (p `advancePtr` i)
+
index bcd91cb..6f8a2cd 100644 (file)
@@ -22,13 +22,18 @@ module Data.Vector.Storable.Mutable(
 
   -- * Unsafe operations
   unsafeSlice, unsafeNew, unsafeNewWith, unsafeRead, unsafeWrite, unsafeSwap,
-  unsafeCopy, unsafeGrow
+  unsafeCopy, unsafeGrow,
+
+  -- * Accessing the underlying memory
+  unsafeFromForeignPtr, unsafeToForeignPtr, unsafeWith
 ) where
 
 import qualified Data.Vector.Generic.Mutable as G
 
 import Foreign.Storable
 import Foreign.ForeignPtr
+import Foreign.Ptr
+import Foreign.Marshal.Array ( advancePtr )
 
 import Control.Monad.Primitive
 
@@ -70,6 +75,30 @@ instance Storable a => G.MVector MVector a where
     = unsafePrimToPrim
     $ withForeignPtr p $ \ptr -> pokeElemOff ptr (i+j) x
 
+-- | Create a mutable vector from a 'ForeignPtr' with an offset and a length.
+-- Modifying data through the 'ForeignPtr' afterwards is unsafe if the vector
+-- could have been frozen before the modification.
+unsafeFromForeignPtr :: ForeignPtr a    -- ^ pointer
+                     -> Int             -- ^ offset
+                     -> Int             -- ^ length
+                     -> MVector s a
+{-# INLINE unsafeFromForeignPtr #-}
+unsafeFromForeignPtr p i n = MVector i n p
+
+-- | Yield the underlying 'ForeignPtr' together with the offset to the data
+-- and its length. Modifying the data through the 'ForeignPtr' is
+-- unsafe if the vector could have frozen before the modification.
+unsafeToForeignPtr :: MVector s a -> (ForeignPtr a, Int, Int)
+{-# INLINE unsafeToForeignPtr #-}
+unsafeToForeignPtr (MVector i n p) = (p,i,n)
+
+-- | Pass a pointer to the vector's data to the IO action. Modifying data
+-- through the pointer is unsafe if the vector could have been frozen before
+-- the modification.
+unsafeWith :: Storable a => IOVector a -> (Ptr a -> IO b) -> IO b
+{-# INLINE unsafeWith #-}
+unsafeWith (MVector i n fp) m
+  = withForeignPtr fp $ \p -> m (p `advancePtr` i)
 
 -- | Yield a part of the mutable vector without copying it. No bounds checks
 -- are performed.