streaming-commons-0.2.2.2: Data/Text/Internal/Unsafe/Char.hs
{-# LANGUAGE CPP, MagicHash #-}
-- |
-- Module : Data.Text.Internal.Unsafe.Char
-- Copyright : (c) 2008, 2009 Tom Harper,
-- (c) 2009, 2010 Bryan O'Sullivan,
-- (c) 2009 Duncan Coutts
--
-- License : BSD-style
-- Maintainer : bos@serpentine.com
-- Stability : experimental
-- Portability : GHC
--
-- /Warning/: this is an internal module, and does not have a stable
-- API or name. Functions in this module may not check or enforce
-- preconditions expected by public modules. Use at your own risk!
--
-- Fast character manipulation functions.
module Data.Text.Internal.Unsafe.Char
(
ord
, unsafeChr
, unsafeChr8
, unsafeChr32
, unsafeWrite
-- , unsafeWriteRev
) 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(..), Word#, chr#, ord#, word2Int#)
import GHC.Word (Word8(..), Word16(..), Word32(..))
import qualified Data.Text.Array as A
#if MIN_VERSION_base(4,16,0)
import GHC.Exts (Word8#, Word16#, Word32#, word8ToWord#, word16ToWord#, word32ToWord#)
#endif
ord :: Char -> Int
ord (C# c#) = I# (ord# c#)
{-# INLINE ord #-}
unsafeChr :: Word16 -> Char
unsafeChr (W16# w#) = C# (chr# (word2Int# (word16ToWordCompat# w#)))
{-# INLINE unsafeChr #-}
unsafeChr8 :: Word8 -> Char
unsafeChr8 (W8# w#) = C# (chr# (word2Int# (word8ToWordCompat# w#)))
{-# INLINE unsafeChr8 #-}
unsafeChr32 :: Word32 -> Char
unsafeChr32 (W32# w#) = C# (chr# (word2Int# (word32ToWordCompat# w#)))
{-# INLINE unsafeChr32 #-}
-- | Write a character into the array at the given offset. Returns
-- the number of 'Word16's written.
unsafeWrite :: A.MArray s -> Int -> Char -> ST s Int
unsafeWrite marr i c
| n < 0x10000 = do
#if defined(ASSERTS)
assert (i >= 0) . assert (i < A.length marr) $ return ()
#endif
A.unsafeWrite marr i (fromIntegral n)
return 1
| otherwise = do
#if defined(ASSERTS)
assert (i >= 0) . assert (i < A.length marr - 1) $ return ()
#endif
A.unsafeWrite marr i lo
A.unsafeWrite marr (i+1) hi
return 2
where n = ord c
m = n - 0x10000
lo = fromIntegral $ (m `shiftR` 10) + 0xD800
hi = fromIntegral $ (m .&. 0x3FF) + 0xDC00
{-# INLINE unsafeWrite #-}
{-
unsafeWriteRev :: A.MArray s Word16 -> Int -> Char -> ST s Int
unsafeWriteRev marr i c
| n < 0x10000 = do
assert (i >= 0) . assert (i < A.length marr) $
A.unsafeWrite marr i (fromIntegral n)
return (i-1)
| otherwise = do
assert (i >= 1) . assert (i < A.length marr) $
A.unsafeWrite marr (i-1) lo
A.unsafeWrite marr i hi
return (i-2)
where n = ord c
m = n - 0x10000
lo = fromIntegral $ (m `shiftR` 10) + 0xD800
hi = fromIntegral $ (m .&. 0x3FF) + 0xDC00
{-# INLINE unsafeWriteRev #-}
-}
#if MIN_VERSION_base(4,16,0)
word8ToWordCompat# :: Word8# -> Word#
word8ToWordCompat# = word8ToWord#
word16ToWordCompat# :: Word16# -> Word#
word16ToWordCompat# = word16ToWord#
word32ToWordCompat# :: Word32# -> Word#
word32ToWordCompat# = word32ToWord#
#else
word8ToWordCompat# :: Word# -> Word#
word8ToWordCompat# x = x
word16ToWordCompat# :: Word# -> Word#
word16ToWordCompat# x = x
word32ToWordCompat# :: Word# -> Word#
word32ToWordCompat# x = x
#endif