{-# LANGUAGE CPP #-}
{-# OPTIONS_HADDOCK hide #-}
--  GIMP Toolkit (GTK) FFI extras and version dependencies
--
--  Author : Axel Simon
--
--  Created: 22 June 2001
--
--  Copyright (C) 1999-2005 Axel Simon
--
--  This library is free software; you can redistribute it and/or
--  modify it under the terms of the GNU Lesser General Public
--  License as published by the Free Software Foundation; either
--  version 2.1 of the License, or (at your option) any later version.
--
--  This library is distributed in the hope that it will be useful,
--  but WITHOUT ANY WARRANTY; without even the implied warranty of
--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
--  Lesser General Public License for more details.
--
-- #hide

-- |
--
-- This module serves as an impedance matcher for different compiler
-- versions. It also adds a few FFI utility functions.
--

module System.Glib.FFI (
  nullForeignPtr,
  maybeNull,
  newForeignPtr,
  withForeignPtrs,
#if MIN_VERSION_base(4,4,0)
  unsafePerformIO,
  unsafeForeignPtrToPtr,
#endif
  module Foreign,
  module Foreign.C
  ) where

-- We should almost certainly not be using the standard free function anywhere
-- in the glib or gtk bindings, so we do not re-export it from this module.

import Foreign.C

#if MIN_VERSION_base(4,4,0)
import Foreign hiding (unsafePerformIO, unsafeForeignPtrToPtr, newForeignPtr, free)
import System.IO.Unsafe (unsafePerformIO)

import Foreign.ForeignPtr.Unsafe (unsafeForeignPtrToPtr)
#else
import Foreign hiding (newForeignPtr, free)
#endif

import qualified Foreign.Concurrent

newForeignPtr :: Ptr a -> FinalizerPtr a -> IO (ForeignPtr a)
newForeignPtr :: forall a. Ptr a -> FinalizerPtr a -> IO (ForeignPtr a)
newForeignPtr Ptr a
p FinalizerPtr a
finalizer
   = forall a. Ptr a -> IO () -> IO (ForeignPtr a)
Foreign.Concurrent.newForeignPtr Ptr a
p (forall a. FinalizerPtr a -> Ptr a -> IO ()
mkFinalizer FinalizerPtr a
finalizer Ptr a
p)

foreign import ccall "dynamic"
   mkFinalizer :: FinalizerPtr a -> Ptr a -> IO ()

nullForeignPtr :: ForeignPtr a
nullForeignPtr :: forall a. ForeignPtr a
nullForeignPtr = forall a. IO a -> a
unsafePerformIO forall a b. (a -> b) -> a -> b
$ forall a. Ptr a -> IO (ForeignPtr a)
newForeignPtr_ forall a. Ptr a
nullPtr

-- This is useful when it comes to marshaling lists of GObjects
--
withForeignPtrs :: [ForeignPtr a] -> ([Ptr a] -> IO b) -> IO b
withForeignPtrs :: forall a b. [ForeignPtr a] -> ([Ptr a] -> IO b) -> IO b
withForeignPtrs [ForeignPtr a]
fptrs [Ptr a] -> IO b
body = do
  b
result <- [Ptr a] -> IO b
body (forall a b. (a -> b) -> [a] -> [b]
map forall a. ForeignPtr a -> Ptr a
unsafeForeignPtrToPtr [ForeignPtr a]
fptrs)
  forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ forall a. ForeignPtr a -> IO ()
touchForeignPtr [ForeignPtr a]
fptrs
  forall (m :: * -> *) a. Monad m => a -> m a
return b
result

-- A marshaling utility function that is used by the code produced by the code
-- generator to marshal return values that can be null
maybeNull :: (IO (Ptr a) -> IO a) -> IO (Ptr a) -> IO (Maybe a)
maybeNull :: forall a. (IO (Ptr a) -> IO a) -> IO (Ptr a) -> IO (Maybe a)
maybeNull IO (Ptr a) -> IO a
marshal IO (Ptr a)
genPtr = do
  Ptr a
ptr <- IO (Ptr a)
genPtr
  if Ptr a
ptr forall a. Eq a => a -> a -> Bool
== forall a. Ptr a
nullPtr
    then forall (m :: * -> *) a. Monad m => a -> m a
return forall a. Maybe a
Nothing
    else do a
result <- IO (Ptr a) -> IO a
marshal (forall (m :: * -> *) a. Monad m => a -> m a
return Ptr a
ptr)
            forall (m :: * -> *) a. Monad m => a -> m a
return (forall a. a -> Maybe a
Just a
result)