nanovg-0.8.1.0: src/NanoVG/Internal/FFIHelpers.hs
module NanoVG.Internal.FFIHelpers
(withCString
,useAsCStringLen'
,useAsPtr
,one
,null
,bitMask
) where
import Control.Monad ((>=>))
import Data.Bits ((.|.))
import Data.ByteString hiding (null)
import qualified Data.Set as S
import qualified Data.Text as T
import qualified Data.Text.Encoding as T
import Foreign.C.String (CString)
import Foreign.C.Types
import Foreign.Marshal (copyBytes, mallocBytes)
import Foreign.Ptr
import Prelude hiding (null)
-- | Marshal a Haskell string into a NUL terminated C string using temporary storage.
withCString :: T.Text -> (CString -> IO b) -> IO b
withCString t = useAsCString (T.encodeUtf8 t)
-- | Wrapper around 'useAsCStringLen' that uses 'CUChar's
useAsCStringLen' :: ByteString -> ((Ptr CUChar,CInt) -> IO a) -> IO a
useAsCStringLen' bs f = useAsCStringLen bs ((\(ptr,len) -> return (castPtr ptr,fromIntegral len)) >=> copyCStringLen >=> f)
where
-- | Copy memory under given pointer to a new address.
-- The allocated memory is not garbage-collected and needs to be freed manually later.
-- In the case of 'createFontMem' and 'createFontMemAtIndex' (the only places using it)
-- it is freed by NanoVG as a part of 'nvgDeleteGL3'.
copyCStringLen :: Integral b => (Ptr a, b) -> IO (Ptr a, b)
copyCStringLen (from, len) =
let intLen = fromIntegral len
in do
to <- mallocBytes intLen
copyBytes to from intLen
return (to, len)
-- | Wrapper around 'useAsCStringLen'' that discards the length
useAsPtr :: ByteString -> (Ptr CUChar -> IO a) -> IO a
useAsPtr bs f = useAsCStringLen' bs (f . fst)
-- | Marshalling helper for a constant one
one :: Num a => (a -> b) -> b
one f = f 1
-- | Marshalling helper for a constant 'nullPtr'
null :: (Ptr a -> b) -> b
null f = f nullPtr
-- | Combine the values in the set using a bitwise or
bitMask :: Enum a => S.Set a -> CInt
bitMask = S.fold (.|.) 0 . S.map (fromIntegral . fromEnum)