Movatterモバイル変換
[0]ホーム
{-# LANGUAGE Trustworthy #-}{-# LANGUAGE NoImplicitPrelude, MagicHash, ScopedTypeVariables #-}------------------------------------------------------------------------------- |-- Module : Foreign.Marshal.Array-- Copyright : (c) The FFI task force 2001-- License : BSD-style (see the file libraries/base/LICENSE)---- Maintainer : ffi@haskell.org-- Stability : provisional-- Portability : portable---- Marshalling support: routines allocating, storing, and retrieving Haskell-- lists that are represented as arrays in the foreign language-------------------------------------------------------------------------------moduleForeign.Marshal.Array(-- * Marshalling arrays-- ** Allocation--mallocArray,mallocArray0,allocaArray,allocaArray0,reallocArray,reallocArray0,callocArray,callocArray0,-- ** Marshalling--peekArray,peekArray0,pokeArray,pokeArray0,-- ** Combined allocation and marshalling--newArray,newArray0,withArray,withArray0,withArrayLen,withArrayLen0,-- ** Copying-- | (argument order: destination, source)copyArray,moveArray,-- ** Finding the length--lengthArray0,-- ** Indexing--advancePtr,)whereimportForeign.Ptr(Ptr,plusPtr)importForeign.Storable(Storable(alignment,sizeOf,peekElemOff,pokeElemOff))importForeign.Marshal.Alloc(mallocBytes,callocBytes,allocaBytesAligned,reallocBytes)importForeign.Marshal.Utils(copyBytes,moveBytes)importGHC.NumimportGHC.ListimportGHC.Base-- allocation-- ------------ |Allocate storage for the given number of elements of a storable type-- (like 'Foreign.Marshal.Alloc.malloc', but for multiple elements).--mallocArray::foralla.Storablea=>Int->IO(Ptra)mallocArray :: Int -> IO (Ptr a)mallocArrayIntsize=Int -> IO (Ptr a)forall a. Int -> IO (Ptr a)mallocBytes(IntsizeInt -> Int -> Intforall a. Num a => a -> a -> a*a -> Intforall a. Storable a => a -> IntsizeOf(aforall a. HasCallStack => aundefined::a))-- |Like 'mallocArray', but add an extra position to hold a special-- termination element.--mallocArray0::Storablea=>Int->IO(Ptra)mallocArray0 :: Int -> IO (Ptr a)mallocArray0Intsize=Int -> IO (Ptr a)forall a. Storable a => Int -> IO (Ptr a)mallocArray(IntsizeInt -> Int -> Intforall a. Num a => a -> a -> a+Int1)-- |Like 'mallocArray', but allocated memory is filled with bytes of value zero.--callocArray::foralla.Storablea=>Int->IO(Ptra)callocArray :: Int -> IO (Ptr a)callocArrayIntsize=Int -> IO (Ptr a)forall a. Int -> IO (Ptr a)callocBytes(IntsizeInt -> Int -> Intforall a. Num a => a -> a -> a*a -> Intforall a. Storable a => a -> IntsizeOf(aforall a. HasCallStack => aundefined::a))-- |Like 'callocArray0', but allocated memory is filled with bytes of value-- zero.--callocArray0::Storablea=>Int->IO(Ptra)callocArray0 :: Int -> IO (Ptr a)callocArray0Intsize=Int -> IO (Ptr a)forall a. Storable a => Int -> IO (Ptr a)callocArray(IntsizeInt -> Int -> Intforall a. Num a => a -> a -> a+Int1)-- |Temporarily allocate space for the given number of elements-- (like 'Foreign.Marshal.Alloc.alloca', but for multiple elements).--allocaArray::forallab.Storablea=>Int->(Ptra->IOb)->IOballocaArray :: Int -> (Ptr a -> IO b) -> IO ballocaArrayIntsize=Int -> Int -> (Ptr a -> IO b) -> IO bforall a b. Int -> Int -> (Ptr a -> IO b) -> IO ballocaBytesAligned(IntsizeInt -> Int -> Intforall a. Num a => a -> a -> a*a -> Intforall a. Storable a => a -> IntsizeOf(aforall a. HasCallStack => aundefined::a))(a -> Intforall a. Storable a => a -> Intalignment(aforall a. HasCallStack => aundefined::a))-- |Like 'allocaArray', but add an extra position to hold a special-- termination element.--allocaArray0::Storablea=>Int->(Ptra->IOb)->IOballocaArray0 :: Int -> (Ptr a -> IO b) -> IO ballocaArray0Intsize=Int -> (Ptr a -> IO b) -> IO bforall a b. Storable a => Int -> (Ptr a -> IO b) -> IO ballocaArray(IntsizeInt -> Int -> Intforall a. Num a => a -> a -> a+Int1){-# INLINEallocaArray0#-}-- needed to get allocaArray to inline into withCString, for unknown-- reasons --SDM 23/4/2010, see #4004 for benchmark-- |Adjust the size of an array--reallocArray::foralla.Storablea=>Ptra->Int->IO(Ptra)reallocArray :: Ptr a -> Int -> IO (Ptr a)reallocArrayPtr aptrIntsize=Ptr a -> Int -> IO (Ptr a)forall a. Ptr a -> Int -> IO (Ptr a)reallocBytesPtr aptr(IntsizeInt -> Int -> Intforall a. Num a => a -> a -> a*a -> Intforall a. Storable a => a -> IntsizeOf(aforall a. HasCallStack => aundefined::a))-- |Adjust the size of an array including an extra position for the end marker.--reallocArray0::Storablea=>Ptra->Int->IO(Ptra)reallocArray0 :: Ptr a -> Int -> IO (Ptr a)reallocArray0Ptr aptrIntsize=Ptr a -> Int -> IO (Ptr a)forall a. Storable a => Ptr a -> Int -> IO (Ptr a)reallocArrayPtr aptr(IntsizeInt -> Int -> Intforall a. Num a => a -> a -> a+Int1)-- marshalling-- ------------- |Convert an array of given length into a Haskell list. The implementation-- is tail-recursive and so uses constant stack space.--peekArray::Storablea=>Int->Ptra->IO[a]peekArray :: Int -> Ptr a -> IO [a]peekArrayIntsizePtr aptr|IntsizeInt -> Int -> Boolforall a. Ord a => a -> a -> Bool<=Int0=[a] -> IO [a]forall (m :: * -> *) a. Monad m => a -> m areturn[]|Boolotherwise=Int -> [a] -> IO [a]f(IntsizeInt -> Int -> Intforall a. Num a => a -> a -> a-Int1)[]wheref :: Int -> [a] -> IO [a]fInt0[a]acc=doae<-Ptr a -> Int -> IO aforall a. Storable a => Ptr a -> Int -> IO apeekElemOffPtr aptrInt0;[a] -> IO [a]forall (m :: * -> *) a. Monad m => a -> m areturn(aea -> [a] -> [a]forall a. a -> [a] -> [a]:[a]acc)fIntn[a]acc=doae<-Ptr a -> Int -> IO aforall a. Storable a => Ptr a -> Int -> IO apeekElemOffPtr aptrIntn;Int -> [a] -> IO [a]f(IntnInt -> Int -> Intforall a. Num a => a -> a -> a-Int1)(aea -> [a] -> [a]forall a. a -> [a] -> [a]:[a]acc)-- |Convert an array terminated by the given end marker into a Haskell list--peekArray0::(Storablea,Eqa)=>a->Ptra->IO[a]peekArray0 :: a -> Ptr a -> IO [a]peekArray0amarkerPtr aptr=doIntsize<-a -> Ptr a -> IO Intforall a. (Storable a, Eq a) => a -> Ptr a -> IO IntlengthArray0amarkerPtr aptrInt -> Ptr a -> IO [a]forall a. Storable a => Int -> Ptr a -> IO [a]peekArrayIntsizePtr aptr-- |Write the list elements consecutive into memory--pokeArray::Storablea=>Ptra->[a]->IO()pokeArray :: Ptr a -> [a] -> IO ()pokeArrayPtr aptr[a]vals0=[a] -> Int# -> IO ()go[a]vals0Int#0#wherego :: [a] -> Int# -> IO ()go[]Int#_=() -> IO ()forall (m :: * -> *) a. Monad m => a -> m areturn()go(aval:[a]vals)Int#n#=doPtr a -> Int -> a -> IO ()forall a. Storable a => Ptr a -> Int -> a -> IO ()pokeElemOffPtr aptr(Int# -> IntI#Int#n#)aval;[a] -> Int# -> IO ()go[a]vals(Int#n#Int# -> Int# -> Int#+#Int#1#)-- |Write the list elements consecutive into memory and terminate them with the-- given marker element--pokeArray0::Storablea=>a->Ptra->[a]->IO()pokeArray0 :: a -> Ptr a -> [a] -> IO ()pokeArray0amarkerPtr aptr[a]vals0=[a] -> Int# -> IO ()go[a]vals0Int#0#wherego :: [a] -> Int# -> IO ()go[]Int#n#=Ptr a -> Int -> a -> IO ()forall a. Storable a => Ptr a -> Int -> a -> IO ()pokeElemOffPtr aptr(Int# -> IntI#Int#n#)amarkergo(aval:[a]vals)Int#n#=doPtr a -> Int -> a -> IO ()forall a. Storable a => Ptr a -> Int -> a -> IO ()pokeElemOffPtr aptr(Int# -> IntI#Int#n#)aval;[a] -> Int# -> IO ()go[a]vals(Int#n#Int# -> Int# -> Int#+#Int#1#)-- combined allocation and marshalling-- ------------------------------------- |Write a list of storable elements into a newly allocated, consecutive-- sequence of storable values-- (like 'Foreign.Marshal.Utils.new', but for multiple elements).--newArray::Storablea=>[a]->IO(Ptra)newArray :: [a] -> IO (Ptr a)newArray[a]vals=doPtr aptr<-Int -> IO (Ptr a)forall a. Storable a => Int -> IO (Ptr a)mallocArray([a] -> Intforall a. [a] -> Intlength[a]vals)Ptr a -> [a] -> IO ()forall a. Storable a => Ptr a -> [a] -> IO ()pokeArrayPtr aptr[a]valsPtr a -> IO (Ptr a)forall (m :: * -> *) a. Monad m => a -> m areturnPtr aptr-- |Write a list of storable elements into a newly allocated, consecutive-- sequence of storable values, where the end is fixed by the given end marker--newArray0::Storablea=>a->[a]->IO(Ptra)newArray0 :: a -> [a] -> IO (Ptr a)newArray0amarker[a]vals=doPtr aptr<-Int -> IO (Ptr a)forall a. Storable a => Int -> IO (Ptr a)mallocArray0([a] -> Intforall a. [a] -> Intlength[a]vals)a -> Ptr a -> [a] -> IO ()forall a. Storable a => a -> Ptr a -> [a] -> IO ()pokeArray0amarkerPtr aptr[a]valsPtr a -> IO (Ptr a)forall (m :: * -> *) a. Monad m => a -> m areturnPtr aptr-- |Temporarily store a list of storable values in memory-- (like 'Foreign.Marshal.Utils.with', but for multiple elements).--withArray::Storablea=>[a]->(Ptra->IOb)->IObwithArray :: [a] -> (Ptr a -> IO b) -> IO bwithArray[a]vals=[a] -> (Int -> Ptr a -> IO b) -> IO bforall a b. Storable a => [a] -> (Int -> Ptr a -> IO b) -> IO bwithArrayLen[a]vals((Int -> Ptr a -> IO b) -> IO b)-> ((Ptr a -> IO b) -> Int -> Ptr a -> IO b)-> (Ptr a -> IO b)-> IO bforall b c a. (b -> c) -> (a -> b) -> a -> c.(Ptr a -> IO b) -> Int -> Ptr a -> IO bforall a b. a -> b -> aconst-- |Like 'withArray', but the action gets the number of values-- as an additional parameter--withArrayLen::Storablea=>[a]->(Int->Ptra->IOb)->IObwithArrayLen :: [a] -> (Int -> Ptr a -> IO b) -> IO bwithArrayLen[a]valsInt -> Ptr a -> IO bf=Int -> (Ptr a -> IO b) -> IO bforall a b. Storable a => Int -> (Ptr a -> IO b) -> IO ballocaArrayIntlen((Ptr a -> IO b) -> IO b) -> (Ptr a -> IO b) -> IO bforall a b. (a -> b) -> a -> b$\Ptr aptr->doPtr a -> [a] -> IO ()forall a. Storable a => Ptr a -> [a] -> IO ()pokeArrayPtr aptr[a]valsInt -> Ptr a -> IO bfIntlenPtr aptrwherelen :: Intlen=[a] -> Intforall a. [a] -> Intlength[a]vals-- |Like 'withArray', but a terminator indicates where the array ends--withArray0::Storablea=>a->[a]->(Ptra->IOb)->IObwithArray0 :: a -> [a] -> (Ptr a -> IO b) -> IO bwithArray0amarker[a]vals=a -> [a] -> (Int -> Ptr a -> IO b) -> IO bforall a b.Storable a =>a -> [a] -> (Int -> Ptr a -> IO b) -> IO bwithArrayLen0amarker[a]vals((Int -> Ptr a -> IO b) -> IO b)-> ((Ptr a -> IO b) -> Int -> Ptr a -> IO b)-> (Ptr a -> IO b)-> IO bforall b c a. (b -> c) -> (a -> b) -> a -> c.(Ptr a -> IO b) -> Int -> Ptr a -> IO bforall a b. a -> b -> aconst-- |Like 'withArrayLen', but a terminator indicates where the array ends--withArrayLen0::Storablea=>a->[a]->(Int->Ptra->IOb)->IObwithArrayLen0 :: a -> [a] -> (Int -> Ptr a -> IO b) -> IO bwithArrayLen0amarker[a]valsInt -> Ptr a -> IO bf=Int -> (Ptr a -> IO b) -> IO bforall a b. Storable a => Int -> (Ptr a -> IO b) -> IO ballocaArray0Intlen((Ptr a -> IO b) -> IO b) -> (Ptr a -> IO b) -> IO bforall a b. (a -> b) -> a -> b$\Ptr aptr->doa -> Ptr a -> [a] -> IO ()forall a. Storable a => a -> Ptr a -> [a] -> IO ()pokeArray0amarkerPtr aptr[a]valsbres<-Int -> Ptr a -> IO bfIntlenPtr aptrb -> IO bforall (m :: * -> *) a. Monad m => a -> m areturnbreswherelen :: Intlen=[a] -> Intforall a. [a] -> Intlength[a]vals-- copying (argument order: destination, source)-- --------- |Copy the given number of elements from the second array (source) into the-- first array (destination); the copied areas may /not/ overlap--copyArray::foralla.Storablea=>Ptra->Ptra->Int->IO()copyArray :: Ptr a -> Ptr a -> Int -> IO ()copyArrayPtr adestPtr asrcIntsize=Ptr a -> Ptr a -> Int -> IO ()forall a. Ptr a -> Ptr a -> Int -> IO ()copyBytesPtr adestPtr asrc(IntsizeInt -> Int -> Intforall a. Num a => a -> a -> a*a -> Intforall a. Storable a => a -> IntsizeOf(aforall a. HasCallStack => aundefined::a))-- |Copy the given number of elements from the second array (source) into the-- first array (destination); the copied areas /may/ overlap--moveArray::foralla.Storablea=>Ptra->Ptra->Int->IO()moveArray :: Ptr a -> Ptr a -> Int -> IO ()moveArrayPtr adestPtr asrcIntsize=Ptr a -> Ptr a -> Int -> IO ()forall a. Ptr a -> Ptr a -> Int -> IO ()moveBytesPtr adestPtr asrc(IntsizeInt -> Int -> Intforall a. Num a => a -> a -> a*a -> Intforall a. Storable a => a -> IntsizeOf(aforall a. HasCallStack => aundefined::a))-- finding the length-- -------------------- |Return the number of elements in an array, excluding the terminator--lengthArray0::(Storablea,Eqa)=>a->Ptra->IOIntlengthArray0 :: a -> Ptr a -> IO IntlengthArray0amarkerPtr aptr=Int -> IO IntloopInt0whereloop :: Int -> IO IntloopInti=doaval<-Ptr a -> Int -> IO aforall a. Storable a => Ptr a -> Int -> IO apeekElemOffPtr aptrIntiifavala -> a -> Boolforall a. Eq a => a -> a -> Bool==amarkerthenInt -> IO Intforall (m :: * -> *) a. Monad m => a -> m areturnIntielseInt -> IO Intloop(IntiInt -> Int -> Intforall a. Num a => a -> a -> a+Int1)-- indexing-- ---------- |Advance a pointer into an array by the given number of elements--advancePtr::foralla.Storablea=>Ptra->Int->PtraadvancePtr :: Ptr a -> Int -> Ptr aadvancePtrPtr aptrInti=Ptr aptrPtr a -> Int -> Ptr aforall a b. Ptr a -> Int -> Ptr b`plusPtr`(IntiInt -> Int -> Intforall a. Num a => a -> a -> a*a -> Intforall a. Storable a => a -> IntsizeOf(aforall a. HasCallStack => aundefined::a))
[8]ページ先頭