@@ -19,14 +19,10 @@ module Data.Text.Fusion
19 -- * Types
19 -- * Types
20 Stream(..)
20 Stream(..)
21 , Step(..)
21 , Step(..)
24 -- * Creation and elimination
23 -- * Creation and elimination
26 , unstream
25 , unstream
31 -- * Basic interface
27 -- * Basic interface
@@ -90,33 +86,22 @@ import Prelude hiding
90 foldl1, foldr1, concatMap, any, all, maximum, minimum, take, drop,
86 foldl1, foldr1, concatMap, any, all, maximum, minimum, take, drop,
91 takeWhile, dropWhile, elem, zipWith)
87 takeWhile, dropWhile, elem, zipWith)
92import Data.Char (ord)
88import Data.Char (ord)
93−import Control.Exception (assert)
94import Control.Monad (liftM2)
89import Control.Monad (liftM2)
95import Control.Monad.ST (runST, ST)
90import Control.Monad.ST (runST, ST)
96−import Data.Bits (shiftL, shiftR, (.&.))
91+import Data.Bits (shiftR, (.&.))
97−import qualified Data.ByteString as B
98−import qualified Data.ByteString.Unsafe as B
99−import Data.ByteString.Internal (ByteString(..), mallocByteString, memcpy)
100import qualified Data.List as L
92import qualified Data.List as L
101−import Data.Word (Word8, Word16, Word32)
93+import Data.Word (Word16)
102−import Foreign.ForeignPtr (withForeignPtr, ForeignPtr)
103−import Foreign.Storable (pokeByteOff)
104import GHC.Exts (Int(..), (+#))
94import GHC.Exts (Int(..), (+#))
105−import System.IO.Unsafe (unsafePerformIO)
106import Data.Text.Internal (Text(..), empty)
95import Data.Text.Internal (Text(..), empty)
107−import Data.Text.UnsafeChar (unsafeChr, unsafeChr8, unsafeChr32)
96+import Data.Text.UnsafeChar (unsafeChr)
108import qualified Data.Text.Array as A
97import qualified Data.Text.Array as A
109−import qualified Data.Text.Utf8 as U8
110import qualified Data.Text.Utf16 as U16
98import qualified Data.Text.Utf16 as U16
111−import qualified Data.Text.Utf32 as U32
113default(Int)
100default(Int)
115infixl 2 :!:
102infixl 2 :!:
116data PairS a b = !a :!: !b
103data PairS a b = !a :!: !b
118−data T4 a b c d = T4 !a !b !c !d
120data Switch = S1 | S2
105data Switch = S1 | S2
122data Stream a = forall s. Stream (s -> Step s a) !s {-# UNPACK #-}!Int
107data Stream a = forall s. Stream (s -> Step s a) !s {-# UNPACK #-}!Int
@@ -125,9 +110,6 @@ data Step s a = Done
125 | Skip !s
110 | Skip !s
126 | Yield !a !s
111 | Yield !a !s
128−data Encoding = ASCII | Utf8 | Utf16BE | Utf16LE | Utf32BE | Utf32LE
129− deriving (Read, Show, Eq)
131-- | /O(n)/ Convert a Text into a Stream Char.
113-- | /O(n)/ Convert a Text into a Stream Char.
132stream :: Text -> Stream Char
114stream :: Text -> Stream Char
133stream (Text arr off len) = Stream next off len
115stream (Text arr off len) = Stream next off len
@@ -176,6 +158,7 @@ unstream (Stream next0 s0 len) = Text (fst a) 0 (snd a)
176 r :: Word16
158 r :: Word16
177 r = fromIntegral $ (m .&. (0x3FF :: Int)) + (0xDC00 :: Int)
159 r = fromIntegral $ (m .&. (0x3FF :: Int)) + (0xDC00 :: Int)
178{-# INLINE [0] unstream #-}
160{-# INLINE [0] unstream #-}
161+{-# RULES "STREAM stream/unstream fusion" forall s. stream (unstream s) = s #-}
181copy :: A.MArray s Word16 -> A.MArray s Word16 -> ST s ()
164copy :: A.MArray s Word16 -> A.MArray s Word16 -> ST s ()
@@ -201,247 +184,9 @@ eq (Stream next1 s1 _) (Stream next2 s2 _) = cmp (next1 s1) (next2 s2)
201 cmp (next1 s1') (next2 s2')
184 cmp (next1 s1') (next2 s2')
202{-# SPECIALISE eq :: Stream Char -> Stream Char -> Bool #-}
185{-# SPECIALISE eq :: Stream Char -> Stream Char -> Bool #-}
204−-- | /O(n) Convert a ByteString into a Stream Char, using the specified encoding standard.
205−stream_bs :: Encoding -> ByteString -> Stream Char
206−stream_bs ASCII bs = Stream next 0 l
212− | otherwise = Yield (unsafeChr8 x1) (i+1)
214− x1 = B.unsafeIndex bs i
215−stream_bs Utf8 bs = Stream next 0 l
221− | U8.validate1 x1 = Yield (unsafeChr8 x1) (i+1)
222− | i+1 < l && U8.validate2 x1 x2 = Yield (U8.chr2 x1 x2) (i+2)
223− | i+2 < l && U8.validate3 x1 x2 x3 = Yield (U8.chr3 x1 x2 x3) (i+3)
224− | i+3 < l && U8.validate4 x1 x2 x3 x4 = Yield (U8.chr4 x1 x2 x3 x4) (i+4)
225− | otherwise = error "bsStream: bad UTF-8 stream"
231− idx = B.unsafeIndex bs
232−stream_bs Utf16LE bs = Stream next 0 l
238− | i+1 < l && U16.validate1 x1 = Yield (unsafeChr x1) (i+2)
239− | i+3 < l && U16.validate2 x1 x2 = Yield (U16.chr2 x1 x2) (i+4)
240− | otherwise = error $ "bsStream: bad UTF-16LE stream"
242− x1 = (shiftL (idx (i + 1)) 8) + (idx i)
243− x2 = (shiftL (idx (i + 3)) 8) + (idx (i + 2))
244− idx = fromIntegral . B.unsafeIndex bs :: Int -> Word16
245−stream_bs Utf16BE bs = Stream next 0 l
251− | i+1 < l && U16.validate1 x1 = Yield (unsafeChr x1) (i+2)
252− | i+3 < l && U16.validate2 x1 x2 = Yield (U16.chr2 x1 x2) (i+4)
253− | otherwise = error $ "bsStream: bad UTF16-BE stream "
255− x1 = (shiftL (idx i) 8) + (idx (i + 1))
256− x2 = (shiftL (idx (i + 2)) 8) + (idx (i + 3))
257− idx = fromIntegral . B.unsafeIndex bs :: Int -> Word16
258−stream_bs Utf32BE bs = Stream next 0 l
264− | i+3 < l && U32.validate x = Yield (unsafeChr32 x) (i+4)
265− | otherwise = error "bsStream: bad UTF-32BE stream"
267− x = shiftL x1 24 + shiftL x2 16 + shiftL x3 8 + x4
272− idx = fromIntegral . B.unsafeIndex bs :: Int -> Word32
273−stream_bs Utf32LE bs = Stream next 0 l
279− | i+3 < l && U32.validate x = Yield (unsafeChr32 x) (i+4)
280− | otherwise = error "bsStream: bad UTF-32LE stream"
282− x = shiftL x4 24 + shiftL x3 16 + shiftL x2 8 + x1
287− idx = fromIntegral . B.unsafeIndex bs :: Int -> Word32
288−{-# INLINE [0] stream_bs #-}
290internalError :: String -> a
187internalError :: String -> a
291internalError func = error $ "Data.Text.Fusion." ++ func ++ ": internal error"
188internalError func = error $ "Data.Text.Fusion." ++ func ++ ": internal error"
293−-- | /O(n)/ Convert a Stream Char into a Stream Word8 using the specified encoding standard.
294−restream :: Encoding -> Stream Char -> Stream Word8
295−restream ASCII (Stream next0 s0 len) = Stream next s0 (len*2)
297− next !s = case next0 s of
300− Yield x xs -> Yield x' xs
301− where x' = fromIntegral (ord x) :: Word8
302−restream Utf8 (Stream next0 s0 len) =
303− Stream next (T4 (Just s0) Nothing Nothing Nothing) (len*2)
306− next (T4 (Just s) Nothing Nothing Nothing) = case next0 s of
308− Skip s' -> Skip (T4 (Just s') Nothing Nothing Nothing)
310− | n <= 0x7F -> Yield c (T4 (Just xs) Nothing Nothing Nothing)
311− | n <= 0x07FF -> Yield (fst c2) (T4 (Just xs) (Just $ snd c2) Nothing Nothing)
312− | n <= 0xFFFF -> Yield (fst3 c3) (T4 (Just xs) (Just $ snd3 c3) (Just $ trd3 c3) Nothing)
313− | otherwise -> Yield (fst4 c4) (T4 (Just xs) (Just $ snd4 c4) (Just $ trd4 c4) (Just $ fth4 c4))
323− fst4 (x1,_,_,_) = x1
324− snd4 (_,x2,_,_) = x2
325− trd4 (_,_,x3,_) = x3
326− fth4 (_,_,_,x4) = x4
327− next (T4 (Just s) (Just x2) Nothing Nothing) = Yield x2 (T4 (Just s) Nothing Nothing Nothing)
328− next (T4 (Just s) (Just x2) x3 Nothing) = Yield x2 (T4 (Just s) x3 Nothing Nothing)
329− next (T4 (Just s) (Just x2) x3 x4) = Yield x2 (T4 (Just s) x3 x4 Nothing)
330− next _ = internalError "restream Utf8"
331−restream Utf16BE (Stream next0 s0 len) =
332− Stream next (T4 (Just s0) Nothing Nothing Nothing) (len*2)
335− next (T4 (Just s) Nothing Nothing Nothing) = case next0 s of
337− Skip s' -> Skip (T4 (Just s') Nothing Nothing Nothing)
339− | n < 0x10000 -> Yield (fromIntegral $ shiftR n 8) (T4 (Just xs) (Just (fromIntegral n)) Nothing Nothing)
340− | otherwise -> Yield c1 (T4 (Just xs) (Just c2) (Just c3) (Just c4))
344− c1 = fromIntegral (shiftR n1 18 + 0xD8)
345− c2 = fromIntegral (shiftR n1 10)
347− c3 = fromIntegral (shiftR n2 8 + 0xDC)
348− c4 = fromIntegral n2
349− next (T4 (Just s) (Just x2) Nothing Nothing) = Yield x2 (T4 (Just s) Nothing Nothing Nothing)
350− next (T4 (Just s) (Just x2) x3 Nothing) = Yield x2 (T4 (Just s) x3 Nothing Nothing)
351− next (T4 (Just s) (Just x2) x3 x4) = Yield x2 (T4 (Just s) x3 x4 Nothing)
352− next _ = internalError "restream Utf16BE"
353−restream Utf16LE (Stream next0 s0 len) =
354− Stream next (T4 (Just s0) Nothing Nothing Nothing) (len*2)
357− next (T4 (Just s) Nothing Nothing Nothing) = case next0 s of
359− Skip s' -> Skip (T4 (Just s') Nothing Nothing Nothing)
361− | n < 0x10000 -> Yield (fromIntegral n) (T4 (Just xs) (Just (fromIntegral $ shiftR n 8)) Nothing Nothing)
362− | otherwise -> Yield c1 (T4 (Just xs) (Just c2) (Just c3) (Just c4))
366− c2 = fromIntegral (shiftR n1 18 + 0xD8)
367− c1 = fromIntegral (shiftR n1 10)
369− c4 = fromIntegral (shiftR n2 8 + 0xDC)
370− c3 = fromIntegral n2
371− next (T4 (Just s) (Just x2) Nothing Nothing) = Yield x2 (T4 (Just s) Nothing Nothing Nothing)
372− next (T4 (Just s) (Just x2) x3 Nothing) = Yield x2 (T4 (Just s) x3 Nothing Nothing)
373− next (T4 (Just s) (Just x2) x3 x4) = Yield x2 (T4 (Just s) x3 x4 Nothing)
374− next _ = internalError "restream Utf16LE"
375−restream Utf32BE (Stream next0 s0 len) =
376− Stream next (T4 (Just s0) Nothing Nothing Nothing) (len*2)
379− next (T4 (Just s) Nothing Nothing Nothing) = case next0 s of
381− Skip s' -> Skip (T4 (Just s') Nothing Nothing Nothing)
382− Yield x xs -> Yield c1 (T4 (Just xs) (Just c2) (Just c3) (Just c4))
385− c1 = fromIntegral $ shiftR n 24
386− c2 = fromIntegral $ shiftR n 16
387− c3 = fromIntegral $ shiftR n 8
389− next (T4 (Just s) (Just x2) Nothing Nothing) = Yield x2 (T4 (Just s) Nothing Nothing Nothing)
390− next (T4 (Just s) (Just x2) x3 Nothing) = Yield x2 (T4 (Just s) x3 Nothing Nothing)
391− next (T4 (Just s) (Just x2) x3 x4) = Yield x2 (T4 (Just s) x3 x4 Nothing)
392− next _ = internalError "restream Utf32BE"
393−restream Utf32LE (Stream next0 s0 len) =
394− Stream next (T4 (Just s0) Nothing Nothing Nothing) (len*2)
397− next (T4 (Just s) Nothing Nothing Nothing) = case next0 s of
399− Skip s' -> Skip (T4 (Just s') Nothing Nothing Nothing)
400− Yield x xs -> Yield c1 (T4 (Just xs) (Just c2) (Just c3) (Just c4))
403− c4 = fromIntegral $ shiftR n 24
404− c3 = fromIntegral $ shiftR n 16
405− c2 = fromIntegral $ shiftR n 8
407− next (T4 (Just s) (Just x2) Nothing Nothing) = Yield x2 (T4 (Just s) Nothing Nothing Nothing)
408− next (T4 (Just s) (Just x2) x3 Nothing) = Yield x2 (T4 (Just s) x3 Nothing Nothing)
409− next (T4 (Just s) (Just x2) x3 x4) = Yield x2 (T4 (Just s) x3 x4 Nothing)
410− next _ = internalError "restream Utf32LE"
411−{-# INLINE restream #-}
414−-- | /O(n)/ Convert a Stream Word8 to a ByteString
415−unstream_bs :: Stream Word8 -> ByteString
416−unstream_bs (Stream next s0 len) = unsafePerformIO $ do
417− fp0 <- mallocByteString len
420− loop !fp !n !off !s = case next s of
421− Done -> trimUp fp n off
422− Skip s' -> loop fp n off s'
424− | n == off -> realloc fp n off s' x
426− withForeignPtr fp $ \p -> pokeByteOff p off x
427− loop fp n (off+1) s'
428− {-# NOINLINE realloc #-}
429− realloc fp n off s x = do
431− fp' <- copy0 fp n n'
432− withForeignPtr fp' $ \p -> pokeByteOff p off x
433− loop fp' n' (off+1) s
434− {-# NOINLINE trimUp #-}
435− trimUp fp _ off = return $! PS fp 0 off
436− copy0 :: ForeignPtr Word8 -> Int -> Int -> IO (ForeignPtr Word8)
437− copy0 !src !srcLen !destLen = assert (srcLen <= destLen) $ do
438− dest <- mallocByteString destLen
439− withForeignPtr src $ \src' ->
440− withForeignPtr dest $ \dest' ->
441− memcpy dest' src' (fromIntegral destLen)
443−{-# RULES "STREAM stream/unstream fusion" forall s. stream (unstream s) = s #-}
445-- ----------------------------------------------------------------------------
190-- ----------------------------------------------------------------------------
446-- * Basic stream functions
191-- * Basic stream functions