{- Bustle.GVariant: bindings for GVariant Copyright © 2020 Will Thompson 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. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -} {-# LANGUAGE ForeignFunctionInterface #-} module Bustle.GVariant ( -- * Types GVariant , TypeAnnotate(..) -- * Constructors , makeNewGVariant , wrapNewGVariant -- * Methods , variantGetChild , variantGetString , variantPrint ) where import Foreign.ForeignPtr import Foreign.Ptr import Foreign.C import System.Glib.UTFString import Control.Monad (guard) import Control.Monad.Trans (liftIO) import Control.Monad.Trans.Maybe data TypeAnnotate = NoAnnotations | WithAnnotations deriving (Show, Ord, Eq, Enum) newtype GVariant = GVariant { unGVariant :: ForeignPtr GVariant } deriving (Eq, Ord, Show) makeNewGVariant :: IO (Ptr GVariant) -> IO GVariant makeNewGVariant act = wrapNewGVariant (act >>= g_variant_ref) wrapNewGVariant :: IO (Ptr GVariant) -> IO GVariant wrapNewGVariant act = do vPtr <- act v <- newForeignPtr g_variant_unref vPtr return $ GVariant v -- Foreign imports foreign import ccall unsafe "g_variant_is_of_type" g_variant_is_of_type :: Ptr a -> CString -> IO CInt foreign import ccall unsafe "g_variant_n_children" g_variant_n_children :: Ptr a -> IO CSize foreign import ccall unsafe "g_variant_get_child_value" g_variant_get_child_value :: Ptr a -> CSize -> IO (Ptr a) foreign import ccall unsafe "g_variant_get_string" g_variant_get_string :: Ptr a -> Ptr CSize -> IO CString foreign import ccall unsafe "g_variant_print" g_variant_print :: Ptr a -> CInt -> IO CString foreign import ccall unsafe "g_variant_ref" g_variant_ref :: Ptr GVariant -> IO (Ptr GVariant) foreign import ccall unsafe "&g_variant_unref" g_variant_unref :: FunPtr (Ptr GVariant -> IO ()) -- Bindings variantNChildren :: GVariant -> IO Word variantNChildren v = withForeignPtr (unGVariant v) $ \vPtr -> do fromIntegral <$> g_variant_n_children vPtr variantGetChild :: GVariant -> Word -> IO (Maybe GVariant) variantGetChild v i = withForeignPtr (unGVariant v) $ \vPtr -> runMaybeT $ do n <- liftIO $ variantNChildren v guard (i < n) liftIO $ wrapNewGVariant $ g_variant_get_child_value vPtr (fromIntegral i) variantGetString :: GVariant -> IO (Maybe String) variantGetString v = withForeignPtr (unGVariant v) $ \vPtr -> runMaybeT $ do r <- liftIO $ withCString "s" $ g_variant_is_of_type vPtr guard (r /= 0) s <- liftIO $ g_variant_get_string vPtr nullPtr liftIO $ peekUTFString s variantPrint :: GVariant -> TypeAnnotate -> IO String variantPrint v annotate = withForeignPtr (unGVariant v) $ \vPtr -> do cstr <- g_variant_print vPtr (fromIntegral $ fromEnum annotate) readUTFString cstr