mutable-iter 0.5 → 0.6
raw patch · 3 files changed
+78/−27 lines, 3 filesdep ~iteratee
Dependency ranges changed: iteratee
Files
- mutable-iter.cabal +4/−3
- src/Data/MutableIter.hs +52/−18
- src/Data/MutableIter/IOBuffer.hs +22/−6
mutable-iter.cabal view
@@ -1,8 +1,8 @@ Name: mutable-iter-Version: 0.5+Version: 0.6 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://tanimoto.us/~jwlato/haskell/mutable-iter+Homepage: http://jwlato.webfactional.com/haskell/mutable-iter License: BSD3 License-file: LICENSE Author: John W. Lato@@ -26,9 +26,10 @@ Exposed-modules: Data.MutableIter ,Data.MutableIter.Binary ,Data.MutableIter.IOBuffer+ ghc-options: -funfolding-use-threshold=64 Build-depends: base >= 4 && < 6,- iteratee >= 0.5 && < 0.8,+ iteratee >= 0.5 && < 0.9, MonadCatchIO-transformers >= 0.2 && < 0.3, transformers >= 0.2 && < 0.3, vector >= 0.4 && < 0.9
src/Data/MutableIter.hs view
@@ -17,6 +17,7 @@ ,idone ,icont ,guardNull+ ,isStreamFinished ,head ,heads ,peek@@ -24,9 +25,11 @@ ,dropWhile ,foldl' ,mapStream+ ,mapChunk ,mapAccum ,convStream ,takeUpTo+ ,fromUVector ,enumHandleRandom ,fileDriverRandom ,newFp@@ -42,8 +45,9 @@ import qualified Data.Iteratee as I import Data.Maybe+import qualified Data.Vector.Unboxed as U -import Control.Exception (SomeException, IOException)+import Control.Exception (SomeException, IOException, toException) import Control.Monad import Control.Monad.CatchIO as CIO import Control.Monad.IO.Class@@ -95,7 +99,7 @@ mapIteratee f = lift . f . I.run . unwrap joinIob :: (MonadCatchIO m, Storable el) =>- MIteratee (IOBuffer r el) m (MIteratee (IOBuffer r el') m a)+ MIteratee (IOBuffer r el) m (MIteratee s m a) -> MIteratee (IOBuffer r el) m a joinIob outer = outer >>= \inner -> MIteratee $ I.Iteratee $ \od oc -> let onDone x _ = od x (I.Chunk empty)@@ -133,22 +137,35 @@ guardNull buf onEmpty onFull = do isNull <- liftIO $ null buf if isNull then onEmpty else onFull+{-# INLINE guardNull #-} +isStreamFinished ::+ (MonadCatchIO m, Storable el) =>+ MIteratee (IOBuffer r el) m (Maybe SomeException)+isStreamFinished = liftI step+ where+ step s@(I.Chunk buf) = guardNull buf (liftI step) (idone Nothing s)+ step s@(I.EOF e) =+ idone (Just $ fromMaybe (toException I.EofException) e) s+{-# INLINE isStreamFinished #-}+ head :: (MonadCatchIO m, Storable el) => MIteratee (IOBuffer r el) m el head = liftI step where- step (I.Chunk buf) = guardNull buf (icont step Nothing) $ do+ step (I.Chunk buf) = guardNull buf (liftI step) $ do x <- liftIO $ pop buf idone x (I.Chunk buf) step str = MIteratee . I.throwErr . toException $ I.EofException+{-# INLINE head #-} peek :: (MonadCatchIO m, Storable el) => MIteratee (IOBuffer r el) m (Maybe el) peek = liftI step where- step c@(I.Chunk buf) = guardNull buf (icont step Nothing) $ do+ step c@(I.Chunk buf) = guardNull buf (liftI step) $ do x <- liftIO $ IB.lookAtHead buf idone x c step str = idone Nothing str+{-# INLINE peek #-} heads :: (MonadCatchIO m, Storable el, Eq el) => [el]@@ -159,32 +176,35 @@ loop cnt str = liftI (step cnt str) step cnt s@(x:xs) (I.Chunk buf) = do mx <- liftIO $ IB.lookAtHead buf- maybe (icont (step cnt s) Nothing) (\h -> if h == x+ maybe (liftI (step cnt s)) (\h -> if h == x then liftIO (pop buf) >> step (succ cnt) xs (I.Chunk buf) else idone cnt (I.Chunk buf)) mx step cnt s str = idone cnt str+{-# INLINE heads #-} drop :: (MonadCatchIO m, Storable el) => Int -> MIteratee (IOBuffer r el) m () drop n = liftI (step n) where step 0 str = idone () str- step n' (I.Chunk buf) = guardNull buf (icont (step n') Nothing) $ do+ step n' (I.Chunk buf) = guardNull buf (liftI (step n')) $ do l <- liftIO $ IB.length buf if n' < l then liftIO (IB.drop n' buf) >> idone () (I.Chunk buf) else liftIO (IB.drop l buf) >> liftI (step (n' - l)) step _ str = idone () str+{-# INLINE drop #-} dropWhile :: (MonadCatchIO m, Storable el) => (el -> Bool) -> MIteratee (IOBuffer r el) m () dropWhile pred = liftI step where- step (I.Chunk buf) = guardNull buf (icont step Nothing) $ do+ step (I.Chunk buf) = guardNull buf (liftI step) $ do liftIO $ IB.dropWhile pred buf l <- liftIO $ IB.length buf- if l == 0 then icont step Nothing else idone () (I.Chunk buf)+ if l == 0 then liftI step else idone () (I.Chunk buf) step str = idone () str+{-# INLINE dropWhile #-} foldl' :: (MonadCatchIO m, Storable el, Show a) => (a -> el -> a)@@ -194,8 +214,9 @@ where step acc (I.Chunk buf) = guardNull buf (liftI (step acc)) $ do newacc <- liftIO $ IB.foldl' f acc buf- icont (step newacc) Nothing+ liftI (step newacc) step acc str = idone acc str+{-# INLINE foldl' #-} -- -----------------------------------------------------------@@ -213,14 +234,12 @@ onCont k Nothing = I.runIter (unwrap $ f (MIteratee . k)) od oc onCont _ (Just e) = I.runIter (I.throwErr e) od oc in I.runIter (unwrap inner) onDone (onCont)+{-# INLINE eneeCheckIfDone #-} mapStream :: (MonadCatchIO pr, Storable elo, Storable eli) => Int -> (eli -> elo)- -> MEnumeratee (IOBuffer r eli)- (IOBuffer r elo)- pr- a+ -> MEnumeratee (IOBuffer r eli) (IOBuffer r elo) pr a mapStream maxlen f i = do offp <- liftIO $ newFp 0 bufp <- liftIO $ mallocForeignPtrArray maxlen@@ -233,6 +252,17 @@ goMap offp bufp $ k (I.Chunk newIOBuf) step _ _ k s = idone (liftI k) s +mapChunk :: (Storable el, MonadCatchIO m) =>+ (IOBuffer r el -> m s2)+ -> MEnumeratee (IOBuffer r el) s2 m a+mapChunk f i = go i+ where+ go = eneeCheckIfDone (liftI . step)+ step k (I.Chunk buf) = lift (f buf) >>= go . k . I.Chunk+ step k s = idone (liftI k) s+{-# INLINE mapChunk #-}++ mapAccum :: (MonadCatchIO pr, Storable eli, Storable elo) => Int -> (b -> eli -> (b,elo))@@ -252,13 +282,10 @@ convStream :: (MonadCatchIO pr, Storable elo, Storable eli) => MIteratee (IOBuffer r eli) pr (IOBuffer r elo)- -> MEnumeratee (IOBuffer r eli)- (IOBuffer r elo)- pr- a+ -> MEnumeratee (IOBuffer r eli) (IOBuffer r elo) pr a convStream fi = eneeCheckIfDone check where- check k = MIteratee (I.isStreamFinished) >>=+ check k = isStreamFinished >>= maybe (step k) (idone (liftI k) . I.EOF . Just) step k = fi >>= convStream fi . k . I.Chunk @@ -284,6 +311,13 @@ -- --------------------------------------------- -- drivers and enumerators++-- So users don't need to manually work with IOBuffers all the time+fromUVector :: (U.Unbox el, Storable el, MonadCatchIO m) =>+ I.Iteratee (U.Vector el) m a+ -> MIteratee (IOBuffer r el) m a+fromUVector = joinIob . mapChunk (liftIO . IB.freeze) . MIteratee+{-# INLINE fromUVector #-} makeHandleCallback :: (MonadCatchIO m, Storable el) => ForeignPtr Int
src/Data/MutableIter/IOBuffer.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE BangPatterns, ScopedTypeVariables #-}+{-# LANGUAGE BangPatterns, ScopedTypeVariables, FlexibleContexts #-} module Data.MutableIter.IOBuffer ( IOBuffer@@ -19,6 +19,7 @@ ,foldl' ,castBuffer ,freeze+ ,thaw ,hPut ,unsafeToForeignPtr )@@ -27,7 +28,7 @@ import Prelude hiding (length, take, drop, null, splitAt, dropWhile) -import qualified Data.Vector.Storable as V+import qualified Data.Vector.Generic as G import qualified Data.Iteratee as I import Control.Monad import Control.Monad.CatchIO@@ -193,12 +194,27 @@ return $ IOBuffer len po pb)) -- |Safely convert an IOBuffer to a Vector.--- TODO: finish this implementation, look at Vector docs.-freeze :: (Storable el) => IOBuffer r el -> IO (V.Vector el)-freeze (IOBuffer 0 _ _) = return V.empty+freeze :: (Storable el, G.Vector v el, G.Vector v Int) =>+ IOBuffer r el+ -> IO (v el)+freeze (IOBuffer 0 _ _) = return G.empty freeze buf = withBuf buf $ \l po pb -> do+ len <- length buf off <- peek po- return undefined+ let vIx = G.enumFromN 0 len+ vRes <- G.forM vIx (\ix -> peekElemOff (pb `advancePtr` off) ix)+ return vRes+{-# INLINE freeze #-}++-- |Safely convert a Vector to an IOBuffer+thaw :: (Storable el, G.Vector v el) => v el -> IO (IOBuffer r el)+thaw vec = do+ offp <- newFp 0+ bufp <- mallocForeignPtrArray (G.length vec)+ withForeignPtr bufp $ \p ->+ G.foldM' (\ix el -> pokeElemOff p ix el >> return (ix+1)) 0 vec+ return $ createIOBuffer (G.length vec) offp bufp+{-# INLINE thaw #-} -- |Write out the contents of the IOBuffer to a handle. This operation -- drains the buffer.