content: {-# LANGUAGE BangPatterns, RankNTypes, MagicHash, UnboxedTuples #-}
  
  module T5359a (linesT) where
  
  import GHC.Base hiding (empty)
  import GHC.Word
  import GHC.ST (ST(..), runST)
  import Unsafe.Coerce( unsafeCoerce# )
  
  nullT :: Text -> Bool
  nullT (Text _ _ len) = len <= 0
  {-# INLINE [1] nullT #-}
  
  spanT :: (Char -> Bool) -> Text -> (Text, Text)
  spanT p t@(Text arr off len) = (textP arr off k, textP arr (off+k) (len-k))
    where k = loop 0
          loop !i | i >= len || not (p c) = i
                  | otherwise             = loop (i+d)
              where Iter c d              = iter t i
  {-# INLINE spanT #-}
  
  linesT :: Text -> [Text]
  linesT ps | nullT ps  = []
            | otherwise = h : if nullT t
                              then []
                              else linesT (unsafeTail t)
      where (h,t) = spanT (/= '\n') ps
  {-# INLINE linesT #-}
  
  unsafeTail :: Text -> Text
  unsafeTail t@(Text arr off len) = Text arr (off+d) (len-d)
    where d = iter_ t 0
  {-# INLINE unsafeTail #-}
  
  data Iter = Iter {-# UNPACK #-} !Char {-# UNPACK #-} !Int
  
  iter :: Text -> Int -> Iter
  iter (Text arr _ _) i = Iter (unsafeChrT m) 1
    where m = unsafeIndex arr i
  {-# INLINE iter #-}
  
  iter_ :: Text -> Int -> Int
  iter_ (Text arr off _) i | m < 0xD800 || m > 0xDBFF = 1
                           | otherwise                = 2
    where m = unsafeIndex arr (off+i)
  {-# INLINE iter_ #-}
  
  data Text = Text {-# UNPACK #-}!Array {-# UNPACK #-}!Int {-# UNPACK #-}!Int
  
  text :: Array -> Int -> Int -> Text
  text arr off len = Text arr off len
  {-# INLINE text #-}
  
  emptyT :: Text
  emptyT = Text empty 0 0
  {-# INLINE [1] emptyT #-}
  
  textP :: Array -> Int -> Int -> Text
  textP arr off len | len == 0  = emptyT
                    | otherwise = text arr off len
  {-# INLINE textP #-}
  
  unsafeChrT :: Word16 -> Char
  unsafeChrT (W16# w#) = C# (chr# (word2Int# (word16ToWord# w#)))
  {-# INLINE unsafeChrT #-}
  
  data Array = Array ByteArray#
  
  data MArray s = MArray (MutableByteArray# s)
  
  new :: forall s. Int -> ST s (MArray s)
  new n@(I# len#)
    | n < 0 || n /= 0 = error $ "Data.Text.Array.new: size overflow"
    | otherwise = ST $ \s1# ->
         case newByteArray# len# s1# of
           (# s2#, marr# #) -> (# s2#, MArray marr# #)
  {-# INLINE new #-}
  
  unsafeFreeze :: MArray s -> ST s Array
  unsafeFreeze (MArray maBA) = ST $ \s# -> (# s#, Array (unsafeCoerce# maBA) #)
  {-# INLINE unsafeFreeze #-}
  
  unsafeIndex :: Array -> Int -> Word16
  unsafeIndex (Array aBA) (I# i#) =
      case indexWord16Array# aBA i# of r# -> (W16# r#)
  {-# INLINE unsafeIndex #-}
  
  empty :: Array
  empty = runST (new 0 >>= unsafeFreeze)
  