-- | A properly aligned ForeignPtr type.-- This can be currently achieved only by wasting some bytes.moduleForeign.ForeignPtr.Aligned(AlignedForeignPtr,Alignment,align,fromAlignment,mallocAlignedForeignPtr,mallocAlignedForeignPtrArray,mallocAlignedForeignPtrBytes,withAlignedForeignPtr,finalizeAlignedForeignPtr,touchAlignedForeignPtr,castAlignedForeignPtr)where--------------------------------------------------------------------------------importData.BitsimportForeign.PtrimportForeign.ForeignPtrimportForeign.StorableimportSystem.IO.Unsafe---------------------------------------------------------------------------------- | Should be a power of two.newtypeAlignment=Alignment{fromAlignment::Int}derivingShowisPowerOfTwo::Int->BoolisPowerOfTwok|k<1=False|k==1=True|True=ifoddkthenFalseelseisPowerOfTwo(k`div`2)-- | A \"smart\" constructor which checks whether the input -- is a power of two.align::Int->Alignmentalignk=ifisPowerOfTwokthenAlignmentkelseerror"invalid alignment"-- | The aligned ForeignPtr typedataAlignedForeignPtra=AFPtr{_fptr::{-# UNPACK #-}!(ForeignPtra),_offset::{-# UNPACK #-}!Int}instanceShow(AlignedForeignPtra)whereshowafptr=unsafePerformIO$withAlignedForeignPtrafptr$\p->return(showp)mallocAlignedForeignPtr::Storablea=>Alignment->IO(AlignedForeignPtra)mallocAlignedForeignPtralign=mallocAlignedForeignPtrArrayalign1mallocAlignedForeignPtrArray::Storablea=>Alignment->Int->IO(AlignedForeignPtra)mallocAlignedForeignPtrArrayalignn=workerwhereworker=mallocAlignedForeignPtrBytesalign(n*sizeOfundef)undef=ioAFPtrUndefinedworker-- | This is here only to avoid the @ScopedTypeVariables@ language extension-- for more portability.ioAFPtrUndefined::IO(AlignedForeignPtra)->aioAFPtrUndefined_=undefinedmallocAlignedForeignPtrBytes::Alignment->Int->IO(AlignedForeignPtra)mallocAlignedForeignPtrBytes(Alignmentalign)n=dofptr<-mallocForeignPtrBytes(n+align)-- (n+align-1) would be enough, to be precise. But usually that's an odd number.ofs<-withForeignPtrfptr$\p->doletj=ptrToIntPtrpa=fromIntegralalign::IntPtrk=(j+a-1).&.(complement(a-1))return$fromIntegral(k-j)return(AFPtrfptrofs)withAlignedForeignPtr::AlignedForeignPtra->(Ptra->IOb)->IObwithAlignedForeignPtr(AFPtrfptrofs)action=withForeignPtrfptr$\p->action(p`plusPtr`ofs)finalizeAlignedForeignPtr::AlignedForeignPtra->IO()finalizeAlignedForeignPtr(AFPtrfptrofs)=finalizeForeignPtrfptrtouchAlignedForeignPtr::AlignedForeignPtra->IO()touchAlignedForeignPtr(AFPtrfptrofs)=touchForeignPtrfptrcastAlignedForeignPtr::AlignedForeignPtra->AlignedForeignPtrbcastAlignedForeignPtr(AFPtrfptrofs)=AFPtr(castForeignPtrfptr)ofs--------------------------------------------------------------------------------