packages feed

mutable-iter 0.6 → 0.6.1

raw patch · 3 files changed

+105/−2 lines, 3 files

Files

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)