Movatterモバイル変換
[0]ホーム
{-# LANGUAGE Trustworthy #-}{-# LANGUAGE NoImplicitPrelude, MagicHash #-}------------------------------------------------------------------------------- |-- 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::Storablea=>Int->IO(Ptra)mallocArray=doMallocundefinedwheredoMalloc::Storablea'=>a'->Int->IO(Ptra')doMallocdummysize=mallocBytes(size*sizeOfdummy)-- |Like 'mallocArray', but add an extra position to hold a special-- termination element.--mallocArray0::Storablea=>Int->IO(Ptra)mallocArray0size=mallocArray(size+1)-- |Like 'mallocArray', but allocated memory is filled with bytes of value zero.--callocArray::Storablea=>Int->IO(Ptra)callocArray=doCallocundefinedwheredoCalloc::Storablea'=>a'->Int->IO(Ptra')doCallocdummysize=callocBytes(size*sizeOfdummy)-- |Like 'callocArray0', but allocated memory is filled with bytes of value-- zero.--callocArray0::Storablea=>Int->IO(Ptra)callocArray0size=callocArray(size+1)-- |Temporarily allocate space for the given number of elements-- (like 'Foreign.Marshal.Alloc.alloca', but for multiple elements).--allocaArray::Storablea=>Int->(Ptra->IOb)->IOballocaArray=doAllocaundefinedwheredoAlloca::Storablea'=>a'->Int->(Ptra'->IOb')->IOb'doAllocadummysize=allocaBytesAligned(size*sizeOfdummy)(alignmentdummy)-- |Like 'allocaArray', but add an extra position to hold a special-- termination element.--allocaArray0::Storablea=>Int->(Ptra->IOb)->IOballocaArray0size=allocaArray(size+1){-# 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::Storablea=>Ptra->Int->IO(Ptra)reallocArray=doReallocundefinedwheredoRealloc::Storablea'=>a'->Ptra'->Int->IO(Ptra')doReallocdummyptrsize=reallocBytesptr(size*sizeOfdummy)-- |Adjust the size of an array including an extra position for the end marker.--reallocArray0::Storablea=>Ptra->Int->IO(Ptra)reallocArray0ptrsize=reallocArrayptr(size+1)-- 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]peekArraysizeptr|size<=0=return[]|otherwise=f(size-1)[]wheref0acc=doe<-peekElemOffptr0;return(e:acc)fnacc=doe<-peekElemOffptrn;f(n-1)(e:acc)-- |Convert an array terminated by the given end marker into a Haskell list--peekArray0::(Storablea,Eqa)=>a->Ptra->IO[a]peekArray0markerptr=dosize<-lengthArray0markerptrpeekArraysizeptr-- |Write the list elements consecutive into memory--pokeArray::Storablea=>Ptra->[a]->IO()pokeArrayptrvals0=govals00#wherego[]_=return()go(val:vals)n#=dopokeElemOffptr(I#n#)val;govals(n#+#1#)-- |Write the list elements consecutive into memory and terminate them with the-- given marker element--pokeArray0::Storablea=>a->Ptra->[a]->IO()pokeArray0markerptrvals0=govals00#wherego[]n#=pokeElemOffptr(I#n#)markergo(val:vals)n#=dopokeElemOffptr(I#n#)val;govals(n#+#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)newArrayvals=doptr<-mallocArray(lengthvals)pokeArrayptrvalsreturnptr-- |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)newArray0markervals=doptr<-mallocArray0(lengthvals)pokeArray0markerptrvalsreturnptr-- |Temporarily store a list of storable values in memory-- (like 'Foreign.Marshal.Utils.with', but for multiple elements).--withArray::Storablea=>[a]->(Ptra->IOb)->IObwithArrayvals=withArrayLenvals.const-- |Like 'withArray', but the action gets the number of values-- as an additional parameter--withArrayLen::Storablea=>[a]->(Int->Ptra->IOb)->IObwithArrayLenvalsf=allocaArraylen$\ptr->dopokeArrayptrvalsflenptrwherelen=lengthvals-- |Like 'withArray', but a terminator indicates where the array ends--withArray0::Storablea=>a->[a]->(Ptra->IOb)->IObwithArray0markervals=withArrayLen0markervals.const-- |Like 'withArrayLen', but a terminator indicates where the array ends--withArrayLen0::Storablea=>a->[a]->(Int->Ptra->IOb)->IObwithArrayLen0markervalsf=allocaArray0len$\ptr->dopokeArray0markerptrvalsres<-flenptrreturnreswherelen=lengthvals-- 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::Storablea=>Ptra->Ptra->Int->IO()copyArray=doCopyundefinedwheredoCopy::Storablea'=>a'->Ptra'->Ptra'->Int->IO()doCopydummydestsrcsize=copyBytesdestsrc(size*sizeOfdummy)-- |Copy the given number of elements from the second array (source) into the-- first array (destination); the copied areas /may/ overlap--moveArray::Storablea=>Ptra->Ptra->Int->IO()moveArray=doMoveundefinedwheredoMove::Storablea'=>a'->Ptra'->Ptra'->Int->IO()doMovedummydestsrcsize=moveBytesdestsrc(size*sizeOfdummy)-- finding the length-- -------------------- |Return the number of elements in an array, excluding the terminator--lengthArray0::(Storablea,Eqa)=>a->Ptra->IOIntlengthArray0markerptr=loop0whereloopi=doval<-peekElemOffptriifval==markerthenreturnielseloop(i+1)-- indexing-- ---------- |Advance a pointer into an array by the given number of elements--advancePtr::Storablea=>Ptra->Int->PtraadvancePtr=doAdvanceundefinedwheredoAdvance::Storablea'=>a'->Ptra'->Int->Ptra'doAdvancedummyptri=ptr`plusPtr`(i*sizeOfdummy)
[8]ページ先頭