module Foreign.Storable.FixedArray where

import Control.Monad.Trans.State (StateT, evalStateT, get, put, )
import Control.Monad.Trans.Class (lift, )

import Foreign.Ptr (Ptr, castPtr, )
import Foreign.Storable (Storable(..))
import Foreign.Marshal.Array (advancePtr, )


{-# INLINE roundUp #-}
roundUp :: Int -> Int -> Int
roundUp :: Int -> Int -> Int
roundUp Int
m Int
x = Int
x Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int -> Int -> Int
forall a. Integral a => a -> a -> a
mod (-Int
x) Int
m

{-# INLINE sizeOfArray #-}
sizeOfArray :: Storable a => Int -> a -> Int
sizeOfArray :: Int -> a -> Int
sizeOfArray Int
n a
x =
   Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int -> Int -> Int
roundUp (a -> Int
forall a. Storable a => a -> Int
alignment a
x) (a -> Int
forall a. Storable a => a -> Int
sizeOf a
x)

{-# INLINE pokeNext #-}
pokeNext :: (Storable a) => a -> StateT (Ptr a) IO ()
pokeNext :: a -> StateT (Ptr a) IO ()
pokeNext a
x =
   do Ptr a
ptr <- StateT (Ptr a) IO (Ptr a)
forall (m :: * -> *) s. Monad m => StateT s m s
get
      IO () -> StateT (Ptr a) IO ()
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (IO () -> StateT (Ptr a) IO ()) -> IO () -> StateT (Ptr a) IO ()
forall a b. (a -> b) -> a -> b
$ Ptr a -> a -> IO ()
forall a. Storable a => Ptr a -> a -> IO ()
poke Ptr a
ptr a
x
      Ptr a -> StateT (Ptr a) IO ()
forall (m :: * -> *) s. Monad m => s -> StateT s m ()
put (Ptr a
ptr Ptr a -> Int -> Ptr a
forall a. Storable a => Ptr a -> Int -> Ptr a
`advancePtr` Int
1)
-- ToDo: put (ptr `plusPtr` roundUp (alignment x) (sizeOf x))

{-# INLINE peekNext #-}
peekNext :: (Storable a) => StateT (Ptr a) IO a
peekNext :: StateT (Ptr a) IO a
peekNext =
   do Ptr a
ptr <- StateT (Ptr a) IO (Ptr a)
forall (m :: * -> *) s. Monad m => StateT s m s
get
      a
a <- IO a -> StateT (Ptr a) IO a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (IO a -> StateT (Ptr a) IO a) -> IO a -> StateT (Ptr a) IO a
forall a b. (a -> b) -> a -> b
$ Ptr a -> IO a
forall a. Storable a => Ptr a -> IO a
peek Ptr a
ptr
      Ptr a -> StateT (Ptr a) IO ()
forall (m :: * -> *) s. Monad m => s -> StateT s m ()
put (Ptr a
ptr Ptr a -> Int -> Ptr a
forall a. Storable a => Ptr a -> Int -> Ptr a
`advancePtr` Int
1)
      a -> StateT (Ptr a) IO a
forall (m :: * -> *) a. Monad m => a -> m a
return a
a

run :: Ptr (t a) -> StateT (Ptr a) IO c -> IO c
run :: Ptr (t a) -> StateT (Ptr a) IO c -> IO c
run Ptr (t a)
ptr StateT (Ptr a) IO c
act =
   StateT (Ptr a) IO c -> Ptr a -> IO c
forall (m :: * -> *) s a. Monad m => StateT s m a -> s -> m a
evalStateT StateT (Ptr a) IO c
act (Ptr (t a) -> Ptr a
forall a b. Ptr a -> Ptr b
castPtr Ptr (t a)
ptr)