{-# LANGUAGE Trustworthy #-}
{-# LANGUAGE NoImplicitPrelude #-}
module Foreign.Marshal.Utils (
  
  
  
  with,
  new,
  
  
  fromBool,
  toBool,
  
  
  maybeNew,
  maybeWith,
  maybePeek,
  
  
  withMany,
  
  
  
  copyBytes,
  moveBytes,
) where
import Data.Maybe
import Foreign.Ptr              ( Ptr, nullPtr )
import Foreign.Storable         ( Storable(poke) )
import Foreign.C.Types          ( CSize(..) )
import Foreign.Marshal.Alloc    ( malloc, alloca )
import GHC.Real                 ( fromIntegral )
import GHC.Num
import GHC.Base
new     :: Storable a => a -> IO (Ptr a)
new val  = 
  do 
    ptr <- malloc
    poke ptr val
    return ptr
with       :: Storable a => a -> (Ptr a -> IO b) -> IO b
with val f  =
  alloca $ \ptr -> do
    poke ptr val
    res <- f ptr
    return res
fromBool       :: Num a => Bool -> a
fromBool False  = 0
fromBool True   = 1
toBool :: (Eq a, Num a) => a -> Bool
toBool  = (/= 0)
maybeNew :: (      a -> IO (Ptr b))
         -> (Maybe a -> IO (Ptr b))
maybeNew  = maybe (return nullPtr)
maybeWith :: (      a -> (Ptr b -> IO c) -> IO c) 
          -> (Maybe a -> (Ptr b -> IO c) -> IO c)
maybeWith  = maybe ($ nullPtr)
maybePeek                           :: (Ptr a -> IO b) -> Ptr a -> IO (Maybe b)
maybePeek peek ptr | ptr == nullPtr  = return Nothing
                   | otherwise       = do a <- peek ptr; return (Just a)
withMany :: (a -> (b -> res) -> res)  
         -> [a]                       
         -> ([b] -> res)              
         -> res
withMany _       []     f = f []
withMany withFoo (x:xs) f = withFoo x $ \x' ->
                              withMany withFoo xs (\xs' -> f (x':xs'))
copyBytes               :: Ptr a -> Ptr a -> Int -> IO ()
copyBytes dest src size  = do _ <- memcpy dest src (fromIntegral size)
                              return ()
moveBytes               :: Ptr a -> Ptr a -> Int -> IO ()
moveBytes dest src size  = do _ <- memmove dest src (fromIntegral size)
                              return ()
foreign import ccall unsafe "string.h" memcpy  :: Ptr a -> Ptr a -> CSize -> IO (Ptr a)
foreign import ccall unsafe "string.h" memmove :: Ptr a -> Ptr a -> CSize -> IO (Ptr a)