packages feed

libclang-bindings-0.1.0.0: src/Clang/Internal/FFI.hs

-- | Internal utilities for working with the C FFI
module Clang.Internal.FFI (
    withArrayOrNull
  , withCStrings
  , withOptCString
  ) where

import Foreign
import Foreign.C

-- | Alternative to 'withArrayLen' that returns a null pointer when the passed
-- array is empty
withArrayOrNull :: Storable a => [a] -> (Ptr a -> Int -> IO r) -> IO r
withArrayOrNull xs k
    | null xs   = k nullPtr 0
    | otherwise =
        let arrayLength = length xs
        in  allocaArray arrayLength $ \ptr -> do
              pokeArray ptr xs
              k ptr arrayLength

-- | Extension of 'withCString' for multiple CStrings
withCStrings :: [String] -> (Ptr CString -> CInt -> IO r) -> IO r
withCStrings = \args k ->
    allocaArray (length args) $ \arr ->
      go args $ \args' -> do
        pokeArray arr args'
        k arr (fromIntegral $ length args)
  where
    go :: [String] -> ([CString] -> IO r) -> IO r
    go []     k = k []
    go (x:xs) k = withCString x  $ \x'  ->
                  go          xs $ \xs' ->
                  k (x' : xs')

-- | Variation on 'withCString' which uses @NULL@ for 'Nothing'
withOptCString :: Maybe String -> (CString -> IO a) -> IO a
withOptCString (Just str) = withCString str
withOptCString Nothing    = ($ nullPtr)