common/util/Util/GFlags.hs (78 lines of code) (raw):

-- Copyright (c) Facebook, Inc. and its affiliates. {-# LANGUAGE ForeignFunctionInterface #-} module Util.GFlags ( FlagException(..) , getFlagValue , setFlagDefault , setFlagValue , setFlagValueIfDefault , withFlagSaver ) where import Control.Exception import Data.Text (Text) import Foreign.C import Foreign.Ptr import Foreign.Storable import Foreign.CPP.HsStruct import qualified Util.Text as Text -- export data FlagException = FlagException Text deriving (Eq, Show) instance Exception FlagException getFlagValue :: Text -> IO (Either FlagException Text) getFlagValue k = do Text.useTextAsCString k $ \ ck -> do withHsText $ \ out -> do c_get_flag_value ck out >>= \ case 0 -> Left <$> pure (FlagException k) _ -> Right <$> hsText <$> peek out setFlagDefault :: Text -> Text -> IO (Either FlagException ()) setFlagDefault = resultOfWithCStringKV c_set_flag_default setFlagValue :: Text -> Text -> IO (Either FlagException ()) setFlagValue = resultOfWithCStringKV c_set_flag_value setFlagValueIfDefault :: Text -> Text -> IO (Either FlagException ()) setFlagValueIfDefault = resultOfWithCStringKV c_set_flag_value_if_default withFlagSaver :: IO a -> IO a withFlagSaver = bracketConst c_flag_saver_create c_flag_saver_delete -- utility data FlagSaver -- C++ gflags::FlagSaver withHsText :: (Ptr HsText -> IO a) -> IO a withHsText = bracket c_hs_string_create c_hs_string_delete resultOfWithCStringKV :: (CString -> CString -> IO CInt) -> Text -> Text -> IO (Either FlagException ()) resultOfWithCStringKV cb k v = result k <$> withCStringKV k v cb withCStringKV :: Text -> Text -> (CString -> CString -> IO a) -> IO a withCStringKV k v cb = do Text.useTextAsCString k $ \ ck -> do Text.useTextAsCString v $ \ cv -> do cb ck cv result :: Text -> CInt -> Either FlagException () result k 0 = Left (FlagException k) result _ _ = Right () bracketConst :: IO a -> (a -> IO b) -> IO c -> IO c bracketConst before after = bracket before after . const -- ffi foreign import ccall unsafe "facebook_gflags_hs_set_flag_default" c_set_flag_default :: CString -> CString -> IO CInt foreign import ccall unsafe "facebook_gflags_hs_set_flag_value" c_set_flag_value :: CString -> CString -> IO CInt foreign import ccall unsafe "facebook_gflags_hs_set_flag_value_if_default" c_set_flag_value_if_default :: CString -> CString -> IO CInt foreign import ccall unsafe "facebook_gflags_hs_get_flag_value" c_get_flag_value :: CString -> Ptr HsText -> IO CInt foreign import ccall unsafe "facebook_gflags_hs_flag_saver_create" c_flag_saver_create :: IO (Ptr FlagSaver) foreign import ccall unsafe "facebook_gflags_hs_flag_saver_delete" c_flag_saver_delete :: Ptr FlagSaver -> IO () foreign import ccall unsafe "facebook_gflags_hs_hs_string_create" c_hs_string_create :: IO (Ptr HsText) foreign import ccall unsafe "facebook_gflags_hs_hs_string_delete" c_hs_string_delete :: Ptr HsText -> IO ()