on 3de89fe help sign in
3346 lines 117 kB history raw
1{-# LANGUAGE BangPatterns #-}
2{-# LANGUAGE CPP #-}
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 #-}
17#endif
19#include "inline.hs"
21-- |
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
26-- Copyright : (c) Bjoern Hoehrmann 2008-2009
27--
28-- License : BSD3
29-- Maintainer : harendra.kumar@gmail.com
30-- Stability : experimental
31-- Portability : GHC
32--
33-- Direct style re-implementation of CPS style stream in StreamK module. The
34-- symbol or suffix 'D' in this module denotes the "Direct" style. GHC is able
35-- to INLINE and fuse direct style better, providing better performance than
36-- CPS implementation.
37--
38-- @
39-- import qualified Streamly.Streams.StreamD as D
40-- @
42-- Some of the functions in this file have been adapted from the vector
43-- library, https://hackage.haskell.org/package/vector.
45module Streamly.Streams.StreamD
46 (
47 -- * The stream type
48 Step (..)
49 , Stream (..)
51 -- * Construction
52 , nil
53 , cons
55 -- * Deconstruction
56 , uncons
58 -- * Generation
59 -- ** Unfolds
60 , unfoldr
61 , unfoldrM
62 , unfold
64 -- ** Specialized Generation
65 -- | Generate a monadic stream from a seed.
66 , repeat
67 , replicate
68 , replicateM
69 , fromIndices
70 , fromIndicesM
71 , generate
72 , generateM
74 -- ** Enumerations
75 , enumerateFromStepIntegral
76 , enumerateFromIntegral
77 , enumerateFromThenIntegral
78 , enumerateFromToIntegral
79 , enumerateFromThenToIntegral
81 , enumerateFromStepNum
82 , numFrom
83 , numFromThen
84 , enumerateFromToFractional
85 , enumerateFromThenToFractional
87 -- ** Conversions
88 -- | Transform an input structure into a stream.
89 -- | Direct style stream does not support @fromFoldable@.
90 , yield
91 , yieldM
92 , fromList
93 , fromListM
94 , fromStreamK
95 , fromStreamD
97 -- * Elimination
98 -- ** General Folds
99 , foldrS
100 , foldrT
101 , foldrM
102 , foldrMx
103 , foldr
104 , foldr1
106 , foldl'
107 , foldlM'
108 , foldlS
109 , foldlT
110 , reverse
111 , reverse'
113 , foldlx'
114 , foldlMx'
116 -- ** Specialized Folds
117 , tap
118 , drain
119 , null
120 , head
121 , tail
122 , last
123 , elem
124 , notElem
125 , all
126 , any
127 , maximum
128 , maximumBy
129 , minimum
130 , minimumBy
131 , findIndices
132 , lookup
133 , findM
134 , find
135 , (!!)
137 -- ** Flattening nested streams
138 , concatMapM
139 , concatMap
140 , ConcatMapUState (..)
141 , concatMapU
142 , ConcatUnfoldInterleaveState (..)
143 , concatUnfoldInterleave
144 , concatUnfoldRoundrobin
145 , AppendState(..)
146 , append
147 , InterleaveState(..)
148 , interleave
149 , interleaveMin
150 , interleaveFst
151 , roundRobin -- interleaveFair?/ParallelFair
152 , interleaveFstThenConcat
154 -- ** Grouping
155 , groupsOf
156 , groupsBy
157 , groupsRollingBy
159 -- ** Splitting
160 , splitBy
161 , splitSuffixBy
162 , wordsBy
163 , splitSuffixBy'
165 , splitOn
166 , splitSuffixOn
168 , splitInnerBy
169 , splitInnerBySuffix
171 -- ** Substreams
172 , isPrefixOf
173 , isSubsequenceOf
174 , stripPrefix
176 -- ** Map and Fold
177 , mapM_
179 -- ** Conversions
180 -- | Transform a stream into another type.
181 , toList
182 , toListRev
183 , toStreamK
184 , toStreamD
186 -- * Transformation
187 , transform
189 -- ** By folding (scans)
190 , scanlM'
191 , scanl'
192 , scanlM
193 , scanl
194 , scanl1M'
195 , scanl1'
196 , scanl1M
197 , scanl1
199 , prescanl'
200 , prescanlM'
202 , postscanl
203 , postscanlM
204 , postscanl'
205 , postscanlM'
207 , postscanlx'
208 , postscanlMx'
209 , scanlMx'
210 , scanlx'
212 -- * Filtering
213 , filter
214 , filterM
215 , uniq
216 , take
217 , takeWhile
218 , takeWhileM
219 , drop
220 , dropWhile
221 , dropWhileM
223 -- * Mapping
224 , map
225 , mapM
226 , sequence
228 -- * Inserting
229 , intersperseM
230 , intersperse
231 , insertAfterEach
232 , insertBy
234 -- * Deleting
235 , deleteBy
237 -- ** Map and Filter
238 , mapMaybe
239 , mapMaybeM
241 -- * Zipping
242 , indexed
243 , indexedR
244 , zipWith
245 , zipWithM
247 -- * Comparisons
248 , eqBy
249 , cmpBy
251 -- * Merging
252 , mergeBy
253 , mergeByM
255 -- * Transformation comprehensions
256 , the
258 -- * Exceptions
259 , before
260 , after
261 , bracket
262 , onException
263 , finally
264 , handle
266 -- * UTF8 Encoding / Decoding transformations.
267 , decodeUtf8
268 , encodeUtf8
269 , decodeUtf8Lenient
270 , decodeUtf8Arrays
271 , decodeUtf8ArraysLenient
272 )
273where
275import Control.Exception (Exception)
276import Control.Monad (void)
277import Control.Monad.Catch (MonadCatch)
278import Control.Monad.IO.Class (MonadIO(..))
279import Control.Monad.Trans (MonadTrans(lift))
280import Data.Bits (shiftR, shiftL, (.|.), (.&.))
281#if __GLASGOW_HASKELL__ >= 801
282import Data.Functor.Identity (Identity)
283#endif
284import Data.Maybe (fromJust, isJust)
285import Data.Word (Word32)
286import Foreign.Ptr (Ptr)
287import Foreign.Storable (Storable(..))
288import GHC.Base (assert, Char(..), unsafeChr, ord)
289import GHC.IO.Encoding.Failure (isSurrogate)
290import GHC.Types (SPEC(..))
291import GHC.Word (Word8(..))
292import System.IO.Unsafe (unsafePerformIO)
293import Prelude
294 hiding (map, mapM, mapM_, repeat, foldr, last, take, filter,
295 takeWhile, drop, dropWhile, all, any, maximum, minimum, elem,
296 notElem, null, head, tail, zipWith, lookup, foldr1, sequence,
297 (!!), scanl, scanl1, concatMap, replicate, enumFromTo, concat,
298 reverse)
300import qualified Control.Monad.Catch as MC
302import Streamly.Internal.Memory.Array.Types (Array(..))
303import Streamly.Internal.Data.Fold.Types (Fold(..))
304import Streamly.Internal.Data.Pipe.Types (Pipe(..), PipeState(..))
305import Streamly.Internal.Data.SVar (MonadAsync, defState, adaptState)
306import Streamly.Internal.Data.Unfold.Types (Unfold(..))
307import Streamly.Internal.Data.Strict (Tuple'(..))
309import Streamly.Streams.StreamD.Type
311import qualified Streamly.Internal.Data.Pipe.Types as Pipe
312import qualified Streamly.Internal.Memory.Array.Types as A
313import qualified Streamly.Memory.Ring as RB
314import qualified Streamly.Streams.StreamK as K
316import Foreign.Ptr (plusPtr)
317import Foreign.ForeignPtr.Unsafe (unsafeForeignPtrToPtr)
318import Foreign.ForeignPtr (ForeignPtr, touchForeignPtr)
320------------------------------------------------------------------------------
321-- Construction
322------------------------------------------------------------------------------
324-- | An empty 'Stream'.
325{-# INLINE_NORMAL nil #-}
326nil :: Monad m => Stream m a
327nil = Stream (\_ _ -> return Stop) ()
329{-# INLINE_NORMAL consM #-}
330consM :: Monad m => m a -> Stream m a -> Stream m a
331consM m (Stream step state) = Stream step1 Nothing
332 where
333 {-# INLINE_LATE step1 #-}
334 step1 _ Nothing = m >>= \x -> return $ Yield x (Just state)
335 step1 gst (Just st) = do
336 r <- step gst st
337 return $
338 case r of
339 Yield a s -> Yield a (Just s)
340 Skip s -> Skip (Just s)
341 Stop -> Stop
343-- XXX implement in terms of consM?
344-- cons x = consM (return x)
345--
346-- | Can fuse but has O(n^2) complexity.
347{-# INLINE_NORMAL cons #-}
348cons :: Monad m => a -> Stream m a -> Stream m a
349cons x (Stream step state) = Stream step1 Nothing
350 where
351 {-# INLINE_LATE step1 #-}
352 step1 _ Nothing = return $ Yield x (Just state)
353 step1 gst (Just st) = do
354 r <- step gst st
355 return $
356 case r of
357 Yield a s -> Yield a (Just s)
358 Skip s -> Skip (Just s)
359 Stop -> Stop
361-------------------------------------------------------------------------------
362-- Deconstruction
363-------------------------------------------------------------------------------
365-- Does not fuse, has the same performance as the StreamK version.
366{-# INLINE_NORMAL uncons #-}
367uncons :: Monad m => Stream m a -> m (Maybe (a, Stream m a))
368uncons (UnStream step state) = go state
369 where
370 go st = do
371 r <- step defState st
372 case r of
373 Yield x s -> return $ Just (x, Stream step s)
374 Skip s -> go s
375 Stop -> return Nothing
377------------------------------------------------------------------------------
378-- Generation by unfold
379------------------------------------------------------------------------------
381{-# INLINE_NORMAL unfoldrM #-}
382unfoldrM :: Monad m => (s -> m (Maybe (a, s))) -> s -> Stream m a
383unfoldrM next state = Stream step state
384 where
385 {-# INLINE_LATE step #-}
386 step _ st = do
387 r <- next st
388 return $ case r of
389 Just (x, s) -> Yield x s
390 Nothing -> Stop
392{-# INLINE_LATE unfoldr #-}
393unfoldr :: Monad m => (s -> Maybe (a, s)) -> s -> Stream m a
394unfoldr f = unfoldrM (return . f)
396-- | Convert an 'Unfold' into a 'Stream' by supplying it a seed.
397--
398{-# INLINE_NORMAL unfold #-}
399unfold :: Monad m => Unfold m a b -> a -> Stream m b
400unfold (Unfold ustep inject) seed = Stream step Nothing
401 where
402 {-# INLINE_LATE step #-}
403 step _ Nothing = inject seed >>= return . Skip . Just
404 step _ (Just st) = do
405 r <- ustep st
406 return $ case r of
407 Yield x s -> Yield x (Just s)
408 Skip s -> Skip (Just s)
409 Stop -> Stop
411------------------------------------------------------------------------------
412-- Specialized Generation
413------------------------------------------------------------------------------
415repeat :: Monad m => a -> Stream m a
416repeat x = Stream (\_ _ -> return $ Yield x ()) ()
418{-# INLINE_NORMAL replicateM #-}
419replicateM :: forall m a. Monad m => Int -> m a -> Stream m a
420replicateM n p = Stream step n
421 where
422 {-# INLINE_LATE step #-}
423 step _ (i :: Int)
424 | i <= 0 = return Stop
425 | otherwise = do
426 x <- p
427 return $ Yield x (i - 1)
429{-# INLINE_NORMAL replicate #-}
430replicate :: Monad m => Int -> a -> Stream m a
431replicate n x = replicateM n (return x)
433-- This would not work properly for floats, therefore we put an Integral
434-- constraint.
435-- | Can be used to enumerate unbounded integrals. This does not check for
436-- overflow or underflow for bounded integrals.
437{-# INLINE_NORMAL enumerateFromStepIntegral #-}
438enumerateFromStepIntegral :: (Integral a, Monad m) => a -> a -> Stream m a
439enumerateFromStepIntegral from stride =
440 from `seq` stride `seq` Stream step from
441 where
442 {-# INLINE_LATE step #-}
443 step _ !x = return $ Yield x $! (x + stride)
445-- We are assuming that "to" is constrained by the type to be within
446-- max/min bounds.
447{-# INLINE enumerateFromToIntegral #-}
448enumerateFromToIntegral :: (Monad m, Integral a) => a -> a -> Stream m a
449enumerateFromToIntegral from to =
450 takeWhile (<= to) $ enumerateFromStepIntegral from 1
452{-# INLINE enumerateFromIntegral #-}
453enumerateFromIntegral :: (Monad m, Integral a, Bounded a) => a -> Stream m a
454enumerateFromIntegral from = enumerateFromToIntegral from maxBound
456data EnumState a = EnumInit | EnumYield a a a | EnumStop
458{-# INLINE_NORMAL enumerateFromThenToIntegralUp #-}
459enumerateFromThenToIntegralUp
460 :: (Monad m, Integral a)
461 => a -> a -> a -> Stream m a
462enumerateFromThenToIntegralUp from next to = Stream step EnumInit
463 where
464 {-# INLINE_LATE step #-}
465 step _ EnumInit =
466 return $
467 if to < next
468 then if to < from
469 then Stop
470 else Yield from EnumStop
471 else -- from <= next <= to
472 let stride = next - from
473 in Skip $ EnumYield from stride (to - stride)
475 step _ (EnumYield x stride toMinus) =
476 return $
477 if x > toMinus
478 then Yield x EnumStop
479 else Yield x $ EnumYield (x + stride) stride toMinus
481 step _ EnumStop = return Stop
483{-# INLINE_NORMAL enumerateFromThenToIntegralDn #-}
484enumerateFromThenToIntegralDn
485 :: (Monad m, Integral a)
486 => a -> a -> a -> Stream m a
487enumerateFromThenToIntegralDn from next to = Stream step EnumInit
488 where
489 {-# INLINE_LATE step #-}
490 step _ EnumInit =
491 return $ if to > next
492 then if to > from
493 then Stop
494 else Yield from EnumStop
495 else -- from >= next >= to
496 let stride = next - from
497 in Skip $ EnumYield from stride (to - stride)
499 step _ (EnumYield x stride toMinus) =
500 return $
501 if x < toMinus
502 then Yield x EnumStop
503 else Yield x $ EnumYield (x + stride) stride toMinus
505 step _ EnumStop = return Stop
507{-# INLINE_NORMAL enumerateFromThenToIntegral #-}
508enumerateFromThenToIntegral
509 :: (Monad m, Integral a)
510 => a -> a -> a -> Stream m a
511enumerateFromThenToIntegral from next to
512 | next >= from = enumerateFromThenToIntegralUp from next to
513 | otherwise = enumerateFromThenToIntegralDn from next to
515{-# INLINE_NORMAL enumerateFromThenIntegral #-}
516enumerateFromThenIntegral
517 :: (Monad m, Integral a, Bounded a)
518 => a -> a -> Stream m a
519enumerateFromThenIntegral from next =
520 if next > from
521 then enumerateFromThenToIntegralUp from next maxBound
522 else enumerateFromThenToIntegralDn from next minBound
524-- For floating point numbers if the increment is less than the precision then
525-- it just gets lost. Therefore we cannot always increment it correctly by just
526-- repeated addition.
527-- 9007199254740992 + 1 + 1 :: Double => 9.007199254740992e15
528-- 9007199254740992 + 2 :: Double => 9.007199254740994e15
530-- Instead we accumulate the increment counter and compute the increment
531-- everytime before adding it to the starting number.
532--
533-- This works for Integrals as well as floating point numbers, but
534-- enumerateFromStepIntegral is faster for integrals.
535{-# INLINE_NORMAL enumerateFromStepNum #-}
536enumerateFromStepNum :: (Monad m, Num a) => a -> a -> Stream m a
537enumerateFromStepNum from stride = Stream step 0
538 where
539 {-# INLINE_LATE step #-}
540 step _ !i = return $ (Yield $! (from + i * stride)) $! (i + 1)
542{-# INLINE_NORMAL numFrom #-}
543numFrom :: (Monad m, Num a) => a -> Stream m a
544numFrom from = enumerateFromStepNum from 1
546{-# INLINE_NORMAL numFromThen #-}
547numFromThen :: (Monad m, Num a) => a -> a -> Stream m a
548numFromThen from next = enumerateFromStepNum from (next - from)
550-- We cannot write a general function for Num. The only way to write code
551-- portable between the two is to use a 'Real' constraint and convert between
552-- Fractional and Integral using fromRational which is horribly slow.
553{-# INLINE_NORMAL enumerateFromToFractional #-}
554enumerateFromToFractional
555 :: (Monad m, Fractional a, Ord a)
556 => a -> a -> Stream m a
557enumerateFromToFractional from to =
558 takeWhile (<= to + 1 / 2) $ enumerateFromStepNum from 1
560{-# INLINE_NORMAL enumerateFromThenToFractional #-}
561enumerateFromThenToFractional
562 :: (Monad m, Fractional a, Ord a)
563 => a -> a -> a -> Stream m a
564enumerateFromThenToFractional from next to =
565 takeWhile predicate $ numFromThen from next
566 where
567 mid = (next - from) / 2
568 predicate | next >= from = (<= to + mid)
569 | otherwise = (>= to + mid)
571-------------------------------------------------------------------------------
572-- Generation by Conversion
573-------------------------------------------------------------------------------
575{-# INLINE_NORMAL fromIndicesM #-}
576fromIndicesM :: Monad m => (Int -> m a) -> Stream m a
577fromIndicesM gen = Stream step 0
578 where
579 {-# INLINE_LATE step #-}
580 step _ i = do
581 x <- gen i
582 return $ Yield x (i + 1)
584{-# INLINE fromIndices #-}
585fromIndices :: Monad m => (Int -> a) -> Stream m a
586fromIndices gen = fromIndicesM (return . gen)
588{-# INLINE_NORMAL generateM #-}
589generateM :: Monad m => Int -> (Int -> m a) -> Stream m a
590generateM n gen = n `seq` Stream step 0
591 where
592 {-# INLINE_LATE step #-}
593 step _ i | i < n = do
594 x <- gen i
595 return $ Yield x (i + 1)
596 | otherwise = return Stop
598{-# INLINE generate #-}
599generate :: Monad m => Int -> (Int -> a) -> Stream m a
600generate n gen = generateM n (return . gen)
602-- XXX we need the MonadAsync constraint because of a rewrite rule.
603-- | Convert a list of monadic actions to a 'Stream'
604{-# INLINE_LATE fromListM #-}
605fromListM :: MonadAsync m => [m a] -> Stream m a
606fromListM = Stream step
607 where
608 {-# INLINE_LATE step #-}
609 step _ (m:ms) = m >>= \x -> return $ Yield x ms
610 step _ [] = return Stop
612{-# INLINE toStreamD #-}
613toStreamD :: (K.IsStream t, Monad m) => t m a -> Stream m a
614toStreamD = fromStreamK . K.toStream
616------------------------------------------------------------------------------
617-- Elimination by Folds
618------------------------------------------------------------------------------
620------------------------------------------------------------------------------
621-- Right Folds
622------------------------------------------------------------------------------
624{-# INLINE_NORMAL foldr1 #-}
625foldr1 :: Monad m => (a -> a -> a) -> Stream m a -> m (Maybe a)
626foldr1 f m = do
627 r <- uncons m
628 case r of
629 Nothing -> return Nothing
630 Just (h, t) -> fmap Just (foldr f h t)
632------------------------------------------------------------------------------
633-- Left Folds
634------------------------------------------------------------------------------
636{-# INLINE_NORMAL foldlT #-}
637foldlT :: (Monad m, Monad (s m), MonadTrans s)
638 => (s m b -> a -> s m b) -> s m b -> Stream m a -> s m b
639foldlT fstep begin (Stream step state) = go SPEC begin state
640 where
641 go !_ acc st = do
642 r <- lift $ step defState st
643 case r of
644 Yield x s -> go SPEC (fstep acc x) s
645 Skip s -> go SPEC acc s
646 Stop -> acc
648-- Note, this is going to have horrible performance, because of the nature of
649-- the stream type (i.e. direct stream vs CPS). Its only for reference, it is
650-- likely be practically unusable.
651{-# INLINE_NORMAL foldlS #-}
652foldlS :: Monad m
653 => (Stream m b -> a -> Stream m b) -> Stream m b -> Stream m a -> Stream m b
654foldlS fstep begin (Stream step state) = Stream step' (Left (state, begin))
655 where
656 step' gst (Left (st, acc)) = do
657 r <- step (adaptState gst) st
658 return $ case r of
659 Yield x s -> Skip (Left (s, fstep acc x))
660 Skip s -> Skip (Left (s, acc))
661 Stop -> Skip (Right acc)
663 step' gst (Right (Stream stp stt)) = do
664 r <- stp (adaptState gst) stt
665 return $ case r of
666 Yield x s -> Yield x (Right (Stream stp s))
667 Skip s -> Skip (Right (Stream stp s))
668 Stop -> Stop
670------------------------------------------------------------------------------
671-- Specialized Folds
672------------------------------------------------------------------------------
674-- | Run a streaming composition, discard the results.
675{-# INLINE_LATE drain #-}
676drain :: Monad m => Stream m a -> m ()
677-- drain = foldrM (\_ xs -> xs) (return ())
678drain (Stream step state) = go SPEC state
679 where
680 go !_ st = do
681 r <- step defState st
682 case r of
683 Yield _ s -> go SPEC s
684 Skip s -> go SPEC s
685 Stop -> return ()
687{-# INLINE_NORMAL null #-}
688null :: Monad m => Stream m a -> m Bool
689null m = foldrM (\_ _ -> return False) (return True) m
691{-# INLINE_NORMAL head #-}
692head :: Monad m => Stream m a -> m (Maybe a)
693head m = foldrM (\x _ -> return (Just x)) (return Nothing) m
695-- Does not fuse, has the same performance as the StreamK version.
696{-# INLINE_NORMAL tail #-}
697tail :: Monad m => Stream m a -> m (Maybe (Stream m a))
698tail (UnStream step state) = go state
699 where
700 go st = do
701 r <- step defState st
702 case r of
703 Yield _ s -> return (Just $ Stream step s)
704 Skip s -> go s
705 Stop -> return Nothing
707-- XXX will it fuse? need custom impl?
708{-# INLINE_NORMAL last #-}
709last :: Monad m => Stream m a -> m (Maybe a)
710last = foldl' (\_ y -> Just y) Nothing
712{-# INLINE_NORMAL elem #-}
713elem :: (Monad m, Eq a) => a -> Stream m a -> m Bool
714-- elem e m = foldrM (\x xs -> if x == e then return True else xs) (return False) m
715elem e (Stream step state) = go state
716 where
717 go st = do
718 r <- step defState st
719 case r of
720 Yield x s
721 | x == e -> return True
722 | otherwise -> go s
723 Skip s -> go s
724 Stop -> return False
726{-# INLINE_NORMAL notElem #-}
727notElem :: (Monad m, Eq a) => a -> Stream m a -> m Bool
728notElem e s = fmap not (elem e s)
730{-# INLINE_NORMAL all #-}
731all :: Monad m => (a -> Bool) -> Stream m a -> m Bool
732-- all p m = foldrM (\x xs -> if p x then xs else return False) (return True) m
733all p (Stream step state) = go state
734 where
735 go st = do
736 r <- step defState st
737 case r of
738 Yield x s
739 | p x -> go s
740 | otherwise -> return False
741 Skip s -> go s
742 Stop -> return True
744{-# INLINE_NORMAL any #-}
745any :: Monad m => (a -> Bool) -> Stream m a -> m Bool
746-- any p m = foldrM (\x xs -> if p x then return True else xs) (return False) m
747any p (Stream step state) = go state
748 where
749 go st = do
750 r <- step defState st
751 case r of
752 Yield x s
753 | p x -> return True
754 | otherwise -> go s
755 Skip s -> go s
756 Stop -> return False
758{-# INLINE_NORMAL maximum #-}
759maximum :: (Monad m, Ord a) => Stream m a -> m (Maybe a)
760maximum (Stream step state) = go Nothing state
761 where
762 go Nothing st = do
763 r <- step defState st
764 case r of
765 Yield x s -> go (Just x) s
766 Skip s -> go Nothing s
767 Stop -> return Nothing
768 go (Just acc) st = do
769 r <- step defState st
770 case r of
771 Yield x s
772 | acc <= x -> go (Just x) s
773 | otherwise -> go (Just acc) s
774 Skip s -> go (Just acc) s
775 Stop -> return (Just acc)
777{-# INLINE_NORMAL maximumBy #-}
778maximumBy :: Monad m => (a -> a -> Ordering) -> Stream m a -> m (Maybe a)
779maximumBy cmp (Stream step state) = go Nothing state
780 where
781 go Nothing st = do
782 r <- step defState st
783 case r of
784 Yield x s -> go (Just x) s
785 Skip s -> go Nothing s
786 Stop -> return Nothing
787 go (Just acc) st = do
788 r <- step defState st
789 case r of
790 Yield x s -> case cmp acc x of
791 GT -> go (Just acc) s
792 _ -> go (Just x) s
793 Skip s -> go (Just acc) s
794 Stop -> return (Just acc)
796{-# INLINE_NORMAL minimum #-}
797minimum :: (Monad m, Ord a) => Stream m a -> m (Maybe a)
798minimum (Stream step state) = go Nothing state
799 where
800 go Nothing st = do
801 r <- step defState st
802 case r of
803 Yield x s -> go (Just x) s
804 Skip s -> go Nothing s
805 Stop -> return Nothing
806 go (Just acc) st = do
807 r <- step defState st
808 case r of
809 Yield x s
810 | acc <= x -> go (Just acc) s
811 | otherwise -> go (Just x) s
812 Skip s -> go (Just acc) s
813 Stop -> return (Just acc)
815{-# INLINE_NORMAL minimumBy #-}
816minimumBy :: Monad m => (a -> a -> Ordering) -> Stream m a -> m (Maybe a)
817minimumBy cmp (Stream step state) = go Nothing state
818 where
819 go Nothing st = do
820 r <- step defState st
821 case r of
822 Yield x s -> go (Just x) s
823 Skip s -> go Nothing s
824 Stop -> return Nothing
825 go (Just acc) st = do
826 r <- step defState st
827 case r of
828 Yield x s -> case cmp acc x of
829 GT -> go (Just x) s
830 _ -> go (Just acc) s
831 Skip s -> go (Just acc) s
832 Stop -> return (Just acc)
834{-# INLINE_NORMAL (!!) #-}
835(!!) :: (Monad m) => Stream m a -> Int -> m (Maybe a)
836(Stream step state) !! i = go i state
837 where
838 go n st = do
839 r <- step defState st
840 case r of
841 Yield x s | n < 0 -> return Nothing
842 | n == 0 -> return $ Just x
843 | otherwise -> go (n - 1) s
844 Skip s -> go n s
845 Stop -> return Nothing
847{-# INLINE_NORMAL lookup #-}
848lookup :: (Monad m, Eq a) => a -> Stream m (a, b) -> m (Maybe b)
849lookup e m = foldrM (\(a, b) xs -> if e == a then return (Just b) else xs)
850 (return Nothing) m
852{-# INLINE_NORMAL findM #-}
853findM :: Monad m => (a -> m Bool) -> Stream m a -> m (Maybe a)
854findM p m = foldrM (\x xs -> p x >>= \r -> if r then return (Just x) else xs)
855 (return Nothing) m
857{-# INLINE find #-}
858find :: Monad m => (a -> Bool) -> Stream m a -> m (Maybe a)
859find p = findM (return . p)
861{-# INLINE_NORMAL findIndices #-}
862findIndices :: Monad m => (a -> Bool) -> Stream m a -> Stream m Int
863findIndices p (Stream step state) = Stream step' (state, 0)
864 where
865 {-# INLINE_LATE step' #-}
866 step' gst (st, i) = do
867 r <- step (adaptState gst) st
868 return $ case r of
869 Yield x s -> if p x then Yield i (s, i+1) else Skip (s, i+1)
870 Skip s -> Skip (s, i+1)
871 Stop -> Stop
873{-# INLINE toListRev #-}
874toListRev :: Monad m => Stream m a -> m [a]
875toListRev = foldl' (flip (:)) []
877-- We can implement reverse as:
878--
879-- > reverse = foldlS (flip cons) nil
880--
881-- However, this implementation is unusable because of the horrible performance
882-- of cons. So we just convert it to a list first and then stream from the
883-- list.
884--
885-- XXX Maybe we can use an Array instead of a list here?
886{-# INLINE_NORMAL reverse #-}
887reverse :: Monad m => Stream m a -> Stream m a
888reverse m = Stream step Nothing
889 where
890 {-# INLINE_LATE step #-}
891 step _ Nothing = do
892 xs <- toListRev m
893 return $ Skip (Just xs)
894 step _ (Just (x:xs)) = return $ Yield x (Just xs)
895 step _ (Just []) = return Stop
897-- Much faster reverse for Storables
898{-# INLINE_NORMAL reverse' #-}
899reverse' :: forall m a. (MonadIO m, Storable a) => Stream m a -> Stream m a
900{-
901-- This commented implementation copies the whole stream into one single array
902-- and then streams from that array, this is 3-4x faster than the chunked code
903-- that follows. Though this could be problematic due to unbounded large
904-- allocations. We need to figure out why the chunked code is slower and if we
905-- can optimize the chunked code to work as fast as this one. It may be a
906-- fusion issue?
907import Foreign.ForeignPtr (touchForeignPtr)
908import Foreign.ForeignPtr.Unsafe (unsafeForeignPtrToPtr)
909import Foreign.Ptr (Ptr, plusPtr)
910reverse' m = Stream step Nothing
911 where
912 {-# INLINE_LATE step #-}
913 step _ Nothing = do
914 arr <- A.fromStreamD m
915 let p = aEnd arr `plusPtr` negate (sizeOf (undefined :: a))
916 return $ Skip $ Just (aStart arr, p)
918 step _ (Just (start, p)) | p < unsafeForeignPtrToPtr start = return Stop
920 step _ (Just (start, p)) = do
921 let !x = A.unsafeInlineIO $ do
922 r <- peek p
923 touchForeignPtr start
924 return r
925 next = p `plusPtr` negate (sizeOf (undefined :: a))
926 return $ Yield x (Just (start, next))
927-}
928reverse' m =
929 A.flattenArraysRev
930 $ fromStreamK
931 $ K.reverse
932 $ toStreamK
933 $ A.fromStreamDArraysOf A.defaultChunkSize m
936------------------------------------------------------------------------------
937-- Grouping/Splitting
938------------------------------------------------------------------------------
940{-# INLINE_NORMAL splitSuffixBy' #-}
941splitSuffixBy' :: Monad m
942 => (a -> Bool) -> Fold m a b -> Stream m a -> Stream m b
943splitSuffixBy' predicate f (Stream step state) =
944 Stream (stepOuter f) (Just state)
946 where
948 {-# INLINE_LATE stepOuter #-}
949 stepOuter (Fold fstep initial done) gst (Just st) = do
950 res <- step (adaptState gst) st
951 case res of
952 Yield x s -> do
953 acc <- initial
954 acc' <- fstep acc x
955 if (predicate x)
956 then done acc' >>= \val -> return $ Yield val (Just s)
957 else go SPEC s acc'
959 Skip s -> return $ Skip $ Just s
960 Stop -> return Stop
962 where
964 go !_ stt !acc = do
965 res <- step (adaptState gst) stt
966 case res of
967 Yield x s -> do
968 acc' <- fstep acc x
969 if (predicate x)
970 then done acc' >>= \val -> return $ Yield val (Just s)
971 else go SPEC s acc'
972 Skip s -> go SPEC s acc
973 Stop -> done acc >>= \val -> return $ Yield val Nothing
975 stepOuter _ _ Nothing = return Stop
977{-# INLINE_NORMAL groupsBy #-}
978groupsBy :: Monad m
979 => (a -> a -> Bool)
980 -> Fold m a b
981 -> Stream m a
982 -> Stream m b
983groupsBy cmp f (Stream step state) = Stream (stepOuter f) (Just state, Nothing)
985 where
987 {-# INLINE_LATE stepOuter #-}
988 stepOuter (Fold fstep initial done) gst (Just st, Nothing) = do
989 res <- step (adaptState gst) st
990 case res of
991 Yield x s -> do
992 acc <- initial
993 acc' <- fstep acc x
994 go SPEC x s acc'
996 Skip s -> return $ Skip $ (Just s, Nothing)
997 Stop -> return Stop
999 where
1001 go !_ prev stt !acc = do
1002 res <- step (adaptState gst) stt
1003 case res of
1004 Yield x s -> do
1005 if cmp x prev
1006 then do
1007 acc' <- fstep acc x
1008 go SPEC prev s acc'
1009 else done acc >>= \r -> return $ Yield r (Just s, Just x)
1010 Skip s -> go SPEC prev s acc
1011 Stop -> done acc >>= \r -> return $ Yield r (Nothing, Nothing)
1013 stepOuter (Fold fstep initial done) gst (Just st, Just prev) = do
1014 acc <- initial
1015 acc' <- fstep acc prev
1016 go SPEC st acc'
1018 where
1020 -- XXX code duplicated from the previous equation
1021 go !_ stt !acc = do
1022 res <- step (adaptState gst) stt
1023 case res of
1024 Yield x s -> do
1025 if cmp x prev
1026 then do
1027 acc' <- fstep acc x
1028 go SPEC s acc'
1029 else done acc >>= \r -> return $ Yield r (Just s, Just x)
1030 Skip s -> go SPEC s acc
1031 Stop -> done acc >>= \r -> return $ Yield r (Nothing, Nothing)
1033 stepOuter _ _ (Nothing,_) = return Stop
1035{-# INLINE_NORMAL groupsRollingBy #-}
1036groupsRollingBy :: Monad m
1037 => (a -> a -> Bool)
1038 -> Fold m a b
1039 -> Stream m a
1040 -> Stream m b
1041groupsRollingBy cmp f (Stream step state) =
1042 Stream (stepOuter f) (Just state, Nothing)
1043 where
1045 {-# INLINE_LATE stepOuter #-}
1046 stepOuter (Fold fstep initial done) gst (Just st, Nothing) = do
1047 res <- step (adaptState gst) st
1048 case res of
1049 Yield x s -> do
1050 acc <- initial
1051 acc' <- fstep acc x
1052 go SPEC x s acc'
1054 Skip s -> return $ Skip $ (Just s, Nothing)
1055 Stop -> return Stop
1057 where
1058 go !_ prev stt !acc = do
1059 res <- step (adaptState gst) stt
1060 case res of
1061 Yield x s -> do
1062 if cmp prev x
1063 then do
1064 acc' <- fstep acc x
1065 go SPEC x s acc'
1066 else
1067 done acc >>= \r -> return $ Yield r (Just s, Just x)
1068 Skip s -> go SPEC prev s acc
1069 Stop -> done acc >>= \r -> return $ Yield r (Nothing, Nothing)
1071 stepOuter (Fold fstep initial done) gst (Just st, Just prev') = do
1072 acc <- initial
1073 acc' <- fstep acc prev'
1074 go SPEC prev' st acc'
1076 where
1077 go !_ prevv stt !acc = do
1078 res <- step (adaptState gst) stt
1079 case res of
1080 Yield x s -> do
1081 if cmp prevv x
1082 then do
1083 acc' <- fstep acc x
1084 go SPEC x s acc'
1085 else done acc >>= \r -> return $ Yield r (Just s, Just x)
1086 Skip s -> go SPEC prevv s acc
1087 Stop -> done acc >>= \r -> return $ Yield r (Nothing, Nothing)
1089 stepOuter _ _ (Nothing, _) = return Stop
1091{-# INLINE_NORMAL splitBy #-}
1092splitBy :: Monad m => (a -> Bool) -> Fold m a b -> Stream m a -> Stream m b
1093splitBy predicate f (Stream step state) = Stream (step' f) (Just state)
1095 where
1097 {-# INLINE_LATE step' #-}
1098 step' (Fold fstep initial done) gst (Just st) = initial >>= go SPEC st
1100 where
1102 go !_ stt !acc = do
1103 res <- step (adaptState gst) stt
1104 case res of
1105 Yield x s -> do
1106 if predicate x
1107 then done acc >>= \r -> return $ Yield r (Just s)
1108 else do
1109 acc' <- fstep acc x
1110 go SPEC s acc'
1111 Skip s -> go SPEC s acc
1112 Stop -> done acc >>= \r -> return $ Yield r Nothing
1114 step' _ _ Nothing = return Stop
1116-- XXX requires -funfolding-use-threshold=150 in lines-unlines benchmark
1117{-# INLINE_NORMAL splitSuffixBy #-}
1118splitSuffixBy :: Monad m
1119 => (a -> Bool) -> Fold m a b -> Stream m a -> Stream m b
1120splitSuffixBy predicate f (Stream step state) = Stream (step' f) (Just state)
1122 where
1124 {-# INLINE_LATE step' #-}
1125 step' (Fold fstep initial done) gst (Just st) = do
1126 res <- step (adaptState gst) st
1127 case res of
1128 Yield x s -> do
1129 acc <- initial
1130 if predicate x
1131 then done acc >>= \val -> return $ Yield val (Just s)
1132 else do
1133 acc' <- fstep acc x
1134 go SPEC s acc'
1136 Skip s -> return $ Skip $ Just s
1137 Stop -> return Stop
1139 where
1141 go !_ stt !acc = do
1142 res <- step (adaptState gst) stt
1143 case res of
1144 Yield x s -> do
1145 if predicate x
1146 then done acc >>= \r -> return $ Yield r (Just s)
1147 else do
1148 acc' <- fstep acc x
1149 go SPEC s acc'
1150 Skip s -> go SPEC s acc
1151 Stop -> done acc >>= \r -> return $ Yield r Nothing
1153 step' _ _ Nothing = return Stop
1155{-# INLINE_NORMAL wordsBy #-}
1156wordsBy :: Monad m => (a -> Bool) -> Fold m a b -> Stream m a -> Stream m b
1157wordsBy predicate f (Stream step state) = Stream (stepOuter f) (Just state)
1159 where
1161 {-# INLINE_LATE stepOuter #-}
1162 stepOuter (Fold fstep initial done) gst (Just st) = do
1163 res <- step (adaptState gst) st
1164 case res of
1165 Yield x s -> do
1166 if predicate x
1167 then return $ Skip (Just s)
1168 else do
1169 acc <- initial
1170 acc' <- fstep acc x
1171 go SPEC s acc'
1173 Skip s -> return $ Skip $ Just s
1174 Stop -> return Stop
1176 where
1178 go !_ stt !acc = do
1179 res <- step (adaptState gst) stt
1180 case res of
1181 Yield x s -> do
1182 if predicate x
1183 then done acc >>= \r -> return $ Yield r (Just s)
1184 else do
1185 acc' <- fstep acc x
1186 go SPEC s acc'
1187 Skip s -> go SPEC s acc
1188 Stop -> done acc >>= \r -> return $ Yield r Nothing
1190 stepOuter _ _ Nothing = return Stop
1192-- String search algorithms:
1193-- http://www-igm.univ-mlv.fr/~lecroq/string/index.html
1196-- TODO can we unify the splitting operations using a splitting configuration
1197-- like in the split package.
1199data SplitStyle = Infix | Suffix | Prefix deriving (Eq, Show)
1201data SplitOptions = SplitOptions
1202 { style :: SplitStyle
1203 , withSep :: Bool -- ^ keep the separators in output
1204 -- , compact :: Bool -- ^ treat multiple consecutive separators as one
1205 -- , trimHead :: Bool -- ^ drop blank at head
1206 -- , trimTail :: Bool -- ^ drop blank at tail
1210data SplitOnState s a =
1211 GO_START
1212 | GO_EMPTY_PAT s
1213 | GO_SINGLE_PAT s a
1214 | GO_SHORT_PAT s
1215 | GO_KARP_RABIN s !(RB.Ring a) !(Ptr a)
1216 | GO_DONE
1218{-# INLINE_NORMAL splitOn #-}
1219splitOn
1220 :: forall m a b. (MonadIO m, Storable a, Enum a, Eq a)
1221 => Array a
1222 -> Fold m a b
1223 -> Stream m a
1224 -> Stream m b
1225splitOn patArr@Array{..} (Fold fstep initial done) (Stream step state) =
1226 Stream stepOuter GO_START
1228 where
1230 patLen = A.length patArr
1231 maxIndex = patLen - 1
1232 elemBits = sizeOf (undefined :: a) * 8
1234 {-# INLINE_LATE stepOuter #-}
1235 stepOuter _ GO_START =
1236 if patLen == 0
1237 then return $ Skip $ GO_EMPTY_PAT state
1238 else if patLen == 1
1239 then do
1240 r <- liftIO $ (A.unsafeIndexIO patArr 0)
1241 return $ Skip $ GO_SINGLE_PAT state r
1242 else if sizeOf (undefined :: a) * patLen
1243 <= sizeOf (undefined :: Word)
1244 then return $ Skip $ GO_SHORT_PAT state
1245 else do
1246 (rb, rhead) <- liftIO $ RB.new patLen
1247 return $ Skip $ GO_KARP_RABIN state rb rhead
1249 stepOuter gst (GO_SINGLE_PAT stt pat) = initial >>= go SPEC stt
1251 where
1253 go !_ st !acc = do
1254 res <- step (adaptState gst) st
1255 case res of
1256 Yield x s -> do
1257 if pat == x
1258 then do
1259 r <- done acc
1260 return $ Yield r (GO_SINGLE_PAT s pat)
1261 else fstep acc x >>= go SPEC s
1262 Skip s -> go SPEC s acc
1263 Stop -> done acc >>= \r -> return $ Yield r GO_DONE
1265 stepOuter gst (GO_SHORT_PAT stt) = initial >>= go0 SPEC 0 (0 :: Word) stt
1267 where
1269 mask :: Word
1270 mask = (1 `shiftL` (elemBits * patLen)) - 1
1272 addToWord wrd a = (wrd `shiftL` elemBits) .|. fromIntegral (fromEnum a)
1274 patWord :: Word
1275 patWord = mask .&. A.foldl' addToWord 0 patArr
1277 go0 !_ !idx wrd st !acc = do
1278 res <- step (adaptState gst) st
1279 case res of
1280 Yield x s -> do
1281 let wrd' = addToWord wrd x
1282 if idx == maxIndex
1283 then do
1284 if wrd' .&. mask == patWord
1285 then do
1286 r <- done acc
1287 return $ Yield r (GO_SHORT_PAT s)
1288 else go1 SPEC wrd' s acc
1289 else go0 SPEC (idx + 1) wrd' s acc
1290 Skip s -> go0 SPEC idx wrd s acc
1291 Stop -> do
1292 acc' <- if idx /= 0
1293 then go2 wrd idx acc
1294 else return acc
1295 done acc' >>= \r -> return $ Yield r GO_DONE
1297 {-# INLINE go1 #-}
1298 go1 !_ wrd st !acc = do
1299 res <- step (adaptState gst) st
1300 case res of
1301 Yield x s -> do
1302 let wrd' = addToWord wrd x
1303 old = (mask .&. wrd) `shiftR` (elemBits * (patLen - 1))
1304 acc' <- fstep acc (toEnum $ fromIntegral old)
1305 if wrd' .&. mask == patWord
1306 then done acc' >>= \r -> return $ Yield r (GO_SHORT_PAT s)
1307 else go1 SPEC wrd' s acc'
1308 Skip s -> go1 SPEC wrd s acc
1309 Stop -> do
1310 acc' <- go2 wrd patLen acc
1311 done acc' >>= \r -> return $ Yield r GO_DONE
1313 go2 !wrd !n !acc | n > 0 = do
1314 let old = (mask .&. wrd) `shiftR` (elemBits * (n - 1))
1315 fstep acc (toEnum $ fromIntegral old) >>= go2 wrd (n - 1)
1316 go2 _ _ acc = return acc
1318 stepOuter gst (GO_KARP_RABIN stt rb rhead) = do
1319 initial >>= go0 SPEC 0 rhead stt
1321 where
1323 k = 2891336453 :: Word32
1324 coeff = k ^ patLen
1325 addCksum cksum a = cksum * k + fromIntegral (fromEnum a)
1326 deltaCksum cksum old new =
1327 addCksum cksum new - coeff * fromIntegral (fromEnum old)
1329 -- XXX shall we use a random starting hash or 1 instead of 0?
1330 patHash = A.foldl' addCksum 0 patArr
1332 -- rh == ringHead
1333 go0 !_ !idx !rh st !acc = do
1334 res <- step (adaptState gst) st
1335 case res of
1336 Yield x s -> do
1337 rh' <- liftIO $ RB.unsafeInsert rb rh x
1338 if idx == maxIndex
1339 then do
1340 let fold = RB.unsafeFoldRing (RB.ringBound rb)
1341 let !ringHash = fold addCksum 0 rb
1342 if ringHash == patHash
1343 then go2 SPEC ringHash rh' s acc
1344 else go1 SPEC ringHash rh' s acc
1345 else go0 SPEC (idx + 1) rh' s acc
1346 Skip s -> go0 SPEC idx rh s acc
1347 Stop -> do
1348 !acc' <- if idx /= 0
1349 then RB.unsafeFoldRingM rh fstep acc rb
1350 else return acc
1351 done acc' >>= \r -> return $ Yield r GO_DONE
1353 -- XXX Theoretically this code can do 4 times faster if GHC generates
1354 -- optimal code. If we use just "(cksum' == patHash)" condition it goes
1355 -- 4x faster, as soon as we add the "RB.unsafeEqArray rb v" condition
1356 -- the generated code changes drastically and becomes 4x slower. Need
1357 -- to investigate what is going on with GHC.
1358 {-# INLINE go1 #-}
1359 go1 !_ !cksum !rh st !acc = do
1360 res <- step (adaptState gst) st
1361 case res of
1362 Yield x s -> do
1363 old <- liftIO $ peek rh
1364 let cksum' = deltaCksum cksum old x
1365 acc' <- fstep acc old
1367 if (cksum' == patHash)
1368 then do
1369 rh' <- liftIO (RB.unsafeInsert rb rh x)
1370 go2 SPEC cksum' rh' s acc'
1371 else do
1372 rh' <- liftIO (RB.unsafeInsert rb rh x)
1373 go1 SPEC cksum' rh' s acc'
1374 Skip s -> go1 SPEC cksum rh s acc
1375 Stop -> do
1376 acc' <- RB.unsafeFoldRingFullM rh fstep acc rb
1377 done acc' >>= \r -> return $ Yield r GO_DONE
1379 go2 !_ !cksum' !rh' s !acc' = do
1380 if RB.unsafeEqArray rb rh' patArr
1381 then do
1382 r <- done acc'
1383 return $ Yield r (GO_KARP_RABIN s rb rhead)
1384 else go1 SPEC cksum' rh' s acc'
1386 stepOuter gst (GO_EMPTY_PAT st) = do
1387 res <- step (adaptState gst) st
1388 case res of
1389 Yield x s -> do
1390 acc <- initial
1391 acc' <- fstep acc x
1392 done acc' >>= \r -> return $ Yield r (GO_EMPTY_PAT s)
1393 Skip s -> return $ Skip (GO_EMPTY_PAT s)
1394 Stop -> return Stop
1396 stepOuter _ GO_DONE = return Stop
1398{-# INLINE_NORMAL splitSuffixOn #-}
1399splitSuffixOn
1400 :: forall m a b. (MonadIO m, Storable a, Enum a, Eq a)
1401 => Bool
1402 -> Array a
1403 -> Fold m a b
1404 -> Stream m a
1405 -> Stream m b
1406splitSuffixOn withSep patArr@Array{..} (Fold fstep initial done)
1407 (Stream step state) =
1408 Stream stepOuter GO_START
1410 where
1412 patLen = A.length patArr
1413 maxIndex = patLen - 1
1414 elemBits = sizeOf (undefined :: a) * 8
1416 {-# INLINE_LATE stepOuter #-}
1417 stepOuter _ GO_START =
1418 if patLen == 0
1419 then return $ Skip $ GO_EMPTY_PAT state
1420 else if patLen == 1
1421 then do
1422 r <- liftIO $ (A.unsafeIndexIO patArr 0)
1423 return $ Skip $ GO_SINGLE_PAT state r
1424 else if sizeOf (undefined :: a) * patLen
1425 <= sizeOf (undefined :: Word)
1426 then return $ Skip $ GO_SHORT_PAT state
1427 else do
1428 (rb, rhead) <- liftIO $ RB.new patLen
1429 return $ Skip $ GO_KARP_RABIN state rb rhead
1431 stepOuter gst (GO_SINGLE_PAT stt pat) = do
1432 -- This first part is the only difference between splitOn and
1433 -- splitSuffixOn.
1434 -- If the last element is a separator do not issue a blank segment.
1435 res <- step (adaptState gst) stt
1436 case res of
1437 Yield x s -> do
1438 acc <- initial
1439 if pat == x
1440 then do
1441 acc' <- if withSep then fstep acc x else return acc
1442 done acc' >>= \r -> return $ Yield r (GO_SINGLE_PAT s pat)
1443 else fstep acc x >>= go SPEC s
1444 Skip s -> return $ Skip $ (GO_SINGLE_PAT s pat)
1445 Stop -> return Stop
1447 where
1449 -- This is identical for splitOn and splitSuffixOn
1450 go !_ st !acc = do
1451 res <- step (adaptState gst) st
1452 case res of
1453 Yield x s -> do
1454 if pat == x
1455 then do
1456 acc' <- if withSep then fstep acc x else return acc
1457 r <- done acc'
1458 return $ Yield r (GO_SINGLE_PAT s pat)
1459 else fstep acc x >>= go SPEC s
1460 Skip s -> go SPEC s acc
1461 Stop -> done acc >>= \r -> return $ Yield r GO_DONE
1463 stepOuter gst (GO_SHORT_PAT stt) = do
1465 -- Call "initial" only if the stream yields an element, otherwise we
1466 -- may call "initial" but never yield anything. initial may produce a
1467 -- side effect, therefore we will end up doing and discard a side
1468 -- effect.
1470 let idx = 0
1471 let wrd = 0
1472 res <- step (adaptState gst) stt
1473 case res of
1474 Yield x s -> do
1475 acc <- initial
1476 let wrd' = addToWord wrd x
1477 acc' <- if withSep then fstep acc x else return acc
1478 if idx == maxIndex
1479 then do
1480 if wrd' .&. mask == patWord
1481 then done acc' >>= \r -> return $ Yield r (GO_SHORT_PAT s)
1482 else go0 SPEC (idx + 1) wrd' s acc'
1483 else go0 SPEC (idx + 1) wrd' s acc'
1484 Skip s -> return $ Skip (GO_SHORT_PAT s)
1485 Stop -> return Stop
1487 where
1489 mask :: Word
1490 mask = (1 `shiftL` (elemBits * patLen)) - 1
1492 addToWord wrd a = (wrd `shiftL` elemBits) .|. fromIntegral (fromEnum a)
1494 patWord :: Word
1495 patWord = mask .&. A.foldl' addToWord 0 patArr
1497 go0 !_ !idx wrd st !acc = do
1498 res <- step (adaptState gst) st
1499 case res of
1500 Yield x s -> do
1501 let wrd' = addToWord wrd x
1502 acc' <- if withSep then fstep acc x else return acc
1503 if idx == maxIndex
1504 then do
1505 if wrd' .&. mask == patWord
1506 then do
1507 r <- done acc'
1508 return $ Yield r (GO_SHORT_PAT s)
1509 else go1 SPEC wrd' s acc'
1510 else go0 SPEC (idx + 1) wrd' s acc'
1511 Skip s -> go0 SPEC idx wrd s acc
1512 Stop -> do
1513 if (idx == maxIndex) && (wrd .&. mask == patWord)
1514 then return Stop
1515 else do
1516 acc' <- if idx /= 0 && not withSep
1517 then go2 wrd idx acc
1518 else return acc
1519 done acc' >>= \r -> return $ Yield r GO_DONE
1521 {-# INLINE go1 #-}
1522 go1 !_ wrd st !acc = do
1523 res <- step (adaptState gst) st
1524 case res of
1525 Yield x s -> do
1526 let wrd' = addToWord wrd x
1527 old = (mask .&. wrd) `shiftR` (elemBits * (patLen - 1))
1528 acc' <- if withSep
1529 then fstep acc x
1530 else fstep acc (toEnum $ fromIntegral old)
1531 if wrd' .&. mask == patWord
1532 then done acc' >>= \r -> return $ Yield r (GO_SHORT_PAT s)
1533 else go1 SPEC wrd' s acc'
1534 Skip s -> go1 SPEC wrd s acc
1535 Stop ->
1536 -- If the last sequence is a separator do not issue a blank
1537 -- segment.
1538 if wrd .&. mask == patWord
1539 then return Stop
1540 else do
1541 acc' <- if withSep
1542 then return acc
1543 else go2 wrd patLen acc
1544 done acc' >>= \r -> return $ Yield r GO_DONE
1546 go2 !wrd !n !acc | n > 0 = do
1547 let old = (mask .&. wrd) `shiftR` (elemBits * (n - 1))
1548 fstep acc (toEnum $ fromIntegral old) >>= go2 wrd (n - 1)
1549 go2 _ _ acc = return acc
1551 stepOuter gst (GO_KARP_RABIN stt rb rhead) = do
1552 let idx = 0
1553 res <- step (adaptState gst) stt
1554 case res of
1555 Yield x s -> do
1556 acc <- initial
1557 acc' <- if withSep then fstep acc x else return acc
1558 rh' <- liftIO (RB.unsafeInsert rb rhead x)
1559 if idx == maxIndex
1560 then do
1561 let fold = RB.unsafeFoldRing (RB.ringBound rb)
1562 let !ringHash = fold addCksum 0 rb
1563 if ringHash == patHash
1564 then go2 SPEC ringHash rh' s acc'
1565 else go0 SPEC (idx + 1) rh' s acc'
1566 else go0 SPEC (idx + 1) rh' s acc'
1567 Skip s -> return $ Skip (GO_KARP_RABIN s rb rhead)
1568 Stop -> return Stop
1570 where
1572 k = 2891336453 :: Word32
1573 coeff = k ^ patLen
1574 addCksum cksum a = cksum * k + fromIntegral (fromEnum a)
1575 deltaCksum cksum old new =
1576 addCksum cksum new - coeff * fromIntegral (fromEnum old)
1578 -- XXX shall we use a random starting hash or 1 instead of 0?
1579 patHash = A.foldl' addCksum 0 patArr
1581 -- rh == ringHead
1582 go0 !_ !idx !rh st !acc = do
1583 res <- step (adaptState gst) st
1584 case res of
1585 Yield x s -> do
1586 acc' <- if withSep then fstep acc x else return acc
1587 rh' <- liftIO (RB.unsafeInsert rb rh x)
1588 if idx == maxIndex
1589 then do
1590 let fold = RB.unsafeFoldRing (RB.ringBound rb)
1591 let !ringHash = fold addCksum 0 rb
1592 if ringHash == patHash
1593 then go2 SPEC ringHash rh' s acc'
1594 else go1 SPEC ringHash rh' s acc'
1595 else go0 SPEC (idx + 1) rh' s acc'
1596 Skip s -> go0 SPEC idx rh s acc
1597 Stop -> do
1598 -- do not issue a blank segment when we end at pattern
1599 if (idx == maxIndex) && RB.unsafeEqArray rb rh patArr
1600 then return Stop
1601 else do
1602 !acc' <- if idx /= 0 && not withSep
1603 then RB.unsafeFoldRingM rh fstep acc rb
1604 else return acc
1605 done acc' >>= \r -> return $ Yield r GO_DONE
1607 -- XXX Theoretically this code can do 4 times faster if GHC generates
1608 -- optimal code. If we use just "(cksum' == patHash)" condition it goes
1609 -- 4x faster, as soon as we add the "RB.unsafeEqArray rb v" condition
1610 -- the generated code changes drastically and becomes 4x slower. Need
1611 -- to investigate what is going on with GHC.
1612 {-# INLINE go1 #-}
1613 go1 !_ !cksum !rh st !acc = do
1614 res <- step (adaptState gst) st
1615 case res of
1616 Yield x s -> do
1617 old <- liftIO $ peek rh
1618 let cksum' = deltaCksum cksum old x
1619 acc' <- if withSep
1620 then fstep acc x
1621 else fstep acc old
1623 if (cksum' == patHash)
1624 then do
1625 rh' <- liftIO (RB.unsafeInsert rb rh x)
1626 go2 SPEC cksum' rh' s acc'
1627 else do
1628 rh' <- liftIO (RB.unsafeInsert rb rh x)
1629 go1 SPEC cksum' rh' s acc'
1630 Skip s -> go1 SPEC cksum rh s acc
1631 Stop -> do
1632 if RB.unsafeEqArray rb rh patArr
1633 then return Stop
1634 else do
1635 acc' <- if withSep
1636 then return acc
1637 else RB.unsafeFoldRingFullM rh fstep acc rb
1638 done acc' >>= \r -> return $ Yield r GO_DONE
1640 go2 !_ !cksum' !rh' s !acc' = do
1641 if RB.unsafeEqArray rb rh' patArr
1642 then do
1643 r <- done acc'
1644 return $ Yield r (GO_KARP_RABIN s rb rhead)
1645 else go1 SPEC cksum' rh' s acc'
1647 stepOuter gst (GO_EMPTY_PAT st) = do
1648 res <- step (adaptState gst) st
1649 case res of
1650 Yield x s -> do
1651 acc <- initial
1652 acc' <- fstep acc x
1653 done acc' >>= \r -> return $ Yield r (GO_EMPTY_PAT s)
1654 Skip s -> return $ Skip (GO_EMPTY_PAT s)
1655 Stop -> return Stop
1657 stepOuter _ GO_DONE = return Stop
1659data SplitState s arr
1660 = SplitInitial s
1661 | SplitBuffering s arr
1662 | SplitSplitting s arr
1663 | SplitYielding arr (SplitState s arr)
1664 | SplitFinishing
1666-- XXX An alternative approach would be to use a partial fold (Fold m a b) to
1667-- split using a splitBy like combinator. The Fold would consume upto the
1668-- separator and return any leftover which can then be fed to the next fold.
1670-- We can revisit this once we have partial folds/parsers.
1672-- | Performs infix separator style splitting.
1673{-# INLINE_NORMAL splitInnerBy #-}
1674splitInnerBy
1675 :: Monad m
1676 => (f a -> m (f a, Maybe (f a))) -- splitter
1677 -> (f a -> f a -> m (f a)) -- joiner
1678 -> Stream m (f a)
1679 -> Stream m (f a)
1680splitInnerBy splitter joiner (Stream step1 state1) =
1681 (Stream step (SplitInitial state1))
1683 where
1685 {-# INLINE_LATE step #-}
1686 step gst (SplitInitial st) = do
1687 r <- step1 gst st
1688 case r of
1689 Yield x s -> do
1690 (x1, mx2) <- splitter x
1691 return $ case mx2 of
1692 Nothing -> Skip (SplitBuffering s x1)
1693 Just x2 -> Skip (SplitYielding x1 (SplitSplitting s x2))
1694 Skip s -> return $ Skip (SplitInitial s)
1695 Stop -> return $ Stop
1697 step gst (SplitBuffering st buf) = do
1698 r <- step1 gst st
1699 case r of
1700 Yield x s -> do
1701 (x1, mx2) <- splitter x
1702 buf' <- joiner buf x1
1703 return $ case mx2 of
1704 Nothing -> Skip (SplitBuffering s buf')
1705 Just x2 -> Skip (SplitYielding buf' (SplitSplitting s x2))
1706 Skip s -> return $ Skip (SplitBuffering s buf)
1707 Stop -> return $ Skip (SplitYielding buf SplitFinishing)
1709 step _ (SplitSplitting st buf) = do
1710 (x1, mx2) <- splitter buf
1711 return $ case mx2 of
1712 Nothing -> Skip $ SplitBuffering st x1
1713 Just x2 -> Skip $ SplitYielding x1 (SplitSplitting st x2)
1715 step _ (SplitYielding x next) = return $ Yield x next
1716 step _ SplitFinishing = return $ Stop
1718-- | Performs infix separator style splitting.
1719{-# INLINE_NORMAL splitInnerBySuffix #-}
1720splitInnerBySuffix
1721 :: (Monad m, Eq (f a), Monoid (f a))
1722 => (f a -> m (f a, Maybe (f a))) -- splitter
1723 -> (f a -> f a -> m (f a)) -- joiner
1724 -> Stream m (f a)
1725 -> Stream m (f a)
1726splitInnerBySuffix splitter joiner (Stream step1 state1) =
1727 (Stream step (SplitInitial state1))
1729 where
1731 {-# INLINE_LATE step #-}
1732 step gst (SplitInitial st) = do
1733 r <- step1 gst st
1734 case r of
1735 Yield x s -> do
1736 (x1, mx2) <- splitter x
1737 return $ case mx2 of
1738 Nothing -> Skip (SplitBuffering s x1)
1739 Just x2 -> Skip (SplitYielding x1 (SplitSplitting s x2))
1740 Skip s -> return $ Skip (SplitInitial s)
1741 Stop -> return $ Stop
1743 step gst (SplitBuffering st buf) = do
1744 r <- step1 gst st
1745 case r of
1746 Yield x s -> do
1747 (x1, mx2) <- splitter x
1748 buf' <- joiner buf x1
1749 return $ case mx2 of
1750 Nothing -> Skip (SplitBuffering s buf')
1751 Just x2 -> Skip (SplitYielding buf' (SplitSplitting s x2))
1752 Skip s -> return $ Skip (SplitBuffering s buf)
1753 Stop -> return $
1754 if buf == mempty
1755 then Stop
1756 else Skip (SplitYielding buf SplitFinishing)
1758 step _ (SplitSplitting st buf) = do
1759 (x1, mx2) <- splitter buf
1760 return $ case mx2 of
1761 Nothing -> Skip $ SplitBuffering st x1
1762 Just x2 -> Skip $ SplitYielding x1 (SplitSplitting st x2)
1764 step _ (SplitYielding x next) = return $ Yield x next
1765 step _ SplitFinishing = return $ Stop
1767------------------------------------------------------------------------------
1768-- Substreams
1769------------------------------------------------------------------------------
1771{-# INLINE_NORMAL isPrefixOf #-}
1772isPrefixOf :: (Eq a, Monad m) => Stream m a -> Stream m a -> m Bool
1773isPrefixOf (Stream stepa ta) (Stream stepb tb) = go (ta, tb, Nothing)
1774 where
1775 go (sa, sb, Nothing) = do
1776 r <- stepa defState sa
1777 case r of
1778 Yield x sa' -> go (sa', sb, Just x)
1779 Skip sa' -> go (sa', sb, Nothing)
1780 Stop -> return True
1782 go (sa, sb, Just x) = do
1783 r <- stepb defState sb
1784 case r of
1785 Yield y sb' ->
1786 if x == y
1787 then go (sa, sb', Nothing)
1788 else return False
1789 Skip sb' -> go (sa, sb', Just x)
1790 Stop -> return False
1792{-# INLINE_NORMAL isSubsequenceOf #-}
1793isSubsequenceOf :: (Eq a, Monad m) => Stream m a -> Stream m a -> m Bool
1794isSubsequenceOf (Stream stepa ta) (Stream stepb tb) = go (ta, tb, Nothing)
1795 where
1796 go (sa, sb, Nothing) = do
1797 r <- stepa defState sa
1798 case r of
1799 Yield x sa' -> go (sa', sb, Just x)
1800 Skip sa' -> go (sa', sb, Nothing)
1801 Stop -> return True
1803 go (sa, sb, Just x) = do
1804 r <- stepb defState sb
1805 case r of
1806 Yield y sb' ->
1807 if x == y
1808 then go (sa, sb', Nothing)
1809 else go (sa, sb', Just x)
1810 Skip sb' -> go (sa, sb', Just x)
1811 Stop -> return False
1813{-# INLINE_NORMAL stripPrefix #-}
1814stripPrefix
1815 :: (Eq a, Monad m)
1816 => Stream m a -> Stream m a -> m (Maybe (Stream m a))
1817stripPrefix (Stream stepa ta) (Stream stepb tb) = go (ta, tb, Nothing)
1818 where
1819 go (sa, sb, Nothing) = do
1820 r <- stepa defState sa
1821 case r of
1822 Yield x sa' -> go (sa', sb, Just x)
1823 Skip sa' -> go (sa', sb, Nothing)
1824 Stop -> return $ Just (Stream stepb sb)
1826 go (sa, sb, Just x) = do
1827 r <- stepb defState sb
1828 case r of
1829 Yield y sb' ->
1830 if x == y
1831 then go (sa, sb', Nothing)
1832 else return Nothing
1833 Skip sb' -> go (sa, sb', Just x)
1834 Stop -> return Nothing
1836------------------------------------------------------------------------------
1837-- Map and Fold
1838------------------------------------------------------------------------------
1840-- | Execute a monadic action for each element of the 'Stream'
1841{-# INLINE_NORMAL mapM_ #-}
1842mapM_ :: Monad m => (a -> m b) -> Stream m a -> m ()
1843mapM_ m = drain . mapM m
1845-------------------------------------------------------------------------------
1846-- Stream transformations using Unfolds
1847-------------------------------------------------------------------------------
1849-- Define a unique structure to use in inspection testing
1850data ConcatMapUState o i =
1851 ConcatMapUOuter o
1852 | ConcatMapUInner o i
1854-- | @concatMapU unfold stream@ uses @unfold@ to map the input stream elements
1855-- to streams and then flattens the generated streams into a single output
1856-- stream.
1858-- This is like 'concatMap' but uses an unfold with an explicit state to
1859-- generate the stream instead of a 'Stream' type generator. This allows better
1860-- optimization via fusion. This can be many times more efficient than
1861-- 'concatMap'.
1863{-# INLINE_NORMAL concatMapU #-}
1864concatMapU :: Monad m => Unfold m a b -> Stream m a -> Stream m b
1865concatMapU (Unfold istep inject) (Stream ostep ost) =
1866 Stream step (ConcatMapUOuter ost)
1867 where
1868 {-# INLINE_LATE step #-}
1869 step gst (ConcatMapUOuter o) = do
1870 r <- ostep (adaptState gst) o
1871 case r of
1872 Yield a o' -> do
1873 i <- inject a
1874 i `seq` return (Skip (ConcatMapUInner o' i))
1875 Skip o' -> return $ Skip (ConcatMapUOuter o')
1876 Stop -> return $ Stop
1878 step _ (ConcatMapUInner o i) = do
1879 r <- istep i
1880 return $ case r of
1881 Yield x i' -> Yield x (ConcatMapUInner o i')
1882 Skip i' -> Skip (ConcatMapUInner o i')
1883 Stop -> Skip (ConcatMapUOuter o)
1885data ConcatUnfoldInterleaveState o i =
1886 ConcatUnfoldInterleaveOuter o [i]
1887 | ConcatUnfoldInterleaveInner o [i]
1888 | ConcatUnfoldInterleaveInnerL [i] [i]
1889 | ConcatUnfoldInterleaveInnerR [i] [i]
1891-- XXX use arrays to store state instead of lists.
1892-- XXX In general we can use different scheduling strategies e.g. how to
1893-- schedule the outer vs inner loop or assigning weights to different streams
1894-- or outer and inner loops.
1896-- After a yield, switch to the next stream. Do not switch streams on Skip.
1897-- Yield from outer stream switches to the inner stream.
1899-- There are two choices here, (1) exhaust the outer stream first and then
1900-- start yielding from the inner streams, this is much simpler to implement,
1901-- (2) yield at least one element from an inner stream before going back to
1902-- outer stream and opening the next stream from it.
1904-- Ideally, we need some scheduling bias to inner streams vs outer stream.
1905-- Maybe we can configure the behavior.
1907{-# INLINE_NORMAL concatUnfoldInterleave #-}
1908concatUnfoldInterleave :: Monad m => Unfold m a b -> Stream m a -> Stream m b
1909concatUnfoldInterleave (Unfold istep inject) (Stream ostep ost) =
1910 Stream step (ConcatUnfoldInterleaveOuter ost [])
1911 where
1912 {-# INLINE_LATE step #-}
1913 step gst (ConcatUnfoldInterleaveOuter o ls) = do
1914 r <- ostep (adaptState gst) o
1915 case r of
1916 Yield a o' -> do
1917 i <- inject a
1918 i `seq` return (Skip (ConcatUnfoldInterleaveInner o' (i : ls)))
1919 Skip o' -> return $ Skip (ConcatUnfoldInterleaveOuter o' ls)
1920 Stop -> return $ Skip (ConcatUnfoldInterleaveInnerL ls [])
1922 step _ (ConcatUnfoldInterleaveInner _ []) = undefined
1923 step _ (ConcatUnfoldInterleaveInner o (st:ls)) = do
1924 r <- istep st
1925 return $ case r of
1926 Yield x s -> Yield x (ConcatUnfoldInterleaveOuter o (s:ls))
1927 Skip s -> Skip (ConcatUnfoldInterleaveInner o (s:ls))
1928 Stop -> Skip (ConcatUnfoldInterleaveOuter o ls)
1930 step _ (ConcatUnfoldInterleaveInnerL [] []) = return Stop
1931 step _ (ConcatUnfoldInterleaveInnerL [] rs) =
1932 return $ Skip (ConcatUnfoldInterleaveInnerR [] rs)
1934 step _ (ConcatUnfoldInterleaveInnerL (st:ls) rs) = do
1935 r <- istep st
1936 return $ case r of
1937 Yield x s -> Yield x (ConcatUnfoldInterleaveInnerL ls (s:rs))
1938 Skip s -> Skip (ConcatUnfoldInterleaveInnerL (s:ls) rs)
1939 Stop -> Skip (ConcatUnfoldInterleaveInnerL ls rs)
1941 step _ (ConcatUnfoldInterleaveInnerR [] []) = return Stop
1942 step _ (ConcatUnfoldInterleaveInnerR ls []) =
1943 return $ Skip (ConcatUnfoldInterleaveInnerL ls [])
1945 step _ (ConcatUnfoldInterleaveInnerR ls (st:rs)) = do
1946 r <- istep st
1947 return $ case r of
1948 Yield x s -> Yield x (ConcatUnfoldInterleaveInnerR (s:ls) rs)
1949 Skip s -> Skip (ConcatUnfoldInterleaveInnerR ls (s:rs))
1950 Stop -> Skip (ConcatUnfoldInterleaveInnerR ls rs)
1952-- XXX In general we can use different scheduling strategies e.g. how to
1953-- schedule the outer vs inner loop or assigning weights to different streams
1954-- or outer and inner loops.
1956-- This could be inefficient if the tasks are too small.
1958-- Compared to concatUnfoldInterleave this one switches streams on Skips.
1960{-# INLINE_NORMAL concatUnfoldRoundrobin #-}
1961concatUnfoldRoundrobin :: Monad m => Unfold m a b -> Stream m a -> Stream m b
1962concatUnfoldRoundrobin (Unfold istep inject) (Stream ostep ost) =
1963 Stream step (ConcatUnfoldInterleaveOuter ost [])
1964 where
1965 {-# INLINE_LATE step #-}
1966 step gst (ConcatUnfoldInterleaveOuter o ls) = do
1967 r <- ostep (adaptState gst) o
1968 case r of
1969 Yield a o' -> do
1970 i <- inject a
1971 i `seq` return (Skip (ConcatUnfoldInterleaveInner o' (i : ls)))
1972 Skip o' -> return $ Skip (ConcatUnfoldInterleaveInner o' ls)
1973 Stop -> return $ Skip (ConcatUnfoldInterleaveInnerL ls [])
1975 step _ (ConcatUnfoldInterleaveInner o []) =
1976 return $ Skip (ConcatUnfoldInterleaveOuter o [])
1978 step _ (ConcatUnfoldInterleaveInner o (st:ls)) = do
1979 r <- istep st
1980 return $ case r of
1981 Yield x s -> Yield x (ConcatUnfoldInterleaveOuter o (s:ls))
1982 Skip s -> Skip (ConcatUnfoldInterleaveOuter o (s:ls))
1983 Stop -> Skip (ConcatUnfoldInterleaveOuter o ls)
1985 step _ (ConcatUnfoldInterleaveInnerL [] []) = return Stop
1986 step _ (ConcatUnfoldInterleaveInnerL [] rs) =
1987 return $ Skip (ConcatUnfoldInterleaveInnerR [] rs)
1989 step _ (ConcatUnfoldInterleaveInnerL (st:ls) rs) = do
1990 r <- istep st
1991 return $ case r of
1992 Yield x s -> Yield x (ConcatUnfoldInterleaveInnerL ls (s:rs))
1993 Skip s -> Skip (ConcatUnfoldInterleaveInnerL ls (s:rs))
1994 Stop -> Skip (ConcatUnfoldInterleaveInnerL ls rs)
1996 step _ (ConcatUnfoldInterleaveInnerR [] []) = return Stop
1997 step _ (ConcatUnfoldInterleaveInnerR ls []) =
1998 return $ Skip (ConcatUnfoldInterleaveInnerL ls [])
2000 step _ (ConcatUnfoldInterleaveInnerR ls (st:rs)) = do
2001 r <- istep st
2002 return $ case r of
2003 Yield x s -> Yield x (ConcatUnfoldInterleaveInnerR (s:ls) rs)
2004 Skip s -> Skip (ConcatUnfoldInterleaveInnerR (s:ls) rs)
2005 Stop -> Skip (ConcatUnfoldInterleaveInnerR ls rs)
2007data AppendState s1 s2 = AppendFirst s1 | AppendSecond s2
2009-- Note that this could be much faster compared to the CPS stream. However, as
2010-- the number of streams being composed increases this may become expensive.
2011-- Need to see where the breaking point is between the two.
2013{-# INLINE_NORMAL append #-}
2014append :: Monad m => Stream m a -> Stream m a -> Stream m a
2015append (Stream step1 state1) (Stream step2 state2) =
2016 Stream step (AppendFirst state1)
2018 where
2020 {-# INLINE_LATE step #-}
2021 step gst (AppendFirst st) = do
2022 r <- step1 gst st
2023 return $ case r of
2024 Yield a s -> Yield a (AppendFirst s)
2025 Skip s -> Skip (AppendFirst s)
2026 Stop -> Skip (AppendSecond state2)
2028 step gst (AppendSecond st) = do
2029 r <- step2 gst st
2030 return $ case r of
2031 Yield a s -> Yield a (AppendSecond s)
2032 Skip s -> Skip (AppendSecond s)
2033 Stop -> Stop
2035data InterleaveState s1 s2 = InterleaveFirst s1 s2 | InterleaveSecond s1 s2
2036 | InterleaveSecondOnly s2 | InterleaveFirstOnly s1
2038{-# INLINE_NORMAL interleave #-}
2039interleave :: Monad m => Stream m a -> Stream m a -> Stream m a
2040interleave (Stream step1 state1) (Stream step2 state2) =
2041 Stream step (InterleaveFirst state1 state2)
2043 where
2045 {-# INLINE_LATE step #-}
2046 step gst (InterleaveFirst st1 st2) = do
2047 r <- step1 gst st1
2048 return $ case r of
2049 Yield a s -> Yield a (InterleaveSecond s st2)
2050 Skip s -> Skip (InterleaveFirst s st2)
2051 Stop -> Skip (InterleaveSecondOnly st2)
2053 step gst (InterleaveSecond st1 st2) = do
2054 r <- step2 gst st2
2055 return $ case r of
2056 Yield a s -> Yield a (InterleaveFirst st1 s)
2057 Skip s -> Skip (InterleaveSecond st1 s)
2058 Stop -> Skip (InterleaveFirstOnly st1)
2060 step gst (InterleaveFirstOnly st1) = do
2061 r <- step1 gst st1
2062 return $ case r of
2063 Yield a s -> Yield a (InterleaveFirstOnly s)
2064 Skip s -> Skip (InterleaveFirstOnly s)
2065 Stop -> Stop
2067 step gst (InterleaveSecondOnly st2) = do
2068 r <- step2 gst st2
2069 return $ case r of
2070 Yield a s -> Yield a (InterleaveSecondOnly s)
2071 Skip s -> Skip (InterleaveSecondOnly s)
2072 Stop -> Stop
2074{-# INLINE_NORMAL interleaveMin #-}
2075interleaveMin :: Monad m => Stream m a -> Stream m a -> Stream m a
2076interleaveMin (Stream step1 state1) (Stream step2 state2) =
2077 Stream step (InterleaveFirst state1 state2)
2079 where
2081 {-# INLINE_LATE step #-}
2082 step gst (InterleaveFirst st1 st2) = do
2083 r <- step1 gst st1
2084 return $ case r of
2085 Yield a s -> Yield a (InterleaveSecond s st2)
2086 Skip s -> Skip (InterleaveFirst s st2)
2087 Stop -> Stop
2089 step gst (InterleaveSecond st1 st2) = do
2090 r <- step2 gst st2
2091 return $ case r of
2092 Yield a s -> Yield a (InterleaveFirst st1 s)
2093 Skip s -> Skip (InterleaveSecond st1 s)
2094 Stop -> Stop
2096 step _ (InterleaveFirstOnly _) = undefined
2097 step _ (InterleaveSecondOnly _) = undefined
2099{-# INLINE_NORMAL interleaveFst #-}
2100interleaveFst :: Monad m => Stream m a -> Stream m a -> Stream m a
2101interleaveFst (Stream step1 state1) (Stream step2 state2) =
2102 Stream step (InterleaveFirst state1 state2)
2104 where
2106 {-# INLINE_LATE step #-}
2107 step gst (InterleaveFirst st1 st2) = do
2108 r <- step1 gst st1
2109 return $ case r of
2110 Yield a s -> Yield a (InterleaveSecond s st2)
2111 Skip s -> Skip (InterleaveFirst s st2)
2112 Stop -> Stop
2114 step gst (InterleaveSecond st1 st2) = do
2115 r <- step2 gst st2
2116 return $ case r of
2117 Yield a s -> Yield a (InterleaveFirst st1 s)
2118 Skip s -> Skip (InterleaveSecond st1 s)
2119 Stop -> Skip (InterleaveFirstOnly st1)
2121 step gst (InterleaveFirstOnly st1) = do
2122 r <- step1 gst st1
2123 return $ case r of
2124 Yield a s -> Yield a (InterleaveFirstOnly s)
2125 Skip s -> Skip (InterleaveFirstOnly s)
2126 Stop -> Stop
2128 step _ (InterleaveSecondOnly _) = undefined
2130{-# INLINE_NORMAL roundRobin #-}
2131roundRobin :: Monad m => Stream m a -> Stream m a -> Stream m a
2132roundRobin (Stream step1 state1) (Stream step2 state2) =
2133 Stream step (InterleaveFirst state1 state2)
2135 where
2137 {-# INLINE_LATE step #-}
2138 step gst (InterleaveFirst st1 st2) = do
2139 r <- step1 gst st1
2140 return $ case r of
2141 Yield a s -> Yield a (InterleaveSecond s st2)
2142 Skip s -> Skip (InterleaveSecond s st2)
2143 Stop -> Skip (InterleaveSecondOnly st2)
2145 step gst (InterleaveSecond st1 st2) = do
2146 r <- step2 gst st2
2147 return $ case r of
2148 Yield a s -> Yield a (InterleaveFirst st1 s)
2149 Skip s -> Skip (InterleaveFirst st1 s)
2150 Stop -> Skip (InterleaveFirstOnly st1)
2152 step gst (InterleaveSecondOnly st2) = do
2153 r <- step2 gst st2
2154 return $ case r of
2155 Yield a s -> Yield a (InterleaveSecondOnly s)
2156 Skip s -> Skip (InterleaveSecondOnly s)
2157 Stop -> Stop
2159 step gst (InterleaveFirstOnly st1) = do
2160 r <- step1 gst st1
2161 return $ case r of
2162 Yield a s -> Yield a (InterleaveFirstOnly s)
2163 Skip s -> Skip (InterleaveFirstOnly s)
2164 Stop -> Stop
2166data ICUState s1 s2 i1 i2 =
2167 ICUFirst s1 s2
2168 | ICUSecond s1 s2
2169 | ICUSecondOnly s2
2170 | ICUFirstOnly s1
2171 | ICUFirstInner s1 s2 i1
2172 | ICUSecondInner s1 s2 i2
2173 | ICUFirstOnlyInner s1 i1
2174 | ICUSecondOnlyInner s2 i2
2176-- | Interleave streams (full streams, not the elements) unfolded from two
2177-- input streams and concat. Stop when the first stream stops. If the second
2178-- stream ends before the first one then first stream still keeps running alone
2179-- without any interleaving with the second stream.
2181-- [a1, a2, ... an] [b1, b2 ...]
2182-- => [streamA1, streamA2, ... streamAn] [streamB1, streamB2, ...]
2183-- => [streamA1, streamB1, streamA2...StreamAn, streamBn]
2184-- => [a11, a12, ...a1j, b11, b12, ...b1k, a21, a22, ...]
2186{-# INLINE_NORMAL interleaveFstThenConcat #-}
2187interleaveFstThenConcat
2188 :: Monad m
2189 => Unfold m a c -> Stream m a -> Unfold m b c -> Stream m b -> Stream m c
2190interleaveFstThenConcat
2191 (Unfold istep1 inject1) (Stream step1 state1)
2192 (Unfold istep2 inject2) (Stream step2 state2) =
2193 Stream step (ICUFirst state1 state2)
2195 where
2197 {-# INLINE_LATE step #-}
2198 step gst (ICUFirst s1 s2) = do
2199 r <- step1 (adaptState gst) s1
2200 case r of
2201 Yield a s -> do
2202 i <- inject1 a
2203 i `seq` return (Skip (ICUFirstInner s s2 i))
2204 Skip s -> return $ Skip (ICUFirst s s2)
2205 Stop -> return Stop
2207 step gst (ICUFirstOnly s1) = do
2208 r <- step1 (adaptState gst) s1
2209 case r of
2210 Yield a s -> do
2211 i <- inject1 a
2212 i `seq` return (Skip (ICUFirstOnlyInner s i))
2213 Skip s -> return $ Skip (ICUFirstOnly s)
2214 Stop -> return Stop
2216 step _ (ICUFirstInner s1 s2 i1) = do
2217 r <- istep1 i1
2218 return $ case r of
2219 Yield x i' -> Yield x (ICUFirstInner s1 s2 i')
2220 Skip i' -> Skip (ICUFirstInner s1 s2 i')
2221 Stop -> Skip (ICUSecond s1 s2)
2223 step _ (ICUFirstOnlyInner s1 i1) = do
2224 r <- istep1 i1
2225 return $ case r of
2226 Yield x i' -> Yield x (ICUFirstOnlyInner s1 i')
2227 Skip i' -> Skip (ICUFirstOnlyInner s1 i')
2228 Stop -> Skip (ICUFirstOnly s1)
2230 step gst (ICUSecond s1 s2) = do
2231 r <- step2 (adaptState gst) s2
2232 case r of
2233 Yield a s -> do
2234 i <- inject2 a
2235 i `seq` return (Skip (ICUSecondInner s1 s i))
2236 Skip s -> return $ Skip (ICUSecond s1 s)
2237 Stop -> return $ Skip (ICUFirstOnly s1)
2239 step _ (ICUSecondInner s1 s2 i2) = do
2240 r <- istep2 i2
2241 return $ case r of
2242 Yield x i' -> Yield x (ICUSecondInner s1 s2 i')
2243 Skip i' -> Skip (ICUSecondInner s1 s2 i')
2244 Stop -> Skip (ICUFirst s1 s2)
2246 step _ (ICUSecondOnly _s2) = undefined
2247 step _ (ICUSecondOnlyInner _s2 _i2) = undefined
2249------------------------------------------------------------------------------
2250-- Exceptions
2251------------------------------------------------------------------------------
2253-- | Run a side effect before the stream yields its first element.
2254{-# INLINE_NORMAL before #-}
2255before :: Monad m => m b -> Stream m a -> Stream m a
2256before action (Stream step state) = Stream step' Nothing
2258 where
2260 {-# INLINE_LATE step' #-}
2261 step' _ Nothing = action >> return (Skip (Just state))
2263 step' gst (Just st) = do
2264 res <- step gst st
2265 case res of
2266 Yield x s -> return $ Yield x (Just s)
2267 Skip s -> return $ Skip (Just s)
2268 Stop -> return Stop
2270-- | Run a side effect whenever the stream stops normally.
2271{-# INLINE_NORMAL after #-}
2272after :: Monad m => m b -> Stream m a -> Stream m a
2273after action (Stream step state) = Stream step' state
2275 where
2277 {-# INLINE_LATE step' #-}
2278 step' gst st = do
2279 res <- step gst st
2280 case res of
2281 Yield x s -> return $ Yield x s
2282 Skip s -> return $ Skip s
2283 Stop -> action >> return Stop
2285-- XXX These combinators are expensive due to the call to
2286-- onException/handle/try on each step. Therefore, when possible, they should
2287-- be called in an outer loop where we perform less iterations. For example, we
2288-- cannot call them on each iteration in a char stream, instead we can call
2289-- them when doing an IO on an array.
2291-- XXX For high performance error checks in busy streams we may need another
2292-- Error constructor in step.
2294-- | Run a side effect whenever the stream aborts due to an exception. The
2295-- exception is not caught, simply rethrown.
2296{-# INLINE_NORMAL onException #-}
2297onException :: MonadCatch m => m b -> Stream m a -> Stream m a
2298onException action (Stream step state) = Stream step' state
2300 where
2302 {-# INLINE_LATE step' #-}
2303 step' gst st = do
2304 res <- step gst st `MC.onException` action
2305 case res of
2306 Yield x s -> return $ Yield x s
2307 Skip s -> return $ Skip s
2308 Stop -> return Stop
2310-- | Run a side effect whenever the stream stops normally or aborts due to an
2311-- exception.
2312{-# INLINE finally #-}
2313finally :: MonadCatch m => m b -> Stream m a -> Stream m a
2314-- finally action xs = after action $ onException action xs
2315finally action xs = bracket (return ()) (\_ -> action) (const xs)
2317-- XXX bracket is like concatMap, it generates a stream and then flattens it.
2318-- Like concatMap it has 10x worse performance compared to linear fused
2319-- compositions.
2321-- | Run the first action before the stream starts and remember its output,
2322-- generate a stream using the output, run the second action providing the
2323-- remembered value as an argument whenever the stream ends normally or due to
2324-- an exception.
2325{-# INLINE_NORMAL bracket #-}
2326bracket :: MonadCatch m => m b -> (b -> m c) -> (b -> Stream m a) -> Stream m a
2327bracket bef aft bet = Stream step' Nothing
2329 where
2331 {-# INLINE_LATE step' #-}
2332 step' _ Nothing = bef >>= \x -> return (Skip (Just (bet x, x)))
2334 -- NOTE: It is important to use UnStream instead of the Stream pattern
2335 -- here, otherwise we get huge perf degradation, see note in concatMap.
2336 step' gst (Just (UnStream step state, v)) = do
2337 res <- step gst state `MC.onException` aft v
2338 case res of
2339 Yield x s -> return $ Yield x (Just (Stream step s, v))
2340 Skip s -> return $ Skip (Just (Stream step s, v))
2341 Stop -> aft v >> return Stop
2343-- | When evaluating a stream if an exception occurs, stream evaluation aborts
2344-- and the specified exception handler is run with the exception as argument.
2345{-# INLINE_NORMAL handle #-}
2346handle :: (MonadCatch m, Exception e) => (e -> m a) -> Stream m a -> Stream m a
2347handle f (Stream step state) = Stream step' (Just state)
2349 where
2351 {-# INLINE_LATE step' #-}
2352 step' gst (Just st) = do
2353 res <- MC.try $ step gst st
2354 case res of
2355 Left e -> f e >>= \x -> return (Yield x Nothing)
2356 Right r -> case r of
2357 Yield x s -> return $ Yield x (Just s)
2358 Skip s -> return $ Skip (Just s)
2359 Stop -> return Stop
2361 step' _ Nothing = return Stop
2363-------------------------------------------------------------------------------
2364-- General transformation
2365-------------------------------------------------------------------------------
2367{-# INLINE_NORMAL transform #-}
2368transform :: Monad m => Pipe m a b -> Stream m a -> Stream m b
2369transform (Pipe pstep1 pstep2 pstate) (Stream step state) =
2370 Stream step' (Consume pstate, state)
2372 where
2374 {-# INLINE_LATE step' #-}
2376 step' gst (Consume pst, st) = pst `seq` do
2377 r <- step (adaptState gst) st
2378 case r of
2379 Yield x s -> do
2380 res <- pstep1 pst x
2381 case res of
2382 Pipe.Yield b pst' -> return $ Yield b (pst', s)
2383 Pipe.Continue pst' -> return $ Skip (pst', s)
2384 Skip s -> return $ Skip (Consume pst, s)
2385 Stop -> return Stop
2387 step' _ (Produce pst, st) = pst `seq` do
2388 res <- pstep2 pst
2389 case res of
2390 Pipe.Yield b pst' -> return $ Yield b (pst', st)
2391 Pipe.Continue pst' -> return $ Skip (pst', st)
2393------------------------------------------------------------------------------
2394-- Transformation by Folding (Scans)
2395------------------------------------------------------------------------------
2397------------------------------------------------------------------------------
2398-- Prescans
2399------------------------------------------------------------------------------
2401-- XXX Is a prescan useful, discarding the last step does not sound useful? I
2402-- am not sure about the utility of this function, so this is implemented but
2403-- not exposed. We can expose it if someone provides good reasons why this is
2404-- useful.
2406-- XXX We have to execute the stream one step ahead to know that we are at the
2407-- last step. The vector implementation of prescan executes the last fold step
2408-- but does not yield the result. This means we have executed the effect but
2409-- discarded value. This does not sound right. In this implementation we are
2410-- not executing the last fold step.
2411{-# INLINE_NORMAL prescanlM' #-}
2412prescanlM' :: Monad m => (b -> a -> m b) -> m b -> Stream m a -> Stream m b
2413prescanlM' f mz (Stream step state) = Stream step' (state, mz)
2414 where
2415 {-# INLINE_LATE step' #-}
2416 step' gst (st, prev) = do
2417 r <- step (adaptState gst) st
2418 case r of
2419 Yield x s -> do
2420 acc <- prev
2421 return $ Yield acc (s, f acc x)
2422 Skip s -> return $ Skip (s, prev)
2423 Stop -> return Stop
2425{-# INLINE prescanl' #-}
2426prescanl' :: Monad m => (b -> a -> b) -> b -> Stream m a -> Stream m b
2427prescanl' f z = prescanlM' (\a b -> return (f a b)) (return z)
2429------------------------------------------------------------------------------
2430-- Monolithic postscans (postscan followed by a map)
2431------------------------------------------------------------------------------
2433-- The performance of a modular postscan followed by a map seems to be
2434-- equivalent to this monolithic scan followed by map therefore we may not need
2435-- this implementation. We just have it for performance comparison and in case
2436-- modular version does not perform well in some situation.
2438{-# INLINE_NORMAL postscanlMx' #-}
2439postscanlMx' :: Monad m
2440 => (x -> a -> m x) -> m x -> (x -> m b) -> Stream m a -> Stream m b
2441postscanlMx' fstep begin done (Stream step state) = do
2442 Stream step' (state, begin)
2443 where
2444 {-# INLINE_LATE step' #-}
2445 step' gst (st, acc) = do
2446 r <- step (adaptState gst) st
2447 case r of
2448 Yield x s -> do
2449 old <- acc
2450 y <- fstep old x
2451 v <- done y
2452 v `seq` y `seq` return (Yield v (s, return y))
2453 Skip s -> return $ Skip (s, acc)
2454 Stop -> return Stop
2456{-# INLINE_NORMAL postscanlx' #-}
2457postscanlx' :: Monad m
2458 => (x -> a -> x) -> x -> (x -> b) -> Stream m a -> Stream m b
2459postscanlx' fstep begin done s =
2460 postscanlMx' (\b a -> return (fstep b a)) (return begin) (return . done) s
2462-- XXX do we need consM strict to evaluate the begin value?
2463{-# INLINE scanlMx' #-}
2464scanlMx' :: Monad m
2465 => (x -> a -> m x) -> m x -> (x -> m b) -> Stream m a -> Stream m b
2466scanlMx' fstep begin done s =
2467 (begin >>= \x -> x `seq` done x) `consM` postscanlMx' fstep begin done s
2469{-# INLINE scanlx' #-}
2470scanlx' :: Monad m
2471 => (x -> a -> x) -> x -> (x -> b) -> Stream m a -> Stream m b
2472scanlx' fstep begin done s =
2473 scanlMx' (\b a -> return (fstep b a)) (return begin) (return . done) s
2475------------------------------------------------------------------------------
2476-- postscans
2477------------------------------------------------------------------------------
2479{-# INLINE_NORMAL postscanlM' #-}
2480postscanlM' :: Monad m => (b -> a -> m b) -> b -> Stream m a -> Stream m b
2481postscanlM' fstep begin (Stream step state) =
2482 begin `seq` Stream step' (state, begin)
2483 where
2484 {-# INLINE_LATE step' #-}
2485 step' gst (st, acc) = acc `seq` do
2486 r <- step (adaptState gst) st
2487 case r of
2488 Yield x s -> do
2489 y <- fstep acc x
2490 y `seq` return (Yield y (s, y))
2491 Skip s -> return $ Skip (s, acc)
2492 Stop -> return Stop
2494{-# INLINE_NORMAL postscanl' #-}
2495postscanl' :: Monad m => (a -> b -> a) -> a -> Stream m b -> Stream m a
2496postscanl' f = postscanlM' (\a b -> return (f a b))
2498{-# INLINE_NORMAL postscanlM #-}
2499postscanlM :: Monad m => (b -> a -> m b) -> b -> Stream m a -> Stream m b
2500postscanlM fstep begin (Stream step state) = Stream step' (state, begin)
2501 where
2502 {-# INLINE_LATE step' #-}
2503 step' gst (st, acc) = do
2504 r <- step (adaptState gst) st
2505 case r of
2506 Yield x s -> do
2507 y <- fstep acc x
2508 return (Yield y (s, y))
2509 Skip s -> return $ Skip (s, acc)
2510 Stop -> return Stop
2512{-# INLINE_NORMAL postscanl #-}
2513postscanl :: Monad m => (a -> b -> a) -> a -> Stream m b -> Stream m a
2514postscanl f = postscanlM (\a b -> return (f a b))
2516{-# INLINE_NORMAL scanlM' #-}
2517scanlM' :: Monad m => (b -> a -> m b) -> b -> Stream m a -> Stream m b
2518scanlM' fstep begin s = begin `seq` (begin `cons` postscanlM' fstep begin s)
2520{-# INLINE scanl' #-}
2521scanl' :: Monad m => (b -> a -> b) -> b -> Stream m a -> Stream m b
2522scanl' f = scanlM' (\a b -> return (f a b))
2524{-# INLINE_NORMAL scanlM #-}
2525scanlM :: Monad m => (b -> a -> m b) -> b -> Stream m a -> Stream m b
2526scanlM fstep begin s = begin `cons` postscanlM fstep begin s
2528{-# INLINE scanl #-}
2529scanl :: Monad m => (b -> a -> b) -> b -> Stream m a -> Stream m b
2530scanl f = scanlM (\a b -> return (f a b))
2532{-# INLINE_NORMAL scanl1M #-}
2533scanl1M :: Monad m => (a -> a -> m a) -> Stream m a -> Stream m a
2534scanl1M fstep (Stream step state) = Stream step' (state, Nothing)
2535 where
2536 {-# INLINE_LATE step' #-}
2537 step' gst (st, Nothing) = do
2538 r <- step gst st
2539 case r of
2540 Yield x s -> return $ Yield x (s, Just x)
2541 Skip s -> return $ Skip (s, Nothing)
2542 Stop -> return Stop
2544 step' gst (st, Just acc) = do
2545 r <- step gst st
2546 case r of
2547 Yield y s -> do
2548 z <- fstep acc y
2549 return $ Yield z (s, Just z)
2550 Skip s -> return $ Skip (s, Just acc)
2551 Stop -> return Stop
2553{-# INLINE scanl1 #-}
2554scanl1 :: Monad m => (a -> a -> a) -> Stream m a -> Stream m a
2555scanl1 f = scanl1M (\x y -> return (f x y))
2557{-# INLINE_NORMAL scanl1M' #-}
2558scanl1M' :: Monad m => (a -> a -> m a) -> Stream m a -> Stream m a
2559scanl1M' fstep (Stream step state) = Stream step' (state, Nothing)
2560 where
2561 {-# INLINE_LATE step' #-}
2562 step' gst (st, Nothing) = do
2563 r <- step gst st
2564 case r of
2565 Yield x s -> x `seq` return $ Yield x (s, Just x)
2566 Skip s -> return $ Skip (s, Nothing)
2567 Stop -> return Stop
2569 step' gst (st, Just acc) = acc `seq` do
2570 r <- step gst st
2571 case r of
2572 Yield y s -> do
2573 z <- fstep acc y
2574 z `seq` return $ Yield z (s, Just z)
2575 Skip s -> return $ Skip (s, Just acc)
2576 Stop -> return Stop
2578{-# INLINE scanl1' #-}
2579scanl1' :: Monad m => (a -> a -> a) -> Stream m a -> Stream m a
2580scanl1' f = scanl1M' (\x y -> return (f x y))
2582{-# INLINE tap #-}
2583tap :: Monad m => Fold m a b -> Stream m a -> Stream m a
2584tap (Fold fstep initial extract) (Stream step state) = Stream step' Nothing
2586 where
2588 step' _ Nothing = do
2589 r <- initial
2590 return $ Skip (Just (r, state))
2592 step' gst (Just (acc, st)) = do
2593 r <- step gst st
2594 case r of
2595 Yield x s -> do
2596 acc' <- fstep acc x
2597 return $ Yield x (Just (acc', s))
2598 Skip s -> return $ Skip (Just (acc, s))
2599 Stop -> do
2600 void $ extract acc
2601 return $ Stop
2603-------------------------------------------------------------------------------
2604-- Filtering
2605-------------------------------------------------------------------------------
2607{-# INLINE_NORMAL takeWhileM #-}
2608takeWhileM :: Monad m => (a -> m Bool) -> Stream m a -> Stream m a
2609takeWhileM f (Stream step state) = Stream step' state
2610 where
2611 {-# INLINE_LATE step' #-}
2612 step' gst st = do
2613 r <- step gst st
2614 case r of
2615 Yield x s -> do
2616 b <- f x
2617 return $ if b then Yield x s else Stop
2618 Skip s -> return $ Skip s
2619 Stop -> return Stop
2621{-# INLINE takeWhile #-}
2622takeWhile :: Monad m => (a -> Bool) -> Stream m a -> Stream m a
2623takeWhile f = takeWhileM (return . f)
2625{-# INLINE_NORMAL drop #-}
2626drop :: Monad m => Int -> Stream m a -> Stream m a
2627drop n (Stream step state) = Stream step' (state, Just n)
2628 where
2629 {-# INLINE_LATE step' #-}
2630 step' gst (st, Just i)
2631 | i > 0 = do
2632 r <- step gst st
2633 return $
2634 case r of
2635 Yield _ s -> Skip (s, Just (i - 1))
2636 Skip s -> Skip (s, Just i)
2637 Stop -> Stop
2638 | otherwise = return $ Skip (st, Nothing)
2640 step' gst (st, Nothing) = do
2641 r <- step gst st
2642 return $
2643 case r of
2644 Yield x s -> Yield x (s, Nothing)
2645 Skip s -> Skip (s, Nothing)
2646 Stop -> Stop
2648data DropWhileState s a
2649 = DropWhileDrop s
2650 | DropWhileYield a s
2651 | DropWhileNext s
2653{-# INLINE_NORMAL dropWhileM #-}
2654dropWhileM :: Monad m => (a -> m Bool) -> Stream m a -> Stream m a
2655dropWhileM f (Stream step state) = Stream step' (DropWhileDrop state)
2656 where
2657 {-# INLINE_LATE step' #-}
2658 step' gst (DropWhileDrop st) = do
2659 r <- step gst st
2660 case r of
2661 Yield x s -> do
2662 b <- f x
2663 if b
2664 then return $ Skip (DropWhileDrop s)
2665 else return $ Skip (DropWhileYield x s)
2666 Skip s -> return $ Skip (DropWhileDrop s)
2667 Stop -> return Stop
2669 step' gst (DropWhileNext st) = do
2670 r <- step gst st
2671 case r of
2672 Yield x s -> return $ Skip (DropWhileYield x s)
2673 Skip s -> return $ Skip (DropWhileNext s)
2674 Stop -> return Stop
2676 step' _ (DropWhileYield x st) = return $ Yield x (DropWhileNext st)
2678{-# INLINE dropWhile #-}
2679dropWhile :: Monad m => (a -> Bool) -> Stream m a -> Stream m a
2680dropWhile f = dropWhileM (return . f)
2682{-# INLINE_NORMAL filterM #-}
2683filterM :: Monad m => (a -> m Bool) -> Stream m a -> Stream m a
2684filterM f (Stream step state) = Stream step' state
2685 where
2686 {-# INLINE_LATE step' #-}
2687 step' gst st = do
2688 r <- step gst st
2689 case r of
2690 Yield x s -> do
2691 b <- f x
2692 return $ if b
2693 then Yield x s
2694 else Skip s
2695 Skip s -> return $ Skip s
2696 Stop -> return Stop
2698{-# INLINE filter #-}
2699filter :: Monad m => (a -> Bool) -> Stream m a -> Stream m a
2700filter f = filterM (return . f)
2702{-# INLINE_NORMAL uniq #-}
2703uniq :: (Eq a, Monad m) => Stream m a -> Stream m a
2704uniq (Stream step state) = Stream step' (Nothing, state)
2705 where
2706 {-# INLINE_LATE step' #-}
2707 step' gst (Nothing, st) = do
2708 r <- step gst st
2709 case r of
2710 Yield x s -> return $ Yield x (Just x, s)
2711 Skip s -> return $ Skip (Nothing, s)
2712 Stop -> return Stop
2713 step' gst (Just x, st) = do
2714 r <- step gst st
2715 case r of
2716 Yield y s | x == y -> return $ Skip (Just x, s)
2717 | otherwise -> return $ Yield y (Just y, s)
2718 Skip s -> return $ Skip (Just x, s)
2719 Stop -> return Stop
2721------------------------------------------------------------------------------
2722-- Transformation by Mapping
2723------------------------------------------------------------------------------
2725{-# INLINE_NORMAL sequence #-}
2726sequence :: Monad m => Stream m (m a) -> Stream m a
2727sequence (Stream step state) = Stream step' state
2728 where
2729 {-# INLINE_LATE step' #-}
2730 step' gst st = do
2731 r <- step (adaptState gst) st
2732 case r of
2733 Yield x s -> x >>= \a -> return (Yield a s)
2734 Skip s -> return $ Skip s
2735 Stop -> return Stop
2737------------------------------------------------------------------------------
2738-- Inserting
2739------------------------------------------------------------------------------
2741data LoopState x s = FirstYield s
2742 | InterspersingYield s
2743 | YieldAndCarry x s
2745{-# INLINE_NORMAL intersperseM #-}
2746intersperseM :: Monad m => m a -> Stream m a -> Stream m a
2747intersperseM m (Stream step state) = Stream step' (FirstYield state)
2748 where
2749 {-# INLINE_LATE step' #-}
2750 step' gst (FirstYield st) = do
2751 r <- step gst st
2752 return $
2753 case r of
2754 Yield x s -> Skip (YieldAndCarry x s)
2755 Skip s -> Skip (FirstYield s)
2756 Stop -> Stop
2758 step' gst (InterspersingYield st) = do
2759 r <- step gst st
2760 case r of
2761 Yield x s -> do
2762 a <- m
2763 return $ Yield a (YieldAndCarry x s)
2764 Skip s -> return $ Skip $ InterspersingYield s
2765 Stop -> return Stop
2767 step' _ (YieldAndCarry x st) = return $ Yield x (InterspersingYield st)
2769data SuffixState s a
2770 = SuffixElem s
2771 | SuffixSuffix s
2772 | SuffixYield a (SuffixState s a)
2774{-# INLINE_NORMAL insertAfterEach #-}
2775insertAfterEach :: forall m a. Monad m => m a -> Stream m a -> Stream m a
2776insertAfterEach action (Stream step state) = Stream step' (SuffixElem state)
2777 where
2778 {-# INLINE_LATE step' #-}
2779 step' gst (SuffixElem st) = do
2780 r <- step gst st
2781 return $ case r of
2782 Yield x s -> Skip (SuffixYield x (SuffixSuffix s))
2783 Skip s -> Skip (SuffixElem s)
2784 Stop -> Stop
2786 step' _ (SuffixSuffix st) = do
2787 action >>= \r -> return $ Skip (SuffixYield r (SuffixElem st))
2789 step' _ (SuffixYield x next) = return $ Yield x next
2791{-# INLINE intersperse #-}
2792intersperse :: Monad m => a -> Stream m a -> Stream m a
2793intersperse a = intersperseM (return a)
2795{-# INLINE_NORMAL insertBy #-}
2796insertBy :: Monad m => (a -> a -> Ordering) -> a -> Stream m a -> Stream m a
2797insertBy cmp a (Stream step state) = Stream step' (state, False, Nothing)
2798 where
2799 {-# INLINE_LATE step' #-}
2800 step' gst (st, False, _) = do
2801 r <- step gst st
2802 case r of
2803 Yield x s -> case cmp a x of
2804 GT -> return $ Yield x (s, False, Nothing)
2805 _ -> return $ Yield a (s, True, Just x)
2806 Skip s -> return $ Skip (s, False, Nothing)
2807 Stop -> return $ Yield a (st, True, Nothing)
2809 step' _ (_, True, Nothing) = return Stop
2811 step' gst (st, True, Just prev) = do
2812 r <- step gst st
2813 case r of
2814 Yield x s -> return $ Yield prev (s, True, Just x)
2815 Skip s -> return $ Skip (s, True, Just prev)
2816 Stop -> return $ Yield prev (st, True, Nothing)
2818------------------------------------------------------------------------------
2819-- Deleting
2820------------------------------------------------------------------------------
2822{-# INLINE_NORMAL deleteBy #-}
2823deleteBy :: Monad m => (a -> a -> Bool) -> a -> Stream m a -> Stream m a
2824deleteBy eq x (Stream step state) = Stream step' (state, False)
2825 where
2826 {-# INLINE_LATE step' #-}
2827 step' gst (st, False) = do
2828 r <- step gst st
2829 case r of
2830 Yield y s -> return $
2831 if eq x y then Skip (s, True) else Yield y (s, False)
2832 Skip s -> return $ Skip (s, False)
2833 Stop -> return Stop
2835 step' gst (st, True) = do
2836 r <- step gst st
2837 case r of
2838 Yield y s -> return $ Yield y (s, True)
2839 Skip s -> return $ Skip (s, True)
2840 Stop -> return Stop
2842------------------------------------------------------------------------------
2843-- Transformation by Map and Filter
2844------------------------------------------------------------------------------
2846-- XXX Will this always fuse properly?
2847{-# INLINE_NORMAL mapMaybe #-}
2848mapMaybe :: Monad m => (a -> Maybe b) -> Stream m a -> Stream m b
2849mapMaybe f = fmap fromJust . filter isJust . map f
2851{-# INLINE_NORMAL mapMaybeM #-}
2852mapMaybeM :: Monad m => (a -> m (Maybe b)) -> Stream m a -> Stream m b
2853mapMaybeM f = fmap fromJust . filter isJust . mapM f
2855------------------------------------------------------------------------------
2856-- Zipping
2857------------------------------------------------------------------------------
2859{-# INLINE_NORMAL indexed #-}
2860indexed :: Monad m => Stream m a -> Stream m (Int, a)
2861indexed (Stream step state) = Stream step' (state, 0)
2862 where
2863 {-# INLINE_LATE step' #-}
2864 step' gst (st, i) = i `seq` do
2865 r <- step (adaptState gst) st
2866 case r of
2867 Yield x s -> return $ Yield (i, x) (s, i+1)
2868 Skip s -> return $ Skip (s, i)
2869 Stop -> return Stop
2871{-# INLINE_NORMAL indexedR #-}
2872indexedR :: Monad m => Int -> Stream m a -> Stream m (Int, a)
2873indexedR m (Stream step state) = Stream step' (state, m)
2874 where
2875 {-# INLINE_LATE step' #-}
2876 step' gst (st, i) = i `seq` do
2877 r <- step (adaptState gst) st
2878 case r of
2879 Yield x s -> let i' = i - 1
2880 in return $ Yield (i, x) (s, i')
2881 Skip s -> return $ Skip (s, i)
2882 Stop -> return Stop
2884{-# INLINE_NORMAL zipWithM #-}
2885zipWithM :: Monad m
2886 => (a -> b -> m c) -> Stream m a -> Stream m b -> Stream m c
2887zipWithM f (Stream stepa ta) (Stream stepb tb) = Stream step (ta, tb, Nothing)
2888 where
2889 {-# INLINE_LATE step #-}
2890 step gst (sa, sb, Nothing) = do
2891 r <- stepa (adaptState gst) sa
2892 return $
2893 case r of
2894 Yield x sa' -> Skip (sa', sb, Just x)
2895 Skip sa' -> Skip (sa', sb, Nothing)
2896 Stop -> Stop
2898 step gst (sa, sb, Just x) = do
2899 r <- stepb (adaptState gst) sb
2900 case r of
2901 Yield y sb' -> do
2902 z <- f x y
2903 return $ Yield z (sa, sb', Nothing)
2904 Skip sb' -> return $ Skip (sa, sb', Just x)
2905 Stop -> return Stop
2907#if __GLASGOW_HASKELL__ >= 801
2908{-# RULES "zipWithM xs xs"
2909 forall f xs. zipWithM @Identity f xs xs = mapM (\x -> f x x) xs #-}
2910#endif
2912{-# INLINE zipWith #-}
2913zipWith :: Monad m => (a -> b -> c) -> Stream m a -> Stream m b -> Stream m c
2914zipWith f = zipWithM (\a b -> return (f a b))
2916------------------------------------------------------------------------------
2917-- Merging
2918------------------------------------------------------------------------------
2920{-# INLINE_NORMAL mergeByM #-}
2921mergeByM
2922 :: (Monad m)
2923 => (a -> a -> m Ordering) -> Stream m a -> Stream m a -> Stream m a
2924mergeByM cmp (Stream stepa ta) (Stream stepb tb) =
2925 Stream step (Just ta, Just tb, Nothing, Nothing)
2926 where
2927 {-# INLINE_LATE step #-}
2929 -- one of the values is missing, and the corresponding stream is running
2930 step gst (Just sa, sb, Nothing, b) = do
2931 r <- stepa gst sa
2932 return $ case r of
2933 Yield a sa' -> Skip (Just sa', sb, Just a, b)
2934 Skip sa' -> Skip (Just sa', sb, Nothing, b)
2935 Stop -> Skip (Nothing, sb, Nothing, b)
2937 step gst (sa, Just sb, a, Nothing) = do
2938 r <- stepb gst sb
2939 return $ case r of
2940 Yield b sb' -> Skip (sa, Just sb', a, Just b)
2941 Skip sb' -> Skip (sa, Just sb', a, Nothing)
2942 Stop -> Skip (sa, Nothing, a, Nothing)
2944 -- both the values are available
2945 step _ (sa, sb, Just a, Just b) = do
2946 res <- cmp a b
2947 return $ case res of
2948 GT -> Yield b (sa, sb, Just a, Nothing)
2949 _ -> Yield a (sa, sb, Nothing, Just b)
2951 -- one of the values is missing, corresponding stream is done
2952 step _ (Nothing, sb, Nothing, Just b) =
2953 return $ Yield b (Nothing, sb, Nothing, Nothing)
2955 step _ (sa, Nothing, Just a, Nothing) =
2956 return $ Yield a (sa, Nothing, Nothing, Nothing)
2958 step _ (Nothing, Nothing, Nothing, Nothing) = return Stop
2960{-# INLINE mergeBy #-}
2961mergeBy
2962 :: (Monad m)
2963 => (a -> a -> Ordering) -> Stream m a -> Stream m a -> Stream m a
2964mergeBy cmp = mergeByM (\a b -> return $ cmp a b)
2966------------------------------------------------------------------------------
2967-- Transformation comprehensions
2968------------------------------------------------------------------------------
2970{-# INLINE_NORMAL the #-}
2971the :: (Eq a, Monad m) => Stream m a -> m (Maybe a)
2972the (Stream step state) = go state
2973 where
2974 go st = do
2975 r <- step defState st
2976 case r of
2977 Yield x s -> go' x s
2978 Skip s -> go s
2979 Stop -> return Nothing
2980 go' n st = do
2981 r <- step defState st
2982 case r of
2983 Yield x s | x == n -> go' n s
2984 | otherwise -> return Nothing
2985 Skip s -> go' n s
2986 Stop -> return (Just n)
2988--------------------------------------------------------------------------------
2989-- UTF8 Encoding / Decoding
2990--------------------------------------------------------------------------------
2992-- UTF-8 primitives, Lifted from GHC.IO.Encoding.UTF8.
2994{-# INLINE ord2 #-}
2995ord2 :: Char -> WList
2996ord2 c = assert (n >= 0x80 && n <= 0x07ff) (WCons x1 (WCons x2 WNil))
2997 where
2998 n = ord c
2999 x1 = fromIntegral $ (n `shiftR` 6) + 0xC0
3000 x2 = fromIntegral $ (n .&. 0x3F) + 0x80
3002{-# INLINE ord3 #-}
3003ord3 :: Char -> WList
3004ord3 c = assert (n >= 0x0800 && n <= 0xffff) (WCons x1 (WCons x2 (WCons x3 WNil)))
3005 where
3006 n = ord c
3007 x1 = fromIntegral $ (n `shiftR` 12) + 0xE0
3008 x2 = fromIntegral $ ((n `shiftR` 6) .&. 0x3F) + 0x80
3009 x3 = fromIntegral $ (n .&. 0x3F) + 0x80
3011{-# INLINE ord4 #-}
3012ord4 :: Char -> WList
3013ord4 c = assert (n >= 0x10000) (WCons x1 (WCons x2 (WCons x3 (WCons x4 WNil))))
3014 where
3015 n = ord c
3016 x1 = fromIntegral $ (n `shiftR` 18) + 0xF0
3017 x2 = fromIntegral $ ((n `shiftR` 12) .&. 0x3F) + 0x80
3018 x3 = fromIntegral $ ((n `shiftR` 6) .&. 0x3F) + 0x80
3019 x4 = fromIntegral $ (n .&. 0x3F) + 0x80
3021data CodingFailureMode
3022 = TransliterateCodingFailure
3023 | ErrorOnCodingFailure
3024 deriving (Show)
3026{-# INLINE replacementChar #-}
3027replacementChar :: Char
3028replacementChar = '\xFFFD'
3030-- Int helps in cheaper conversion from Int to Char
3031type CodePoint = Int
3032type DecoderState = Word8
3034-- See http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ for details.
3036{-# INLINE runFold #-}
3037runFold :: (Monad m) => Fold m a b -> Stream m a -> m b
3038runFold (Fold step begin done) = foldlMx' step begin done
3040-- Aligning to cacheline makes a barely noticeable difference
3041utf8d :: A.Array Word8
3042utf8d = unsafePerformIO $ runFold (A.writeAligned 64) $ fromList [
3043 -- The first part of the table maps bytes to character classes that
3044 -- to reduce the size of the transition table and create bitmasks.
3045 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
3046 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
3047 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
3048 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
3049 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
3050 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
3051 8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
3052 10,3,3,3,3,3,3,3,3,3,3,3,3,4,3,3, 11,6,6,6,5,8,8,8,8,8,8,8,8,8,8,8,
3054 -- The second part is a transition table that maps a combination
3055 -- of a state of the automaton and a character class to a state.
3056 0,12,24,36,60,96,84,12,12,12,48,72, 12,12,12,12,12,12,12,12,12,12,12,12,
3057 12, 0,12,12,12,12,12, 0,12, 0,12,12, 12,24,12,12,12,12,12,24,12,24,12,12,
3058 12,12,12,12,12,12,12,24,12,12,12,12, 12,24,12,12,12,12,12,12,12,24,12,12,
3059 12,12,12,12,12,12,12,36,12,36,12,12, 12,36,12,12,12,12,12,36,12,36,12,12,
3060 12,36,12,12,12,12,12,12,12,12,12,12
3063-- | Return element at the specified index without checking the bounds.
3064-- and without touching the foreign ptr.
3065{-# INLINE_NORMAL unsafePeekElemOff #-}
3066unsafePeekElemOff :: forall a. Storable a => Ptr a -> Int -> a
3067unsafePeekElemOff p i = let !x = A.unsafeInlineIO $ peekElemOff p i in x
3069-- decode is split into two separate cases to avoid branching instructions.
3070-- From the higher level flow we already know which case we are in so we can
3071-- call the appropriate decode function.
3073-- When the state is 0
3074{-# INLINE decode0 #-}
3075decode0 :: Ptr Word8 -> Word8 -> Tuple' DecoderState CodePoint
3076decode0 table byte =
3077 let !t = table `unsafePeekElemOff` fromIntegral byte
3078 !codep' = (0xff `shiftR` (fromIntegral t)) .&. fromIntegral byte
3079 !state' = table `unsafePeekElemOff` (256 + fromIntegral t)
3080 in (Tuple' state' codep')
3082-- When the state is not 0
3083{-# INLINE decode1 #-}
3084decode1
3085 :: Ptr Word8
3086 -> DecoderState
3087 -> CodePoint
3088 -> Word8
3089 -> Tuple' DecoderState CodePoint
3090decode1 table state codep byte =
3091 -- Remember codep is Int type!
3092 -- Can it be unsafe to convert the resulting to Char?
3093 let !t = table `unsafePeekElemOff` fromIntegral byte
3094 !codep' = (fromIntegral byte .&. 0x3f) .|. (codep `shiftL` 6)
3095 !state' = table `unsafePeekElemOff`
3096 (256 + fromIntegral state + fromIntegral t)
3097 in (Tuple' state' codep')
3100data FreshPoint s
3101 = FreshPointDecodeInit s
3102 | FreshPointDecodeFirst s Word8
3103 | FreshPointDecoding s !DecoderState !CodePoint
3104 | YieldAndContinue !Char (FreshPoint s)
3105 | Done
3107-- XXX Add proper error messages
3108{-# INLINE_NORMAL decodeUtf8With #-}
3109decodeUtf8With :: Monad m => CodingFailureMode -> Stream m Word8 -> Stream m Char
3110decodeUtf8With cfm (Stream step state) =
3111 let Array p _ _ = utf8d
3112 !ptr = (unsafeForeignPtrToPtr p)
3113 in Stream (step' ptr) (FreshPointDecodeInit state)
3114 where
3115 {-# INLINE transliterateOrError #-}
3116 transliterateOrError e s =
3117 case cfm of
3118 ErrorOnCodingFailure -> error e
3119 TransliterateCodingFailure -> YieldAndContinue replacementChar s
3120 {-# INLINE inputUnderflow #-}
3121 inputUnderflow =
3122 case cfm of
3123 ErrorOnCodingFailure ->
3124 error "Streamly.Streams.StreamD.decodeUtf8With: Input Underflow"
3125 TransliterateCodingFailure -> YieldAndContinue replacementChar Done
3126 {-# INLINE_LATE step' #-}
3127 step' _ gst (FreshPointDecodeInit st) = do
3128 r <- step (adaptState gst) st
3129 case r of
3130 Yield x s ->
3131 -- Note: It is important to use a ">" instead of a "<=" test
3132 -- here for GHC to generate code layout for default branch
3133 -- prediction for the common case. This is fragile and might
3134 -- change with the compiler versions, we need a more reliable
3135 -- "likely" primitive to control branch predication.
3136 case x > 0x7f of
3137 False ->
3138 return $ Skip $ YieldAndContinue
3139 (unsafeChr (fromIntegral x))
3140 (FreshPointDecodeInit s)
3141 -- Using a separate state here generates a jump to a
3142 -- separate code block in the core which seems to perform
3143 -- slightly better for the non-ascii case.
3144 True -> return $ Skip $ FreshPointDecodeFirst s x
3145 Skip s -> return $ Skip (FreshPointDecodeInit s)
3146 Stop -> return $ Skip Done
3148 step' table _ (FreshPointDecodeFirst st x) = do
3149 let (Tuple' sv cp) = decode0 table x
3150 return $
3151 case sv of
3152 12 ->
3153 Skip $
3154 transliterateOrError
3155 "Streamly.Streams.StreamD.decodeUtf8ArraysWith: Invalid UTF8 codepoint encountered"
3156 (FreshPointDecodeInit st)
3157 0 -> error "unreachable state"
3158 _ -> Skip (FreshPointDecoding st sv cp)
3160 step' table gst (FreshPointDecoding st statePtr codepointPtr) = do
3161 r <- step (adaptState gst) st
3162 case r of
3163 Yield x s -> do
3164 let (Tuple' sv cp) = decode1 table statePtr codepointPtr x
3165 return $
3166 case sv of
3167 0 -> Skip $ YieldAndContinue (unsafeChr cp)
3168 (FreshPointDecodeInit s)
3169 12 ->
3170 Skip $
3171 transliterateOrError
3172 "Streamly.Streams.StreamD.decodeUtf8With: Invalid UTF8 codepoint encountered"
3173 (FreshPointDecodeInit s)
3174 _ -> Skip (FreshPointDecoding s sv cp)
3175 Skip s -> return $ Skip (FreshPointDecoding s statePtr codepointPtr)
3176 Stop -> return $ Skip inputUnderflow
3178 step' _ _ (YieldAndContinue c s) = return $ Yield c s
3179 step' _ _ Done = return Stop
3181{-# INLINE decodeUtf8 #-}
3182decodeUtf8 :: Monad m => Stream m Word8 -> Stream m Char
3183decodeUtf8 = decodeUtf8With ErrorOnCodingFailure
3185{-# INLINE decodeUtf8Lenient #-}
3186decodeUtf8Lenient :: Monad m => Stream m Word8 -> Stream m Char
3187decodeUtf8Lenient = decodeUtf8With TransliterateCodingFailure
3189data FlattenState s a
3190 = OuterLoop s !(Maybe (DecoderState, CodePoint))
3191 | InnerLoopDecodeInit s (ForeignPtr a) !(Ptr a) !(Ptr a)
3192 | InnerLoopDecodeFirst s (ForeignPtr a) !(Ptr a) !(Ptr a) Word8
3193 | InnerLoopDecoding s (ForeignPtr a) !(Ptr a) !(Ptr a)
3194 !DecoderState !CodePoint
3195 | YAndC !Char (FlattenState s a) -- These constructors can be
3196 -- encoded in the FreshPoint
3197 -- type, I prefer to keep these
3198 -- flat even though that means
3199 -- coming up with new names
3200 | D
3202-- The normal decodeUtf8 above should fuse with flattenArrays
3203-- to create this exact code but it doesn't for some reason, as of now this
3204-- remains the fastest way I could figure out to decodeUtf8.
3206-- XXX Add Proper error messages
3207{-# INLINE_NORMAL decodeUtf8ArraysWith #-}
3208decodeUtf8ArraysWith ::
3209 MonadIO m
3210 => CodingFailureMode
3211 -> Stream m (A.Array Word8)
3212 -> Stream m Char
3213decodeUtf8ArraysWith cfm (Stream step state) =
3214 let Array p _ _ = utf8d
3215 !ptr = (unsafeForeignPtrToPtr p)
3216 in Stream (step' ptr) (OuterLoop state Nothing)
3217 where
3218 {-# INLINE transliterateOrError #-}
3219 transliterateOrError e s =
3220 case cfm of
3221 ErrorOnCodingFailure -> error e
3222 TransliterateCodingFailure -> YAndC replacementChar s
3223 {-# INLINE inputUnderflow #-}
3224 inputUnderflow =
3225 case cfm of
3226 ErrorOnCodingFailure ->
3227 error
3228 "Streamly.Streams.StreamD.decodeUtf8ArraysWith: Input Underflow"
3229 TransliterateCodingFailure -> YAndC replacementChar D
3230 {-# INLINE_LATE step' #-}
3231 step' _ gst (OuterLoop st Nothing) = do
3232 r <- step (adaptState gst) st
3233 return $
3234 case r of
3235 Yield A.Array {..} s ->
3236 let p = unsafeForeignPtrToPtr aStart
3237 in Skip (InnerLoopDecodeInit s aStart p aEnd)
3238 Skip s -> Skip (OuterLoop s Nothing)
3239 Stop -> Skip D
3240 step' _ gst (OuterLoop st dst@(Just (ds, cp))) = do
3241 r <- step (adaptState gst) st
3242 return $
3243 case r of
3244 Yield A.Array {..} s ->
3245 let p = unsafeForeignPtrToPtr aStart
3246 in Skip (InnerLoopDecoding s aStart p aEnd ds cp)
3247 Skip s -> Skip (OuterLoop s dst)
3248 Stop -> Skip inputUnderflow
3249 step' _ _ (InnerLoopDecodeInit st startf p end)
3250 | p == end = do
3251 liftIO $ touchForeignPtr startf
3252 return $ Skip $ OuterLoop st Nothing
3253 step' _ _ (InnerLoopDecodeInit st startf p end) = do
3254 x <- liftIO $ peek p
3255 -- Note: It is important to use a ">" instead of a "<=" test here for
3256 -- GHC to generate code layout for default branch prediction for the
3257 -- common case. This is fragile and might change with the compiler
3258 -- versions, we need a more reliable "likely" primitive to control
3259 -- branch predication.
3260 case x > 0x7f of
3261 False ->
3262 return $ Skip $ YAndC
3263 (unsafeChr (fromIntegral x))
3264 (InnerLoopDecodeInit st startf (p `plusPtr` 1) end)
3265 -- Using a separate state here generates a jump to a separate code
3266 -- block in the core which seems to perform slightly better for the
3267 -- non-ascii case.
3268 True -> return $ Skip $ InnerLoopDecodeFirst st startf p end x
3270 step' table _ (InnerLoopDecodeFirst st startf p end x) = do
3271 let (Tuple' sv cp) = decode0 table x
3272 return $
3273 case sv of
3274 12 ->
3275 Skip $
3276 transliterateOrError
3277 "Streamly.Streams.StreamD.decodeUtf8ArraysWith: Invalid UTF8 codepoint encountered"
3278 (InnerLoopDecodeInit st startf (p `plusPtr` 1) end)
3279 0 -> error "unreachable state"
3280 _ -> Skip (InnerLoopDecoding st startf (p `plusPtr` 1) end sv cp)
3281 step' _ _ (InnerLoopDecoding st startf p end sv cp)
3282 | p == end = do
3283 liftIO $ touchForeignPtr startf
3284 return $ Skip $ OuterLoop st (Just (sv, cp))
3285 step' table _ (InnerLoopDecoding st startf p end statePtr codepointPtr) = do
3286 x <- liftIO $ peek p
3287 let (Tuple' sv cp) = decode1 table statePtr codepointPtr x
3288 return $
3289 case sv of
3290 0 ->
3291 Skip $
3292 YAndC
3293 (unsafeChr cp)
3294 (InnerLoopDecodeInit st startf (p `plusPtr` 1) end)
3295 12 ->
3296 Skip $
3297 transliterateOrError
3298 "Streamly.Streams.StreamD.decodeUtf8ArraysWith: Invalid UTF8 codepoint encountered"
3299 (InnerLoopDecodeInit st startf (p `plusPtr` 1) end)
3300 _ -> Skip (InnerLoopDecoding st startf (p `plusPtr` 1) end sv cp)
3301 step' _ _ (YAndC c s) = return $ Yield c s
3302 step' _ _ D = return Stop
3304{-# INLINE decodeUtf8Arrays #-}
3305decodeUtf8Arrays ::
3306 MonadIO m
3307 => Stream m (A.Array Word8)
3308 -> Stream m Char
3309decodeUtf8Arrays = decodeUtf8ArraysWith ErrorOnCodingFailure
3311{-# INLINE decodeUtf8ArraysLenient #-}
3312decodeUtf8ArraysLenient ::
3313 MonadIO m
3314 => Stream m (A.Array Word8)
3315 -> Stream m Char
3316decodeUtf8ArraysLenient = decodeUtf8ArraysWith TransliterateCodingFailure
3318data WList = WCons !Word8 !WList | WNil
3320data EncodeState s = EncodeState s !WList
3322{-# INLINE_NORMAL encodeUtf8 #-}
3323encodeUtf8 :: Monad m => Stream m Char -> Stream m Word8
3324encodeUtf8 (Stream step state) = Stream step' (EncodeState state WNil)
3325 where
3326 {-# INLINE_LATE step' #-}
3327 step' gst (EncodeState st WNil) = do
3328 r <- step (adaptState gst) st
3329 return $
3330 case r of
3331 Yield c s ->
3332 case ord c of
3334 | x <= 0x7F ->
3335 Skip
3336 (EncodeState s (WCons (fromIntegral x) WNil))
3337 | x <= 0x7FF -> Skip (EncodeState s (ord2 c))
3338 | x <= 0xFFFF ->
3339 if isSurrogate c
3340 then error
3341 "Streamly.Streams.StreamD.encodeUtf8: Encountered a surrogate"
3342 else Skip (EncodeState s (ord3 c))
3343 | otherwise -> Skip (EncodeState s (ord4 c))
3344 Skip s -> Skip (EncodeState s WNil)
3345 Stop -> Stop
3346 step' _ (EncodeState s (WCons x xs)) = return $ Yield x (EncodeState s xs)