module Data.Text.Lazy.Fusion
(
stream
, unstream
, unstreamChunks
, length
, unfoldrN
, index
, countChar
) where
import Prelude hiding (length)
import qualified Data.Text.Fusion.Common as S
import Data.Text.Fusion.Internal
import Data.Text.Fusion.Size (isEmpty)
import Data.Text.Lazy.Internal
import qualified Data.Text.Internal as I
import qualified Data.Text.Array as A
import Data.Text.UnsafeChar (unsafeWrite)
import Data.Text.Unsafe (iter)
import Data.Int (Int64)
default(Int64)
stream :: Text -> Stream Char
stream text = Stream next (text :*: 0) 4
where
next (Empty :*: _) = Done
next (txt@(Chunk t@(I.Text _ _ len) ts) :*: i)
| i >= len = next (ts :*: 0)
| otherwise = Yield c (txt :*: i+d)
where (c,d) = iter t i
unstreamChunks :: Int -> Stream Char -> Text
unstreamChunks chunkSize (Stream next s0 len0)
| isEmpty len0 = Empty
| otherwise = outer s0
where
outer s = case next s of
Done -> Empty
Skip s' -> outer s'
Yield x s' -> I.Text arr 0 len `chunk` outer s''
where (arr,(s'',len)) = A.run2 fill
fill = do a <- A.unsafeNew unknownLength
i <- unsafeWrite a 0 x
inner a unknownLength s' i
unknownLength = 4
inner marr len s i
| i + 1 >= chunkSize = return (marr, (s,i))
| i + 1 >= len = do
let newLen = min (len * 2) chunkSize
marr' <- A.unsafeNew newLen
A.copy marr marr'
inner marr' newLen s i
| otherwise =
case next s of
Done -> return (marr,(s,i))
Skip s' -> inner marr len s' i
Yield x s' -> unsafeWrite marr i x >>= inner marr len s'
unstream :: Stream Char -> Text
unstream = unstreamChunks defaultChunkSize
length :: Stream Char -> Int64
length = S.lengthI
unfoldrN :: Int64 -> (a -> Maybe (Char,a)) -> a -> Stream Char
unfoldrN n = S.unfoldrNI n
index :: Stream Char -> Int64 -> Char
index = S.indexI
countChar :: Char -> Stream Char -> Int64
countChar = S.countCharI