macos-corelibs-0.0.1.0: src/MacSdk/Framework/CoreFoundation/String.hsc
{-# LANGUAGE TypeSynonymInstances #-}
module MacSdk.Framework.CoreFoundation.String
( CFStringEncoding(..)
, CFStringRef
, CFString
-- * Conversion
, toCString
, fromCString
, fromCStringWithAllocator
, toString
, fromString
) where
import MacSdk.Framework.CoreFoundation.Allocator
import MacSdk.Framework.CoreFoundation.Object
import MacSdk.Framework.CoreFoundation.Array
import Foreign
import Foreign.C.String
import Foreign.C.Types (CBool(..), CInt(..))
import Control.Monad
import Control.Monad.IO.Class (MonadIO(..))
#include <Carbon/Carbon.h>
type ForeignCFStringEncoding = Word32
-- | String encodings to be used when converting from and to CFString references.
data CFStringEncoding
= CFStringEncodingMacRoman
-- ^ An encoding constant that identifies the Mac Roman encoding.
| CFStringEncodingWindowsLatin1
-- ^ An encoding constant that identifies the Windows Latin 1 encoding
-- (ANSI codepage 1252).
| CFStringEncodingISOLatin1
-- ^ An encoding constant that identifies the ISO Latin 1 encoding
-- (ISO 8859-1)
| CFStringEncodingNextStepLatin
-- ^ An encoding constant that identifies the NextStep/OpenStep encoding.
| CFStringEncodingASCII
-- ^ An encoding constant that identifies the ASCII encoding (decimal values 0
-- through 127).
| CFStringEncodingUnicode
-- ^ An encoding constant that identifies the Unicode encoding.
| CFStringEncodingUTF8
-- ^ An encoding constant that identifies the UTF 8 encoding.
| CFStringEncodingNonLossyASCII
-- ^ An encoding constant that identifies non-lossy ASCII encoding.
| CFStringEncodingUTF16
-- ^ An encoding constant that identifies kTextEncodingUnicodeDefault +
-- kUnicodeUTF16Format encoding (alias of kCFStringEncodingUnicode).
| CFStringEncodingUTF16BE
-- ^ An encoding constant that identifies kTextEncodingUnicodeDefault +
-- kUnicodeUTF16BEFormat encoding. This constant specifies big-endian byte
-- order.
| CFStringEncodingUTF16LE
-- ^ An encoding constant that identifies kTextEncodingUnicodeDefault +
-- kUnicodeUTF16LEFormat encoding. This constant specifies little-endian byte
-- order.
| CFStringEncodingUTF32
-- ^ An encoding constant that identifies kTextEncodingUnicodeDefault +
-- kUnicodeUTF32Format encoding.
| CFStringEncodingUTF32BE
-- ^ An encoding constant that identifies kTextEncodingUnicodeDefault +
-- kUnicodeUTF32BEFormat encoding. This constant specifies big-endian byte
-- order.
| CFStringEncodingUTF32LE
-- ^ An encoding constant that identifies kTextEncodingUnicodeDefault +
-- kUnicodeUTF32LEFormat encoding. This constant specifies little-endian byte
-- order.
toForeignEncoding :: CFStringEncoding -> ForeignCFStringEncoding
toForeignEncoding = \case
CFStringEncodingMacRoman -> (#const kCFStringEncodingMacRoman)
CFStringEncodingWindowsLatin1 -> (#const kCFStringEncodingWindowsLatin1)
CFStringEncodingISOLatin1 -> (#const kCFStringEncodingISOLatin1)
CFStringEncodingNextStepLatin -> (#const kCFStringEncodingNextStepLatin)
CFStringEncodingASCII -> (#const kCFStringEncodingASCII)
CFStringEncodingUnicode -> (#const kCFStringEncodingUnicode)
CFStringEncodingUTF8 -> (#const kCFStringEncodingUTF8)
CFStringEncodingNonLossyASCII -> (#const kCFStringEncodingNonLossyASCII)
CFStringEncodingUTF16 -> (#const kCFStringEncodingUTF16)
CFStringEncodingUTF16BE -> (#const kCFStringEncodingUTF16BE)
CFStringEncodingUTF16LE -> (#const kCFStringEncodingUTF16LE)
CFStringEncodingUTF32 -> (#const kCFStringEncodingUTF32)
CFStringEncodingUTF32BE -> (#const kCFStringEncodingUTF32BE)
CFStringEncodingUTF32LE -> (#const kCFStringEncodingUTF32LE)
data CFString_
type CFStringRef = Ptr CFString_
instance CFClass CFString_
type CFString = Object CFString_
foreign import ccall unsafe "CFStringGetCString"
cfStringGetCString
:: CFStringRef -> CString -> CFIndex -> ForeignCFStringEncoding -> IO CBool
foreign import ccall "CFStringCreateWithCString" cfStringCreateWithCString
:: CFAllocatorRef -> Ptr a -> ForeignCFStringEncoding -> IO CFStringRef
foreign import ccall "CFStringGetLength"
cfStringGetLength :: CFStringRef -> IO CFIndex
foreign import ccall "CFStringGetMaximumSizeForEncoding"
cfStringGetMaximumSizeForEncoding
:: CFIndex -> ForeignCFStringEncoding -> IO CFIndex
-- | Creates a CFString reference from a C-style string, using a provided
-- allocator and string encoding.
fromCStringWithAllocator
:: MonadIO m => Allocator -> CString -> CFStringEncoding -> m CFString
fromCStringWithAllocator allo cstr enc = liftIO $ withCFPtr allo $ \pallo ->
cfStringCreateWithCString pallo cstr (toForeignEncoding enc) >>= manageCFObj
-- | Creates a CFString reference from an ASCII-encoded C-style string, using a
-- default allocator.
fromCString :: MonadIO m => CFStringEncoding -> CString -> m CFString
fromCString enc cstr =
liftIO (nullAllocator >>= \allo -> fromCStringWithAllocator allo cstr enc)
-- | Creates a CFString reference from a regular string with ASCII encoding.
fromString :: MonadIO m => CFStringEncoding -> String -> m CFString
fromString enc str = liftIO (newCString str >>= fromCString enc)
-- | Converts a Core Foundation String to a C-style null-terminated string. It
-- returns 'Nothing' if the conversion is unsuccessfull.
toCString :: MonadIO m => CFStringEncoding -> CFString -> m (Maybe CString)
toCString enc cfs = liftIO . withCFPtr cfs $ \s -> do
len <- cfStringGetLength s
bytes <- cfStringGetMaximumSizeForEncoding len foreignEnc -- stringEncodingUTF8
cstr <- mallocArray (fromIntegral bytes + 1)
res <- cfStringGetCString s cstr (bytes + 1) foreignEnc -- stringEncodingUTF8
if toBool res
then pure (Just cstr)
else free cstr >> pure Nothing
where foreignEnc = toForeignEncoding enc
-- | Converts a CFString reference to a regular string.
toString :: MonadIO m => CFStringEncoding -> CFString -> m (Maybe String)
toString enc =
liftIO . (maybe (pure Nothing) (fmap Just . peekCString) <=< toCString enc)