{-# LANGUAGE CPP #-}
{-# LANGUAGE NoImplicitPrelude #-}
module GHC.Internal.IO.Windows.Encoding
( encodeMultiByte
, encodeMultiByteIO
, encodeMultiByteRawIO
, decodeMultiByte
, decodeMultiByteIO
, wideCharToMultiByte
, multiByteToWideChar
, withGhcInternalToUTF16
, withUTF16ToGhcInternal
) where
import GHC.Internal.Word (Word8, Word16)
import GHC.Internal.Foreign.C.Types (CInt(..))
import GHC.Internal.Foreign.C.String (peekCAStringLen, peekCWStringLen,
withCWStringLen, withCAStringLen, )
import GHC.Internal.Foreign.Ptr (nullPtr, Ptr ())
import GHC.Internal.Foreign.Marshal.Array (allocaArray)
import GHC.Internal.Foreign.Marshal.Unsafe (unsafeLocalState)
import GHC.Internal.Windows
import GHC.Internal.IO.Encoding.CodePage (CodePage, getCurrentCodePage)
import GHC.Internal.IO
import GHC.Internal.Base
import GHC.Internal.Real
encodeMultiByte :: CodePage -> String -> String
encodeMultiByte :: Word32 -> String -> String
encodeMultiByte Word32
cp = IO String -> String
forall a. IO a -> a
unsafeLocalState (IO String -> String) -> (String -> IO String) -> String -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word32 -> String -> IO String
encodeMultiByteIO Word32
cp
{-# INLINE encodeMultiByteIO' #-}
encodeMultiByteIO' :: CodePage -> String -> ((LPCSTR, CInt) -> IO a) -> IO a
encodeMultiByteIO' :: forall a. Word32 -> String -> ((LPCSTR, CInt) -> IO a) -> IO a
encodeMultiByteIO' Word32
cp String
wstr (LPCSTR, CInt) -> IO a
transformer =
String -> (CWStringLen -> IO a) -> IO a
forall a. String -> (CWStringLen -> IO a) -> IO a
withCWStringLen String
wstr ((CWStringLen -> IO a) -> IO a) -> (CWStringLen -> IO a) -> IO a
forall a b. (a -> b) -> a -> b
$ \(Ptr CWchar
cwstr,Int
len) -> do
mbchars' <- String -> IO CInt -> IO CInt
forall a. (Eq a, Num a) => String -> IO a -> IO a
failIfZero String
"WideCharToMultiByte" (IO CInt -> IO CInt) -> IO CInt -> IO CInt
forall a b. (a -> b) -> a -> b
$ Word32
-> Word32
-> Ptr CWchar
-> CInt
-> LPCSTR
-> CInt
-> LPCSTR
-> LPBOOL
-> IO CInt
wideCharToMultiByte
Word32
cp
Word32
0
Ptr CWchar
cwstr
(Int -> CInt
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
len)
LPCSTR
forall a. Ptr a
nullPtr CInt
0
LPCSTR
forall a. Ptr a
nullPtr LPBOOL
forall a. Ptr a
nullPtr
allocaArray (fromIntegral mbchars') $ \LPCSTR
mbstr -> do
mbchars <- String -> IO CInt -> IO CInt
forall a. (Eq a, Num a) => String -> IO a -> IO a
failIfZero String
"WideCharToMultiByte" (IO CInt -> IO CInt) -> IO CInt -> IO CInt
forall a b. (a -> b) -> a -> b
$ Word32
-> Word32
-> Ptr CWchar
-> CInt
-> LPCSTR
-> CInt
-> LPCSTR
-> LPBOOL
-> IO CInt
wideCharToMultiByte
Word32
cp
Word32
0
Ptr CWchar
cwstr
(Int -> CInt
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
len)
LPCSTR
mbstr CInt
mbchars'
LPCSTR
forall a. Ptr a
nullPtr LPBOOL
forall a. Ptr a
nullPtr
transformer (mbstr,fromIntegral mbchars)
encodeMultiByteIO :: CodePage -> String -> IO String
encodeMultiByteIO :: Word32 -> String -> IO String
encodeMultiByteIO Word32
_ String
"" = String -> IO String
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return String
""
encodeMultiByteIO Word32
cp String
s = Word32 -> String -> ((LPCSTR, CInt) -> IO String) -> IO String
forall a. Word32 -> String -> ((LPCSTR, CInt) -> IO a) -> IO a
encodeMultiByteIO' Word32
cp String
s (LPCSTR, CInt) -> IO String
forall {a}. Integral a => (LPCSTR, a) -> IO String
toString
where toString :: (LPCSTR, a) -> IO String
toString (LPCSTR
st,a
l) = CStringLen -> IO String
peekCAStringLen (LPCSTR
st,a -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral a
l)
encodeMultiByteRawIO :: CodePage -> String -> IO (LPCSTR, CInt)
encodeMultiByteRawIO :: Word32 -> String -> IO (LPCSTR, CInt)
encodeMultiByteRawIO Word32
_ String
"" = (LPCSTR, CInt) -> IO (LPCSTR, CInt)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (LPCSTR
forall a. Ptr a
nullPtr, CInt
0)
encodeMultiByteRawIO Word32
cp String
s = Word32
-> String
-> ((LPCSTR, CInt) -> IO (LPCSTR, CInt))
-> IO (LPCSTR, CInt)
forall a. Word32 -> String -> ((LPCSTR, CInt) -> IO a) -> IO a
encodeMultiByteIO' Word32
cp String
s (LPCSTR, CInt) -> IO (LPCSTR, CInt)
forall {m :: * -> *} {a} {b} {a}.
(Monad m, Integral a, Num b) =>
(a, a) -> m (a, b)
toSizedCString
where toSizedCString :: (a, a) -> m (a, b)
toSizedCString (a
st,a
l) = (a, b) -> m (a, b)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (a
st, a -> b
forall a b. (Integral a, Num b) => a -> b
fromIntegral a
l)
foreign import ccall "WideCharToMultiByte"
wideCharToMultiByte
:: CodePage
-> DWORD
-> LPCWSTR
-> CInt
-> LPSTR
-> CInt
-> LPCSTR
-> LPBOOL
-> IO CInt
stringToUnicode :: CodePage -> String -> IO String
stringToUnicode :: Word32 -> String -> IO String
stringToUnicode Word32
_cp String
"" = String -> IO String
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return String
""
stringToUnicode Word32
cp String
mbstr =
String -> (CStringLen -> IO String) -> IO String
forall a. String -> (CStringLen -> IO a) -> IO a
withCAStringLen String
mbstr ((CStringLen -> IO String) -> IO String)
-> (CStringLen -> IO String) -> IO String
forall a b. (a -> b) -> a -> b
$ \(LPCSTR
cstr,Int
len) -> do
wchars <- String -> IO CInt -> IO CInt
forall a. (Eq a, Num a) => String -> IO a -> IO a
failIfZero String
"MultiByteToWideChar" (IO CInt -> IO CInt) -> IO CInt -> IO CInt
forall a b. (a -> b) -> a -> b
$ Word32 -> Word32 -> LPCSTR -> CInt -> Ptr CWchar -> CInt -> IO CInt
multiByteToWideChar
Word32
cp
Word32
0
LPCSTR
cstr
(Int -> CInt
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
len)
Ptr CWchar
forall a. Ptr a
nullPtr CInt
0
allocaArray (fromIntegral wchars) $ \Ptr CWchar
cwstr -> do
wchars' <- String -> IO CInt -> IO CInt
forall a. (Eq a, Num a) => String -> IO a -> IO a
failIfZero String
"MultiByteToWideChar" (IO CInt -> IO CInt) -> IO CInt -> IO CInt
forall a b. (a -> b) -> a -> b
$ Word32 -> Word32 -> LPCSTR -> CInt -> Ptr CWchar -> CInt -> IO CInt
multiByteToWideChar
Word32
cp
Word32
0
LPCSTR
cstr
(Int -> CInt
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
len)
Ptr CWchar
cwstr CInt
wchars
peekCWStringLen (cwstr,fromIntegral wchars')
foreign import ccall unsafe "MultiByteToWideChar"
multiByteToWideChar
:: CodePage
-> DWORD
-> LPCSTR
-> CInt
-> LPWSTR
-> CInt
-> IO CInt
decodeMultiByte :: CodePage -> String -> String
decodeMultiByte :: Word32 -> String -> String
decodeMultiByte Word32
cp = IO String -> String
forall a. IO a -> a
unsafeLocalState (IO String -> String) -> (String -> IO String) -> String -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word32 -> String -> IO String
decodeMultiByteIO Word32
cp
decodeMultiByteIO :: CodePage -> String -> IO String
decodeMultiByteIO :: Word32 -> String -> IO String
decodeMultiByteIO = Word32 -> String -> IO String
stringToUnicode
{-# INLINE decodeMultiByteIO #-}
foreign import ccall unsafe "MultiByteToWideChar"
multiByteToWideChar'
:: CodePage
-> DWORD
-> Ptr Word8
-> CInt
-> Ptr Word16
-> CInt
-> IO CInt
withGhcInternalToUTF16 :: Ptr Word8 -> Int -> ((Ptr Word16, CInt) -> IO a)
-> IO a
withGhcInternalToUTF16 :: forall a. Ptr Word8 -> Int -> ((Ptr Word16, CInt) -> IO a) -> IO a
withGhcInternalToUTF16 Ptr Word8
ptr Int
len (Ptr Word16, CInt) -> IO a
fn
= do cp <- IO Word32
getCurrentCodePage
wchars <- failIfZero "withGhcInternalToUTF16" $
multiByteToWideChar' cp 0 ptr (fromIntegral len) nullPtr 0
allocaArray (fromIntegral wchars) $ \Ptr Word16
cwstr -> do
wchars' <- String -> IO CInt -> IO CInt
forall a. (Eq a, Num a) => String -> IO a -> IO a
failIfZero String
"withGhcInternalToUTF16" (IO CInt -> IO CInt) -> IO CInt -> IO CInt
forall a b. (a -> b) -> a -> b
$
Word32
-> Word32 -> Ptr Word8 -> CInt -> Ptr Word16 -> CInt -> IO CInt
multiByteToWideChar' Word32
cp Word32
0 Ptr Word8
ptr (Int -> CInt
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
len) Ptr Word16
cwstr CInt
wchars
fn (cwstr, wchars')
foreign import ccall "WideCharToMultiByte"
wideCharToMultiByte'
:: CodePage
-> DWORD
-> Ptr Word16
-> CInt
-> Ptr Word8
-> CInt
-> LPCSTR
-> LPBOOL
-> IO CInt
withUTF16ToGhcInternal :: Ptr Word8
-> Int
-> ( CInt
-> Ptr Word16
-> IO CInt
)
-> IO Int
withUTF16ToGhcInternal :: Ptr Word8 -> Int -> (CInt -> Ptr Word16 -> IO CInt) -> IO Int
withUTF16ToGhcInternal Ptr Word8
ptr Int
len CInt -> Ptr Word16 -> IO CInt
fn
= do cp <- IO Word32
getCurrentCodePage
let reqBytes = Int -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int
len Int -> Int -> Int
forall a. Integral a => a -> a -> a
`div` Int
2)
allocaArray reqBytes $ \Ptr Word16
w_ptr -> do
w_len <- CInt -> Ptr Word16 -> IO CInt
fn (Int -> CInt
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
reqBytes) Ptr Word16
w_ptr
if w_len == 0
then return 0 else do
mbchars' <- failIfZero "withUTF16ToGhcInternal" $
wideCharToMultiByte' cp 0 w_ptr
(fromIntegral w_len) nullPtr
0 nullPtr nullPtr
assert (mbchars' <= (fromIntegral len)) $ do
mbchars <- failIfZero "withUTF16ToGhcInternal" $
wideCharToMultiByte' cp 0 w_ptr
(fromIntegral w_len) ptr
mbchars' nullPtr nullPtr
return $ fromIntegral mbchars