@@ -23,6 +23,7 @@ module Streamly.Memory.Ring
23 , unsafeFoldRing
23 , unsafeFoldRing
24 , unsafeFoldRingM
24 , unsafeFoldRingM
25 , unsafeFoldRingFullM
25 , unsafeFoldRingFullM
27 -- * Fast Byte Comparisons
28 -- * Fast Byte Comparisons
28 , unsafeEqArray
29 , unsafeEqArray
@@ -209,6 +210,9 @@ unsafeFoldRingM ptr f z Ring {..} =
209-- pointer. Assuming the supplied ringHead pointer points to the oldest item,
210-- pointer. Assuming the supplied ringHead pointer points to the oldest item,
210-- this would fold the ring starting from the oldest item to the newest item in
211-- this would fold the ring starting from the oldest item to the newest item in
211-- the ring.
212-- the ring.
214+-- Note, this will crash on ring of 0 size.
212{-# INLINE unsafeFoldRingFullM #-}
216{-# INLINE unsafeFoldRingFullM #-}
213unsafeFoldRingFullM :: forall m a b. (MonadIO m, Storable a)
217unsafeFoldRingFullM :: forall m a b. (MonadIO m, Storable a)
214 => Ptr a -> (b -> a -> m b) -> b -> Ring a -> m b
218 => Ptr a -> (b -> a -> m b) -> b -> Ring a -> m b
@@ -222,3 +226,25 @@ unsafeFoldRingFullM rh f z rb@Ring {..} =
222 if ptr == rh
226 if ptr == rh
223 then return acc'
227 then return acc'
224 else go acc' ptr
228 else go acc' ptr
230+-- | Fold @Int@ items in the ring starting at @Ptr a@. Won't fold more
231+-- than the length of the ring.
233+-- Note, this will crash on ring of 0 size.
235+{-# INLINE unsafeFoldRingNM #-}
236+unsafeFoldRingNM :: forall m a b. (MonadIO m, Storable a)
237+ => Int -> Ptr a -> (b -> a -> m b) -> b -> Ring a -> m b
238+unsafeFoldRingNM count rh f z rb@Ring {..} =
239+ withForeignPtrM ringStart $ \_ -> go count z rh
243+ go 0 acc _ = return acc
244+ go !n !acc !start = do
245+ let !x = A.unsafeInlineIO $ peek start
247+ let ptr = advance rb start
248+ if ptr == rh || n == 0
250+ else go (n - 1) acc' ptr