    {-# LANGUAGE DeriveDataTypeable, EmptyDataDecls, ForeignFunctionInterface #-}
    -- |
    -- Module      : Data.Text.ICU.Convert.Internal
    -- Copyright   : (c) Bryan O'Sullivan 2009
    --
    -- License     : BSD-style
    -- Maintainer  : bos@serpentine.com
    -- Stability   : experimental
    -- Portability : GHC
    --
    -- Low-level character set types and functions.

    module Data.Text.ICU.Convert.Internal
        (
          Converter(..)
        , UConverter
        , getName
        , withConverter
        ) where

    import Data.Text.ICU.Error.Internal (UErrorCode, handleError)
    import Data.Typeable (Typeable)
    import Foreign.C.String (CString, peekCString)
    import Foreign.ForeignPtr (ForeignPtr, withForeignPtr)
    import Foreign.Ptr (Ptr)
    import System.IO.Unsafe (unsafePerformIO)

    data UConverter

    -- | Character set converter type.  /Note/: this structure is not
    -- thread safe. It is /not/ safe to use value of this type
    -- simultaneously from multiple threads.
    data Converter = Converter {-# UNPACK #-} !(ForeignPtr UConverter)
                     deriving (Converter -> Converter -> Bool
    (Converter -> Converter -> Bool)
    -> (Converter -> Converter -> Bool) -> Eq Converter
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: Converter -> Converter -> Bool
    == :: Converter -> Converter -> Bool
    $c/= :: Converter -> Converter -> Bool
    /= :: Converter -> Converter -> Bool
    Eq, Typeable)

    instance Show Converter where
        show :: Converter -> String
    show Converter
    c = String
    "Converter " String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ ShowS
    forall a. Show a => a -> String
    show (Converter -> String
    getName Converter
    c)

    withConverter :: Converter -> (Ptr UConverter -> IO a) -> IO a
    {-# INLINE withConverter #-}
    withConverter :: forall a. Converter -> (Ptr UConverter -> IO a) -> IO a
    withConverter (Converter ForeignPtr UConverter
    cnv) Ptr UConverter -> IO a
    action = ForeignPtr UConverter -> (Ptr UConverter -> IO a) -> IO a
    forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
    withForeignPtr ForeignPtr UConverter
    cnv Ptr UConverter -> IO a
    action

    -- | Gets the internal, canonical name of the converter.
    getName :: Converter -> String
    getName :: Converter -> String
    getName Converter
    cnv = IO String -> String
    forall a. IO a -> a
    unsafePerformIO (IO String -> String)
    -> ((Ptr UConverter -> IO String) -> IO String)
    -> (Ptr UConverter -> IO String)
    -> String
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    .
      Converter -> (Ptr UConverter -> IO String) -> IO String
    forall a. Converter -> (Ptr UConverter -> IO a) -> IO a
    withConverter Converter
    cnv ((Ptr UConverter -> IO String) -> String)
    -> (Ptr UConverter -> IO String) -> String
    forall a b. (a -> b) -> a -> b
    $ \Ptr UConverter
    ptr ->
        CString -> IO String
    peekCString (CString -> IO String) -> IO CString -> IO String
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
    =<< (Ptr UErrorCode -> IO CString) -> IO CString
    forall a. (Ptr UErrorCode -> IO a) -> IO a
    handleError (Ptr UConverter -> Ptr UErrorCode -> IO CString
    ucnv_getName Ptr UConverter
    ptr)

    foreign import ccall unsafe "hs_text_icu.h __hs_ucnv_getName" ucnv_getName
        :: Ptr UConverter -> Ptr UErrorCode -> IO CString