on master help sign in
Deprecate MutArray/Stream module, move funcs to MutArray module
2417874Harendra Kumar
core/src/Streamly/Internal/Data/MutArray.hs+13
@@ -13,6 +13,7 @@ module Streamly.Internal.Data.MutArray
13 -- * MutArray module
13 -- * MutArray module
14 , sliceIndexerFromLen
14 , sliceIndexerFromLen
15 , slicerFromLen
15 , slicerFromLen
16+ , compactChunksLE
16 -- * Unboxed IORef
17 -- * Unboxed IORef
17 , module Streamly.Internal.Data.IORef.Unboxed
18 , module Streamly.Internal.Data.IORef.Unboxed
18
19
@@ -24,9 +25,13 @@ where
24
25
25#include "inline.hs"
26#include "inline.hs"
26
27
28+import Control.Monad.IO.Class (MonadIO(..))
29+import Streamly.Internal.Data.Stream.Type (Stream)
27import Streamly.Internal.Data.Unbox (Unbox)
30import Streamly.Internal.Data.Unbox (Unbox)
28import Streamly.Internal.Data.Unfold.Type (Unfold(..))
31import Streamly.Internal.Data.Unfold.Type (Unfold(..))
29
32
33+-- import qualified Streamly.Internal.Data.Stream.Nesting as Stream
34+-- import qualified Streamly.Internal.Data.Stream.Transform as Stream
30import qualified Streamly.Internal.Data.Unfold as Unfold
35import qualified Streamly.Internal.Data.Unfold as Unfold
31
36
32import Prelude hiding (foldr, length, read, splitAt)
37import Prelude hiding (foldr, length, read, splitAt)
@@ -77,3 +82,11 @@ getSlicesFromLen :: forall m a. (Monad m, Unbox a)
77 -> Int -- ^ length of the slice
82 -> Int -- ^ length of the slice
78 -> Unfold m (MutArray a) (MutArray a)
83 -> Unfold m (MutArray a) (MutArray a)
79getSlicesFromLen = slicerFromLen
84getSlicesFromLen = slicerFromLen
85+
86+-- | Scan @compactChunksLE n@ coalesces adjacent arrays in the input stream
87+-- only if the combined size would be less than or equal to n.
88+{-# INLINE compactChunksLE #-}
89+compactChunksLE :: (MonadIO m, Unbox a) =>
90+ Int -> Stream m (MutArray a) -> Stream m (MutArray a)
91+-- compactLE n = Stream.catRights . Stream.parseManyD (pCompactChunksLE n)
92+compactChunksLE = rCompactChunksLE
core/src/Streamly/Internal/Data/MutArray/Stream.hs+11−195
@@ -12,6 +12,7 @@
12-- keep this as a separate module and release it.
12-- keep this as a separate module and release it.
13--
13--
14module Streamly.Internal.Data.MutArray.Stream
14module Streamly.Internal.Data.MutArray.Stream
15+{-# DEPRECATED "Please use \"Streamly.Internal.Data.MutArray\" instead." #-}
15 (
16 (
16 -- * Generation
17 -- * Generation
17 MArray.chunksOf
18 MArray.chunksOf
@@ -21,7 +22,7 @@ module Streamly.Internal.Data.MutArray.Stream
21
22
22 -- * Compaction
23 -- * Compaction
23 , packArraysChunksOf
24 , packArraysChunksOf
24− , SpliceState (..)
25+ , MArray.SpliceState (..)
25 , lpackArraysChunksOf
26 , lpackArraysChunksOf
26 , compact -- chunksCompact
27 , compact -- chunksCompact
27 , compactLE
28 , compactLE
@@ -35,19 +36,12 @@ module Streamly.Internal.Data.MutArray.Stream
35 )
36 )
36where
37where
37
38
38−#include "inline.hs"
39−#include "ArrayMacros.h"
40−
41import Control.Monad.IO.Class (MonadIO(..))
39import Control.Monad.IO.Class (MonadIO(..))
42−import Control.Monad (when)
43−import Data.Bifunctor (first)
44−import Data.Proxy (Proxy(..))
45−import Streamly.Internal.Data.Unbox (Unbox, sizeOf)
40+import Streamly.Internal.Data.Unbox (Unbox)
46import Streamly.Internal.Data.MutArray.Type (MutArray(..))
41import Streamly.Internal.Data.MutArray.Type (MutArray(..))
47import Streamly.Internal.Data.Fold.Type (Fold(..))
42import Streamly.Internal.Data.Fold.Type (Fold(..))
48import Streamly.Internal.Data.Parser (ParseError)
43import Streamly.Internal.Data.Parser (ParseError)
49import Streamly.Internal.Data.Stream.Type (Stream)
44import Streamly.Internal.Data.Stream.Type (Stream)
50−import Streamly.Internal.Data.Tuple.Strict (Tuple'(..))
51
45
52import qualified Streamly.Internal.Data.MutArray as MArray
46import qualified Streamly.Internal.Data.MutArray as MArray
53import qualified Streamly.Internal.Data.Fold.Type as FL
47import qualified Streamly.Internal.Data.Fold.Type as FL
@@ -58,12 +52,6 @@ import qualified Streamly.Internal.Data.Stream as D
58-- Compact
52-- Compact
59-------------------------------------------------------------------------------
53-------------------------------------------------------------------------------
60
54
61−data SpliceState s arr
62− = SpliceInitial s
63− | SpliceBuffering s arr
64− | SpliceYielding arr (SpliceState s arr)
65− | SpliceFinish
66−
67-- XXX This can be removed once compactLEFold/compactLE are implemented.
55-- XXX This can be removed once compactLEFold/compactLE are implemented.
68--
56--
69-- | This mutates the first array (if it has space) to append values from the
57-- | This mutates the first array (if it has space) to append values from the
@@ -78,117 +66,18 @@ data SpliceState s arr
78-- actual array size may be less than the specified chunk size.
66-- actual array size may be less than the specified chunk size.
79--
67--
80-- @since 0.7.0
68-- @since 0.7.0
81−{-# INLINE_NORMAL packArraysChunksOf #-}
69+{-# INLINE packArraysChunksOf #-}
82packArraysChunksOf :: (MonadIO m, Unbox a)
70packArraysChunksOf :: (MonadIO m, Unbox a)
83 => Int -> D.Stream m (MutArray a) -> D.Stream m (MutArray a)
71 => Int -> D.Stream m (MutArray a) -> D.Stream m (MutArray a)
84−packArraysChunksOf n (D.Stream step state) =
72+packArraysChunksOf = MArray.compactChunksLE
85− D.Stream step' (SpliceInitial state)
86−
87− where
88−
89− {-# INLINE_LATE step' #-}
90− step' gst (SpliceInitial st) = do
91− when (n <= 0) $
92− -- XXX we can pass the module string from the higher level API
93− error $ "Streamly.Internal.Data.MutArray.Type.packArraysChunksOf: the size of "
94− ++ "arrays [" ++ show n ++ "] must be a natural number"
95− r <- step gst st
96− case r of
97− D.Yield arr s -> return $
98− let len = MArray.byteLength arr
99− in if len >= n
100− then D.Skip (SpliceYielding arr (SpliceInitial s))
101− else D.Skip (SpliceBuffering s arr)
102− D.Skip s -> return $ D.Skip (SpliceInitial s)
103− D.Stop -> return D.Stop
104−
105− step' gst (SpliceBuffering st buf) = do
106− r <- step gst st
107− case r of
108− D.Yield arr s -> do
109− let len = MArray.byteLength buf + MArray.byteLength arr
110− if len > n
111− then return $
112− D.Skip (SpliceYielding buf (SpliceBuffering s arr))
113− else do
114− buf' <- if MArray.byteCapacity buf < n
115− then liftIO $ MArray.realloc n buf
116− else return buf
117− buf'' <- MArray.spliceUnsafe buf' arr
118− return $ D.Skip (SpliceBuffering s buf'')
119− D.Skip s -> return $ D.Skip (SpliceBuffering s buf)
120− D.Stop -> return $ D.Skip (SpliceYielding buf SpliceFinish)
121−
122− step' _ SpliceFinish = return D.Stop
123−
124− step' _ (SpliceYielding arr next) = return $ D.Yield arr next
125
73
126-- XXX Remove this once compactLEFold is implemented
74-- XXX Remove this once compactLEFold is implemented
127-- lpackArraysChunksOf = Fold.many compactLEFold
75-- lpackArraysChunksOf = Fold.many compactLEFold
128--
76--
129−{-# INLINE_NORMAL lpackArraysChunksOf #-}
77+{-# INLINE lpackArraysChunksOf #-}
130lpackArraysChunksOf :: (MonadIO m, Unbox a)
78lpackArraysChunksOf :: (MonadIO m, Unbox a)
131 => Int -> Fold m (MutArray a) () -> Fold m (MutArray a) ()
79 => Int -> Fold m (MutArray a) () -> Fold m (MutArray a) ()
132−lpackArraysChunksOf n (Fold step1 initial1 _ final1) =
80+lpackArraysChunksOf = MArray.lCompactChunksGE
133− Fold step initial extract final
134−
135− where
136−
137− initial = do
138− when (n <= 0) $
139− -- XXX we can pass the module string from the higher level API
140− error $ "Streamly.Internal.Data.MutArray.Type.packArraysChunksOf: the size of "
141− ++ "arrays [" ++ show n ++ "] must be a natural number"
142−
143− r <- initial1
144− return $ first (Tuple' Nothing) r
145−
146− step (Tuple' Nothing r1) arr =
147− let len = MArray.byteLength arr
148− in if len >= n
149− then do
150− r <- step1 r1 arr
151− case r of
152− FL.Done _ -> return $ FL.Done ()
153− FL.Partial s -> do
154− _ <- final1 s
155− res <- initial1
156− return $ first (Tuple' Nothing) res
157− else return $ FL.Partial $ Tuple' (Just arr) r1
158−
159− step (Tuple' (Just buf) r1) arr = do
160− let len = MArray.byteLength buf + MArray.byteLength arr
161− buf' <- if MArray.byteCapacity buf < len
162− then liftIO $ MArray.realloc (max n len) buf
163− else return buf
164− buf'' <- MArray.spliceUnsafe buf' arr
165−
166− -- XXX this is common in both the equations of step
167− if len >= n
168− then do
169− r <- step1 r1 buf''
170− case r of
171− FL.Done _ -> return $ FL.Done ()
172− FL.Partial s -> do
173− _ <- final1 s
174− res <- initial1
175− return $ first (Tuple' Nothing) res
176− else return $ FL.Partial $ Tuple' (Just buf'') r1
177−
178− -- XXX Several folds do extract >=> final, therefore, we need to make final
179− -- return "m b" rather than using extract post it if we want extract to be
180− -- partial.
181− --
182− -- extract forces the pending buffer to be sent to the fold which is not
183− -- what we want.
184− extract _ = error "lpackArraysChunksOf: not designed for scanning"
185−
186− final (Tuple' Nothing r1) = final1 r1
187− final (Tuple' (Just buf) r1) = do
188− r <- step1 r1 buf
189− case r of
190− FL.Partial rr -> final1 rr
191− FL.Done _ -> return ()
192
81
193-- XXX Same as compactLE, to be removed once that is implemented.
82-- XXX Same as compactLE, to be removed once that is implemented.
194--
83--
@@ -208,48 +97,11 @@ compact = packArraysChunksOf
208-- actual array size may be less than the specified chunk size.
97-- actual array size may be less than the specified chunk size.
209--
98--
210-- /Internal/
99-- /Internal/
211−{-# INLINE_NORMAL compactLEParserD #-}
100+{-# INLINE compactLEParserD #-}
212compactLEParserD ::
101compactLEParserD ::
213 forall m a. (MonadIO m, Unbox a)
102 forall m a. (MonadIO m, Unbox a)
214 => Int -> ParserD.Parser (MutArray a) m (MutArray a)
103 => Int -> ParserD.Parser (MutArray a) m (MutArray a)
215−compactLEParserD n = ParserD.Parser step initial extract
104+compactLEParserD = MArray.pCompactChunksLE
216−
217− where
218−
219− nBytes = n * SIZE_OF(a)
220−
221− initial =
222− return
223− $ if n <= 0
224− then error
225− $ functionPath
226− ++ ": the size of arrays ["
227− ++ show n ++ "] must be a natural number"
228− else ParserD.IPartial Nothing
229−
230− step Nothing arr =
231− return
232− $ let len = MArray.byteLength arr
233− in if len >= nBytes
234− then ParserD.Done 0 arr
235− else ParserD.Partial 0 (Just arr)
236− step (Just buf) arr =
237− let len = MArray.byteLength buf + MArray.byteLength arr
238− in if len > nBytes
239− then return $ ParserD.Done 1 buf
240− else do
241− buf1 <-
242− if MArray.byteCapacity buf < nBytes
243− then liftIO $ MArray.realloc nBytes buf
244− else return buf
245− buf2 <- MArray.spliceUnsafe buf1 arr
246− return $ ParserD.Partial 0 (Just buf2)
247−
248− extract Nothing = return $ ParserD.Done 0 MArray.nil
249− extract (Just buf) = return $ ParserD.Done 0 buf
250−
251− functionPath =
252− "Streamly.Internal.Data.Stream.MutChunked.compactLEParserD"
253
105
254-- | Coalesce adjacent arrays in incoming stream to form bigger arrays of a
106-- | Coalesce adjacent arrays in incoming stream to form bigger arrays of a
255-- minimum specified size. Note that if all the arrays in the stream together
107-- minimum specified size. Note that if all the arrays in the stream together
@@ -258,47 +110,11 @@ compactLEParserD n = ParserD.Parser step initial extract
258-- the specified size we stop coalescing further.
110-- the specified size we stop coalescing further.
259--
111--
260-- /Internal/
112-- /Internal/
261−{-# INLINE_NORMAL compactGEFold #-}
113+{-# INLINE compactGEFold #-}
262compactGEFold ::
114compactGEFold ::
263 forall m a. (MonadIO m, Unbox a)
115 forall m a. (MonadIO m, Unbox a)
264 => Int -> FL.Fold m (MutArray a) (MutArray a)
116 => Int -> FL.Fold m (MutArray a) (MutArray a)
265−compactGEFold n = Fold step initial extract extract
117+compactGEFold = MArray.fCompactChunksGE
266−
267− where
268−
269− nBytes = n * SIZE_OF(a)
270−
271− initial =
272− return
273− $ if n < 0
274− then error
275− $ functionPath
276− ++ ": the size of arrays ["
277− ++ show n ++ "] must be a natural number"
278− else FL.Partial Nothing
279−
280− step Nothing arr =
281− return
282− $ let len = MArray.byteLength arr
283− in if len >= nBytes
284− then FL.Done arr
285− else FL.Partial (Just arr)
286− step (Just buf) arr = do
287− let len = MArray.byteLength buf + MArray.byteLength arr
288− buf1 <-
289− if MArray.byteCapacity buf < len
290− then liftIO $ MArray.realloc (max len nBytes) buf
291− else return buf
292− buf2 <- MArray.spliceUnsafe buf1 arr
293− if len >= n
294− then return $ FL.Done buf2
295− else return $ FL.Partial (Just buf2)
296−
297− extract Nothing = return MArray.nil
298− extract (Just buf) = return buf
299−
300− functionPath =
301− "Streamly.Internal.Data.Stream.MutChunked.compactGEFold"
302
118
303-- | Coalesce adjacent arrays in incoming stream to form bigger arrays of a
119-- | Coalesce adjacent arrays in incoming stream to form bigger arrays of a
304-- maximum specified size in bytes.
120-- maximum specified size in bytes.
core/src/Streamly/Internal/Data/MutArray/Type.hs+268−5
@@ -216,15 +216,24 @@ module Streamly.Internal.Data.MutArray.Type
216 , pinnedChunksOf
216 , pinnedChunksOf
217 , buildChunks
217 , buildChunks
218
218
219− -- *** Flatten a stream of arrays
220− , concatChunks
221− , concatChunksRev
222−
223 -- *** Split an array into slices
219 -- *** Split an array into slices
224 -- , getSlicesFromLenN
220 -- , getSlicesFromLenN
225 , splitOn
221 , splitOn
226 -- , slicesOf
222 -- , slicesOf
227
223
224+ -- *** Flatten a stream of arrays
225+ , concatChunks
226+ , concatChunksRev
227+
228+ -- *** Compaction
229+ , SpliceState (..)
230+ , pCompactChunksLE
231+ , rCompactChunksLE
232+ , fCompactChunksGE
233+ , lCompactChunksGE
234+ , compactChunksGE
235+ , compactChunksEQ
236+
228 -- ** Utilities
237 -- ** Utilities
229 , roundUpToPower2
238 , roundUpToPower2
230 , memcpy
239 , memcpy
@@ -248,6 +257,7 @@ where
248
257
249import Control.Monad (when, void)
258import Control.Monad (when, void)
250import Control.Monad.IO.Class (MonadIO(..))
259import Control.Monad.IO.Class (MonadIO(..))
260+import Data.Bifunctor (first)
251import Data.Bits (shiftR, (.|.), (.&.))
261import Data.Bits (shiftR, (.|.), (.&.))
252import Data.Functor.Identity (Identity(..))
262import Data.Functor.Identity (Identity(..))
253import Data.Proxy (Proxy(..))
263import Data.Proxy (Proxy(..))
@@ -274,13 +284,17 @@ import GHC.Ptr (Ptr(..))
274import Streamly.Internal.Data.Fold.Type (Fold(..))
284import Streamly.Internal.Data.Fold.Type (Fold(..))
275import Streamly.Internal.Data.Producer.Type (Producer (..))
285import Streamly.Internal.Data.Producer.Type (Producer (..))
276import Streamly.Internal.Data.Stream.Type (Stream)
286import Streamly.Internal.Data.Stream.Type (Stream)
287+import Streamly.Internal.Data.Parser.Type (Parser (..))
277import Streamly.Internal.Data.StreamK.Type (StreamK)
288import Streamly.Internal.Data.StreamK.Type (StreamK)
278import Streamly.Internal.Data.SVar.Type (adaptState, defState)
289import Streamly.Internal.Data.SVar.Type (adaptState, defState)
290+import Streamly.Internal.Data.Tuple.Strict (Tuple'(..))
279import Streamly.Internal.Data.Unfold.Type (Unfold(..))
291import Streamly.Internal.Data.Unfold.Type (Unfold(..))
280import Streamly.Internal.System.IO (arrayPayloadSize, defaultChunkSize)
292import Streamly.Internal.System.IO (arrayPayloadSize, defaultChunkSize)
281
293
282import qualified Streamly.Internal.Data.Fold.Type as FL
294import qualified Streamly.Internal.Data.Fold.Type as FL
283import qualified Streamly.Internal.Data.MutByteArray.Type as Unboxed
295import qualified Streamly.Internal.Data.MutByteArray.Type as Unboxed
296+import qualified Streamly.Internal.Data.Parser.Type as Parser
297+-- import qualified Streamly.Internal.Data.Fold.Type as Fold
284import qualified Streamly.Internal.Data.Producer as Producer
298import qualified Streamly.Internal.Data.Producer as Producer
285import qualified Streamly.Internal.Data.Stream.Type as D
299import qualified Streamly.Internal.Data.Stream.Type as D
286import qualified Streamly.Internal.Data.Stream.Lift as D
300import qualified Streamly.Internal.Data.Stream.Lift as D
@@ -2582,7 +2596,256 @@ byteEq :: MonadIO m => MutArray a -> MutArray a -> m Bool
2582byteEq arr1 arr2 = fmap (EQ ==) $ byteCmp arr1 arr2
2596byteEq arr1 arr2 = fmap (EQ ==) $ byteCmp arr1 arr2
2583
2597
2584-------------------------------------------------------------------------------
2598-------------------------------------------------------------------------------
2585−-- NFData
2599+-- Compact
2600+-------------------------------------------------------------------------------
2601+
2602+-- | Parser @pCompactChunksLE n@ coalesces adjacent arrays in the input stream
2603+-- only if the combined size would be less than or equal to n.
2604+--
2605+-- /Internal/
2606+{-# INLINE_NORMAL pCompactChunksLE #-}
2607+pCompactChunksLE ::
2608+ forall m a. (MonadIO m, Unbox a)
2609+ => Int -> Parser (MutArray a) m (MutArray a)
2610+pCompactChunksLE n = Parser step initial extract
2611+
2612+ where
2613+
2614+ nBytes = n * SIZE_OF(a)
2615+
2616+ functionName = "Streamly.Internal.Data.MutArray.pCompactChunksLE"
2617+
2618+ initial =
2619+ return
2620+ $ if n <= 0
2621+ then error
2622+ $ functionName
2623+ ++ ": the size of arrays ["
2624+ ++ show n ++ "] must be a natural number"
2625+ else Parser.IPartial Nothing
2626+
2627+ step Nothing arr =
2628+ return
2629+ $ let len = byteLength arr
2630+ in if len >= nBytes
2631+ then Parser.Done 0 arr
2632+ else Parser.Partial 0 (Just arr)
2633+ step (Just buf) arr =
2634+ let len = byteLength buf + byteLength arr
2635+ in if len > nBytes
2636+ then return $ Parser.Done 1 buf
2637+ else do
2638+ -- XXX check this in the Nothing case
2639+ buf1 <-
2640+ if byteCapacity buf < nBytes
2641+ then liftIO $ realloc nBytes buf
2642+ else return buf
2643+ buf2 <- spliceUnsafe buf1 arr
2644+ return $ Parser.Partial 0 (Just buf2)
2645+
2646+ extract Nothing = return $ Parser.Done 0 nil
2647+ extract (Just buf) = return $ Parser.Done 0 buf
2648+
2649+data SpliceState s arr
2650+ = SpliceInitial s
2651+ | SpliceBuffering s arr
2652+ | SpliceYielding arr (SpliceState s arr)
2653+ | SpliceFinish
2654+
2655+-- This mutates the first array (if it has space) to append values from the
2656+-- second one. This would work for immutable arrays as well because an
2657+-- immutable array never has additional space so a new array is allocated
2658+-- instead of mutating it.
2659+
2660+-- | Scan @rCompactChunksLE n@ coalesces adjacent arrays in the input stream
2661+-- only if the combined size would be less than or equal to n.
2662+--
2663+-- /Internal/
2664+{-# INLINE_NORMAL rCompactChunksLE #-}
2665+rCompactChunksLE :: (MonadIO m, Unbox a)
2666+ => Int -> D.Stream m (MutArray a) -> D.Stream m (MutArray a)
2667+rCompactChunksLE n (D.Stream step state) =
2668+ D.Stream step' (SpliceInitial state)
2669+
2670+ where
2671+
2672+ functionName = "Streamly.Internal.Data.MutArray.rCompactChunksLE"
2673+
2674+ {-# INLINE_LATE step' #-}
2675+ step' gst (SpliceInitial st) = do
2676+ when (n <= 0) $
2677+ -- XXX we can pass the module string from the higher level API
2678+ error $ functionName ++ ": the size of arrays [" ++ show n
2679+ ++ "] must be a natural number"
2680+ r <- step gst st
2681+ case r of
2682+ D.Yield arr s -> return $
2683+ let len = byteLength arr
2684+ in if len >= n
2685+ then D.Skip (SpliceYielding arr (SpliceInitial s))
2686+ else D.Skip (SpliceBuffering s arr)
2687+ D.Skip s -> return $ D.Skip (SpliceInitial s)
2688+ D.Stop -> return D.Stop
2689+
2690+ step' gst (SpliceBuffering st buf) = do
2691+ r <- step gst st
2692+ case r of
2693+ D.Yield arr s -> do
2694+ let len = byteLength buf + byteLength arr
2695+ if len > n
2696+ then return $
2697+ D.Skip (SpliceYielding buf (SpliceBuffering s arr))
2698+ else do
2699+ -- XXX check this in the SpliceInitial case
2700+ buf1 <- if byteCapacity buf < n
2701+ then liftIO $ realloc n buf
2702+ else return buf
2703+ buf2 <- spliceUnsafe buf1 arr
2704+ return $ D.Skip (SpliceBuffering s buf2)
2705+ D.Skip s -> return $ D.Skip (SpliceBuffering s buf)
2706+ D.Stop -> return $ D.Skip (SpliceYielding buf SpliceFinish)
2707+
2708+ step' _ SpliceFinish = return D.Stop
2709+
2710+ step' _ (SpliceYielding arr next) = return $ D.Yield arr next
2711+
2712+-- | Fold @fCompactChunksGE n@ coalesces adjacent arrays in the input stream
2713+-- until the size becomes greater than or equal to n.
2714+--
2715+{-# INLINE_NORMAL fCompactChunksGE #-}
2716+fCompactChunksGE ::
2717+ forall m a. (MonadIO m, Unbox a)
2718+ => Int -> FL.Fold m (MutArray a) (MutArray a)
2719+fCompactChunksGE n = Fold step initial extract extract
2720+
2721+ where
2722+
2723+ nBytes = n * SIZE_OF(a)
2724+
2725+ functionName = "Streamly.Internal.Data.MutArray.fCompactChunksGE"
2726+
2727+ initial =
2728+ return
2729+ $ if n < 0
2730+ then error
2731+ $ functionName
2732+ ++ ": the size of arrays ["
2733+ ++ show n ++ "] must be a natural number"
2734+ else FL.Partial Nothing
2735+
2736+ step Nothing arr =
2737+ return
2738+ $ let len = byteLength arr
2739+ in if len >= nBytes
2740+ then FL.Done arr
2741+ else FL.Partial (Just arr)
2742+ step (Just buf) arr = do
2743+ let len = byteLength buf + byteLength arr
2744+ buf1 <-
2745+ if byteCapacity buf < len
2746+ then liftIO $ realloc (max len nBytes) buf
2747+ else return buf
2748+ buf2 <- spliceUnsafe buf1 arr
2749+ if len >= n
2750+ then return $ FL.Done buf2
2751+ else return $ FL.Partial (Just buf2)
2752+
2753+ extract Nothing = return nil
2754+ extract (Just buf) = return buf
2755+
2756+-- | Like 'compactChunksGE' but for transforming folds instead of stream.
2757+--
2758+-- >>> lCompactChunksGE n = Fold.many (MutArray.fCompactChunksGE n)
2759+--
2760+{-# INLINE_NORMAL lCompactChunksGE #-}
2761+lCompactChunksGE :: (MonadIO m, Unbox a)
2762+ => Int -> Fold m (MutArray a) () -> Fold m (MutArray a) ()
2763+-- lCompactChunksGE n = Fold.many (fCompactChunksGE n)
2764+lCompactChunksGE n (Fold step1 initial1 _ final1) =
2765+ Fold step initial extract final
2766+
2767+ where
2768+
2769+ functionName = "Streamly.Internal.Data.MutArray.lCompactChunksGE"
2770+
2771+ initial = do
2772+ when (n <= 0) $
2773+ -- XXX we can pass the module string from the higher level API
2774+ error $ functionName ++ ": the size of arrays ["
2775+ ++ show n ++ "] must be a natural number"
2776+
2777+ r <- initial1
2778+ return $ first (Tuple' Nothing) r
2779+
2780+ step (Tuple' Nothing r1) arr =
2781+ let len = byteLength arr
2782+ in if len >= n
2783+ then do
2784+ r <- step1 r1 arr
2785+ case r of
2786+ FL.Done _ -> return $ FL.Done ()
2787+ FL.Partial s -> do
2788+ _ <- final1 s
2789+ res <- initial1
2790+ return $ first (Tuple' Nothing) res
2791+ else return $ FL.Partial $ Tuple' (Just arr) r1
2792+
2793+ step (Tuple' (Just buf) r1) arr = do
2794+ let len = byteLength buf + byteLength arr
2795+ buf1 <- if byteCapacity buf < len
2796+ then liftIO $ realloc (max n len) buf
2797+ else return buf
2798+ buf2 <- spliceUnsafe buf1 arr
2799+
2800+ -- XXX this is common in both the equations of step
2801+ if len >= n
2802+ then do
2803+ r <- step1 r1 buf2
2804+ case r of
2805+ FL.Done _ -> return $ FL.Done ()
2806+ FL.Partial s -> do
2807+ _ <- final1 s
2808+ res <- initial1
2809+ return $ first (Tuple' Nothing) res
2810+ else return $ FL.Partial $ Tuple' (Just buf2) r1
2811+
2812+ -- XXX Several folds do extract >=> final, therefore, we need to make final
2813+ -- return "m b" rather than using extract post it if we want extract to be
2814+ -- partial.
2815+ --
2816+ -- extract forces the pending buffer to be sent to the fold which is not
2817+ -- what we want.
2818+ extract _ = error "lCompactChunksGE: not designed for scanning"
2819+
2820+ final (Tuple' Nothing r1) = final1 r1
2821+ final (Tuple' (Just buf) r1) = do
2822+ r <- step1 r1 buf
2823+ case r of
2824+ FL.Partial rr -> final1 rr
2825+ FL.Done _ -> return ()
2826+
2827+-- | @compactChunksGE n stream@ coalesces adjacent arrays in the @stream@ until
2828+-- the size becomes greater than or equal to @n@.
2829+--
2830+-- >>> compactChunksGE n = Stream.foldMany (MutArray.fCompactChunksGE n)
2831+--
2832+{-# INLINE compactChunksGE #-}
2833+compactChunksGE ::
2834+ (MonadIO m, Unbox a)
2835+ => Int -> Stream m (MutArray a) -> Stream m (MutArray a)
2836+compactChunksGE n = D.foldMany (fCompactChunksGE n)
2837+
2838+-- | 'compactChunksEQ n' coalesces adajacent arrays in the input stream to
2839+-- arrays of exact size @n@.
2840+--
2841+-- /Unimplemented/
2842+{-# INLINE compactChunksEQ #-}
2843+compactChunksEQ :: -- (MonadIO m, Unbox a) =>
2844+ Int -> Stream m (MutArray a) -> Stream m (MutArray a)
2845+compactChunksEQ _n = undefined -- D.parseManyD (pCompactChunksEQ n)
2846+
2847+-------------------------------------------------------------------------------
2848+-- In-place mutation algorithms
2586-------------------------------------------------------------------------------
2849-------------------------------------------------------------------------------
2587
2850
2588-- | Strip elements which match with predicate from both ends.
2851-- | Strip elements which match with predicate from both ends.