@@ -0,0 +1,887 @@
1+{-# OPTIONS_GHC -fglasgow-exts #-}
2+{-# LANGUAGE BangPatterns #-}
4+module Text.Fusion where
6+import Prelude hiding (map, tail, head, foldr, filter,concat)
9+import Control.Exception(assert)
10+import Control.Monad(liftM2)
11+import Control.Monad.ST(runST,ST(..))
12+import Data.Array.Base
14+import qualified Data.ByteString as B
15+import Data.ByteString.Internal(ByteString(..),mallocByteString,memcpy)
16+import qualified Data.List as L
17+import Data.Word(Word8(..),Word16(..),Word32(..))
18+import Foreign.ForeignPtr(withForeignPtr,ForeignPtr(..))
19+import Foreign.Storable(pokeByteOff)
21+import System.IO.Unsafe(unsafePerformIO)
23+import Text.Internal(Text(..),empty)
24+import Text.UnsafeChar(unsafeChr,unsafeChr8,unsafeChr32)
25+import qualified Text.Utf8 as U8
26+import qualified Text.Utf16 as U16
27+import qualified Text.Utf32 as U32
32+data PairS a b = !a :!: !b
36+data EitherS a b = LeftS !a | RightS !b
38+data Stream a = forall s. Stream (s -> Step s a) !s {-# UNPACK #-}!Int
44+data Encoding = ASCII | Utf8 | Utf16BE | Utf16LE | Utf32BE | Utf32LE
46+-- | /O(n)/ Convert a Text into a Stream Char.
47+stream :: Text -> Stream Char
48+stream (Text arr off len) = Stream next off len
54+ | n >= 0xD800 && n <= 0xDBFF = Yield (U16.chr2 n n2) (i + 2)
55+ | otherwise = Yield (unsafeChr n) (i + 1)
58+ n2 = unsafeAt arr (i + 1)
59+{-# INLINE [0] stream #-}
61+-- | /O(n)/ Convert a Stream Char into a Text.
62+unstream :: Stream Char -> Text
63+unstream (Stream next0 s0 len) = x `seq` Text (fst x) 0 (snd x)
65+ x :: ((UArray Int Word16),Int)
66+ x = runST ((unsafeNewArray_ (0,len+1) :: ST s (STUArray s Int Word16))
67+ >>= (\arr -> loop arr 0 (len+1) s0))
69+ | i + 1 > max = do arr' <- unsafeNewArray_ (0,max*2)
71+ Done -> liftM2 (,) (unsafeFreezeSTUArray arr) (return i)
72+ _ -> copy arr arr' >> loop arr' i (max*2) s
73+ | otherwise = case next0 s of
74+ Done -> liftM2 (,) (unsafeFreezeSTUArray arr) (return i)
75+ Skip s' -> loop arr i max s'
78+ unsafeWrite arr i (fromIntegral n :: Word16)
79+ loop arr (i+1) max s'
82+ unsafeWrite arr (i + 1) r
83+ loop arr (i+2) max s'
90+ l = fromIntegral $ (shiftR m 10) + (0xD800 :: Int)
92+ r = fromIntegral $ (m .&. (0x3FF :: Int)) + (0xDC00 :: Int)
93+{-# INLINE [0] unstream #-}
97+ (_,max) <- getBounds src
101+ | i > max = return ()
102+ | otherwise = do v <- unsafeRead src i
103+ unsafeWrite dest i v
106+-- | /O(n)/ Determines if two streams are equal.
107+eq :: Ord a => Stream a -> Stream a -> Bool
108+eq (Stream next1 s1 _) (Stream next2 s2 _) = compare (next1 s1) (next2 s2)
110+ compare Done Done = True
111+ compare Done _ = False
112+ compare _ Done = False
113+ compare (Skip s1') (Skip s2') = compare (next1 s1') (next2 s2')
114+ compare (Skip s1') x2 = compare (next1 s1') x2
115+ compare x1 (Skip s2') = compare x1 (next2 s2')
116+ compare (Yield x1 s1') (Yield x2 s2') = x1 == x2 &&
117+ compare (next1 s1') (next2 s2')
118+{-# SPECIALISE eq :: Stream Char -> Stream Char -> Bool #-}
121+-- | /O(n) Convert a ByteString into a Stream Char, using the specified encoding standard.
122+stream_bs :: Encoding -> ByteString -> Stream Char
123+stream_bs ASCII bs = Stream next 0 (B.length bs)
128+ | otherwise = Yield (unsafeChr8 x1) (i+1)
132+stream_bs Utf8 bs = Stream next 0 (B.length bs)
137+ | U8.validate1 x1 = Yield (unsafeChr8 x1) (i+1)
138+ | i+1 < l && U8.validate2 x1 x2 = Yield (U8.chr2 x1 x2) (i+2)
139+ | i+2 < l && U8.validate3 x1 x2 x3 = Yield (U8.chr3 x1 x2 x3) (i+3)
140+ | i+3 < l && U8.validate4 x1 x2 x3 x4 = Yield (U8.chr4 x1 x2 x3 x4) (i+4)
141+ | otherwise = error "bsStream: bad UTF-8 stream"
149+stream_bs Utf16LE bs = Stream next 0 (B.length bs)
154+ | i+1 < l && U16.validate1 x1 = Yield (unsafeChr x1) (i+2)
155+ | i+3 < l && U16.validate2 x1 x2 = Yield (U16.chr2 x1 x2) (i+4)
156+ | otherwise = error $ "bsStream: bad UTF-16LE stream"
159+ x1 = (shiftL (index (i + 1)) 8) + (index i)
161+ x2 = (shiftL (index (i + 3)) 8) + (index (i + 2))
163+ index = fromIntegral . B.index bs :: Int -> Word16
164+stream_bs Utf16BE bs = Stream next 0 (B.length bs)
169+ | i+1 < l && U16.validate1 x1 = Yield (unsafeChr x1) (i+2)
170+ | i+3 < l && U16.validate2 x1 x2 = Yield (U16.chr2 x1 x2) (i+4)
171+ | otherwise = error $ "bsStream: bad UTF16-BE stream "
174+ x1 = (shiftL (index i) 8) + (index (i + 1))
176+ x2 = (shiftL (index (i + 2)) 8) + (index (i + 3))
178+ index = fromIntegral . B.index bs
179+stream_bs Utf32BE bs = Stream next 0 (B.length bs)
184+ | i+3 < l && U32.validate x = Yield (unsafeChr32 x) (i+4)
185+ | otherwise = error "bsStream: bad UTF-32BE stream"
188+ x = shiftL x1 24 + shiftL x2 16 + shiftL x3 8 + x4
193+ index = fromIntegral . B.index bs :: Int -> Word32
194+stream_bs Utf32LE bs = Stream next 0 (B.length bs)
199+ | i+3 < l && U32.validate x = Yield (unsafeChr32 x) (i+4)
200+ | otherwise = error "bsStream: bad UTF-32LE stream"
203+ x = shiftL x4 24 + shiftL x3 16 + shiftL x2 8 + x1
208+ index = fromIntegral . B.index bs :: Int -> Word32
209+{-# INLINE [0] stream_bs #-}
211+-- | /O(n)/ Convert a Stream Char into a Stream Word8 using the specified encoding standard.
212+restream :: Encoding -> Stream Char -> Stream Word8
213+restream ASCII (Stream next0 s0 len) = Stream next s0 (len*2)
215+ next !s = case next0 s of
218+ Yield x xs -> Yield x' xs
219+ where x' = fromIntegral (ord x) :: Word8
220+restream Utf8 (Stream next0 s0 len) =
221+ Stream next ((Just s0) :!: Nothing :!: Nothing :!: Nothing) (len*2)
224+ next ((Just s) :!: Nothing :!: Nothing :!: Nothing) = case next0 s of
226+ Skip s' -> Skip ((Just s') :!: Nothing :!: Nothing :!: Nothing)
228+ | n <= 0x7F -> Yield c ((Just xs) :!: Nothing :!: Nothing :!: Nothing)
229+ | n <= 0x07FF -> Yield (fst c2) ((Just xs) :!: (Just $ snd c2) :!: Nothing :!: Nothing)
230+ | n <= 0xFFFF -> Yield (fst3 c3) ((Just xs) :!: (Just $ snd3 c3) :!: (Just $ trd3 c3) :!: Nothing)
231+ | otherwise -> Yield (fst4 c4) ((Just xs) :!: (Just $ snd4 c4) :!: (Just $ trd4 c4) :!: (Just $ fth4 c4))
238+ next ((Just s) :!: (Just x2) :!: Nothing :!: Nothing) = Yield x2 ((Just s) :!: Nothing :!: Nothing :!: Nothing)
239+ next ((Just s) :!: (Just x2) :!: x3 :!: Nothing) = Yield x2 ((Just s) :!: x3 :!: Nothing :!: Nothing)
240+ next ((Just s) :!: (Just x2) :!: x3 :!: x4) = Yield x2 ((Just s) :!: x3 :!: x4 :!: Nothing)
241+restream Utf16BE (Stream next0 s0 len) =
242+ Stream next (Just s0 :!: Nothing :!: Nothing :!: Nothing) (len*2)
245+ next (Just s :!: Nothing :!: Nothing :!: Nothing) = case next0 s of
247+ Skip s' -> Skip (Just s' :!: Nothing :!: Nothing :!: Nothing)
249+ | n < 0x10000 -> Yield (fromIntegral $ shiftR n 8) (Just xs :!: Just (fromIntegral n) :!: Nothing :!: Nothing)
250+ | otherwise -> Yield c1 (Just xs :!: Just c2 :!: Just c3 :!: Just c4)
254+ c1 = fromIntegral (shiftR n1 18 + 0xD8)
255+ c2 = fromIntegral (shiftR n1 10)
257+ c3 = fromIntegral (shiftR n2 8 + 0xDC)
258+ c4 = fromIntegral n2
259+ next ((Just s) :!: (Just x2) :!: Nothing :!: Nothing) = Yield x2 ((Just s) :!: Nothing :!: Nothing :!: Nothing)
260+ next ((Just s) :!: (Just x2) :!: x3 :!: Nothing) = Yield x2 ((Just s) :!: x3 :!: Nothing :!: Nothing)
261+ next ((Just s) :!: (Just x2) :!: x3 :!: x4) = Yield x2 ((Just s) :!: x3 :!: x4 :!: Nothing)
262+restream Utf16LE (Stream next0 s0 len) =
263+ Stream next (Just s0 :!: Nothing :!: Nothing :!: Nothing) (len*2)
266+ next (Just s :!: Nothing :!: Nothing :!: Nothing) = case next0 s of
268+ Skip s' -> Skip (Just s' :!: Nothing :!: Nothing :!: Nothing)
270+ | n < 0x10000 -> Yield (fromIntegral n) (Just xs :!: Just (fromIntegral $ shiftR n 8) :!: Nothing :!: Nothing)
271+ | otherwise -> Yield c1 (Just xs :!: Just c2 :!: Just c3 :!: Just c4)
275+ c2 = fromIntegral (shiftR n1 18 + 0xD8)
276+ c1 = fromIntegral (shiftR n1 10)
278+ c4 = fromIntegral (shiftR n2 8 + 0xDC)
279+ c3 = fromIntegral n2
280+ next ((Just s) :!: (Just x2) :!: Nothing :!: Nothing) = Yield x2 ((Just s) :!: Nothing :!: Nothing :!: Nothing)
281+ next ((Just s) :!: (Just x2) :!: x3 :!: Nothing) = Yield x2 ((Just s) :!: x3 :!: Nothing :!: Nothing)
282+ next ((Just s) :!: (Just x2) :!: x3 :!: x4) = Yield x2 ((Just s) :!: x3 :!: x4 :!: Nothing)
283+restream Utf32BE (Stream next0 s0 len) =
284+ Stream next (Just s0 :!: Nothing :!: Nothing :!: Nothing) (len*2)
287+ next (Just s :!: Nothing :!: Nothing :!: Nothing) = case next0 s of
289+ Skip s' -> Skip (Just s' :!: Nothing :!: Nothing :!: Nothing)
290+ Yield x xs -> Yield c1 (Just xs :!: Just c2 :!: Just c3 :!: Just c4)
293+ c1 = fromIntegral $ shiftR n 24
294+ c2 = fromIntegral $ shiftR n 16
295+ c3 = fromIntegral $ shiftR n 8
297+ next ((Just s) :!: (Just x2) :!: Nothing :!: Nothing) = Yield x2 ((Just s) :!: Nothing :!: Nothing :!: Nothing)
298+ next ((Just s) :!: (Just x2) :!: x3 :!: Nothing) = Yield x2 ((Just s) :!: x3 :!: Nothing :!: Nothing)
299+ next ((Just s) :!: (Just x2) :!: x3 :!: x4) = Yield x2 ((Just s) :!: x3 :!: x4 :!: Nothing)
300+restream Utf32LE (Stream next0 s0 len) =
301+ Stream next (Just s0 :!: Nothing :!: Nothing :!: Nothing) (len*2)
304+ next (Just s :!: Nothing :!: Nothing :!: Nothing) = case next0 s of
306+ Skip s' -> Skip (Just s' :!: Nothing :!: Nothing :!: Nothing)
307+ Yield x xs -> Yield c1 (Just xs :!: Just c2 :!: Just c3 :!: Just c4)
310+ c4 = fromIntegral $ shiftR n 24
311+ c3 = fromIntegral $ shiftR n 16
312+ c2 = fromIntegral $ shiftR n 8
314+ next ((Just s) :!: (Just x2) :!: Nothing :!: Nothing) = Yield x2 ((Just s) :!: Nothing :!: Nothing :!: Nothing)
315+ next ((Just s) :!: (Just x2) :!: x3 :!: Nothing) = Yield x2 ((Just s) :!: x3 :!: Nothing :!: Nothing)
316+ next ((Just s) :!: (Just x2) :!: x3 :!: x4) = Yield x2 ((Just s) :!: x3 :!: x4 :!: Nothing)
317+{-# INLINE restream #-}
328+-- | /O(n)/ Convert a Stream Word8 to a ByteString
329+unstream_bs :: Stream Word8 -> ByteString
330+unstream_bs (Stream next s0 len) = unsafePerformIO $ do
331+ fp0 <- mallocByteString len
334+ loop !fp !n !off !s = case next s of
335+ Done -> trimUp fp n off
336+ Skip s' -> loop fp n off s'
338+ | n == off -> realloc fp n off s' x
340+ withForeignPtr fp $ \p -> pokeByteOff p off x
341+ loop fp n (off+1) s'
342+ {-# NOINLINE realloc #-}
343+ realloc fp n off s x = do
345+ fp' <- copy0 fp n n'
346+ withForeignPtr fp' $ \p -> pokeByteOff p off x
347+ loop fp' n' (off+1) s
348+ {-# NOINLINE trimUp #-}
349+ trimUp fp _ off = return $! PS fp 0 off
350+ copy0 :: ForeignPtr Word8 -> Int -> Int -> IO (ForeignPtr Word8)
351+ copy0 !src !srcLen !destLen = assert (srcLen <= destLen) $ do
352+ dest <- mallocByteString destLen
353+ withForeignPtr src $ \src' ->
354+ withForeignPtr dest $ \dest' ->
355+ memcpy dest' src' (fromIntegral destLen)
357+{-# RULES "STREAM stream/unstream fusion" forall s. stream (unstream s) = s #-}
359+-- ----------------------------------------------------------------------------
360+-- * Basic stream functions
362+-- | /O(n)/ Adds a character to the front of a Stream Char.
363+cons :: Char -> Stream Char -> Stream Char
364+cons w (Stream next0 s0 len) = Stream next (S2 :!: s0) (len+2)
367+ next (S2 :!: s) = Yield w (S1 :!: s)
368+ next (S1 :!: s) = case next0 s of
370+ Skip s' -> Skip (S1 :!: s')
371+ Yield x s' -> Yield x (S1 :!: s')
372+{-# INLINE [0] cons #-}
374+-- | /O(n)/ Adds a character to the end of a stream.
375+snoc :: Stream Char -> Char -> Stream Char
376+snoc (Stream next0 xs0 len) w = Stream next (Just xs0) (len+2)
379+ next (Just xs) = case next0 xs of
380+ Done -> Yield w Nothing
381+ Skip xs' -> Skip (Just xs')
382+ Yield x xs' -> Yield x (Just xs')
384+{-# INLINE [0] snoc #-}
386+-- | /O(n)/ Appends one Stream to the other.
387+append :: Stream Char -> Stream Char -> Stream Char
388+append (Stream next0 s01 len1) (Stream next1 s02 len2) =
389+ Stream next (Left s01) (len1 + len2)
392+ next (Left s1) = case next0 s1 of
393+ Done -> Skip (Right s02)
394+ Skip s1' -> Skip (Left s1')
395+ Yield x s1' -> Yield x (Left s1')
396+ next (Right s2) = case next1 s2 of
398+ Skip s2' -> Skip (Right s2')
399+ Yield x s2' -> Yield x (Right s2')
400+{-# INLINE [0] append #-}
402+-- | /O(1)/ Returns the first character of a Text, which must be non-empty.
403+-- Subject to array fusion.
404+head :: Stream Char -> Char
405+head (Stream next s0 len) = loop_head s0
407+ loop_head !s = case next s of
409+ Skip s' -> loop_head s'
410+ Done -> error "head: Empty list"
411+{-# INLINE [0] head #-}
413+-- | /O(n)/ Returns the last character of a Stream Char, which must be non-empty.
414+last :: Stream Char -> Char
415+last (Stream next s0 len) = loop0_last s0
417+ loop0_last !s = case next s of
418+ Done -> error "last: Empty list"
419+ Skip s' -> seq s' $ loop0_last s'
420+ Yield x s' -> seq s' $ loop_last x s'
421+ loop_last !x !s = case next s of
423+ Skip s' -> seq s' $ loop_last x s'
424+ Yield x' s' -> seq s' $ loop_last x' s'
425+{-# INLINE[0] last #-}
427+-- | /O(1)/ Returns all characters after the head of a Stream Char, which must
429+tail :: Stream Char -> Stream Char
430+tail (Stream next0 s0 len) = Stream next (False :!: s0) (len-1)
433+ next (False :!: s) = case next0 s of
434+ Done -> error "tail"
435+ Skip s' -> Skip (False :!: s')
436+ Yield _ s' -> Skip (True :!: s')
437+ next (True :!: s) = case next0 s of
439+ Skip s' -> Skip (True :!: s')
440+ Yield x s' -> Yield x (True :!: s')
441+{-# INLINE [0] tail #-}
444+-- | /O(1)/ Returns all but the last character of a Stream Char, which
445+-- must be non-empty.
446+init :: Stream Char -> Stream Char
447+init (Stream next0 s0 len) = Stream next (Nothing :!: s0) (len-1)
450+ next (Nothing :!: s) = case next0 s of
451+ Done -> errorEmptyList "init"
452+ Skip s' -> seq s' $ Skip (Nothing :!: s')
453+ Yield x s' -> seq s' $ Skip (Just x :!: s')
454+ next (Just x :!: s) = case next0 s of
456+ Skip s' -> seq s' $ Skip (Just x :!: s')
457+ Yield x' s' -> seq s' $ Yield x (Just x' :!: s')
458+{-# INLINE [0] init #-}
460+-- | /O(1)/ Tests whether a Stream Char is empty or not.
461+null :: Stream Char -> Bool
462+null (Stream next s0 len) = loop_null s0
464+ loop_null !s = case next s of
467+ Skip s' -> loop_null s'
468+{-# INLINE[0] null #-}
470+-- | /O(n)/ Returns the number of characters in a text.
471+length :: Stream Char -> Int
472+length (Stream next s0 len) = loop_length 0# s0
475+ loop_length z# !s = case next s of
477+ Skip s' -> loop_length z# s'
478+ Yield _ s' -> loop_length (z# +# 1#) s'
479+{-# INLINE[0] length #-}
481+-- ----------------------------------------------------------------------------
482+-- * Stream transformations
484+-- | /O(n)/ 'map' @f @xs is the Stream Char obtained by applying @f@ to each element of
486+map :: (Char -> Char) -> Stream Char -> Stream Char
487+map f (Stream next0 s0 len) = Stream next s0 len
490+ next !s = case next0 s of
493+ Yield x s' -> Yield (f x) s'
494+{-# INLINE [0] map #-}
497+ RULES "STREAM map/map fusion" forall f g s.
498+ map f (map g s) = map (\x -> f (g x)) s
501+-- | /O(n)/ The 'intersperse' function takes a character and places it between each of
502+-- the characters of a Stream.
503+intersperse :: Char -> Stream Char -> Stream Char
504+intersperse c (Stream next0 s0 len) = Stream next (s0 :!: Nothing :!: S1) len
507+ next (s :!: Nothing :!: S1) = case next0 s of
509+ Skip s' -> Skip (s' :!: Nothing :!: S1)
510+ Yield x s' -> Skip (s' :!: Just x :!: S1)
511+ next (s :!: Just x :!: S1) = Yield x (s :!: Nothing :!: S2)
512+ next (s :!: Nothing :!: S2) = case next0 s of
514+ Skip s' -> Skip (s' :!: Nothing :!: S2)
515+ Yield x s' -> Yield c (s' :!: Just x :!: S1)
517+-- ----------------------------------------------------------------------------
518+-- * Reducing Streams (folds)
520+-- | foldl, applied to a binary operator, a starting value (typically the
521+-- left-identity of the operator), and a Stream, reduces the Stream using the
522+-- binary operator, from left to right.
523+foldl :: (b -> Char -> b) -> b -> Stream Char -> b
524+foldl f z0 (Stream next s0 len) = loop_foldl z0 s0
526+ loop_foldl z !s = case next s of
528+ Skip s' -> loop_foldl z s'
529+ Yield x s' -> loop_foldl (f z x) s'
530+{-# INLINE [0] foldl #-}
532+-- | A strict version of foldl.
533+foldl' :: (b -> Char -> b) -> b -> Stream Char -> b
534+foldl' f z0 (Stream next s0 len) = loop_foldl' z0 s0
536+ loop_foldl' !z !s = case next s of
538+ Skip s' -> loop_foldl' z s'
539+ Yield x s' -> loop_foldl' (f z x) s'
540+{-# INLINE [0] foldl' #-}
542+-- | foldl1 is a variant of foldl that has no starting value argument,
543+-- and thus must be applied to non-empty Streams.
544+foldl1 :: (Char -> Char -> Char) -> Stream Char -> Char
545+foldl1 f (Stream next s0 len) = loop0_foldl1 s0
547+ loop0_foldl1 !s = case next s of
548+ Skip s' -> loop0_foldl1 s'
549+ Yield x s' -> loop_foldl1 x s'
550+ Done -> errorEmptyList "foldl1"
551+ loop_foldl1 z !s = case next s of
553+ Skip s' -> loop_foldl1 z s'
554+ Yield x s' -> loop_foldl1 (f z x) s'
555+{-# INLINE [0] foldl1 #-}
557+-- | A strict version of foldl1.
558+foldl1' :: (Char -> Char -> Char) -> Stream Char -> Char
559+foldl1' f (Stream next s0 len) = loop0_foldl1' s0
561+ loop0_foldl1' !s = case next s of
562+ Skip s' -> loop0_foldl1' s'
563+ Yield x s' -> loop_foldl1' x s'
564+ Done -> errorEmptyList "foldl1"
565+ loop_foldl1' !z !s = case next s of
567+ Skip s' -> loop_foldl1' z s'
568+ Yield x s' -> loop_foldl1' (f z x) s'
569+{-# INLINE [0] foldl1' #-}
571+-- | 'foldr', applied to a binary operator, a starting value (typically the
572+-- right-identity of the operator), and a stream, reduces the stream using the
573+-- binary operator, from right to left.
574+foldr :: (Char -> b -> b) -> b -> Stream Char -> b
575+foldr f z (Stream next s0 len) = loop_foldr s0
577+ loop_foldr !s = case next s of
579+ Skip s' -> loop_foldr s'
580+ Yield x s' -> f x (loop_foldr s')
581+{-# INLINE [0] foldr #-}
583+-- | foldr1 is a variant of 'foldr' that has no starting value argument,
584+-- and thust must be applied to non-empty streams.
585+-- Subject to array fusion.
586+foldr1 :: (Char -> Char -> Char) -> Stream Char -> Char
587+foldr1 f (Stream next s0 len) = loop0_foldr1 s0
589+ loop0_foldr1 !s = case next s of
590+ Done -> error "foldr1"
591+ Skip s' -> loop0_foldr1 s'
592+ Yield x s' -> loop_foldr1 x s'
594+ loop_foldr1 x !s = case next s of
596+ Skip s' -> loop_foldr1 x s'
597+ Yield x' s' -> f x (loop_foldr1 x' s')
598+{-# INLINE [0] foldr1 #-}
600+-- ----------------------------------------------------------------------------
603+-- | /O(n)/ Concatenate a list of streams. Subject to array fusion.
604+concat :: [Stream Char] -> Stream Char
605+concat = L.foldr append (Stream next Done 0)
609+-- | Map a function over a stream that results in a steram and concatenate the
611+concatMap :: (Char -> Stream Char) -> Stream Char -> Stream Char
612+concatMap f = foldr (append . f) (stream empty)
614+-- | /O(n)/ any @p @xs determines if any character in the stream
615+-- @xs@ satisifes the predicate @p@.
616+any :: (Char -> Bool) -> Stream Char -> Bool
617+any p (Stream next0 s0 len) = loop_any s0
619+ loop_any !s = case next0 s of
621+ Skip s' -> seq s' $ loop_any s'
622+ Yield x s' | p x -> True
623+ | otherwise -> seq s' $ loop_any s'
625+-- | /O(n)/ all @p @xs determines if all characters in the 'Text'
626+-- @xs@ satisify the predicate @p@.
627+all :: (Char -> Bool) -> Stream Char -> Bool
628+all p (Stream next0 s0 len) = loop_all s0
630+ loop_all !s = case next0 s of
632+ Skip s' -> seq s' $ loop_all s'
633+ Yield x s' | p x -> seq s' $ loop_all s'
634+ | otherwise -> False
636+-- | /O(n)/ maximum returns the maximum value from a stream, which must be
638+maximum :: Stream Char -> Char
639+maximum (Stream next0 s0 len) = loop0_maximum s0
641+ loop0_maximum !s = case next0 s of
642+ Done -> errorEmptyList "maximum"
643+ Skip s' -> seq s' $ loop0_maximum s'
644+ Yield x s' -> seq s' $ loop_maximum x s'
645+ loop_maximum !z !s = case next0 s of
647+ Skip s' -> seq s' $ loop_maximum z s'
649+ | x > z -> seq s' $ loop_maximum x s'
650+ | otherwise -> seq s' $ loop_maximum z s'
652+-- | /O(n)/ minimum returns the minimum value from a 'Text', which must be
654+minimum :: Stream Char -> Char
655+minimum (Stream next0 s0 len) = loop0_minimum s0
657+ loop0_minimum !s = case next0 s of
658+ Done -> errorEmptyList "minimum"
659+ Skip s' -> seq s' $ loop0_minimum s'
660+ Yield x s' -> seq s' $ loop_minimum x s'
661+ loop_minimum !z !s = case next0 s of
663+ Skip s' -> seq s' $ loop_minimum z s'
665+ | x < z -> seq s' $ loop_minimum x s'
666+ | otherwise -> seq s' $ loop_minimum z s'
671+-- -----------------------------------------------------------------------------
672+-- * Building streams
674+-- -----------------------------------------------------------------------------
675+-- ** Generating and unfolding streams
677+-- | /O(n)/, where @n@ is the length of the result. The unfoldr function
678+-- is analogous to the List 'unfoldr'. unfoldr builds a stream
679+-- from a seed value. The function takes the element and returns
680+-- Nothing if it is done producing the stream or returns Just
681+-- (a,b), in which case, a is the next Char in the string, and b is
682+-- the seed value for further production.
683+unfoldr :: (a -> Maybe (Char,a)) -> a -> Stream Char
684+unfoldr f s0 = Stream next s0 1
687+ next !s = case f s of
689+ Just (w, s') -> Yield w s'
690+{-# INLINE [0] unfoldr #-}
692+-- | O(n) Like unfoldr, unfoldrN builds a stream from a seed
693+-- value. However, the length of the result should be limited by the
694+-- first argument to unfoldrN. This function is more efficient than
695+-- unfoldr when the maximum length of the result and correct,
696+-- otherwise its complexity performance is similar to 'unfoldr'
697+unfoldrN :: Int -> (a -> Maybe (Char,a)) -> a -> Stream Char
698+unfoldrN n f s0 = Stream next (0 :!: s0) (n*2)
701+ next (z :!: s) = case f s of
703+ Just (w, s') | z >= n -> Done
704+ | otherwise -> Yield w ((z + 1) :!: s')
705+-------------------------------------------------------------------------------
708+-- | /O(n)/ take n, applied to a stream, returns the prefix of the
709+-- stream of length @n@, or the stream itself if @n@ is greater than the
710+-- length of the stream.
711+take :: Int -> Stream Char -> Stream Char
712+take n0 (Stream next0 s0 len) = Stream next (n0 :!: s0) len
715+ next (n :!: s) | n <= 0 = Done
716+ | otherwise = case next0 s of
718+ Skip s' -> Skip (n :!: s')
719+ Yield x s' -> Yield x ((n-1) :!: s')
720+{-# INLINE [0] take #-}
722+-- | /O(n)/ drop n, applied to a stream, returns the suffix of the
723+-- stream of length @n@, or the empty stream if @n@ is greater than the
724+-- length of the stream.
725+drop :: Int -> Stream Char -> Stream Char
726+drop n0 (Stream next0 s0 len) = Stream next (Just ((max 0 n0)) :!: s0) (len - n0)
729+ next (Just !n :!: s)
730+ | n == 0 = Skip (Nothing :!: s)
731+ | otherwise = case next0 s of
733+ Skip s' -> Skip (Just n :!: s')
734+ Yield _ s' -> Skip (Just (n-1) :!: s')
735+ next (Nothing :!: s) = case next0 s of
737+ Skip s' -> Skip (Nothing :!: s')
738+ Yield x s' -> Yield x (Nothing :!: s')
739+{-# INLINE [0] drop #-}
741+-- | takeWhile, applied to a predicate @p@ and a stream, returns the
742+-- longest prefix (possibly empty) of elements that satisfy p.
743+takeWhile :: (Char -> Bool) -> Stream Char -> Stream Char
744+takeWhile p (Stream next0 s0 len) = Stream next s0 len
747+ next !s = case next0 s of
750+ Yield x s' | p x -> Yield x s'
752+{-# INLINE [0] takeWhile #-}
754+-- | dropWhile @p @xs returns the suffix remaining after takeWhile @p @xs.
755+dropWhile :: (Char -> Bool) -> Stream Char -> Stream Char
756+dropWhile p (Stream next0 s0 len) = Stream next (S1 :!: s0) len
759+ next (S1 :!: s) = case next0 s of
761+ Skip s' -> Skip (S1 :!: s')
762+ Yield x s' | p x -> Skip (S1 :!: s')
763+ | otherwise -> Yield x (S2 :!: s')
764+ next (S2 :!: s) = case next0 s of
766+ Skip s' -> Skip (S2 :!: s')
767+ Yield x s' -> Yield x (S2 :!: s')
768+{-# INLINE [0] dropWhile #-}
770+-- ----------------------------------------------------------------------------
773+-------------------------------------------------------------------------------
774+-- ** Searching by equality
776+-- | /O(n)/ elem is the stream membership predicate.
777+elem :: Char -> Stream Char -> Bool
778+elem w (Stream next s0 len) = loop_elem s0
780+ loop_elem !s = case next s of
782+ Skip s' -> loop_elem s'
783+ Yield x s' | x == w -> True
784+ | otherwise -> loop_elem s'
785+{-# INLINE [0] elem #-}
787+-------------------------------------------------------------------------------
788+-- ** Searching with a predicate
790+-- | /O(n)/ The 'find' function takes a predicate and a stream,
791+-- and returns the first element in matching the predicate, or 'Nothing'
792+-- if there is no such element.
794+find :: (Char -> Bool) -> Stream Char -> Maybe Char
795+find p (Stream next s0 len) = loop_find s0
797+ loop_find !s = case next s of
799+ Skip s' -> loop_find s'
800+ Yield x s' | p x -> Just x
801+ | otherwise -> loop_find s'
802+{-# INLINE [0] find #-}
804+-- | /O(n)/ 'filter', applied to a predicate and a stream,
805+-- returns a stream containing those characters that satisfy the
807+filter :: (Char -> Bool) -> Stream Char -> Stream Char
808+filter p (Stream next0 s0 len) = Stream next s0 len
811+ next !s = case next0 s of
814+ Yield x s' | p x -> Yield x s'
815+ | otherwise -> Skip s'
816+{-# INLINE [0] filter #-}
819+ "Stream filter/filter fusion" forall p q s.
820+ filter p (filter q s) = filter (\x -> q x && p x) s
823+-------------------------------------------------------------------------------
824+-- ** Indexing streams
826+-- | /O(1)/ stream index (subscript) operator, starting from 0.
827+index :: Stream Char -> Int -> Char
828+index (Stream next s0 len) n0
829+ | n0 < 0 = error "Stream.(!!): negative index"
830+ | otherwise = loop_index n0 s0
832+ loop_index !n !s = case next s of
833+ Done -> error "Stream.(!!): index too large"
834+ Skip s' -> loop_index n s'
835+ Yield x s' | n == 0 -> x
836+ | otherwise -> loop_index (n-1) s'
837+{-# INLINE [0] index #-}
839+-- | The 'findIndex' function takes a predicate and a stream and
840+-- returns the index of the first element in the stream
841+-- satisfying the predicate.
842+findIndex :: (Char -> Bool) -> Stream Char -> Maybe Int
843+findIndex p (Stream next s0 len) = loop_findIndex 0 s0
845+ loop_findIndex !i !s = case next s of
847+ Skip s' -> loop_findIndex i s' -- hmm. not caught by QC
848+ Yield x s' | p x -> Just i
849+ | otherwise -> loop_findIndex (i+1) s'
850+{-# INLINE [0] findIndex #-}
852+-- | /O(n)/ The 'elemIndex' function returns the index of the first
853+-- element in the given stream which is equal to the query
854+-- element, or 'Nothing' if there is no such element.
855+elemIndex :: Char -> Stream Char -> Maybe Int
856+elemIndex a (Stream next s0 len) = loop_elemIndex 0 s0
858+ loop_elemIndex !i !s = case next s of
860+ Skip s' -> loop_elemIndex i s'
861+ Yield x s' | a == x -> Just i
862+ | otherwise -> loop_elemIndex (i+1) s'
863+{-# INLINE [0] elemIndex #-}
865+-------------------------------------------------------------------------------
868+-- | zipWith generalises 'zip' by zipping with the function given as
869+-- the first argument, instead of a tupling function.
870+zipWith :: (Char -> Char -> Char) -> Stream Char -> Stream Char -> Stream Char
871+zipWith f (Stream next0 sa0 len1) (Stream next1 sb0 len2) = Stream next (sa0 :!: sb0 :!: Nothing) (min len1 len2)
874+ next (sa :!: sb :!: Nothing) = case next0 sa of
876+ Skip sa' -> Skip (sa' :!: sb :!: Nothing)
877+ Yield a sa' -> Skip (sa' :!: sb :!: Just a)
879+ next (sa' :!: sb :!: Just a) = case next1 sb of
881+ Skip sb' -> Skip (sa' :!: sb' :!: Just a)
882+ Yield b sb' -> Yield (f a b) (sa' :!: sb' :!: Nothing)
883+{-# INLINE [0] zipWith #-}
885+errorEmptyList :: String -> a
887+ error ("Prelude." ++ fun ++ ": empty list")