module HaskellWorks.Foreign
  ( mallocForeignPtrBytesWithAlignedPtr
  , mallocForeignPtrBytesWithAlignedCastPtr
  ) where

import Foreign.ForeignPtr (ForeignPtr)
import Foreign.Ptr        (Ptr, alignPtr)
import Foreign.Storable   (Storable)

import qualified Foreign.ForeignPtr        as F
import qualified Foreign.ForeignPtr.Unsafe as F
import qualified Foreign.Ptr               as F

mallocForeignPtrBytesWithAlignedPtr :: Storable a => Int -> Int -> IO (ForeignPtr a, Ptr a)
mallocForeignPtrBytesWithAlignedPtr :: Int -> Int -> IO (ForeignPtr a, Ptr a)
mallocForeignPtrBytesWithAlignedPtr Int
alignment Int
n = do
  ForeignPtr a
fptr <- Int -> IO (ForeignPtr a)
forall a. Int -> IO (ForeignPtr a)
F.mallocForeignPtrBytes (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
alignment)
  let alignedPtr :: Ptr a
alignedPtr = Ptr a -> Int -> Ptr a
forall a. Ptr a -> Int -> Ptr a
alignPtr (ForeignPtr a -> Ptr a
forall a. ForeignPtr a -> Ptr a
F.unsafeForeignPtrToPtr ForeignPtr a
fptr) Int
alignment
  (ForeignPtr a, Ptr a) -> IO (ForeignPtr a, Ptr a)
forall (m :: * -> *) a. Monad m => a -> m a
return (ForeignPtr a
fptr, Ptr a
alignedPtr)

mallocForeignPtrBytesWithAlignedCastPtr :: Storable a => Int -> Int -> IO (ForeignPtr a, Ptr b)
mallocForeignPtrBytesWithAlignedCastPtr :: Int -> Int -> IO (ForeignPtr a, Ptr b)
mallocForeignPtrBytesWithAlignedCastPtr Int
alignment Int
n = do
  ForeignPtr a
fptr <- Int -> IO (ForeignPtr a)
forall a. Int -> IO (ForeignPtr a)
F.mallocForeignPtrBytes (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
alignment)
  let alignedPtr :: Ptr a
alignedPtr = Ptr a -> Int -> Ptr a
forall a. Ptr a -> Int -> Ptr a
alignPtr (ForeignPtr a -> Ptr a
forall a. ForeignPtr a -> Ptr a
F.unsafeForeignPtrToPtr ForeignPtr a
fptr) Int
alignment
  (ForeignPtr a, Ptr b) -> IO (ForeignPtr a, Ptr b)
forall (m :: * -> *) a. Monad m => a -> m a
return (ForeignPtr a
fptr, Ptr a -> Ptr b
forall a b. Ptr a -> Ptr b
F.castPtr Ptr a
alignedPtr)