{-# OPTIONS_GHC -cpp -fglasgow-exts #-}---- Module : Data.StorableVector.Base-- License : BSD-style-- Maintainer : dons@cse.unsw.edu.au-- Stability : experimental-- Portability : portable, requires ffi and cpp-- Tested with : GHC 6.4.1 and Hugs March 2005-- -- | A module containing semi-public StorableVector internals. This exposes-- the StorableVector representation and low level construction functions.-- Modules which extend the StorableVector system will need to use this module-- while ideally most users will be able to make do with the public interface-- modules.--moduleData.StorableVector.Base(-- * The @Vector@ type and representationVector(..),-- instances: Eq, Ord, Show, Read, Data, Typeable-- * Unchecked accessunsafeHead,-- :: Vector a -> aunsafeTail,-- :: Vector a -> Vector aunsafeLast,-- :: Vector a -> aunsafeInit,-- :: Vector a -> Vector aunsafeIndex,-- :: Vector a -> Int -> aunsafeTake,-- :: Int -> Vector a -> Vector aunsafeDrop,-- :: Int -> Vector a -> Vector a-- * Low level introduction and eliminationcreate,-- :: Int -> (Ptr a -> IO ()) -> IO (Vector a)createAndTrim,-- :: Int -> (Ptr a -> IO Int) -> IO (Vector a)createAndTrim',-- :: Int -> (Ptr a -> IO (Int, Int, b)) -> IO (Vector a, b)unsafeCreate,-- :: Int -> (Ptr a -> IO ()) -> Vector afromForeignPtr,-- :: ForeignPtr a -> Int -> Vector atoForeignPtr,-- :: Vector a -> (ForeignPtr a, Int, Int)inlinePerformIO)whereimportForeign.Ptr(Ptr)importForeign.ForeignPtr(ForeignPtr,withForeignPtr,)importForeign.Marshal.Array(advancePtr,copyArray)importForeign.Storable(Storable(peekElemOff))importData.StorableVector.Memory(mallocForeignPtrArray,)importControl.Exception(assert)#if defined(__GLASGOW_HASKELL__)importData.Generics(Data(..),Typeable(..))importGHC.Base(realWorld#)importGHC.IOBase(IO(IO),)#endifimportSystem.IO.Unsafe(unsafePerformIO,)-- CFILES stuff is Hugs only{-# CFILES cbits/fpstring.c #-}-- ------------------------------------------------------------------------------- | A space-efficient representation of a vector, supporting many efficient-- operations.---- Instances of Eq, Ord, Read, Show, Data, Typeable--dataVectora=SV{-# UNPACK #-}!(ForeignPtra){-# UNPACK #-}!Int-- offset{-# UNPACK #-}!Int-- length#if defined(__GLASGOW_HASKELL__)deriving(Data,Typeable)#endif-- ------------------------------------------------------------------------- Extensions to the basic interface---- | A variety of 'head' for non-empty Vectors. 'unsafeHead' omits the-- check for the empty case, so there is an obligation on the programmer-- to provide a proof that the Vector is non-empty.unsafeHead::(Storablea)=>Vectora->aunsafeHead(SVxsl)=assert(l>0)$inlinePerformIO$withForeignPtrx$\p->peekElemOffps{-# INLINE unsafeHead #-}-- | A variety of 'tail' for non-empty Vectors. 'unsafeTail' omits the-- check for the empty case. As with 'unsafeHead', the programmer must-- provide a separate proof that the Vector is non-empty.unsafeTail::(Storablea)=>Vectora->VectoraunsafeTail(SVpssl)=assert(l>0)$SVps(s+1)(l-1){-# INLINE unsafeTail #-}-- | A variety of 'last' for non-empty Vectors. 'unsafeLast' omits the-- check for the empty case, so there is an obligation on the programmer-- to provide a proof that the Vector is non-empty.unsafeLast::(Storablea)=>Vectora->aunsafeLast(SVx_sl)=assert(l>0)$inlinePerformIO$withForeignPtrx$\p->peekElemOffp(l-1){-# INLINE unsafeLast #-}-- | A variety of 'init' for non-empty Vectors. 'unsafeInit' omits the-- check for the empty case. As with 'unsafeLast', the programmer must-- provide a separate proof that the Vector is non-empty.unsafeInit::(Storablea)=>Vectora->VectoraunsafeInit(SVpssl)=assert(l>0)$SVpss(l-1){-# INLINE unsafeInit #-}-- | Unsafe 'Vector' index (subscript) operator, starting from 0, returning a-- single element. This omits the bounds check, which means there is an-- accompanying obligation on the programmer to ensure the bounds are checked in-- some other way.unsafeIndex::(Storablea)=>Vectora->Int->aunsafeIndex(SVxsl)i=assert(i>=0&&i<l)$inlinePerformIO$withForeignPtrx$\p->peekElemOffp(s+i){-# INLINE unsafeIndex #-}-- | A variety of 'take' which omits the checks on @n@ so there is an-- obligation on the programmer to provide a proof that @0 <= n <= 'length' xs@.unsafeTake::(Storablea)=>Int->Vectora->VectoraunsafeTaken(SVxsl)=assert(0<=n&&n<=l)$SVxsn{-# INLINE unsafeTake #-}-- | A variety of 'drop' which omits the checks on @n@ so there is an-- obligation on the programmer to provide a proof that @0 <= n <= 'length' xs@.unsafeDrop::(Storablea)=>Int->Vectora->VectoraunsafeDropn(SVxsl)=assert(0<=n&&n<=l)$SVx(s+n)(l-n){-# INLINE unsafeDrop #-}-- ----------------------------------------------------------------------- Low level constructors-- | /O(1)/ Build a Vector from a ForeignPtrfromForeignPtr::ForeignPtra->Int->VectorafromForeignPtrfpl=SVfp0l-- | /O(1)/ Deconstruct a ForeignPtr from a VectortoForeignPtr::Vectora->(ForeignPtra,Int,Int)toForeignPtr(SVpssl)=(ps,s,l)-- | A way of creating Vectors outside the IO monad. The @Int@-- argument gives the final size of the Vector. Unlike-- 'createAndTrim' the Vector is not reallocated if the final size-- is less than the estimated size.unsafeCreate::(Storablea)=>Int->(Ptra->IO())->VectoraunsafeCreatelf=unsafePerformIO(createlf){-# INLINE unsafeCreate #-}-- | Wrapper of mallocForeignPtrArray.create::(Storablea)=>Int->(Ptra->IO())->IO(Vectora)createlf=dofp<-mallocForeignPtrArraylwithForeignPtrfp$\p->fpreturn$!SVfp0l-- | Given the maximum size needed and a function to make the contents-- of a Vector, createAndTrim makes the 'Vector'. The generating-- function is required to return the actual final size (<= the maximum-- size), and the resulting byte array is realloced to this size.---- createAndTrim is the main mechanism for creating custom, efficient-- Vector functions, using Haskell or C functions to fill the space.--createAndTrim::(Storablea)=>Int->(Ptra->IOInt)->IO(Vectora)createAndTrimlf=dofp<-mallocForeignPtrArraylwithForeignPtrfp$\p->dol'<-fpifassert(l'<=l)$l'>=lthenreturn$!SVfp0lelsecreatel'$\p'->copyArrayp'pl'createAndTrim'::(Storablea)=>Int->(Ptra->IO(Int,Int,b))->IO(Vectora,b)createAndTrim'lf=dofp<-mallocForeignPtrArraylwithForeignPtrfp$\p->do(off,l',res)<-fpifassert(l'<=l)$l'>=lthenreturn$!(SVfp0l,res)elsedops<-createl'$\p'->copyArrayp'(p`advancePtr`off)l'return$!(ps,res)-- | Just like unsafePerformIO, but we inline it. Big performance gains as-- it exposes lots of things to further inlining. /Very unsafe/. In-- particular, you should do no memory allocation inside an-- 'inlinePerformIO' block. On Hugs this is just @unsafePerformIO@.--{-# INLINE inlinePerformIO #-}inlinePerformIO::IOa->a#if defined(__GLASGOW_HASKELL__)inlinePerformIO(IOm)=casemrealWorld#of(#_,r#)->r#elseinlinePerformIO=unsafePerformIO#endif