1{-# LANGUAGE BangPatterns #-}
3{-# LANGUAGE ConstraintKinds #-}
4{-# LANGUAGE ExistentialQuantification #-}
5{-# LANGUAGE FlexibleContexts #-}
6{-# LANGUAGE FlexibleInstances #-}
7{-# LANGUAGE MultiParamTypeClasses #-}
8{-# LANGUAGE PatternSynonyms #-}
9{-# LANGUAGE RecordWildCards #-}
10{-# LANGUAGE ScopedTypeVariables #-}
11{-# LANGUAGE ViewPatterns #-}
12{-# LANGUAGE RankNTypes #-}
13{-# LANGUAGE MagicHash #-}
15#if __GLASGOW_HASKELL__ >= 801
16{-# LANGUAGE TypeApplications #-}
22-- Module : Streamly.Streams.StreamD
23-- Copyright : (c) 2018 Harendra Kumar
24-- Copyright : (c) Roman Leshchinskiy 2008-2010
25-- Copyright : (c) The University of Glasgow, 2009
28-- Maintainer : harendra.kumar@gmail.com
29-- Stability : experimental
32-- Direct style re-implementation of CPS style stream in StreamK module. The
33-- symbol or suffix 'D' in this module denotes the "Direct" style. GHC is able
34-- to INLINE and fuse direct style better, providing better performance than
38-- import qualified Streamly.Streams.StreamD as D
41-- Some of the functions in this file have been adapted from the vector
42-- library, https://hackage.haskell.org/package/vector.
44module Streamly.Streams.StreamD
62 -- ** Specialized Generation
63 -- | Generate a monadic stream from a seed.
73 , enumerateFromStepIntegral
74 , enumerateFromIntegral
75 , enumerateFromThenIntegral
76 , enumerateFromToIntegral
77 , enumerateFromThenToIntegral
79 , enumerateFromStepNum
82 , enumerateFromToFractional
83 , enumerateFromThenToFractional
86 -- | Transform an input structure into a stream.
87 -- | Direct style stream does not support @fromFoldable@.
114 -- ** Specialized Folds
135 -- ** Flattening nested streams
163 -- | Transform a stream into another type.
172 -- ** By folding (scans)
238 -- * Transformation comprehensions
249 -- * UTF8 Encoding / Decoding transformations.
255import Control.Exception (Exception)
256import Control.Monad (void)
257import Control.Monad.Catch (MonadCatch)
258import Control.Monad.IO.Class (MonadIO(..))
259import Control.Monad.Trans (MonadTrans(lift))
260import Data.Bits (shiftR, shiftL, (.|.), (.&.))
261#if __GLASGOW_HASKELL__ >= 801
262import Data.Functor.Identity (Identity)
264import Data.Maybe (fromJust, isJust)
265import Data.Word (Word32)
266import Foreign.Ptr (Ptr)
267import Foreign.Storable (Storable(..))
268import GHC.Base (assert, Char(..), unsafeChr, (-#), (+#), uncheckedIShiftL#,
269 word2Int#, chr#, ord)
270import GHC.IO.Encoding.Failure (isSurrogate)
271import GHC.Types (SPEC(..))
272import GHC.Word (Word8(..))
274 hiding (map, mapM, mapM_, repeat, foldr, last, take, filter,
275 takeWhile, drop, dropWhile, all, any, maximum, minimum, elem,
276 notElem, null, head, tail, zipWith, lookup, foldr1, sequence,
277 (!!), scanl, scanl1, concatMap, replicate, enumFromTo, concat,
280import qualified Control.Monad.Catch as MC
282import Streamly.Memory.Array.Types (Array(..))
283import Streamly.Fold.Types (Fold(..))
284import Streamly.Pipe.Types (Pipe(..), PipeState(..))
285import Streamly.SVar (MonadAsync, defState, adaptState)
286import Streamly.Unfold.Types (Unfold(..))
288import Streamly.Streams.StreamD.Type
290import qualified Streamly.Pipe.Types as Pipe
291import qualified Streamly.Memory.Array.Types as A
292import qualified Streamly.Memory.Ring as RB
293import qualified Streamly.Streams.StreamK as K
295------------------------------------------------------------------------------
297------------------------------------------------------------------------------
299-- | An empty 'Stream'.
300{-# INLINE_NORMAL nil #-}
301nil :: Monad m => Stream m a
302nil = Stream (\_ _ -> return Stop) ()
304{-# INLINE_NORMAL consM #-}
305consM :: Monad m => m a -> Stream m a -> Stream m a
306consM m (Stream step state) = Stream step1 Nothing
308 {-# INLINE_LATE step1 #-}
309 step1 _ Nothing = m >>= \x -> return $ Yield x (Just state)
310 step1 gst (Just st) = do
314 Yield a s -> Yield a (Just s)
315 Skip s -> Skip (Just s)
318-- XXX implement in terms of consM?
319-- cons x = consM (return x)
321-- | Can fuse but has O(n^2) complexity.
322{-# INLINE_NORMAL cons #-}
323cons :: Monad m => a -> Stream m a -> Stream m a
324cons x (Stream step state) = Stream step1 Nothing
326 {-# INLINE_LATE step1 #-}
327 step1 _ Nothing = return $ Yield x (Just state)
328 step1 gst (Just st) = do
332 Yield a s -> Yield a (Just s)
333 Skip s -> Skip (Just s)
336-------------------------------------------------------------------------------
338-------------------------------------------------------------------------------
340-- Does not fuse, has the same performance as the StreamK version.
341{-# INLINE_NORMAL uncons #-}
342uncons :: Monad m => Stream m a -> m (Maybe (a, Stream m a))
343uncons (UnStream step state) = go state
346 r <- step defState st
348 Yield x s -> return $ Just (x, Stream step s)
350 Stop -> return Nothing
352------------------------------------------------------------------------------
353-- Generation by unfold
354------------------------------------------------------------------------------
356{-# INLINE_NORMAL unfoldrM #-}
357unfoldrM :: Monad m => (s -> m (Maybe (a, s))) -> s -> Stream m a
358unfoldrM next state = Stream step state
360 {-# INLINE_LATE step #-}
364 Just (x, s) -> Yield x s
367{-# INLINE_LATE unfoldr #-}
368unfoldr :: Monad m => (s -> Maybe (a, s)) -> s -> Stream m a
369unfoldr f = unfoldrM (return . f)
371------------------------------------------------------------------------------
372-- Specialized Generation
373------------------------------------------------------------------------------
375repeat :: Monad m => a -> Stream m a
376repeat x = Stream (\_ _ -> return $ Yield x ()) ()
378{-# INLINE_NORMAL replicateM #-}
379replicateM :: forall m a. Monad m => Int -> m a -> Stream m a
380replicateM n p = Stream step n
382 {-# INLINE_LATE step #-}
384 | i <= 0 = return Stop
387 return $ Yield x (i - 1)
389{-# INLINE_NORMAL replicate #-}
390replicate :: Monad m => Int -> a -> Stream m a
391replicate n x = replicateM n (return x)
393-- This would not work properly for floats, therefore we put an Integral
395-- | Can be used to enumerate unbounded integrals. This does not check for
396-- overflow or underflow for bounded integrals.
397{-# INLINE_NORMAL enumerateFromStepIntegral #-}
398enumerateFromStepIntegral :: (Integral a, Monad m) => a -> a -> Stream m a
399enumerateFromStepIntegral from stride =
400 from `seq` stride `seq` Stream step from
402 {-# INLINE_LATE step #-}
403 step _ !x = return $ Yield x $! (x + stride)
405-- We are assuming that "to" is constrained by the type to be within
407{-# INLINE enumerateFromToIntegral #-}
408enumerateFromToIntegral :: (Monad m, Integral a) => a -> a -> Stream m a
409enumerateFromToIntegral from to =
410 takeWhile (<= to) $ enumerateFromStepIntegral from 1
412{-# INLINE enumerateFromIntegral #-}
413enumerateFromIntegral :: (Monad m, Integral a, Bounded a) => a -> Stream m a
414enumerateFromIntegral from = enumerateFromToIntegral from maxBound
416data EnumState a = EnumInit | EnumYield a a a | EnumStop
418{-# INLINE_NORMAL enumerateFromThenToIntegralUp #-}
419enumerateFromThenToIntegralUp
420 :: (Monad m, Integral a)
421 => a -> a -> a -> Stream m a
422enumerateFromThenToIntegralUp from next to = Stream step EnumInit
424 {-# INLINE_LATE step #-}
430 else Yield from EnumStop
431 else -- from <= next <= to
432 let stride = next - from
433 in Skip $ EnumYield from stride (to - stride)
435 step _ (EnumYield x stride toMinus) =
438 then Yield x EnumStop
439 else Yield x $ EnumYield (x + stride) stride toMinus
441 step _ EnumStop = return Stop
443{-# INLINE_NORMAL enumerateFromThenToIntegralDn #-}
444enumerateFromThenToIntegralDn
445 :: (Monad m, Integral a)
446 => a -> a -> a -> Stream m a
447enumerateFromThenToIntegralDn from next to = Stream step EnumInit
449 {-# INLINE_LATE step #-}
451 return $ if to > next
454 else Yield from EnumStop
455 else -- from >= next >= to
456 let stride = next - from
457 in Skip $ EnumYield from stride (to - stride)
459 step _ (EnumYield x stride toMinus) =
462 then Yield x EnumStop
463 else Yield x $ EnumYield (x + stride) stride toMinus
465 step _ EnumStop = return Stop
467{-# INLINE_NORMAL enumerateFromThenToIntegral #-}
468enumerateFromThenToIntegral
469 :: (Monad m, Integral a)
470 => a -> a -> a -> Stream m a
471enumerateFromThenToIntegral from next to
472 | next >= from = enumerateFromThenToIntegralUp from next to
473 | otherwise = enumerateFromThenToIntegralDn from next to
475{-# INLINE_NORMAL enumerateFromThenIntegral #-}
476enumerateFromThenIntegral
477 :: (Monad m, Integral a, Bounded a)
478 => a -> a -> Stream m a
479enumerateFromThenIntegral from next =
481 then enumerateFromThenToIntegralUp from next maxBound
482 else enumerateFromThenToIntegralDn from next minBound
484-- For floating point numbers if the increment is less than the precision then
485-- it just gets lost. Therefore we cannot always increment it correctly by just
487-- 9007199254740992 + 1 + 1 :: Double => 9.007199254740992e15
488-- 9007199254740992 + 2 :: Double => 9.007199254740994e15
490-- Instead we accumulate the increment counter and compute the increment
491-- everytime before adding it to the starting number.
493-- This works for Integrals as well as floating point numbers, but
494-- enumerateFromStepIntegral is faster for integrals.
495{-# INLINE_NORMAL enumerateFromStepNum #-}
496enumerateFromStepNum :: (Monad m, Num a) => a -> a -> Stream m a
497enumerateFromStepNum from stride = Stream step 0
499 {-# INLINE_LATE step #-}
500 step _ !i = return $ (Yield $! (from + i * stride)) $! (i + 1)
502{-# INLINE_NORMAL numFrom #-}
503numFrom :: (Monad m, Num a) => a -> Stream m a
504numFrom from = enumerateFromStepNum from 1
506{-# INLINE_NORMAL numFromThen #-}
507numFromThen :: (Monad m, Num a) => a -> a -> Stream m a
508numFromThen from next = enumerateFromStepNum from (next - from)
510-- We cannot write a general function for Num. The only way to write code
511-- portable between the two is to use a 'Real' constraint and convert between
512-- Fractional and Integral using fromRational which is horribly slow.
513{-# INLINE_NORMAL enumerateFromToFractional #-}
514enumerateFromToFractional
515 :: (Monad m, Fractional a, Ord a)
516 => a -> a -> Stream m a
517enumerateFromToFractional from to =
518 takeWhile (<= to + 1 / 2) $ enumerateFromStepNum from 1
520{-# INLINE_NORMAL enumerateFromThenToFractional #-}
521enumerateFromThenToFractional
522 :: (Monad m, Fractional a, Ord a)
523 => a -> a -> a -> Stream m a
524enumerateFromThenToFractional from next to =
525 takeWhile predicate $ numFromThen from next
527 mid = (next - from) / 2
528 predicate | next >= from = (<= to + mid)
529 | otherwise = (>= to + mid)
531-------------------------------------------------------------------------------
532-- Generation by Conversion
533-------------------------------------------------------------------------------
535{-# INLINE_NORMAL fromIndicesM #-}
536fromIndicesM :: Monad m => (Int -> m a) -> Stream m a
537fromIndicesM gen = Stream step 0
539 {-# INLINE_LATE step #-}
542 return $ Yield x (i + 1)
544{-# INLINE fromIndices #-}
545fromIndices :: Monad m => (Int -> a) -> Stream m a
546fromIndices gen = fromIndicesM (return . gen)
548{-# INLINE_NORMAL generateM #-}
549generateM :: Monad m => Int -> (Int -> m a) -> Stream m a
550generateM n gen = n `seq` Stream step 0
552 {-# INLINE_LATE step #-}
553 step _ i | i < n = do
555 return $ Yield x (i + 1)
556 | otherwise = return Stop
558{-# INLINE generate #-}
559generate :: Monad m => Int -> (Int -> a) -> Stream m a
560generate n gen = generateM n (return . gen)
562-- XXX we need the MonadAsync constraint because of a rewrite rule.
563-- | Convert a list of monadic actions to a 'Stream'
564{-# INLINE_LATE fromListM #-}
565fromListM :: MonadAsync m => [m a] -> Stream m a
566fromListM = Stream step
568 {-# INLINE_LATE step #-}
569 step _ (m:ms) = m >>= \x -> return $ Yield x ms
570 step _ [] = return Stop
572{-# INLINE toStreamD #-}
573toStreamD :: (K.IsStream t, Monad m) => t m a -> Stream m a
574toStreamD = fromStreamK . K.toStream
576------------------------------------------------------------------------------
577-- Elimination by Folds
578------------------------------------------------------------------------------
580------------------------------------------------------------------------------
582------------------------------------------------------------------------------
584{-# INLINE_NORMAL foldr1 #-}
585foldr1 :: Monad m => (a -> a -> a) -> Stream m a -> m (Maybe a)
589 Nothing -> return Nothing
590 Just (h, t) -> fmap Just (foldr f h t)
592------------------------------------------------------------------------------
594------------------------------------------------------------------------------
596{-# INLINE_NORMAL foldlT #-}
597foldlT :: (Monad m, Monad (s m), MonadTrans s)
598 => (s m b -> a -> s m b) -> s m b -> Stream m a -> s m b
599foldlT fstep begin (Stream step state) = go SPEC begin state
602 r <- lift $ step defState st
604 Yield x s -> go SPEC (fstep acc x) s
605 Skip s -> go SPEC acc s
608-- Note, this is going to have horrible performance, because of the nature of
609-- the stream type (i.e. direct stream vs CPS). Its only for reference, it is
610-- likely be practically unusable.
611{-# INLINE_NORMAL foldlS #-}
613 => (Stream m b -> a -> Stream m b) -> Stream m b -> Stream m a -> Stream m b
614foldlS fstep begin (Stream step state) = Stream step' (Left (state, begin))
616 step' gst (Left (st, acc)) = do
617 r <- step (adaptState gst) st
619 Yield x s -> Skip (Left (s, fstep acc x))
620 Skip s -> Skip (Left (s, acc))
621 Stop -> Skip (Right acc)
623 step' gst (Right (Stream stp stt)) = do
624 r <- stp (adaptState gst) stt
626 Yield x s -> Yield x (Right (Stream stp s))
627 Skip s -> Skip (Right (Stream stp s))
630------------------------------------------------------------------------------
632------------------------------------------------------------------------------
634-- | Run a streaming composition, discard the results.
635{-# INLINE_LATE drain #-}
636drain :: Monad m => Stream m a -> m ()
637-- drain = foldrM (\_ xs -> xs) (return ())
638drain (Stream step state) = go SPEC state
641 r <- step defState st
643 Yield _ s -> go SPEC s
647{-# INLINE_NORMAL null #-}
648null :: Monad m => Stream m a -> m Bool
649null m = foldrM (\_ _ -> return False) (return True) m
651{-# INLINE_NORMAL head #-}
652head :: Monad m => Stream m a -> m (Maybe a)
653head m = foldrM (\x _ -> return (Just x)) (return Nothing) m
655-- Does not fuse, has the same performance as the StreamK version.
656{-# INLINE_NORMAL tail #-}
657tail :: Monad m => Stream m a -> m (Maybe (Stream m a))
658tail (UnStream step state) = go state
661 r <- step defState st
663 Yield _ s -> return (Just $ Stream step s)
665 Stop -> return Nothing
667-- XXX will it fuse? need custom impl?
668{-# INLINE_NORMAL last #-}
669last :: Monad m => Stream m a -> m (Maybe a)
670last = foldl' (\_ y -> Just y) Nothing
672{-# INLINE_NORMAL elem #-}
673elem :: (Monad m, Eq a) => a -> Stream m a -> m Bool
674-- elem e m = foldrM (\x xs -> if x == e then return True else xs) (return False) m
675elem e (Stream step state) = go state
678 r <- step defState st
681 | x == e -> return True
686{-# INLINE_NORMAL notElem #-}
687notElem :: (Monad m, Eq a) => a -> Stream m a -> m Bool
688notElem e s = fmap not (elem e s)
690{-# INLINE_NORMAL all #-}
691all :: Monad m => (a -> Bool) -> Stream m a -> m Bool
692-- all p m = foldrM (\x xs -> if p x then xs else return False) (return True) m
693all p (Stream step state) = go state
696 r <- step defState st
700 | otherwise -> return False
704{-# INLINE_NORMAL any #-}
705any :: Monad m => (a -> Bool) -> Stream m a -> m Bool
706-- any p m = foldrM (\x xs -> if p x then return True else xs) (return False) m
707any p (Stream step state) = go state
710 r <- step defState st
718{-# INLINE_NORMAL maximum #-}
719maximum :: (Monad m, Ord a) => Stream m a -> m (Maybe a)
720maximum (Stream step state) = go Nothing state
723 r <- step defState st
725 Yield x s -> go (Just x) s
726 Skip s -> go Nothing s
727 Stop -> return Nothing
728 go (Just acc) st = do
729 r <- step defState st
732 | acc <= x -> go (Just x) s
733 | otherwise -> go (Just acc) s
734 Skip s -> go (Just acc) s
735 Stop -> return (Just acc)
737{-# INLINE_NORMAL maximumBy #-}
738maximumBy :: Monad m => (a -> a -> Ordering) -> Stream m a -> m (Maybe a)
739maximumBy cmp (Stream step state) = go Nothing state
742 r <- step defState st
744 Yield x s -> go (Just x) s
745 Skip s -> go Nothing s
746 Stop -> return Nothing
747 go (Just acc) st = do
748 r <- step defState st
750 Yield x s -> case cmp acc x of
751 GT -> go (Just acc) s
753 Skip s -> go (Just acc) s
754 Stop -> return (Just acc)
756{-# INLINE_NORMAL minimum #-}
757minimum :: (Monad m, Ord a) => Stream m a -> m (Maybe a)
758minimum (Stream step state) = go Nothing state
761 r <- step defState st
763 Yield x s -> go (Just x) s
764 Skip s -> go Nothing s
765 Stop -> return Nothing
766 go (Just acc) st = do
767 r <- step defState st
770 | acc <= x -> go (Just acc) s
771 | otherwise -> go (Just x) s
772 Skip s -> go (Just acc) s
773 Stop -> return (Just acc)
775{-# INLINE_NORMAL minimumBy #-}
776minimumBy :: Monad m => (a -> a -> Ordering) -> Stream m a -> m (Maybe a)
777minimumBy cmp (Stream step state) = go Nothing state
780 r <- step defState st
782 Yield x s -> go (Just x) s
783 Skip s -> go Nothing s
784 Stop -> return Nothing
785 go (Just acc) st = do
786 r <- step defState st
788 Yield x s -> case cmp acc x of
791 Skip s -> go (Just acc) s
792 Stop -> return (Just acc)
794{-# INLINE_NORMAL (!!) #-}
795(!!) :: (Monad m) => Stream m a -> Int -> m (Maybe a)
796(Stream step state) !! i = go i state
799 r <- step defState st
801 Yield x s | n < 0 -> return Nothing
802 | n == 0 -> return $ Just x
803 | otherwise -> go (n - 1) s
805 Stop -> return Nothing
807{-# INLINE_NORMAL lookup #-}
808lookup :: (Monad m, Eq a) => a -> Stream m (a, b) -> m (Maybe b)
809lookup e m = foldrM (\(a, b) xs -> if e == a then return (Just b) else xs)
812{-# INLINE_NORMAL findM #-}
813findM :: Monad m => (a -> m Bool) -> Stream m a -> m (Maybe a)
814findM p m = foldrM (\x xs -> p x >>= \r -> if r then return (Just x) else xs)
818find :: Monad m => (a -> Bool) -> Stream m a -> m (Maybe a)
819find p = findM (return . p)
821{-# INLINE_NORMAL findIndices #-}
822findIndices :: Monad m => (a -> Bool) -> Stream m a -> Stream m Int
823findIndices p (Stream step state) = Stream step' (state, 0)
825 {-# INLINE_LATE step' #-}
826 step' gst (st, i) = do
827 r <- step (adaptState gst) st
829 Yield x s -> if p x then Yield i (s, i+1) else Skip (s, i+1)
830 Skip s -> Skip (s, i+1)
833{-# INLINE toListRev #-}
834toListRev :: Monad m => Stream m a -> m [a]
835toListRev = foldl' (flip (:)) []
837-- We can implement reverse as:
839-- > reverse = foldlS (flip cons) nil
841-- However, this implementation is unusable because of the horrible performance
842-- of cons. So we just convert it to a list first and then stream from the
845-- XXX Maybe we can use an Array instead of a list here?
846{-# INLINE_NORMAL reverse #-}
847reverse :: Monad m => Stream m a -> Stream m a
848reverse m = Stream step Nothing
850 {-# INLINE_LATE step #-}
853 return $ Skip (Just xs)
854 step _ (Just (x:xs)) = return $ Yield x (Just xs)
855 step _ (Just []) = return Stop
857-- Much faster reverse for Storables
858{-# INLINE_NORMAL reverse' #-}
859reverse' :: forall m a. (MonadIO m, Storable a) => Stream m a -> Stream m a
861-- This commented implementation copies the whole stream into one single array
862-- and then streams from that array, this is 3-4x faster than the chunked code
863-- that follows. Though this could be problematic due to unbounded large
864-- allocations. We need to figure out why the chunked code is slower and if we
865-- can optimize the chunked code to work as fast as this one. It may be a
867import Foreign.ForeignPtr (touchForeignPtr)
868import Foreign.ForeignPtr.Unsafe (unsafeForeignPtrToPtr)
869import Foreign.Ptr (Ptr, plusPtr)
870reverse' m = Stream step Nothing
872 {-# INLINE_LATE step #-}
874 arr <- A.fromStreamD m
875 let p = aEnd arr `plusPtr` negate (sizeOf (undefined :: a))
876 return $ Skip $ Just (aStart arr, p)
878 step _ (Just (start, p)) | p < unsafeForeignPtrToPtr start = return Stop
880 step _ (Just (start, p)) = do
881 let !x = A.unsafeInlineIO $ do
883 touchForeignPtr start
885 next = p `plusPtr` negate (sizeOf (undefined :: a))
886 return $ Yield x (Just (start, next))
893 $ A.fromStreamDArraysOf A.defaultChunkSize m
896------------------------------------------------------------------------------
898------------------------------------------------------------------------------
900{-# INLINE_NORMAL splitSuffixBy' #-}
901splitSuffixBy' :: Monad m
902 => (a -> Bool) -> Fold m a b -> Stream m a -> Stream m b
903splitSuffixBy' predicate f (Stream step state) =
904 Stream (stepOuter f) (Just state)
908 {-# INLINE_LATE stepOuter #-}
909 stepOuter (Fold fstep initial done) gst (Just st) = do
910 res <- step (adaptState gst) st
916 then done acc' >>= \val -> return $ Yield val (Just s)
919 Skip s -> return $ Skip $ Just s
925 res <- step (adaptState gst) stt
930 then done acc' >>= \val -> return $ Yield val (Just s)
932 Skip s -> go SPEC s acc
933 Stop -> done acc >>= \val -> return $ Yield val Nothing
935 stepOuter _ _ Nothing = return Stop
937{-# INLINE_NORMAL groupsBy #-}
943groupsBy cmp f (Stream step state) = Stream (stepOuter f) (Just state, Nothing)
947 {-# INLINE_LATE stepOuter #-}
948 stepOuter (Fold fstep initial done) gst (Just st, Nothing) = do
949 res <- step (adaptState gst) st
956 Skip s -> return $ Skip $ (Just s, Nothing)
961 go !_ prev stt !acc = do
962 res <- step (adaptState gst) stt
969 else done acc >>= \r -> return $ Yield r (Just s, Just x)
970 Skip s -> go SPEC prev s acc
971 Stop -> done acc >>= \r -> return $ Yield r (Nothing, Nothing)
973 stepOuter (Fold fstep initial done) gst (Just st, Just prev) = do
975 acc' <- fstep acc prev
980 -- XXX code duplicated from the previous equation
982 res <- step (adaptState gst) stt
989 else done acc >>= \r -> return $ Yield r (Just s, Just x)
990 Skip s -> go SPEC s acc
991 Stop -> done acc >>= \r -> return $ Yield r (Nothing, Nothing)
993 stepOuter _ _ (Nothing,_) = return Stop
995{-# INLINE_NORMAL groupsRollingBy #-}
996groupsRollingBy :: Monad m
1001groupsRollingBy cmp f (Stream step state) =
1002 Stream (stepOuter f) (Just state, Nothing)
1005 {-# INLINE_LATE stepOuter #-}
1006 stepOuter (Fold fstep initial done) gst (Just st, Nothing) = do
1007 res <- step (adaptState gst) st
1014 Skip s -> return $ Skip $ (Just s, Nothing)
1018 go !_ prev stt !acc = do
1019 res <- step (adaptState gst) stt
1027 done acc >>= \r -> return $ Yield r (Just s, Just x)
1028 Skip s -> go SPEC prev s acc
1029 Stop -> done acc >>= \r -> return $ Yield r (Nothing, Nothing)
1031 stepOuter (Fold fstep initial done) gst (Just st, Just prev') = do
1033 acc' <- fstep acc prev'
1034 go SPEC prev' st acc'
1037 go !_ prevv stt !acc = do
1038 res <- step (adaptState gst) stt
1045 else done acc >>= \r -> return $ Yield r (Just s, Just x)
1046 Skip s -> go SPEC prevv s acc
1047 Stop -> done acc >>= \r -> return $ Yield r (Nothing, Nothing)
1049 stepOuter _ _ (Nothing, _) = return Stop
1051{-# INLINE_NORMAL splitBy #-}
1052splitBy :: Monad m => (a -> Bool) -> Fold m a b -> Stream m a -> Stream m b
1053splitBy predicate f (Stream step state) = Stream (step' f) (Just state)
1057 {-# INLINE_LATE step' #-}
1058 step' (Fold fstep initial done) gst (Just st) = initial >>= go SPEC st
1063 res <- step (adaptState gst) stt
1067 then done acc >>= \r -> return $ Yield r (Just s)
1071 Skip s -> go SPEC s acc
1072 Stop -> done acc >>= \r -> return $ Yield r Nothing
1074 step' _ _ Nothing = return Stop
1076{-# INLINE_NORMAL splitSuffixBy #-}
1077splitSuffixBy :: Monad m
1078 => (a -> Bool) -> Fold m a b -> Stream m a -> Stream m b
1079splitSuffixBy predicate f (Stream step state) = Stream (step' f) (Just state)
1083 {-# INLINE_LATE step' #-}
1084 step' (Fold fstep initial done) gst (Just st) = do
1085 res <- step (adaptState gst) st
1090 then done acc >>= \val -> return $ Yield val (Just s)
1095 Skip s -> return $ Skip $ Just s
1101 res <- step (adaptState gst) stt
1105 then done acc >>= \r -> return $ Yield r (Just s)
1109 Skip s -> go SPEC s acc
1110 Stop -> done acc >>= \r -> return $ Yield r Nothing
1112 step' _ _ Nothing = return Stop
1114{-# INLINE_NORMAL wordsBy #-}
1115wordsBy :: Monad m => (a -> Bool) -> Fold m a b -> Stream m a -> Stream m b
1116wordsBy predicate f (Stream step state) = Stream (stepOuter f) (Just state)
1120 {-# INLINE_LATE stepOuter #-}
1121 stepOuter (Fold fstep initial done) gst (Just st) = do
1122 res <- step (adaptState gst) st
1126 then return $ Skip (Just s)
1132 Skip s -> return $ Skip $ Just s
1138 res <- step (adaptState gst) stt
1142 then done acc >>= \r -> return $ Yield r (Just s)
1146 Skip s -> go SPEC s acc
1147 Stop -> done acc >>= \r -> return $ Yield r Nothing
1149 stepOuter _ _ Nothing = return Stop
1151-- String search algorithms:
1152-- http://www-igm.univ-mlv.fr/~lecroq/string/index.html
1155-- TODO can we unify the splitting operations using a splitting configuration
1156-- like in the split package.
1158data SplitStyle = Infix | Suffix | Prefix deriving (Eq, Show)
1160data SplitOptions = SplitOptions
1161 { style :: SplitStyle
1162 , withSep :: Bool -- ^ keep the separators in output
1163 -- , compact :: Bool -- ^ treat multiple consecutive separators as one
1164 -- , trimHead :: Bool -- ^ drop blank at head
1165 -- , trimTail :: Bool -- ^ drop blank at tail
1169data SplitOnState s a =
1174 | GO_KARP_RABIN s !(RB.Ring a) !(Ptr a)
1177{-# INLINE_NORMAL splitOn #-}
1179 :: forall m a b. (MonadIO m, Storable a, Enum a, Eq a)
1184splitOn patArr@Array{..} (Fold fstep initial done) (Stream step state) =
1185 Stream stepOuter GO_START
1189 patLen = A.length patArr
1190 maxIndex = patLen - 1
1191 elemBits = sizeOf (undefined :: a) * 8
1193 {-# INLINE_LATE stepOuter #-}
1194 stepOuter _ GO_START =
1196 then return $ Skip $ GO_EMPTY_PAT state
1199 r <- liftIO $ (A.unsafeIndexIO patArr 0)
1200 return $ Skip $ GO_SINGLE_PAT state r
1201 else if sizeOf (undefined :: a) * patLen
1202 <= sizeOf (undefined :: Word)
1203 then return $ Skip $ GO_SHORT_PAT state
1205 (rb, rhead) <- liftIO $ RB.new patLen
1206 return $ Skip $ GO_KARP_RABIN state rb rhead
1208 stepOuter gst (GO_SINGLE_PAT stt pat) = initial >>= go SPEC stt
1213 res <- step (adaptState gst) st
1219 return $ Yield r (GO_SINGLE_PAT s pat)
1220 else fstep acc x >>= go SPEC s
1221 Skip s -> go SPEC s acc
1222 Stop -> done acc >>= \r -> return $ Yield r GO_DONE
1224 stepOuter gst (GO_SHORT_PAT stt) = initial >>= go0 SPEC 0 (0 :: Word) stt
1229 mask = (1 `shiftL` (elemBits * patLen)) - 1
1231 addToWord wrd a = (wrd `shiftL` elemBits) .|. fromIntegral (fromEnum a)
1234 patWord = mask .&. A.foldl' addToWord 0 patArr
1236 go0 !_ !idx wrd st !acc = do
1237 res <- step (adaptState gst) st
1240 let wrd' = addToWord wrd x
1243 if wrd' .&. mask == patWord
1246 return $ Yield r (GO_SHORT_PAT s)
1247 else go1 SPEC wrd' s acc
1248 else go0 SPEC (idx + 1) wrd' s acc
1249 Skip s -> go0 SPEC idx wrd s acc
1252 then go2 wrd idx acc
1254 done acc' >>= \r -> return $ Yield r GO_DONE
1257 go1 !_ wrd st !acc = do
1258 res <- step (adaptState gst) st
1261 let wrd' = addToWord wrd x
1262 old = (mask .&. wrd) `shiftR` (elemBits * (patLen - 1))
1263 acc' <- fstep acc (toEnum $ fromIntegral old)
1264 if wrd' .&. mask == patWord
1265 then done acc' >>= \r -> return $ Yield r (GO_SHORT_PAT s)
1266 else go1 SPEC wrd' s acc'
1267 Skip s -> go1 SPEC wrd s acc
1269 acc' <- go2 wrd patLen acc
1270 done acc' >>= \r -> return $ Yield r GO_DONE
1272 go2 !wrd !n !acc | n > 0 = do
1273 let old = (mask .&. wrd) `shiftR` (elemBits * (n - 1))
1274 fstep acc (toEnum $ fromIntegral old) >>= go2 wrd (n - 1)
1275 go2 _ _ acc = return acc
1277 stepOuter gst (GO_KARP_RABIN stt rb rhead) = do
1278 initial >>= go0 SPEC 0 rhead stt
1282 k = 2891336453 :: Word32
1284 addCksum cksum a = cksum * k + fromIntegral (fromEnum a)
1285 deltaCksum cksum old new =
1286 addCksum cksum new - coeff * fromIntegral (fromEnum old)
1288 -- XXX shall we use a random starting hash or 1 instead of 0?
1289 patHash = A.foldl' addCksum 0 patArr
1292 go0 !_ !idx !rh st !acc = do
1293 res <- step (adaptState gst) st
1296 rh' <- liftIO $ RB.unsafeInsert rb rh x
1299 let fold = RB.unsafeFoldRing (RB.ringBound rb)
1300 let !ringHash = fold addCksum 0 rb
1301 if ringHash == patHash
1302 then go2 SPEC ringHash rh' s acc
1303 else go1 SPEC ringHash rh' s acc
1304 else go0 SPEC (idx + 1) rh' s acc
1305 Skip s -> go0 SPEC idx rh s acc
1307 !acc' <- if idx /= 0
1308 then RB.unsafeFoldRingM rh fstep acc rb
1310 done acc' >>= \r -> return $ Yield r GO_DONE
1312 -- XXX Theoretically this code can do 4 times faster if GHC generates
1313 -- optimal code. If we use just "(cksum' == patHash)" condition it goes
1314 -- 4x faster, as soon as we add the "RB.unsafeEqArray rb v" condition
1315 -- the generated code changes drastically and becomes 4x slower. Need
1316 -- to investigate what is going on with GHC.
1318 go1 !_ !cksum !rh st !acc = do
1319 res <- step (adaptState gst) st
1322 old <- liftIO $ peek rh
1323 let cksum' = deltaCksum cksum old x
1324 acc' <- fstep acc old
1326 if (cksum' == patHash)
1328 rh' <- liftIO (RB.unsafeInsert rb rh x)
1329 go2 SPEC cksum' rh' s acc'
1331 rh' <- liftIO (RB.unsafeInsert rb rh x)
1332 go1 SPEC cksum' rh' s acc'
1333 Skip s -> go1 SPEC cksum rh s acc
1335 acc' <- RB.unsafeFoldRingFullM rh fstep acc rb
1336 done acc' >>= \r -> return $ Yield r GO_DONE
1338 go2 !_ !cksum' !rh' s !acc' = do
1339 if RB.unsafeEqArray rb rh' patArr
1342 return $ Yield r (GO_KARP_RABIN s rb rhead)
1343 else go1 SPEC cksum' rh' s acc'
1345 stepOuter gst (GO_EMPTY_PAT st) = do
1346 res <- step (adaptState gst) st
1351 done acc' >>= \r -> return $ Yield r (GO_EMPTY_PAT s)
1352 Skip s -> return $ Skip (GO_EMPTY_PAT s)
1355 stepOuter _ GO_DONE = return Stop
1357{-# INLINE_NORMAL splitSuffixOn #-}
1359 :: forall m a b. (MonadIO m, Storable a, Enum a, Eq a)
1365splitSuffixOn withSep patArr@Array{..} (Fold fstep initial done)
1366 (Stream step state) =
1367 Stream stepOuter GO_START
1371 patLen = A.length patArr
1372 maxIndex = patLen - 1
1373 elemBits = sizeOf (undefined :: a) * 8
1375 {-# INLINE_LATE stepOuter #-}
1376 stepOuter _ GO_START =
1378 then return $ Skip $ GO_EMPTY_PAT state
1381 r <- liftIO $ (A.unsafeIndexIO patArr 0)
1382 return $ Skip $ GO_SINGLE_PAT state r
1383 else if sizeOf (undefined :: a) * patLen
1384 <= sizeOf (undefined :: Word)
1385 then return $ Skip $ GO_SHORT_PAT state
1387 (rb, rhead) <- liftIO $ RB.new patLen
1388 return $ Skip $ GO_KARP_RABIN state rb rhead
1390 stepOuter gst (GO_SINGLE_PAT stt pat) = do
1391 -- This first part is the only difference between splitOn and
1393 -- If the last element is a separator do not issue a blank segment.
1394 res <- step (adaptState gst) stt
1400 acc' <- if withSep then fstep acc x else return acc
1401 done acc' >>= \r -> return $ Yield r (GO_SINGLE_PAT s pat)
1402 else fstep acc x >>= go SPEC s
1403 Skip s -> return $ Skip $ (GO_SINGLE_PAT s pat)
1408 -- This is identical for splitOn and splitSuffixOn
1410 res <- step (adaptState gst) st
1415 acc' <- if withSep then fstep acc x else return acc
1417 return $ Yield r (GO_SINGLE_PAT s pat)
1418 else fstep acc x >>= go SPEC s
1419 Skip s -> go SPEC s acc
1420 Stop -> done acc >>= \r -> return $ Yield r GO_DONE
1422 stepOuter gst (GO_SHORT_PAT stt) = do
1424 -- Call "initial" only if the stream yields an element, otherwise we
1425 -- may call "initial" but never yield anything. initial may produce a
1426 -- side effect, therefore we will end up doing and discard a side
1431 res <- step (adaptState gst) stt
1435 let wrd' = addToWord wrd x
1436 acc' <- if withSep then fstep acc x else return acc
1439 if wrd' .&. mask == patWord
1440 then done acc' >>= \r -> return $ Yield r (GO_SHORT_PAT s)
1441 else go0 SPEC (idx + 1) wrd' s acc'
1442 else go0 SPEC (idx + 1) wrd' s acc'
1443 Skip s -> return $ Skip (GO_SHORT_PAT s)
1449 mask = (1 `shiftL` (elemBits * patLen)) - 1
1451 addToWord wrd a = (wrd `shiftL` elemBits) .|. fromIntegral (fromEnum a)
1454 patWord = mask .&. A.foldl' addToWord 0 patArr
1456 go0 !_ !idx wrd st !acc = do
1457 res <- step (adaptState gst) st
1460 let wrd' = addToWord wrd x
1461 acc' <- if withSep then fstep acc x else return acc
1464 if wrd' .&. mask == patWord
1467 return $ Yield r (GO_SHORT_PAT s)
1468 else go1 SPEC wrd' s acc'
1469 else go0 SPEC (idx + 1) wrd' s acc'
1470 Skip s -> go0 SPEC idx wrd s acc
1472 if (idx == maxIndex) && (wrd .&. mask == patWord)
1475 acc' <- if idx /= 0 && not withSep
1476 then go2 wrd idx acc
1478 done acc' >>= \r -> return $ Yield r GO_DONE
1481 go1 !_ wrd st !acc = do
1482 res <- step (adaptState gst) st
1485 let wrd' = addToWord wrd x
1486 old = (mask .&. wrd) `shiftR` (elemBits * (patLen - 1))
1489 else fstep acc (toEnum $ fromIntegral old)
1490 if wrd' .&. mask == patWord
1491 then done acc' >>= \r -> return $ Yield r (GO_SHORT_PAT s)
1492 else go1 SPEC wrd' s acc'
1493 Skip s -> go1 SPEC wrd s acc
1495 -- If the last sequence is a separator do not issue a blank
1497 if wrd .&. mask == patWord
1502 else go2 wrd patLen acc
1503 done acc' >>= \r -> return $ Yield r GO_DONE
1505 go2 !wrd !n !acc | n > 0 = do
1506 let old = (mask .&. wrd) `shiftR` (elemBits * (n - 1))
1507 fstep acc (toEnum $ fromIntegral old) >>= go2 wrd (n - 1)
1508 go2 _ _ acc = return acc
1510 stepOuter gst (GO_KARP_RABIN stt rb rhead) = do
1512 res <- step (adaptState gst) stt
1516 acc' <- if withSep then fstep acc x else return acc
1517 rh' <- liftIO (RB.unsafeInsert rb rhead x)
1520 let fold = RB.unsafeFoldRing (RB.ringBound rb)
1521 let !ringHash = fold addCksum 0 rb
1522 if ringHash == patHash
1523 then go2 SPEC ringHash rh' s acc'
1524 else go0 SPEC (idx + 1) rh' s acc'
1525 else go0 SPEC (idx + 1) rh' s acc'
1526 Skip s -> return $ Skip (GO_KARP_RABIN s rb rhead)
1531 k = 2891336453 :: Word32
1533 addCksum cksum a = cksum * k + fromIntegral (fromEnum a)
1534 deltaCksum cksum old new =
1535 addCksum cksum new - coeff * fromIntegral (fromEnum old)
1537 -- XXX shall we use a random starting hash or 1 instead of 0?
1538 patHash = A.foldl' addCksum 0 patArr
1541 go0 !_ !idx !rh st !acc = do
1542 res <- step (adaptState gst) st
1545 acc' <- if withSep then fstep acc x else return acc
1546 rh' <- liftIO (RB.unsafeInsert rb rh x)
1549 let fold = RB.unsafeFoldRing (RB.ringBound rb)
1550 let !ringHash = fold addCksum 0 rb
1551 if ringHash == patHash
1552 then go2 SPEC ringHash rh' s acc'
1553 else go1 SPEC ringHash rh' s acc'
1554 else go0 SPEC (idx + 1) rh' s acc'
1555 Skip s -> go0 SPEC idx rh s acc
1557 -- do not issue a blank segment when we end at pattern
1558 if (idx == maxIndex) && RB.unsafeEqArray rb rh patArr
1561 !acc' <- if idx /= 0 && not withSep
1562 then RB.unsafeFoldRingM rh fstep acc rb
1564 done acc' >>= \r -> return $ Yield r GO_DONE
1566 -- XXX Theoretically this code can do 4 times faster if GHC generates
1567 -- optimal code. If we use just "(cksum' == patHash)" condition it goes
1568 -- 4x faster, as soon as we add the "RB.unsafeEqArray rb v" condition
1569 -- the generated code changes drastically and becomes 4x slower. Need
1570 -- to investigate what is going on with GHC.
1572 go1 !_ !cksum !rh st !acc = do
1573 res <- step (adaptState gst) st
1576 old <- liftIO $ peek rh
1577 let cksum' = deltaCksum cksum old x
1582 if (cksum' == patHash)
1584 rh' <- liftIO (RB.unsafeInsert rb rh x)
1585 go2 SPEC cksum' rh' s acc'
1587 rh' <- liftIO (RB.unsafeInsert rb rh x)
1588 go1 SPEC cksum' rh' s acc'
1589 Skip s -> go1 SPEC cksum rh s acc
1591 if RB.unsafeEqArray rb rh patArr
1596 else RB.unsafeFoldRingFullM rh fstep acc rb
1597 done acc' >>= \r -> return $ Yield r GO_DONE
1599 go2 !_ !cksum' !rh' s !acc' = do
1600 if RB.unsafeEqArray rb rh' patArr
1603 return $ Yield r (GO_KARP_RABIN s rb rhead)
1604 else go1 SPEC cksum' rh' s acc'
1606 stepOuter gst (GO_EMPTY_PAT st) = do
1607 res <- step (adaptState gst) st
1612 done acc' >>= \r -> return $ Yield r (GO_EMPTY_PAT s)
1613 Skip s -> return $ Skip (GO_EMPTY_PAT s)
1616 stepOuter _ GO_DONE = return Stop
1618------------------------------------------------------------------------------
1620------------------------------------------------------------------------------
1622{-# INLINE_NORMAL isPrefixOf #-}
1623isPrefixOf :: (Eq a, Monad m) => Stream m a -> Stream m a -> m Bool
1624isPrefixOf (Stream stepa ta) (Stream stepb tb) = go (ta, tb, Nothing)
1626 go (sa, sb, Nothing) = do
1627 r <- stepa defState sa
1629 Yield x sa' -> go (sa', sb, Just x)
1630 Skip sa' -> go (sa', sb, Nothing)
1633 go (sa, sb, Just x) = do
1634 r <- stepb defState sb
1638 then go (sa, sb', Nothing)
1640 Skip sb' -> go (sa, sb', Just x)
1641 Stop -> return False
1643{-# INLINE_NORMAL isSubsequenceOf #-}
1644isSubsequenceOf :: (Eq a, Monad m) => Stream m a -> Stream m a -> m Bool
1645isSubsequenceOf (Stream stepa ta) (Stream stepb tb) = go (ta, tb, Nothing)
1647 go (sa, sb, Nothing) = do
1648 r <- stepa defState sa
1650 Yield x sa' -> go (sa', sb, Just x)
1651 Skip sa' -> go (sa', sb, Nothing)
1654 go (sa, sb, Just x) = do
1655 r <- stepb defState sb
1659 then go (sa, sb', Nothing)
1660 else go (sa, sb', Just x)
1661 Skip sb' -> go (sa, sb', Just x)
1662 Stop -> return False
1664{-# INLINE_NORMAL stripPrefix #-}
1667 => Stream m a -> Stream m a -> m (Maybe (Stream m a))
1668stripPrefix (Stream stepa ta) (Stream stepb tb) = go (ta, tb, Nothing)
1670 go (sa, sb, Nothing) = do
1671 r <- stepa defState sa
1673 Yield x sa' -> go (sa', sb, Just x)
1674 Skip sa' -> go (sa', sb, Nothing)
1675 Stop -> return $ Just (Stream stepb sb)
1677 go (sa, sb, Just x) = do
1678 r <- stepb defState sb
1682 then go (sa, sb', Nothing)
1684 Skip sb' -> go (sa, sb', Just x)
1685 Stop -> return Nothing
1687------------------------------------------------------------------------------
1689------------------------------------------------------------------------------
1691-- | Execute a monadic action for each element of the 'Stream'
1692{-# INLINE_NORMAL mapM_ #-}
1693mapM_ :: Monad m => (a -> m b) -> Stream m a -> m ()
1694mapM_ m = drain . mapM m
1696-------------------------------------------------------------------------------
1697-- Stream transformations using Unfolds
1698-------------------------------------------------------------------------------
1700-- | @concatMapU unfold stream@ uses @unfold@ to map the input stream elements
1701-- to streams and then flattens the generated streams into a single output
1704-- This is like 'concatMap' but uses an unfold with an explicit state to
1705-- generate the stream instead of a 'Stream' type generator. This allows better
1706-- optimization via fusion. This can be many times more efficient than
1709{-# INLINE_NORMAL concatMapU #-}
1710concatMapU :: Monad m => Unfold m a b -> Stream m a -> Stream m b
1711concatMapU (Unfold istep inject) (Stream ostep u) = Stream step (Left u)
1713 {-# INLINE_LATE step #-}
1714 step gst (Left t) = do
1715 r <- ostep (adaptState gst) t
1719 s `seq` return (Skip (Right (s, t')))
1720 Skip t' -> return $ Skip (Left t')
1721 Stop -> return $ Stop
1723 step _ (Right (s, t)) = do
1726 Yield x s' -> Yield x (Right (s', t))
1727 Skip s' -> Skip (Right (s', t))
1728 Stop -> Skip (Left t)
1730------------------------------------------------------------------------------
1732------------------------------------------------------------------------------
1734-- | Run a side effect before the stream yields its first element.
1735{-# INLINE_NORMAL before #-}
1736before :: Monad m => m b -> Stream m a -> Stream m a
1737before action (Stream step state) = Stream step' Nothing
1741 {-# INLINE_LATE step' #-}
1742 step' _ Nothing = action >> return (Skip (Just state))
1744 step' gst (Just st) = do
1747 Yield x s -> return $ Yield x (Just s)
1748 Skip s -> return $ Skip (Just s)
1751-- | Run a side effect whenever the stream stops normally.
1752{-# INLINE_NORMAL after #-}
1753after :: Monad m => m b -> Stream m a -> Stream m a
1754after action (Stream step state) = Stream step' state
1758 {-# INLINE_LATE step' #-}
1762 Yield x s -> return $ Yield x s
1763 Skip s -> return $ Skip s
1764 Stop -> action >> return Stop
1766-- XXX These combinators are expensive due to the call to
1767-- onException/handle/try on each step. Therefore, when possible, they should
1768-- be called in an outer loop where we perform less iterations. For example, we
1769-- cannot call them on each iteration in a char stream, instead we can call
1770-- them when doing an IO on an array.
1772-- XXX For high performance error checks in busy streams we may need another
1773-- Error constructor in step.
1775-- | Run a side effect whenever the stream aborts due to an exception. The
1776-- exception is not caught simply rethrown.
1777{-# INLINE_NORMAL onException #-}
1778onException :: MonadCatch m => m b -> Stream m a -> Stream m a
1779onException action (Stream step state) = Stream step' state
1783 {-# INLINE_LATE step' #-}
1785 res <- step gst st `MC.onException` action
1787 Yield x s -> return $ Yield x s
1788 Skip s -> return $ Skip s
1791-- | Run a side effect whenever the stream stops normally or aborts due to an
1793{-# INLINE finally #-}
1794finally :: MonadCatch m => m b -> Stream m a -> Stream m a
1795finally action xs = after action $ onException action xs
1797-- XXX bracket is like concatMap, it generates a stream and then flattens it.
1798-- Like concatMap it has 10x worse performance compared to linear fused
1801-- | Run the first action before the stream starts and remember its output,
1802-- generate a stream using the output, run the second action using the
1803-- remembered value as an argument whenever the stream ends normally or due to
1805{-# INLINE_NORMAL bracket #-}
1806bracket :: MonadCatch m => m b -> (b -> m c) -> (b -> Stream m a) -> Stream m a
1807bracket bef aft bet = Stream step' Nothing
1811 {-# INLINE_LATE step' #-}
1812 step' _ Nothing = bef >>= \x -> return (Skip (Just (bet x, x)))
1814 -- NOTE: It is important to use UnStream instead of the Stream pattern
1815 -- here, otherwise we get huge perf degradation, see note in concatMap.
1816 step' gst (Just (UnStream step state, v)) = do
1817 res <- step gst state `MC.onException` aft v
1819 Yield x s -> return $ Yield x (Just (Stream step s, v))
1820 Skip s -> return $ Skip (Just (Stream step s, v))
1821 Stop -> aft v >> return Stop
1823-- | When evaluating a stream if an exception occurs, stream evaluation aborts
1824-- and the specified exception handler is run with the exception as argument.
1825{-# INLINE_NORMAL handle #-}
1826handle :: (MonadCatch m, Exception e) => (e -> m a) -> Stream m a -> Stream m a
1827handle f (Stream step state) = Stream step' (Just state)
1831 {-# INLINE_LATE step' #-}
1832 step' gst (Just st) = do
1833 res <- MC.try $ step gst st
1835 Left e -> f e >>= \x -> return (Yield x Nothing)
1836 Right r -> case r of
1837 Yield x s -> return $ Yield x (Just s)
1838 Skip s -> return $ Skip (Just s)
1841 step' _ Nothing = return Stop
1843-------------------------------------------------------------------------------
1844-- General transformation
1845-------------------------------------------------------------------------------
1847{-# INLINE_NORMAL transform #-}
1848transform :: Monad m => Pipe m a b -> Stream m a -> Stream m b
1849transform (Pipe pstep1 pstep2 pstate) (Stream step state) =
1850 Stream step' (Consume pstate, state)
1854 {-# INLINE_LATE step' #-}
1856 step' gst (Consume pst, st) = pst `seq` do
1857 r <- step (adaptState gst) st
1862 Pipe.Yield b pst' -> return $ Yield b (pst', s)
1863 Pipe.Continue pst' -> return $ Skip (pst', s)
1864 Skip s -> return $ Skip (Consume pst, s)
1867 step' _ (Produce pst, st) = pst `seq` do
1870 Pipe.Yield b pst' -> return $ Yield b (pst', st)
1871 Pipe.Continue pst' -> return $ Skip (pst', st)
1873------------------------------------------------------------------------------
1874-- Transformation by Folding (Scans)
1875------------------------------------------------------------------------------
1877------------------------------------------------------------------------------
1879------------------------------------------------------------------------------
1881-- XXX Is a prescan useful, discarding the last step does not sound useful? I
1882-- am not sure about the utility of this function, so this is implemented but
1883-- not exposed. We can expose it if someone provides good reasons why this is
1886-- XXX We have to execute the stream one step ahead to know that we are at the
1887-- last step. The vector implementation of prescan executes the last fold step
1888-- but does not yield the result. This means we have executed the effect but
1889-- discarded value. This does not sound right. In this implementation we are
1890-- not executing the last fold step.
1891{-# INLINE_NORMAL prescanlM' #-}
1892prescanlM' :: Monad m => (b -> a -> m b) -> m b -> Stream m a -> Stream m b
1893prescanlM' f mz (Stream step state) = Stream step' (state, mz)
1895 {-# INLINE_LATE step' #-}
1896 step' gst (st, prev) = do
1897 r <- step (adaptState gst) st
1901 return $ Yield acc (s, f acc x)
1902 Skip s -> return $ Skip (s, prev)
1905{-# INLINE prescanl' #-}
1906prescanl' :: Monad m => (b -> a -> b) -> b -> Stream m a -> Stream m b
1907prescanl' f z = prescanlM' (\a b -> return (f a b)) (return z)
1909------------------------------------------------------------------------------
1910-- Monolithic postscans (postscan followed by a map)
1911------------------------------------------------------------------------------
1913-- The performance of a modular postscan followed by a map seems to be
1914-- equivalent to this monolithic scan followed by map therefore we may not need
1915-- this implementation. We just have it for performance comparison and in case
1916-- modular version does not perform well in some situation.
1918{-# INLINE_NORMAL postscanlMx' #-}
1919postscanlMx' :: Monad m
1920 => (x -> a -> m x) -> m x -> (x -> m b) -> Stream m a -> Stream m b
1921postscanlMx' fstep begin done (Stream step state) = do
1922 Stream step' (state, begin)
1924 {-# INLINE_LATE step' #-}
1925 step' gst (st, acc) = do
1926 r <- step (adaptState gst) st
1932 v `seq` y `seq` return (Yield v (s, return y))
1933 Skip s -> return $ Skip (s, acc)
1936{-# INLINE_NORMAL postscanlx' #-}
1937postscanlx' :: Monad m
1938 => (x -> a -> x) -> x -> (x -> b) -> Stream m a -> Stream m b
1939postscanlx' fstep begin done s =
1940 postscanlMx' (\b a -> return (fstep b a)) (return begin) (return . done) s
1942-- XXX do we need consM strict to evaluate the begin value?
1943{-# INLINE scanlMx' #-}
1945 => (x -> a -> m x) -> m x -> (x -> m b) -> Stream m a -> Stream m b
1946scanlMx' fstep begin done s =
1947 (begin >>= \x -> x `seq` done x) `consM` postscanlMx' fstep begin done s
1949{-# INLINE scanlx' #-}
1951 => (x -> a -> x) -> x -> (x -> b) -> Stream m a -> Stream m b
1952scanlx' fstep begin done s =
1953 scanlMx' (\b a -> return (fstep b a)) (return begin) (return . done) s
1955------------------------------------------------------------------------------
1957------------------------------------------------------------------------------
1959{-# INLINE_NORMAL postscanlM' #-}
1960postscanlM' :: Monad m => (b -> a -> m b) -> b -> Stream m a -> Stream m b
1961postscanlM' fstep begin (Stream step state) =
1962 begin `seq` Stream step' (state, begin)
1964 {-# INLINE_LATE step' #-}
1965 step' gst (st, acc) = acc `seq` do
1966 r <- step (adaptState gst) st
1970 y `seq` return (Yield y (s, y))
1971 Skip s -> return $ Skip (s, acc)
1974{-# INLINE_NORMAL postscanl' #-}
1975postscanl' :: Monad m => (a -> b -> a) -> a -> Stream m b -> Stream m a
1976postscanl' f = postscanlM' (\a b -> return (f a b))
1978{-# INLINE_NORMAL postscanlM #-}
1979postscanlM :: Monad m => (b -> a -> m b) -> b -> Stream m a -> Stream m b
1980postscanlM fstep begin (Stream step state) = Stream step' (state, begin)
1982 {-# INLINE_LATE step' #-}
1983 step' gst (st, acc) = do
1984 r <- step (adaptState gst) st
1988 return (Yield y (s, y))
1989 Skip s -> return $ Skip (s, acc)
1992{-# INLINE_NORMAL postscanl #-}
1993postscanl :: Monad m => (a -> b -> a) -> a -> Stream m b -> Stream m a
1994postscanl f = postscanlM (\a b -> return (f a b))
1996{-# INLINE_NORMAL scanlM' #-}
1997scanlM' :: Monad m => (b -> a -> m b) -> b -> Stream m a -> Stream m b
1998scanlM' fstep begin s = begin `seq` (begin `cons` postscanlM' fstep begin s)
2000{-# INLINE scanl' #-}
2001scanl' :: Monad m => (b -> a -> b) -> b -> Stream m a -> Stream m b
2002scanl' f = scanlM' (\a b -> return (f a b))
2004{-# INLINE_NORMAL scanlM #-}
2005scanlM :: Monad m => (b -> a -> m b) -> b -> Stream m a -> Stream m b
2006scanlM fstep begin s = begin `cons` postscanlM fstep begin s
2009scanl :: Monad m => (b -> a -> b) -> b -> Stream m a -> Stream m b
2010scanl f = scanlM (\a b -> return (f a b))
2012{-# INLINE_NORMAL scanl1M #-}
2013scanl1M :: Monad m => (a -> a -> m a) -> Stream m a -> Stream m a
2014scanl1M fstep (Stream step state) = Stream step' (state, Nothing)
2016 {-# INLINE_LATE step' #-}
2017 step' gst (st, Nothing) = do
2020 Yield x s -> return $ Yield x (s, Just x)
2021 Skip s -> return $ Skip (s, Nothing)
2024 step' gst (st, Just acc) = do
2029 return $ Yield z (s, Just z)
2030 Skip s -> return $ Skip (s, Just acc)
2033{-# INLINE scanl1 #-}
2034scanl1 :: Monad m => (a -> a -> a) -> Stream m a -> Stream m a
2035scanl1 f = scanl1M (\x y -> return (f x y))
2037{-# INLINE_NORMAL scanl1M' #-}
2038scanl1M' :: Monad m => (a -> a -> m a) -> Stream m a -> Stream m a
2039scanl1M' fstep (Stream step state) = Stream step' (state, Nothing)
2041 {-# INLINE_LATE step' #-}
2042 step' gst (st, Nothing) = do
2045 Yield x s -> x `seq` return $ Yield x (s, Just x)
2046 Skip s -> return $ Skip (s, Nothing)
2049 step' gst (st, Just acc) = acc `seq` do
2054 z `seq` return $ Yield z (s, Just z)
2055 Skip s -> return $ Skip (s, Just acc)
2058{-# INLINE scanl1' #-}
2059scanl1' :: Monad m => (a -> a -> a) -> Stream m a -> Stream m a
2060scanl1' f = scanl1M' (\x y -> return (f x y))
2063tap :: Monad m => Fold m a b -> Stream m a -> Stream m a
2064tap (Fold fstep initial extract) (Stream step state) = Stream step' Nothing
2068 step' _ Nothing = do
2070 return $ Skip (Just (r, state))
2072 step' gst (Just (acc, st)) = do
2077 return $ Yield x (Just (acc', s))
2078 Skip s -> return $ Skip (Just (acc, s))
2083-------------------------------------------------------------------------------
2085-------------------------------------------------------------------------------
2087{-# INLINE_NORMAL takeWhileM #-}
2088takeWhileM :: Monad m => (a -> m Bool) -> Stream m a -> Stream m a
2089takeWhileM f (Stream step state) = Stream step' state
2091 {-# INLINE_LATE step' #-}
2097 return $ if b then Yield x s else Stop
2098 Skip s -> return $ Skip s
2101{-# INLINE takeWhile #-}
2102takeWhile :: Monad m => (a -> Bool) -> Stream m a -> Stream m a
2103takeWhile f = takeWhileM (return . f)
2105{-# INLINE_NORMAL drop #-}
2106drop :: Monad m => Int -> Stream m a -> Stream m a
2107drop n (Stream step state) = Stream step' (state, Just n)
2109 {-# INLINE_LATE step' #-}
2110 step' gst (st, Just i)
2115 Yield _ s -> Skip (s, Just (i - 1))
2116 Skip s -> Skip (s, Just i)
2118 | otherwise = return $ Skip (st, Nothing)
2120 step' gst (st, Nothing) = do
2124 Yield x s -> Yield x (s, Nothing)
2125 Skip s -> Skip (s, Nothing)
2128data DropWhileState s a
2130 | DropWhileYield a s
2133{-# INLINE_NORMAL dropWhileM #-}
2134dropWhileM :: Monad m => (a -> m Bool) -> Stream m a -> Stream m a
2135dropWhileM f (Stream step state) = Stream step' (DropWhileDrop state)
2137 {-# INLINE_LATE step' #-}
2138 step' gst (DropWhileDrop st) = do
2144 then return $ Skip (DropWhileDrop s)
2145 else return $ Skip (DropWhileYield x s)
2146 Skip s -> return $ Skip (DropWhileDrop s)
2149 step' gst (DropWhileNext st) = do
2152 Yield x s -> return $ Skip (DropWhileYield x s)
2153 Skip s -> return $ Skip (DropWhileNext s)
2156 step' _ (DropWhileYield x st) = return $ Yield x (DropWhileNext st)
2158{-# INLINE dropWhile #-}
2159dropWhile :: Monad m => (a -> Bool) -> Stream m a -> Stream m a
2160dropWhile f = dropWhileM (return . f)
2162{-# INLINE_NORMAL filterM #-}
2163filterM :: Monad m => (a -> m Bool) -> Stream m a -> Stream m a
2164filterM f (Stream step state) = Stream step' state
2166 {-# INLINE_LATE step' #-}
2175 Skip s -> return $ Skip s
2178{-# INLINE filter #-}
2179filter :: Monad m => (a -> Bool) -> Stream m a -> Stream m a
2180filter f = filterM (return . f)
2182{-# INLINE_NORMAL uniq #-}
2183uniq :: (Eq a, Monad m) => Stream m a -> Stream m a
2184uniq (Stream step state) = Stream step' (Nothing, state)
2186 {-# INLINE_LATE step' #-}
2187 step' gst (Nothing, st) = do
2190 Yield x s -> return $ Yield x (Just x, s)
2191 Skip s -> return $ Skip (Nothing, s)
2193 step' gst (Just x, st) = do
2196 Yield y s | x == y -> return $ Skip (Just x, s)
2197 | otherwise -> return $ Yield y (Just y, s)
2198 Skip s -> return $ Skip (Just x, s)
2201------------------------------------------------------------------------------
2202-- Transformation by Mapping
2203------------------------------------------------------------------------------
2205{-# INLINE_NORMAL sequence #-}
2206sequence :: Monad m => Stream m (m a) -> Stream m a
2207sequence (Stream step state) = Stream step' state
2209 {-# INLINE_LATE step' #-}
2211 r <- step (adaptState gst) st
2213 Yield x s -> x >>= \a -> return (Yield a s)
2214 Skip s -> return $ Skip s
2217------------------------------------------------------------------------------
2219------------------------------------------------------------------------------
2221data LoopState x s = FirstYield s
2222 | InterspersingYield s
2225{-# INLINE_NORMAL intersperseM #-}
2226intersperseM :: Monad m => m a -> Stream m a -> Stream m a
2227intersperseM m (Stream step state) = Stream step' (FirstYield state)
2229 {-# INLINE_LATE step' #-}
2230 step' gst (FirstYield st) = do
2234 Yield x s -> Skip (YieldAndCarry x s)
2235 Skip s -> Skip (FirstYield s)
2238 step' gst (InterspersingYield st) = do
2243 return $ Yield a (YieldAndCarry x s)
2244 Skip s -> return $ Skip $ InterspersingYield s
2247 step' _ (YieldAndCarry x st) = return $ Yield x (InterspersingYield st)
2252 | SuffixYield a (SuffixState s a)
2254{-# INLINE_NORMAL insertAfterEach #-}
2255insertAfterEach :: forall m a. Monad m => m a -> Stream m a -> Stream m a
2256insertAfterEach action (Stream step state) = Stream step' (SuffixElem state)
2258 {-# INLINE_LATE step' #-}
2259 step' gst (SuffixElem st) = do
2262 Yield x s -> Skip (SuffixYield x (SuffixSuffix s))
2263 Skip s -> Skip (SuffixElem s)
2266 step' _ (SuffixSuffix st) = do
2267 action >>= \r -> return $ Skip (SuffixYield r (SuffixElem st))
2269 step' _ (SuffixYield x next) = return $ Yield x next
2271{-# INLINE intersperse #-}
2272intersperse :: Monad m => a -> Stream m a -> Stream m a
2273intersperse a = intersperseM (return a)
2275{-# INLINE_NORMAL insertBy #-}
2276insertBy :: Monad m => (a -> a -> Ordering) -> a -> Stream m a -> Stream m a
2277insertBy cmp a (Stream step state) = Stream step' (state, False, Nothing)
2279 {-# INLINE_LATE step' #-}
2280 step' gst (st, False, _) = do
2283 Yield x s -> case cmp a x of
2284 GT -> return $ Yield x (s, False, Nothing)
2285 _ -> return $ Yield a (s, True, Just x)
2286 Skip s -> return $ Skip (s, False, Nothing)
2287 Stop -> return $ Yield a (st, True, Nothing)
2289 step' _ (_, True, Nothing) = return Stop
2291 step' gst (st, True, Just prev) = do
2294 Yield x s -> return $ Yield prev (s, True, Just x)
2295 Skip s -> return $ Skip (s, True, Just prev)
2296 Stop -> return $ Yield prev (st, True, Nothing)
2298------------------------------------------------------------------------------
2300------------------------------------------------------------------------------
2302{-# INLINE_NORMAL deleteBy #-}
2303deleteBy :: Monad m => (a -> a -> Bool) -> a -> Stream m a -> Stream m a
2304deleteBy eq x (Stream step state) = Stream step' (state, False)
2306 {-# INLINE_LATE step' #-}
2307 step' gst (st, False) = do
2310 Yield y s -> return $
2311 if eq x y then Skip (s, True) else Yield y (s, False)
2312 Skip s -> return $ Skip (s, False)
2315 step' gst (st, True) = do
2318 Yield y s -> return $ Yield y (s, True)
2319 Skip s -> return $ Skip (s, True)
2322------------------------------------------------------------------------------
2323-- Transformation by Map and Filter
2324------------------------------------------------------------------------------
2326-- XXX Will this always fuse properly?
2327{-# INLINE_NORMAL mapMaybe #-}
2328mapMaybe :: Monad m => (a -> Maybe b) -> Stream m a -> Stream m b
2329mapMaybe f = fmap fromJust . filter isJust . map f
2331{-# INLINE_NORMAL mapMaybeM #-}
2332mapMaybeM :: Monad m => (a -> m (Maybe b)) -> Stream m a -> Stream m b
2333mapMaybeM f = fmap fromJust . filter isJust . mapM f
2335------------------------------------------------------------------------------
2337------------------------------------------------------------------------------
2339{-# INLINE_NORMAL indexed #-}
2340indexed :: Monad m => Stream m a -> Stream m (Int, a)
2341indexed (Stream step state) = Stream step' (state, 0)
2343 {-# INLINE_LATE step' #-}
2344 step' gst (st, i) = i `seq` do
2345 r <- step (adaptState gst) st
2347 Yield x s -> return $ Yield (i, x) (s, i+1)
2348 Skip s -> return $ Skip (s, i)
2351{-# INLINE_NORMAL indexedR #-}
2352indexedR :: Monad m => Int -> Stream m a -> Stream m (Int, a)
2353indexedR m (Stream step state) = Stream step' (state, m)
2355 {-# INLINE_LATE step' #-}
2356 step' gst (st, i) = i `seq` do
2357 r <- step (adaptState gst) st
2359 Yield x s -> let i' = i - 1
2360 in return $ Yield (i, x) (s, i')
2361 Skip s -> return $ Skip (s, i)
2364{-# INLINE_NORMAL zipWithM #-}
2366 => (a -> b -> m c) -> Stream m a -> Stream m b -> Stream m c
2367zipWithM f (Stream stepa ta) (Stream stepb tb) = Stream step (ta, tb, Nothing)
2369 {-# INLINE_LATE step #-}
2370 step gst (sa, sb, Nothing) = do
2371 r <- stepa (adaptState gst) sa
2374 Yield x sa' -> Skip (sa', sb, Just x)
2375 Skip sa' -> Skip (sa', sb, Nothing)
2378 step gst (sa, sb, Just x) = do
2379 r <- stepb (adaptState gst) sb
2383 return $ Yield z (sa, sb', Nothing)
2384 Skip sb' -> return $ Skip (sa, sb', Just x)
2387#if __GLASGOW_HASKELL__ >= 801
2388{-# RULES "zipWithM xs xs"
2389 forall f xs. zipWithM @Identity f xs xs = mapM (\x -> f x x) xs #-}
2392{-# INLINE zipWith #-}
2393zipWith :: Monad m => (a -> b -> c) -> Stream m a -> Stream m b -> Stream m c
2394zipWith f = zipWithM (\a b -> return (f a b))
2396------------------------------------------------------------------------------
2398------------------------------------------------------------------------------
2400{-# INLINE_NORMAL mergeByM #-}
2403 => (a -> a -> m Ordering) -> Stream m a -> Stream m a -> Stream m a
2404mergeByM cmp (Stream stepa ta) (Stream stepb tb) =
2405 Stream step (Just ta, Just tb, Nothing, Nothing)
2407 {-# INLINE_LATE step #-}
2409 -- one of the values is missing, and the corresponding stream is running
2410 step gst (Just sa, sb, Nothing, b) = do
2413 Yield a sa' -> Skip (Just sa', sb, Just a, b)
2414 Skip sa' -> Skip (Just sa', sb, Nothing, b)
2415 Stop -> Skip (Nothing, sb, Nothing, b)
2417 step gst (sa, Just sb, a, Nothing) = do
2420 Yield b sb' -> Skip (sa, Just sb', a, Just b)
2421 Skip sb' -> Skip (sa, Just sb', a, Nothing)
2422 Stop -> Skip (sa, Nothing, a, Nothing)
2424 -- both the values are available
2425 step _ (sa, sb, Just a, Just b) = do
2427 return $ case res of
2428 GT -> Yield b (sa, sb, Just a, Nothing)
2429 _ -> Yield a (sa, sb, Nothing, Just b)
2431 -- one of the values is missing, corresponding stream is done
2432 step _ (Nothing, sb, Nothing, Just b) =
2433 return $ Yield b (Nothing, sb, Nothing, Nothing)
2435 step _ (sa, Nothing, Just a, Nothing) =
2436 return $ Yield a (sa, Nothing, Nothing, Nothing)
2438 step _ (Nothing, Nothing, Nothing, Nothing) = return Stop
2440{-# INLINE mergeBy #-}
2443 => (a -> a -> Ordering) -> Stream m a -> Stream m a -> Stream m a
2444mergeBy cmp = mergeByM (\a b -> return $ cmp a b)
2446------------------------------------------------------------------------------
2447-- Transformation comprehensions
2448------------------------------------------------------------------------------
2450{-# INLINE_NORMAL the #-}
2451the :: (Eq a, Monad m) => Stream m a -> m (Maybe a)
2452the (Stream step state) = go state
2455 r <- step defState st
2457 Yield x s -> go' x s
2459 Stop -> return Nothing
2461 r <- step defState st
2463 Yield x s | x == n -> go' n s
2464 | otherwise -> return Nothing
2466 Stop -> return (Just n)
2468--------------------------------------------------------------------------------
2469-- UTF8 Encoding / Decoding
2470--------------------------------------------------------------------------------
2472-- UTF-8 primitives, Lifted from GHC.IO.Encoding.UTF8.
2474ord2 :: Char -> [Word8]
2475ord2 c = assert (n >= 0x80 && n <= 0x07ff) [x1, x2]
2478 x1 = fromIntegral $ (n `shiftR` 6) + 0xC0
2479 x2 = fromIntegral $ (n .&. 0x3F) + 0x80
2481ord3 :: Char -> [Word8]
2482ord3 c = assert (n >= 0x0800 && n <= 0xffff) [x1, x2, x3]
2485 x1 = fromIntegral $ (n `shiftR` 12) + 0xE0
2486 x2 = fromIntegral $ ((n `shiftR` 6) .&. 0x3F) + 0x80
2487 x3 = fromIntegral $ (n .&. 0x3F) + 0x80
2489ord4 :: Char -> [Word8]
2490ord4 c = assert (n >= 0x10000) [x1, x2, x3, x4]
2493 x1 = fromIntegral $ (n `shiftR` 18) + 0xF0
2494 x2 = fromIntegral $ ((n `shiftR` 12) .&. 0x3F) + 0x80
2495 x3 = fromIntegral $ ((n `shiftR` 6) .&. 0x3F) + 0x80
2496 x4 = fromIntegral $ (n .&. 0x3F) + 0x80
2499chr2 :: Word8 -> Word8 -> Char
2500chr2 (W8# x1#) (W8# x2#) = C# (chr# (z1# +# z2#))
2502 !y1# = word2Int# x1#
2503 !y2# = word2Int# x2#
2504 !z1# = uncheckedIShiftL# (y1# -# 192#) 6#
2508chr3 :: Word8 -> Word8 -> Word8 -> Char
2509chr3 (W8# x1#) (W8# x2#) (W8# x3#) = C# (chr# (z1# +# z2# +# z3#))
2511 !y1# = word2Int# x1#
2512 !y2# = word2Int# x2#
2513 !y3# = word2Int# x3#
2514 !z1# = uncheckedIShiftL# (y1# -# 224#) 12#
2515 !z2# = uncheckedIShiftL# (y2# -# 128#) 6#
2519chr4 :: Word8 -> Word8 -> Word8 -> Word8 -> Char
2520chr4 (W8# x1#) (W8# x2#) (W8# x3#) (W8# x4#) =
2521 C# (chr# (z1# +# z2# +# z3# +# z4#))
2523 !y1# = word2Int# x1#
2524 !y2# = word2Int# x2#
2525 !y3# = word2Int# x3#
2526 !y4# = word2Int# x4#
2527 !z1# = uncheckedIShiftL# (y1# -# 240#) 18#
2528 !z2# = uncheckedIShiftL# (y2# -# 128#) 12#
2529 !z3# = uncheckedIShiftL# (y3# -# 128#) 6#
2532{-# INLINE between #-}
2534 Word8 -- ^ byte to check
2535 -> Word8 -- ^ lower bound
2536 -> Word8 -- ^ upper bound
2538between x y z = x >= y && x <= z
2540{-# INLINE validate3 #-}
2541validate3 :: Word8 -> Word8 -> Word8 -> Bool
2542validate3 x1 x2 x3 = validate3_1 ||
2547 validate3_1 = (x1 == 0xE0) &&
2548 between x2 0xA0 0xBF &&
2549 between x3 0x80 0xBF
2550 validate3_2 = between x1 0xE1 0xEC &&
2551 between x2 0x80 0xBF &&
2552 between x3 0x80 0xBF
2553 validate3_3 = x1 == 0xED &&
2554 between x2 0x80 0x9F &&
2555 between x3 0x80 0xBF
2556 validate3_4 = between x1 0xEE 0xEF &&
2557 between x2 0x80 0xBF &&
2558 between x3 0x80 0xBF
2560{-# INLINE validate4 #-}
2561validate4 :: Word8 -> Word8 -> Word8 -> Word8 -> Bool
2562validate4 x1 x2 x3 x4 = validate4_1 ||
2566 validate4_1 = x1 == 0xF0 &&
2567 between x2 0x90 0xBF &&
2568 between x3 0x80 0xBF &&
2569 between x4 0x80 0xBF
2570 validate4_2 = between x1 0xF1 0xF3 &&
2571 between x2 0x80 0xBF &&
2572 between x3 0x80 0xBF &&
2573 between x4 0x80 0xBF
2574 validate4_3 = x1 == 0xF4 &&
2575 between x2 0x80 0x8F &&
2576 between x3 0x80 0xBF &&
2577 between x4 0x80 0xBF
2579data CodePoint = FreshPoint
2582 | Three !Word8 !Word8
2584 | Four1 !Word8 !Word8
2585 | Four !Word8 !Word8 !Word8
2588{-# INLINE_NORMAL decodeUtf8 #-}
2589decodeUtf8 :: Monad m => Stream m Word8 -> Stream m Char
2590decodeUtf8 (Stream step state) = Stream step' (state, FreshPoint)
2592 {-# INLINE_LATE step' #-}
2593 step' gst (st, FreshPoint) = do
2594 r <- step (adaptState gst) st
2599 Skip (s, YieldPoint $ unsafeChr (fromIntegral c0))
2600 | c0 >= 0xc0 && c0 <= 0xc1 -> error "Invalid Overlong forms"
2601 | c0 >= 0xc2 && c0 <= 0xdf -> Skip (s, Two c0)
2602 | c0 >= 0xe0 && c0 <= 0xef -> Skip (s, GoThree c0)
2603 | c0 >= 0xf0 -> Skip (s, GoFour c0)
2604 | otherwise -> error "Invalid Sequence"
2605 Skip s -> Skip (s, FreshPoint)
2608 -- Decoding of a UTF8 character that spans two bytes with one byte (c0)
2610 step' gst (st, Two c0) = do
2611 r <- step (adaptState gst) st
2615 | c1 < 0x80 || c1 >= 0xc0 -> error "Invalid Sequence"
2616 | otherwise -> Skip (s, YieldPoint $ chr2 c0 c1)
2617 Skip s -> Skip (s, Two c0)
2618 Stop -> error "Input Underflow"
2620 -- Decoding of a UTF8 character that spans three bytes with first byte (c0)
2622 step' gst (st, GoThree c0) = do
2623 r <- step (adaptState gst) st
2627 | not (validate3 c0 c1 0x80) -> error "Invalid Sequence"
2629 | otherwise -> Skip (s, Three c0 c1)
2630 Skip s -> Skip (s, GoThree c0)
2631 Stop -> error "Input Underflow"
2633 -- Two bytes known of a 3 byte UTF8 encoded unicode character.
2634 step' gst (st, Three c0 c1) = do
2635 r <- step (adaptState gst) st
2639 | not (validate3 c0 c1 c2) -> error "Invalid Sequence"
2640 | otherwise -> Skip (s, YieldPoint $ chr3 c0 c1 c2)
2641 Skip s -> Skip (s, Three c0 c1)
2642 Stop -> error "Input Underflow"
2644 -- One byte known of a four byte UTF8 unicode character.
2645 step' gst (st, GoFour c0) = do
2646 r <- step (adaptState gst) st
2650 | not (validate4 c0 c1 0x80 0x80) -> error "Invalid Sequence"
2651 | otherwise -> Skip (s, Four1 c0 c1)
2652 Skip s -> Skip (s, GoFour c0)
2653 Stop -> error "Input Underflow"
2655 -- Two bytes known of a four byte UTF8 unicode character.
2656 step' gst (st, Four1 c0 c1) = do
2657 r <- step (adaptState gst) st
2661 | not (validate4 c0 c1 c2 0x80) -> error "Invalid Sequence"
2662 | otherwise -> Skip (s, Four c0 c1 c2)
2663 Skip s -> Skip (s, Four1 c0 c1)
2664 Stop -> error "Input Underflow"
2666 -- Three bytes known of a three byte UTF8 unicode character.
2667 step' gst (st, Four c0 c1 c2) = do
2668 r <- step (adaptState gst) st
2672 | not (validate4 c0 c1 c2 c3) -> error "Invalid Sequence"
2673 | otherwise -> Skip (s, YieldPoint $ chr4 c0 c1 c2 c3)
2674 Skip s -> Skip (s, Four c0 c1 c2)
2675 Stop -> error "Input Underflow"
2677 -- This way so that we only need one Yield.
2678 step' _ (s, YieldPoint c) = return $ Yield c (s, FreshPoint)
2680data YieldMany x = None
2683{-# INLINE_NORMAL encodeUtf8 #-}
2684encodeUtf8 :: Monad m => Stream m Char -> Stream m Word8
2685encodeUtf8 (Stream step state) = Stream step' (state, None)
2687 {-# INLINE_LATE step' #-}
2688 step' gst (st, None) = do
2689 r <- step (adaptState gst) st
2694 x | x <= 0x7F -> Skip (s, YieldMany [fromIntegral x])
2695 | x <= 0x7FF -> Skip (s, YieldMany (ord2 c))
2698 then error "Encountered a surrogate"
2699 else Skip (s, YieldMany (ord3 c))
2700 | otherwise -> Skip (s, YieldMany (ord4 c))
2701 Skip s -> Skip (s, None)
2703 step' _ (s, YieldMany []) = return $ Skip (s, None)
2704 step' _ (s, YieldMany (x:xs)) = return $ Yield x (s, YieldMany xs)
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list