{-# LANGUAGE CPP, MagicHash #-}
module Data.Text.Internal.Unsafe.Char
(
ord
, unsafeChr
, unsafeChr8
, unsafeChr32
, unsafeWrite
) where
#ifdef ASSERTS
import Control.Exception (assert)
#endif
import Control.Monad.ST (ST)
import Data.Bits ((.&.))
import Data.Text.Internal.Unsafe.Shift (shiftR)
import GHC.Exts (Char(..), Int(..), chr#, ord#, word2Int#)
import GHC.Word (Word8(..), Word16(..), Word32(..))
import qualified Data.Text.Array as A
ord :: Char -> Int
ord (C# c#) = I# (ord# c#)
{-# INLINE ord #-}
unsafeChr :: Word16 -> Char
unsafeChr (W16# w#) = C# (chr# (word2Int# w#))
{-# INLINE unsafeChr #-}
unsafeChr8 :: Word8 -> Char
unsafeChr8 (W8# w#) = C# (chr# (word2Int# w#))
{-# INLINE unsafeChr8 #-}
unsafeChr32 :: Word32 -> Char
unsafeChr32 (W32# w#) = C# (chr# (word2Int# w#))
{-# INLINE unsafeChr32 #-}
unsafeWrite :: A.MArray s -> Int -> Char -> ST s Int
unsafeWrite marr i c
| n < 0x80 = do
#if defined(ASSERTS)
assert (i >= 0) . assert (i < A.length marr) $ return ()
#endif
writeAt i n
return 1
| n < 0x0800 = do
#if defined(ASSERTS)
assert (i >= 0) . assert (i + 1 < A.length marr) $ return ()
#endif
writeAt i $ (n `shiftR` 6) + 0xC0
writeAt (i + 1) $ (n .&. 0x3F) + 0x80
return 2
| n < 0x10000 = do
#if defined(ASSERTS)
assert (i >= 0) . assert (i + 2 < A.length marr) $ return ()
#endif
writeAt i $ (n `shiftR` 12) + 0xE0
writeAt (i + 1) $ ((n `shiftR` 6) .&. 0x3F) + 0x80
writeAt (i + 2) $ (n .&. 0x3F) + 0x80
return 3
| otherwise = do
#if defined(ASSERTS)
assert (i >= 0) . assert (i + 3 < A.length marr) $ return ()
#endif
writeAt i $ (n `shiftR` 18) + 0xF0
writeAt (i + 1) $ ((n `shiftR` 12) .&. 0x3F) + 0x80
writeAt (i + 2) $ ((n `shiftR` 6) .&. 0x3F) + 0x80
writeAt (i + 3) $ (n .&. 0x3F) + 0x80
return 4
where
n = ord c
writeAt i' n' = A.unsafeWrite marr i' (fromIntegral n')
{-# INLINE writeAt #-}
{-# INLINE unsafeWrite #-}