Source

text / Data / Text / Unsafe.hs

Bryan O'Sullivan d1b28de 
Bryan O'Sullivan dcc1207 

Bryan O'Sullivan ed3a60e 
Bryan O'Sullivan dcc1207 
Bryan O'Sullivan 7dfeb13 
Bryan O'Sullivan 9adb5ed 
Bryan O'Sullivan dcc1207 

Bryan O'Sullivan 2f4bcde 
Bryan O'Sullivan dcc1207 



Bryan O'Sullivan 181d5b4 

tibbe c998ce4 
Bryan O'Sullivan 18eead3 
Bryan O'Sullivan d1b28de 
Bryan O'Sullivan dcc1207 
Bryan O'Sullivan 235dbc6 
Bryan O'Sullivan dcc1207 

Bryan O'Sullivan 8743c42 
Bryan O'Sullivan 6937a20 

Bryan O'Sullivan dcc1207 
Bryan O'Sullivan 4d31ea8 
Bryan O'Sullivan c6bb1bb 
Bryan O'Sullivan dcc1207 
Bryan O'Sullivan c6bb1bb 
Bryan O'Sullivan 181d5b4 
Bryan O'Sullivan dcc1207 
Bryan O'Sullivan ed3a60e 
Bryan O'Sullivan dcc1207 

tibbe c998ce4 




Bryan O'Sullivan dcc1207 




Bryan O'Sullivan c6bb1bb 
Bryan O'Sullivan dcc1207 

Bryan O'Sullivan c6bb1bb 

Bryan O'Sullivan dcc1207 

staffehn e17fba9 
Bryan O'Sullivan dcc1207 



Bryan O'Sullivan c6bb1bb 



Bryan O'Sullivan dcc1207 


Bryan O'Sullivan 18eead3 

Bryan O'Sullivan c6bb1bb 


Bryan O'Sullivan 18eead3 
Bryan O'Sullivan c6bb1bb 
Bryan O'Sullivan 18eead3 

Bryan O'Sullivan c6bb1bb 



Bryan O'Sullivan dcc1207 




Bryan O'Sullivan c6bb1bb 


Bryan O'Sullivan dcc1207 
Bryan O'Sullivan 235dbc6 




Bryan O'Sullivan c6bb1bb 
Bryan O'Sullivan 235dbc6 

Bryan O'Sullivan c6bb1bb 



Bryan O'Sullivan 235dbc6 
Bryan O'Sullivan d1b28de 
Bryan O'Sullivan 8743c42 





Bryan O'Sullivan 6937a20 








{-# LANGUAGE CPP, MagicHash, UnboxedTuples #-}
-- |
-- Module      : Data.Text.Unsafe
-- Copyright   : (c) 2009, 2010, 2011 Bryan O'Sullivan
-- License     : BSD-style
-- Maintainer  : bos@serpentine.com, rtomharper@googlemail.com,
--               duncan@haskell.org
-- Stability   : experimental
-- Portability : portable
--
-- A module containing unsafe 'Text' operations, for very very careful
-- use in heavily tested code.
module Data.Text.Unsafe
    (
      inlineInterleaveST
    , inlinePerformIO
    , unsafeDupablePerformIO
    , Iter(..)
    , iter
    , iter_
    , reverseIter
    , unsafeHead
    , unsafeTail
    , lengthWord16
    , takeWord16
    , dropWord16
    ) where

#if defined(ASSERTS)
import Control.Exception (assert)
#endif
import Data.Text.Encoding.Utf16 (chr2)
import Data.Text.Internal (Text(..))
import Data.Text.Unsafe.Base (inlineInterleaveST, inlinePerformIO)
import Data.Text.UnsafeChar (unsafeChr)
import qualified Data.Text.Array as A
#if __GLASGOW_HASKELL__ >= 611
import GHC.IO (unsafeDupablePerformIO)
#else
import GHC.IOBase (unsafeDupablePerformIO)
#endif

-- | /O(1)/ A variant of 'head' for non-empty 'Text'. 'unsafeHead'
-- omits the check for the empty case, so there is an obligation on
-- the programmer to provide a proof that the 'Text' is non-empty.
unsafeHead :: Text -> Char
unsafeHead (Text arr off _len)
    | m < 0xD800 || m > 0xDBFF = unsafeChr m
    | otherwise                = chr2 m n
    where m = A.unsafeIndex arr off
          n = A.unsafeIndex arr (off+1)
{-# INLINE unsafeHead #-}

-- | /O(1)/ A variant of 'tail' for non-empty 'Text'. 'unsafeTail'
-- omits the check for the empty case, so there is an obligation on
-- the programmer to provide a proof that the 'Text' is non-empty.
unsafeTail :: Text -> Text
unsafeTail t@(Text arr off len) =
#if defined(ASSERTS)
    assert (d <= len) $
#endif
    Text arr (off+d) (len-d)
  where d = iter_ t 0
{-# INLINE unsafeTail #-}

data Iter = Iter {-# UNPACK #-} !Char {-# UNPACK #-} !Int

-- | /O(1)/ Iterate (unsafely) one step forwards through a UTF-16
-- array, returning the current character and the delta to add to give
-- the next offset to iterate at.
iter :: Text -> Int -> Iter
iter (Text arr off _len) i
    | m < 0xD800 || m > 0xDBFF = Iter (unsafeChr m) 1
    | otherwise                = Iter (chr2 m n) 2
  where m = A.unsafeIndex arr j
        n = A.unsafeIndex arr k
        j = off + i
        k = j + 1
{-# INLINE iter #-}

-- | /O(1)/ Iterate one step through a UTF-16 array, returning the
-- delta to add to give the next offset to iterate at.
iter_ :: Text -> Int -> Int
iter_ (Text arr off _len) i | m < 0xD800 || m > 0xDBFF = 1
                            | otherwise                = 2
  where m = A.unsafeIndex arr (off+i)
{-# INLINE iter_ #-}

-- | /O(1)/ Iterate one step backwards through a UTF-16 array,
-- returning the current character and the delta to add (i.e. a
-- negative number) to give the next offset to iterate at.
reverseIter :: Text -> Int -> (Char,Int)
reverseIter (Text arr off _len) i
    | m < 0xDC00 || m > 0xDFFF = (unsafeChr m, -1)
    | otherwise                = (chr2 n m,    -2)
  where m = A.unsafeIndex arr j
        n = A.unsafeIndex arr k
        j = off + i
        k = j - 1
{-# INLINE reverseIter #-}

-- | /O(1)/ Return the length of a 'Text' in units of 'Word16'.  This
-- is useful for sizing a target array appropriately before using
-- 'unsafeCopyToPtr'.
lengthWord16 :: Text -> Int
lengthWord16 (Text _arr _off len) = len
{-# INLINE lengthWord16 #-}

-- | /O(1)/ Unchecked take of 'k' 'Word16's from the front of a 'Text'.
takeWord16 :: Int -> Text -> Text
takeWord16 k (Text arr off _len) = Text arr off k
{-# INLINE takeWord16 #-}

-- | /O(1)/ Unchecked drop of 'k' 'Word16's from the front of a 'Text'.
dropWord16 :: Int -> Text -> Text
dropWord16 k (Text arr off len) = Text arr (off+k) (len-k)
{-# INLINE dropWord16 #-}