unwitch-1.0.0: src/Unwitch/Convert/Char.hs
module Unwitch.Convert.Char
( toInt
, toWord
, fromInt
, fromWord
, fromInt#
, fromWord#
)
where
import Data.Char (ord, chr)
import GHC.Exts (Int(..), Word(..), Char(..), chr#,
word2Int#, (>=#), (<=#), leWord#, gtWord#)
-- | Converts a Char to its Unicode codepoint as Int. Infallible.
toInt :: Char -> Int
toInt = ord
-- | Converts a Char to its Unicode codepoint as Word. Infallible.
toWord :: Char -> Word
toWord = fromIntegral . ord
-- | Converts an Int to a Char if it is a valid Unicode codepoint.
-- Valid range: 0..0xD7FF and 0xE000..0x10FFFF (excludes surrogates).
fromInt :: Int -> Maybe Char
fromInt i = if isValidCodepoint (fromIntegral i)
then Just $ chr i
else Nothing
-- | Unboxed variant of 'fromInt'. Checks valid Unicode codepoint range.
fromInt# :: Int -> (# Char | (# #) #)
fromInt# (I# i#) = case i# >=# 0# of
1# -> case i# <=# 0xD7FF# of
1# -> (# C# (chr# i#) | #)
_ -> case i# >=# 0xE000# of
1# -> case i# <=# 0x10FFFF# of
1# -> (# C# (chr# i#) | #)
_ -> (# | (# #) #)
_ -> (# | (# #) #)
_ -> (# | (# #) #)
-- | Converts a Word to a Char if it is a valid Unicode codepoint.
-- Valid range: 0..0xD7FF and 0xE000..0x10FFFF (excludes surrogates).
fromWord :: Word -> Maybe Char
fromWord w = if isValidCodepoint (fromIntegral w)
then Just $ chr (fromIntegral w)
else Nothing
-- | Unboxed variant of 'fromWord'. Checks valid Unicode codepoint range.
fromWord# :: Word -> (# Char | (# #) #)
fromWord# (W# w#) = case leWord# w# 0xD7FF## of
1# -> (# C# (chr# (word2Int# w#)) | #)
_ -> case gtWord# w# 0xDFFF## of
1# -> case leWord# w# 0x10FFFF## of
1# -> (# C# (chr# (word2Int# w#)) | #)
_ -> (# | (# #) #)
_ -> (# | (# #) #)
isValidCodepoint :: Integer -> Bool
isValidCodepoint cp =
(cp >= 0 && cp <= 0xD7FF) || (cp >= 0xE000 && cp <= 0x10FFFF)