mutable-iter 0.6 → 0.6.1
raw patch · 3 files changed
+105/−2 lines, 3 files
Files
- mutable-iter.cabal +1/−1
- src/Data/MutableIter.hs +63/−1
- src/Data/MutableIter/IOBuffer.hs +41/−0
mutable-iter.cabal view
@@ -1,5 +1,5 @@ Name: mutable-iter-Version: 0.6+Version: 0.6.1 Synopsis: iteratees based upon mutable buffers Description: Provides iteratees backed by mutable buffers. This enables iteratees to run without any extra memory allocations. Homepage: http://jwlato.webfactional.com/haskell/mutable-iter
src/Data/MutableIter.hs view
@@ -20,14 +20,18 @@ ,isStreamFinished ,head ,heads+ ,chunk ,peek ,drop ,dropWhile ,foldl'+ ,hopfoldl' ,mapStream ,mapChunk ,mapAccum ,convStream+ ,unfoldConvStream+ ,getChannel ,takeUpTo ,fromUVector ,enumHandleRandom@@ -182,6 +186,14 @@ step cnt s str = idone cnt str {-# INLINE heads #-} +chunk ::+ (MonadCatchIO m, Storable el)+ => MIteratee (IOBuffer r el) m (IOBuffer r el)+chunk = liftI step+ where+ step (I.Chunk buf) = guardNull buf (liftI step) $ idone buf (I.Chunk empty)+ step str = MIteratee . I.throwErr . toException $ I.EofException+ drop :: (MonadCatchIO m, Storable el) => Int -> MIteratee (IOBuffer r el) m () drop n = liftI (step n) where@@ -218,7 +230,26 @@ step acc str = idone acc str {-# INLINE foldl' #-} +hopfoldl' :: (MonadCatchIO m, Storable el, Show a) =>+ Int+ -> (a -> el -> a)+ -> a+ -> MIteratee (IOBuffer r el) m a+hopfoldl' hop f acc' = liftI (step 0 acc')+ where+ step ihop acc (I.Chunk buf) = guardNull buf (liftI (step ihop acc)) $ do+ (newacc, numExtra) <- liftIO $ do+ IB.drop ihop buf+ buflen <- IB.length buf+ let numExtra = buflen `rem` hop+ res <- IB.hopfoldl' hop f acc buf+ IB.drop numExtra buf+ return (res,numExtra)+ liftI (step (hop-numExtra) newacc)+ step _ acc str = idone acc str+{-# INLINE hopfoldl' #-} + -- ----------------------------------------------------------- -- Enumeratees @@ -289,6 +320,37 @@ maybe (step k) (idone (liftI k) . I.EOF . Just) step k = fi >>= convStream fi . k . I.Chunk +-- |The most general stream converter. Given a function to produce iteratee+-- transformers and an initial state, convert the stream using iteratees+-- generated by the function while continually updating the internal state.+unfoldConvStream ::+ (MonadCatchIO m, Storable eli, Storable elo)+ => (acc -> MIteratee (IOBuffer r eli) m (acc, IOBuffer r elo))+ -> acc+ -> MEnumeratee (IOBuffer r eli) (IOBuffer r elo) m a+unfoldConvStream f acc0 = eneeCheckIfDone (check acc0)+ where+ check acc k = isStreamFinished >>=+ maybe (step acc k) (idone (liftI k) . I.EOF . Just)+ step acc k = f acc >>= \(acc', s') ->+ eneeCheckIfDone (check acc') . k . I.Chunk $ s'++-- | Decimate a stream by taking every n'th element, starting at element "m".+getChannel ::+ (MonadCatchIO m, Storable el)+ => Int+ -> Int+ -> MEnumeratee (IOBuffer r el) (IOBuffer r el) m a+getChannel 1 _ = convStream chunk+getChannel numChans chn = unfoldConvStream mkIter chn+ where+ mkIter drp = do+ drop drp+ buf <- chunk+ tlen <- liftIO $ IB.length buf+ newbuf <- liftIO $ IB.decimate numChans buf+ return (tlen `rem` numChans, newbuf)+ takeUpTo :: (MonadCatchIO pr, Storable el) => Int -> MEnumeratee (IOBuffer r el) (IOBuffer r el) pr a@@ -312,7 +374,7 @@ -- --------------------------------------------- -- drivers and enumerators --- So users don't need to manually work with IOBuffers all the time+-- | Convert a Vector iteratee to an MIteratee. Slower but convenient. fromUVector :: (U.Unbox el, Storable el, MonadCatchIO m) => I.Iteratee (U.Vector el) m a -> MIteratee (IOBuffer r el) m a
src/Data/MutableIter/IOBuffer.hs view
@@ -17,6 +17,9 @@ ,mapBuffer ,mapAccumBuffer ,foldl'+ ,hopfoldl'+ ,hopfoldM+ ,decimate ,castBuffer ,freeze ,thaw@@ -297,6 +300,44 @@ off <- peek po go (l-off) i0 (pb `advancePtr` off) {-# INLINE foldl' #-}++hopfoldl' :: (Storable b) => Int -> (a -> b -> a) -> a -> IOBuffer r b -> IO a+hopfoldl' hop f acc (IOBuffer 0 _ _) = return acc+hopfoldl' hop f i0 buf = withBuf buf $ \l po pb ->+ let go !n !acc p | n>0 = do+ el <- peek p+ go (n-1) (f acc el) (p `advancePtr` hop)+ go _ acc _ = return acc+ in do+ off <- peek po+ go (l-off `div` hop) i0 (pb `advancePtr` off)+{-# INLINE hopfoldl' #-}++hopfoldM :: (Storable b) => Int -> (a -> b -> IO a) -> a -> IOBuffer r b -> IO a+hopfoldM hop f acc (IOBuffer 0 _ _) = return acc+hopfoldM hop f i0 buf = withBuf buf $ \l po pb ->+ let go !n !acc p | n>0 = do+ el <- peek p+ acc' <- f acc el+ go (n-1) acc' (p `advancePtr` hop)+ go _ acc _ = return acc+ in do+ off <- peek po+ go ((l-off) `div` hop) i0 (pb `advancePtr` off)+{-# INLINE hopfoldM #-}++-- | Create a new buffer of every 'nth' element. The original buffer is+-- not altered.+decimate :: Storable b => Int -> IOBuffer r b -> IO (IOBuffer r b)+decimate _skp (IOBuffer 0 _ _) = return empty+decimate skip buf = do+ ln <- length buf+ let newlen = ln `div` skip+ bufp <- mallocForeignPtrArray newlen+ withForeignPtr bufp $ \p' ->+ hopfoldM skip (\p el -> poke p el >> return (p `advancePtr` 1)) p' buf+ op <- newFp 0+ return $ createIOBuffer newlen op bufp unsafeToForeignPtr :: IOBuffer r el -> (Int, ForeignPtr Int, ForeignPtr el) unsafeToForeignPtr (IOBuffer l po pb) = (l,po,pb)