module Data.Text.Unsafe
(
inlineInterleaveST
, inlinePerformIO
, unsafeDupablePerformIO
, Iter(..)
, iter
, iterArray
, iter_
, reverseIter
, reverseIterArray
, reverseIter_
, unsafeHead
, unsafeTail
, lengthWord8
, takeWord8
, dropWord8
) where
#if defined(ASSERTS)
import Control.Exception (assert)
import GHC.Stack (HasCallStack)
#endif
import Data.Text.Internal.Encoding.Utf8 (chr2, chr3, chr4, utf8LengthByLeader)
import Data.Text.Internal (Text(..))
import Data.Text.Internal.Unsafe (inlineInterleaveST, inlinePerformIO)
import Data.Text.Internal.Unsafe.Char (unsafeChr8)
import qualified Data.Text.Array as A
import GHC.IO (unsafeDupablePerformIO)
unsafeHead :: Text -> Char
unsafeHead (Text arr off _len) = case utf8LengthByLeader m0 of
1 -> unsafeChr8 m0
2 -> chr2 m0 m1
3 -> chr3 m0 m1 m2
_ -> chr4 m0 m1 m2 m3
where m0 = A.unsafeIndex arr off
m1 = A.unsafeIndex arr (off+1)
m2 = A.unsafeIndex arr (off+2)
m3 = A.unsafeIndex arr (off+3)
unsafeTail :: Text -> Text
unsafeTail t@(Text arr off len) =
#if defined(ASSERTS)
assert (d <= len) $
#endif
Text arr (off+d) (lend)
where d = iter_ t 0
data Iter = Iter !Char !Int
deriving (Show)
iter ::
#if defined(ASSERTS)
HasCallStack =>
#endif
Text -> Int -> Iter
iter (Text arr off _len) i = iterArray arr (off + i)
iterArray :: A.Array -> Int -> Iter
iterArray arr j = Iter chr l
where m0 = A.unsafeIndex arr j
m1 = A.unsafeIndex arr (j+1)
m2 = A.unsafeIndex arr (j+2)
m3 = A.unsafeIndex arr (j+3)
l = utf8LengthByLeader m0
chr = case l of
1 -> unsafeChr8 m0
2 -> chr2 m0 m1
3 -> chr3 m0 m1 m2
_ -> chr4 m0 m1 m2 m3
iter_ :: Text -> Int -> Int
iter_ (Text arr off _len) i = utf8LengthByLeader m
where m = A.unsafeIndex arr (off+i)
reverseIter :: Text -> Int -> Iter
reverseIter (Text arr off _len) i = reverseIterArray arr (off + i)
reverseIterArray :: A.Array -> Int -> Iter
reverseIterArray arr j
| m0 < 0x80 = Iter (unsafeChr8 m0) (1)
| m1 >= 0xC0 = Iter (chr2 m1 m0) (2)
| m2 >= 0xC0 = Iter (chr3 m2 m1 m0) (3)
| otherwise = Iter (chr4 m3 m2 m1 m0) (4)
where m0 = A.unsafeIndex arr j
m1 = A.unsafeIndex arr (j1)
m2 = A.unsafeIndex arr (j2)
m3 = A.unsafeIndex arr (j3)
reverseIter_ :: Text -> Int -> Int
reverseIter_ (Text arr off _len) i
| m0 < 0x80 = 1
| m1 >= 0xC0 = 2
| m2 >= 0xC0 = 3
| otherwise = 4
where m0 = A.unsafeIndex arr j
m1 = A.unsafeIndex arr (j1)
m2 = A.unsafeIndex arr (j2)
j = off + i
lengthWord8 :: Text -> Int
lengthWord8 (Text _arr _off len) = len
takeWord8 :: Int -> Text -> Text
takeWord8 k (Text arr off _len) = Text arr off k
dropWord8 :: Int -> Text -> Text
dropWord8 k (Text arr off len) = Text arr (off+k) (lenk)