1 {-# LANGUAGE CPP, MagicHash #-}
    2 
    3 -- |
    4 -- Module      : Data.Text.UnsafeChar
    5 -- Copyright   : (c) 2008, 2009 Tom Harper,
    6 --               (c) 2009, 2010 Bryan O'Sullivan,
    7 --               (c) 2009 Duncan Coutts
    8 --
    9 -- License     : BSD-style
   10 -- Maintainer  : bos@serpentine.com, rtomharper@googlemail.com,
   11 --               duncan@haskell.org
   12 -- Stability   : experimental
   13 -- Portability : GHC
   14 --
   15 -- Fast character manipulation functions.
   16 module Data.Text.UnsafeChar
   17     (
   18       ord
   19     , unsafeChr
   20     , unsafeChr8
   21     , unsafeChr32
   22     , unsafeWrite
   23     -- , unsafeWriteRev
   24     ) where
   25 
   26 #ifdef ASSERTS
   27 import Control.Exception (assert)
   28 #endif
   29 import Control.Monad.ST (ST)
   30 import Data.Bits ((.&.))
   31 import Data.Text.UnsafeShift (shiftR)
   32 import GHC.Exts (Char(..), Int(..), chr#, ord#, word2Int#)
   33 import GHC.Word (Word8(..), Word16(..), Word32(..))
   34 import qualified Data.Text.Array as A
   35 
   36 ord :: Char -> Int
   37 -- entered 3,457,720 timesord (C# c#) = I# (ord# c#)
   38 {-# INLINE ord #-}
   39 
   40 unsafeChr :: Word16 -> Char
   41 -- entered 8,138,513 timesunsafeChr (W16# w#) = C# (chr# (word2Int# w#))
   42 {-# INLINE unsafeChr #-}
   43 
   44 unsafeChr8 :: Word8 -> Char
   45 -- entered 3778 timesunsafeChr8 (W8# w#) = C# (chr# (word2Int# w#))
   46 {-# INLINE unsafeChr8 #-}
   47 
   48 unsafeChr32 :: Word32 -> Char
   49 -- entered 10,866 timesunsafeChr32 (W32# w#) = C# (chr# (word2Int# w#))
   50 {-# INLINE unsafeChr32 #-}
   51 
   52 -- | Write a character into the array at the given offset.  Returns
   53 -- the number of 'Word16's written.
   54 unsafeWrite :: A.MArray s -> Int -> Char -> ST s Int
   55 -- entered 2,820,735 timesunsafeWrite marr i c
   56     | n < 0x10000 = do
   57 #if defined(ASSERTS)
   58         assert (i >= 0) . assert (i < A.length marr) $ return ()
   59 #endif
   60         A.unsafeWrite marr i (fromIntegral n)
   61         return 1
   62     | otherwise = do
   63 #if defined(ASSERTS)
   64         assert (i >= 0) . assert (i < A.length marr - 1) $ return ()
   65 #endif
   66         A.unsafeWrite marr i lo
   67         A.unsafeWrite marr (i+1) hi
   68         return 2
   69     where n = ord c
   70           m = n - 0x10000
   71           lo = fromIntegral $ (m `shiftR` 10) + 0xD800
   72           hi = fromIntegral $ (m .&. 0x3FF) + 0xDC00
   73 {-# INLINE unsafeWrite #-}
   74 
   75 {-
   76 unsafeWriteRev :: A.MArray s Word16 -> Int -> Char -> ST s Int
   77 unsafeWriteRev marr i c
   78     | n < 0x10000 = do
   79         assert (i >= 0) . assert (i < A.length marr) $
   80           A.unsafeWrite marr i (fromIntegral n)
   81         return (i-1)
   82     | otherwise = do
   83         assert (i >= 1) . assert (i < A.length marr) $
   84           A.unsafeWrite marr (i-1) lo
   85         A.unsafeWrite marr i hi
   86         return (i-2)
   87     where n = ord c
   88           m = n - 0x10000
   89           lo = fromIntegral $ (m `shiftR` 10) + 0xD800
   90           hi = fromIntegral $ (m .&. 0x3FF) + 0xDC00
   91 {-# INLINE unsafeWriteRev #-}
   92 -}