iteratee-compress 0.1.2.1 → 0.2.0.0
raw patch · 2 files changed
+541/−8 lines, 2 filesdep +mtldep −monads-fddep ~iterateePVP ok
version bump matches the API change (PVP)
Dependencies added: mtl
Dependencies removed: monads-fd
Dependency ranges changed: iteratee
API changes (from Hackage documentation)
+ Data.Iteratee.BZip: BestCompression :: BlockSize
+ Data.Iteratee.BZip: BestCompressionWorkFactor :: WorkFactor
+ Data.Iteratee.BZip: BestSpeed :: BlockSize
+ Data.Iteratee.BZip: BestSpeedWorkFactor :: WorkFactor
+ Data.Iteratee.BZip: CompressParams :: BlockSize -> WorkFactor -> !Int -> CompressParams
+ Data.Iteratee.BZip: CompressionLevel :: !Int -> BlockSize
+ Data.Iteratee.BZip: ConfigError :: BZipException
+ Data.Iteratee.BZip: DataError :: BZipException
+ Data.Iteratee.BZip: DataErrorMagic :: BZipException
+ Data.Iteratee.BZip: DecompressParams :: !Bool -> !Int -> DecompressParams
+ Data.Iteratee.BZip: DefaultBlockSize :: BlockSize
+ Data.Iteratee.BZip: DefaultWorkFactor :: WorkFactor
+ Data.Iteratee.BZip: IncorrectBlockSize :: !Int -> BZipParamsException
+ Data.Iteratee.BZip: IncorrectBufferSize :: !Int -> BZipParamsException
+ Data.Iteratee.BZip: IncorrectState :: BZipException
+ Data.Iteratee.BZip: IncorrectWorkFactor :: !Int -> BZipParamsException
+ Data.Iteratee.BZip: MemError :: BZipException
+ Data.Iteratee.BZip: Unexpected :: !Int -> BZipException
+ Data.Iteratee.BZip: WorkFactor :: !Int -> WorkFactor
+ Data.Iteratee.BZip: compressBlockSize :: CompressParams -> BlockSize
+ Data.Iteratee.BZip: compressBufferSize :: CompressParams -> !Int
+ Data.Iteratee.BZip: compressWorkFactor :: CompressParams -> WorkFactor
+ Data.Iteratee.BZip: data BZipException
+ Data.Iteratee.BZip: data BZipParamsException
+ Data.Iteratee.BZip: data BlockSize
+ Data.Iteratee.BZip: data CompressParams
+ Data.Iteratee.BZip: data DecompressParams
+ Data.Iteratee.BZip: data WorkFactor
+ Data.Iteratee.BZip: decompressBufferSize :: DecompressParams -> !Int
+ Data.Iteratee.BZip: decompressSaveMemory :: DecompressParams -> !Bool
+ Data.Iteratee.BZip: defaultCompressParams :: CompressParams
+ Data.Iteratee.BZip: defaultDecompressParams :: DecompressParams
+ Data.Iteratee.BZip: enumCompress :: MonadIO m => CompressParams -> Enumerator ByteString m a
+ Data.Iteratee.BZip: enumDecompress :: MonadIO m => DecompressParams -> Enumerator ByteString m a
+ Data.Iteratee.BZip: instance Eq BZipException
+ Data.Iteratee.BZip: instance Eq BZipFlush
+ Data.Iteratee.BZip: instance Eq BZipParamsException
+ Data.Iteratee.BZip: instance Exception BZipException
+ Data.Iteratee.BZip: instance Exception BZipFlush
+ Data.Iteratee.BZip: instance Exception BZipParamsException
+ Data.Iteratee.BZip: instance Show BZipException
+ Data.Iteratee.BZip: instance Show BZipFlush
+ Data.Iteratee.BZip: instance Show BZipParamsException
+ Data.Iteratee.BZip: instance Typeable BZipException
+ Data.Iteratee.BZip: instance Typeable BZipFlush
+ Data.Iteratee.BZip: instance Typeable BZipParamsException
Files
- Data/Iteratee/BZip.hsc +532/−0
- iteratee-compress.cabal +9/−8
+ Data/Iteratee/BZip.hsc view
@@ -0,0 +1,532 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE ForeignFunctionInterface #-}+{-# LANGUAGE ScopedTypeVariables #-}+module Data.Iteratee.BZip+ (+ -- * Enumerators+ enumCompress,+ enumDecompress,+ -- * Exceptions+ BZipParamsException(..),+ BZipException(..),+ -- * Parameters+ CompressParams(..),+ defaultCompressParams,+ DecompressParams(..),+ defaultDecompressParams,+ BlockSize(..),+ WorkFactor(..)+ )+where+#include <bzlib.h>++import Control.Applicative+import Control.Exception+import Control.Monad.Trans+import Data.ByteString as BS+import Data.ByteString.Internal+import Data.Iteratee+import Data.Iteratee.IO+import Data.Typeable+import Foreign+import Foreign.C+#ifdef DEBUG+import qualified Foreign.Concurrent as C+import System.IO (stderr)+import qualified System.IO as IO+#endif++-- | Denotes error is user-supplied parameter+data BZipParamsException+ = IncorrectBlockSize !Int+ -- ^ Incorrect block size was chosen+ | IncorrectWorkFactor !Int+ -- ^ Incorrect work size was chosen+ | IncorrectBufferSize !Int+ -- ^ Incorrect buffer size was chosen+ deriving (Eq,Typeable)++-- | Denotes error in compression and decompression+data BZipException+ = ConfigError+ -- ^ bzip2 library internal error+ | MemError+ -- ^ Memory allocation failed+ | DataError+ -- ^ Corrupted input+ | DataErrorMagic+ -- ^ Incorrect magic number+ | Unexpected !Int+ -- ^ Unknown or unexpected error+ | IncorrectState+ -- ^ Incorrect state - denotes error in library+ deriving (Eq,Typeable)++-- | Denotes the flush that can be sent to stream+data BZipFlush = BZipFlush+ deriving (Eq,Typeable)++instance Show BZipFlush where+ show BZipFlush = "bzlib: flush requested"++instance Exception BZipFlush++fromFlush :: BZipFlush -> CInt+fromFlush BZipFlush = #{const BZ_FLUSH}++instance Show BZipParamsException where+ show (IncorrectBlockSize size)+ = "bzlib: incorrect block size " ++ show size+ show (IncorrectWorkFactor wf)+ = "bzlib: incorrect work factor " ++ show wf+ show (IncorrectBufferSize size)+ = "bzlib: incorrect buffer size " ++ show size++instance Show BZipException where+ show ConfigError = "bzlib: library is not configure properly"+ show MemError = "bzlib: memory allocation failed"+ show DataError = "bzlib: input is corrupted"+ show DataErrorMagic = "bzlib: magic number does not match"+ show (Unexpected n) = "bzlib: unexpected error " ++ show n+ show IncorrectState = "bzlib: incorrect state"+++instance Exception BZipParamsException+instance Exception BZipException ++newtype BZStream = BZStream (ForeignPtr BZStream)+withBZStream :: BZStream -> (Ptr BZStream -> IO a) -> IO a+withBZStream (BZStream fptr) = withForeignPtr fptr++mallocBZStream :: IO BZStream+mallocBZStream = BZStream <$> mallocForeignPtrBytes #{size bz_stream}++-- Following code is copied from Duncan Coutts bzlib haskell library version+-- 0.5.2.0 ((c) 2006-2008 Duncan Coutts, published on BSD licence) and adapted++-- | Set of parameters for compression. For sane defaults use+-- 'defaultCompressParams'+data CompressParams = CompressParams {+ compressBlockSize :: BlockSize,+ compressWorkFactor :: WorkFactor,+ -- | The size of output buffer. That is the size of 'Chunk's that will be+ -- emitted to inner iterator (except the last 'Chunk').+ compressBufferSize :: !Int+ }++defaultCompressParams+ = CompressParams DefaultBlockSize DefaultWorkFactor (8*1024)++-- | Set of parameters for decompression. For sane defaults see +-- 'defaultDecompressParams'.+data DecompressParams = DecompressParams {+ decompressSaveMemory :: !Bool,+ -- | The size of output buffer. That is the size of 'Chunk's that will be+ -- emitted to inner iterator (except the last 'Chunk').+ decompressBufferSize :: !Int+ }++defaultDecompressParams = DecompressParams False (8*1024)++-- | The compression level specify the tradeoff between speed and compression.+data BlockSize+ = DefaultBlockSize+ -- ^ Default compression level set at 6.+ | BestSpeed+ -- ^ The fastest compression method (however less compression)+ | BestCompression+ -- ^ The best compression method (however slowest)+ | CompressionLevel !Int+ -- ^ Compression level set by number from 0 to 250++data WorkFactor+ = DefaultWorkFactor+ | BestSpeedWorkFactor+ | BestCompressionWorkFactor+ | WorkFactor !Int++fromBlockSize :: BlockSize -> Either BZipParamsException CInt+fromBlockSize DefaultBlockSize = Right $! 6+fromBlockSize BestSpeed = Right $! 1+fromBlockSize BestCompression = Right $! 9+fromBlockSize (CompressionLevel lvl)+ | lvl < 0 || lvl > 250 = Left $! IncorrectBlockSize $! fromIntegral lvl+ | otherwise = Right $! fromIntegral lvl++fromWorkFactor :: WorkFactor -> Either BZipParamsException CInt+fromWorkFactor DefaultWorkFactor = Right $! 0+fromWorkFactor BestSpeedWorkFactor = Right $! 1+fromWorkFactor BestCompressionWorkFactor = Right $! 250+fromWorkFactor (WorkFactor wf)+ | wf < 0 || wf > 250 = Left $! IncorrectWorkFactor $! fromIntegral wf+ | otherwise = Right $! fromIntegral wf++fromErrno :: CInt -> Either BZipException Bool+fromErrno (#{const BZ_OK}) = Right $! True+fromErrno (#{const BZ_RUN_OK}) = Right $! True+fromErrno (#{const BZ_FLUSH_OK}) = Right $! True+fromErrno (#{const BZ_FINISH_OK}) = Right $! True+fromErrno (#{const BZ_STREAM_END}) = Right $! False+fromErrno (#{const BZ_CONFIG_ERROR}) = Left $! ConfigError+fromErrno (#{const BZ_MEM_ERROR}) = Left $! MemError+fromErrno (#{const BZ_DATA_ERROR}) = Left $! DataError+fromErrno (#{const BZ_DATA_ERROR_MAGIC}) = Left $! DataErrorMagic+fromErrno n = Left $! Unexpected $! fromIntegral n++--+-- In following code we go through 7 states. Some of the operations are+-- 'deterministic' like 'insertOut' and some of them depends on input ('fill')+-- or library call.+--+-- (Finished)+-- ^+-- |+-- |+-- | finish+-- |+-- insertOut fill[1] |+--- (Initial) -------------> (EmptyIn) -----------> (Finishing)+-- ^ ^ | ^ |+-- | run[2] | | | \------------------\+-- | | | | |+-- | | | \------------------\ |+-- | run[1] | | flush[0] | |+-- \------------------\ | | fill[0] | | fill[3]+-- | | | | |+-- | | | | |+-- swapOut | | v flush[1] | v+-- (FullOut) -------------> (Invalid) <----------- (Flushing)+--+-- Initial: Initial state, both buffers are empty+-- EmptyIn: Empty in buffer, out waits untill filled+-- FullOut: Out was filled and sent. In was not entirely read+-- Invalid[1]: Both buffers non-empty+-- Finishing: There is no more in data and in buffer is empty. Waits till+-- all outs was sent.+-- Finished: Operation finished+-- Flushing: Flush requested+-- +-- Please note that the decompressing can finish also on flush and finish.+--+-- [1] Named for 'historical' reasons++newtype Initial = Initial BZStream+data EmptyIn = EmptyIn !BZStream !ByteString+data FullOut = FullOut !BZStream !ByteString+data Invalid = Invalid !BZStream !ByteString !ByteString+data Finishing = Finishing !BZStream !ByteString+data Flushing = Flushing !BZStream !BZipFlush !ByteString++withByteString :: ByteString -> (Ptr Word8 -> Int -> IO a) -> IO a+withByteString (PS ptr off len) f+ = withForeignPtr ptr (\ptr' -> f (ptr' `plusPtr` off) len)++#ifdef DEBUG+mkByteString :: MonadIO m => Int -> m ByteString+mkByteString s = liftIO $ do+ base <- mallocForeignPtrArray s+ withForeignPtr base $ \ptr -> C.addForeignPtrFinalizer base $ do+ IO.hPutStrLn stderr $ "Freed buffer " ++ show ptr+ IO.hPutStrLn stderr $ "Allocated buffer " ++ show base+ return $! PS base 0 s++dumpZStream :: BZStream -> IO ()+dumpZStream bzstr = withBZStream bzstr $ \bzptr -> do+ IO.hPutStr stderr $ "<<BZStream@"+ IO.hPutStr stderr $ (show bzptr)+ IO.hPutStr stderr . (" next_in=" ++) . show =<<+ (#{peek bz_stream, next_in} bzptr :: IO (Ptr CChar))+ IO.hPutStr stderr . (" avail_in=" ++) . show =<<+ (#{peek bz_stream, avail_in} bzptr :: IO CUInt)+ total_in_lo <- #{peek bz_stream, total_in_lo32} bzptr :: IO CUInt+ total_in_hi <- #{peek bz_stream, total_in_hi32} bzptr :: IO CUInt+ let total_in_lo' = fromIntegral total_in_lo+ total_in_hi' = fromIntegral total_in_hi `shiftL` 32+ total_in = total_in_lo' + total_in_hi' :: Int64+ IO.hPutStr stderr $ " total_out=" ++ show (total_in :: Int64)+ IO.hPutStr stderr . (" next_out=" ++) . show =<<+ (#{peek bz_stream, next_out} bzptr :: IO (Ptr CChar))+ IO.hPutStr stderr . (" avail_out=" ++) . show =<<+ (#{peek bz_stream, avail_out} bzptr :: IO CUInt)+ total_out_lo <- #{peek bz_stream, total_out_lo32} bzptr :: IO CUInt+ total_out_hi <- #{peek bz_stream, total_out_hi32} bzptr:: IO CUInt+ let total_out_lo' = fromIntegral total_out_lo+ total_out_hi' = fromIntegral total_out_hi `shiftL` 32+ total_out = total_out_lo' + total_out_hi'+ IO.hPutStr stderr $ " total_out=" ++ show (total_out :: Int64)+ IO.hPutStrLn stderr ">>"+#else+mkByteString :: MonadIO m => Int -> m ByteString+mkByteString s = liftIO $ create s (\_ -> return ())+#endif++putOutBuffer :: Int -> BZStream -> IO ByteString+putOutBuffer size bzstr = do+ _out <- mkByteString size+ withByteString _out $ \ptr len -> withBZStream bzstr $ \bzptr -> do+ #{poke bz_stream, next_out} bzptr ptr+ #{poke bz_stream, avail_out} bzptr len+ return _out++putInBuffer :: BZStream -> ByteString -> IO ()+putInBuffer bzstr _in+ = withByteString _in $ \ptr len -> withBZStream bzstr $ \bzptr -> do+ #{poke bz_stream, next_in} bzptr ptr+ #{poke bz_stream, avail_in} bzptr len++pullOutBuffer :: BZStream -> ByteString -> IO ByteString+pullOutBuffer bzstr _out = withByteString _out $ \ptr _ -> do+ next_out <- withBZStream bzstr $ \bzptr -> #{peek bz_stream, next_out} bzptr+ return $! BS.take (next_out `minusPtr` ptr) _out++pullInBuffer :: BZStream -> ByteString -> IO ByteString+pullInBuffer bzstr _in = withByteString _in $ \ptr _ -> do+ next_in <- withBZStream bzstr $ \bzptr -> #{peek bz_stream, next_in} bzptr+ return $! BS.drop (next_in `minusPtr` ptr) _in++insertOut :: MonadIO m+ => Int+ -> (BZStream -> CInt -> IO CInt)+ -> Initial+ -> Enumerator ByteString m a+insertOut size run (Initial bzstr) iter = return $! do+ _out <- liftIO $ putOutBuffer size bzstr+#ifdef DEBUG+ liftIO $ IO.hPutStrLn stderr $ "Inserted out buffer of size " ++ show size+#endif+ joinIM $ fill size run (EmptyIn bzstr _out) iter++fill :: MonadIO m+ => Int+ -> (BZStream -> CInt -> IO CInt)+ -> EmptyIn+ -> Enumerator ByteString m a+fill size run (EmptyIn bzstr _out) iter+ = let fill' (Chunk _in)+ | not (BS.null _in) = do+ liftIO $ putInBuffer bzstr _in+#ifdef DEBUG+ liftIO $ IO.hPutStrLn stderr $+ "Inserted in buffer of size " ++ show (BS.length _in)+#endif+ joinIM $ doRun size run (Invalid bzstr _in _out) iter+ | otherwise = fillI+ fill' (EOF Nothing) = do+ out <- liftIO $ pullOutBuffer bzstr _out + iter' <- lift $ enumPure1Chunk out iter+ joinIM $ finish size run (Finishing bzstr BS.empty) iter'+ fill' (EOF (Just err))+ = case fromException err of+ Just err' ->+ joinIM $ flush size run (Flushing bzstr err' _out) iter+ Nothing -> throwRecoverableErr err fill'+#ifdef DEBUG+ fillI = do+ liftIO $ IO.hPutStrLn stderr $ "About to insert in buffer"+ liftI fill'+#else+ fillI = liftI fill'+#endif+ in return $! fillI++swapOut :: MonadIO m+ => Int+ -> (BZStream -> CInt -> IO CInt)+ -> FullOut+ -> Enumerator ByteString m a+swapOut size run (FullOut bzstr _in) iter = return $! do+ _out <- liftIO $ putOutBuffer size bzstr+#ifdef DEBUG+ liftIO $ IO.hPutStrLn stderr $ "Swapped out buffer of size " ++ show size+#endif+ joinIM $ doRun size run (Invalid bzstr _in _out) iter++doRun :: MonadIO m+ => Int+ -> (BZStream -> CInt -> IO CInt)+ -> Invalid+ -> Enumerator ByteString m a+doRun size run (Invalid bzstr _in _out) iter = return $! do+#ifdef DEBUG+ liftIO $ IO.hPutStrLn stderr $ "About to run"+ liftIO $ dumpZStream bzstr+#endif+ status <- liftIO $ run bzstr #{const BZ_RUN}+#ifdef DEBUG+ liftIO $ IO.hPutStrLn stderr $ "Runned"+#endif+ case fromErrno status of+ Left err -> joinIM $ enumErr err iter+ Right False -> do -- End of stream+ remaining <- liftIO $ pullInBuffer bzstr _in+ out <- liftIO $ pullOutBuffer bzstr _out+ iter' <- lift $ enumPure1Chunk out iter+ res <- lift $ tryRun iter'+ case res of+ Left err@(SomeException _) -> throwErr err+ Right x -> idone x (Chunk remaining)+ Right True -> do -- Continue+ (avail_in, avail_out) <- liftIO $ withBZStream bzstr $ \bzptr -> do+ avail_in <- liftIO $ #{peek bz_stream, avail_in} bzptr+ avail_out <- liftIO $ #{peek bz_stream, avail_out} bzptr+ return (avail_in, avail_out) :: IO (CInt, CInt)+ case avail_out of+ 0 -> do+ out <- liftIO $ pullOutBuffer bzstr _out+ iter' <- lift $ enumPure1Chunk out iter+ joinIM $ case avail_in of+ 0 -> insertOut size run (Initial bzstr) iter'+ _ -> swapOut size run (FullOut bzstr _in) iter'+ _ -> joinIM $ case avail_in of+ 0 -> fill size run (EmptyIn bzstr _out) iter+ _ -> enumErr IncorrectState iter++flush :: MonadIO m+ => Int+ -> (BZStream -> CInt -> IO CInt)+ -> Flushing+ -> Enumerator ByteString m a+flush size run fin@(Flushing bzstr _flush _out) iter = return $! do+ status <- liftIO $ run bzstr (fromFlush _flush)+ case fromErrno status of+ Left err -> joinIM $ enumErr err iter+ Right False -> do -- Finished+ out <- liftIO $ pullOutBuffer bzstr _out+ iter' <- lift $ enumPure1Chunk out iter+ res <- lift $ tryRun iter'+ case res of+ Left err@(SomeException _) -> throwErr err+ Right x -> idone x (Chunk BS.empty)+ Right True -> do+ (avail_in, avail_out) <- liftIO $ withBZStream bzstr $ \bzptr -> do+ avail_in <- liftIO $ #{peek bz_stream, avail_in} bzptr+ avail_out <- liftIO $ #{peek bz_stream, avail_out} bzptr+ return (avail_in, avail_out) :: IO (CInt, CInt)+ case avail_out of+ 0 -> do+ out <- liftIO $ pullOutBuffer bzstr _out+ iter' <- lift $ enumPure1Chunk out iter+ out' <- liftIO $ putOutBuffer size bzstr+ joinIM $ flush size run (Flushing bzstr _flush out') iter'+ _ -> joinIM $ insertOut size run (Initial bzstr) iter++finish :: MonadIO m+ => Int+ -> (BZStream -> CInt -> IO CInt)+ -> Finishing+ -> Enumerator ByteString m a+finish size run fin@(Finishing bzstr _in) iter = return $! do+#ifdef DEBUG+ liftIO $ IO.hPutStrLn stderr $+ "Finishing with out buffer of size " ++ show size+#endif+ _out <- liftIO $ putOutBuffer size bzstr+ status <- liftIO $ run bzstr #{const BZ_FINISH}+ case fromErrno status of+ Left err -> joinIM $ enumErr err iter+ Right False -> do -- Finished+ remaining <- liftIO $ pullInBuffer bzstr _in+ out <- liftIO $ pullOutBuffer bzstr _out+ iter' <- lift $ enumPure1Chunk out iter+ res <- lift $ tryRun iter'+ case res of+ Left err@(SomeException _) -> throwErr err+ Right x -> idone x (Chunk remaining)+ Right True -> do+ (avail_in, avail_out) <- liftIO $ withBZStream bzstr $ \bzptr -> do+ avail_in <- liftIO $ #{peek bz_stream, avail_in} bzptr+ avail_out <- liftIO $ #{peek bz_stream, avail_out} bzptr+ return (avail_in, avail_out) :: IO (CInt, CInt)+ case avail_out of+ 0 -> do+ out <- liftIO $ withBZStream bzstr $ \bzptr ->+ pullOutBuffer bzstr _out+ iter' <- lift $ enumPure1Chunk out iter+ joinIM $ finish size run fin iter'+ _ -> throwErr $! SomeException IncorrectState++foreign import ccall unsafe "BZ2_bzCompressInit"+ compressInit :: Ptr BZStream -> CInt -> CInt+ -> CInt -> IO CInt+foreign import ccall unsafe "BZ2_bzDecompressInit"+ decompressInit :: Ptr BZStream -> CInt -> CInt+ -> IO CInt+foreign import ccall unsafe "BZ2_bzCompress"+ compress :: Ptr BZStream -> CInt -> IO CInt+foreign import ccall unsafe "BZ2_bzDecompress"+ decompress :: Ptr BZStream -> IO CInt+foreign import ccall unsafe "&BZ2_bzCompressEnd"+ compressEnd :: FunPtr (Ptr BZStream -> IO ())+foreign import ccall unsafe "&BZ2_bzDecompressEnd"+ decompressEnd :: FunPtr (Ptr BZStream -> IO ())++#ifdef DEBUG+compress' :: BZStream -> CInt -> IO CInt+compress' bz f = withBZStream bz $ \p -> do+ IO.hPutStrLn stderr "About to run compress"+ compress p f++decompress' :: BZStream -> CInt -> IO CInt+decompress' bz _ = withBZStream bz $ \p -> do+ IO.hPutStrLn stderr "About to run decompress"+ decompress p++verboseLevel :: CInt+verboseLevel = 3+#else+compress' :: BZStream -> CInt -> IO CInt+compress' bz f = withBZStream z $ \p -> compress p f++decompress :: BZStream -> CInt -> IO CInt+decompress' bz f = withBZStream z $ \p -> decompress p f++verboseLevel :: CInt+verboseLevel = 0+#endif++mkCompress :: CompressParams -> IO (Either BZipParamsException Initial)+mkCompress (CompressParams blk wf _)+ = case fromBlockSize blk of+ Left err -> return $! Left $! err+ Right blk' -> case fromWorkFactor wf of+ Left err -> return $! Left $! err+ Right wf' -> do+ bzstr <- mallocForeignPtrBytes #{size bz_stream}+ withForeignPtr bzstr $ \bzptr -> do+ memset (castPtr bzptr) 0 #{size bz_stream}+ compressInit bzptr blk' verboseLevel wf' `finally`+ addForeignPtrFinalizer compressEnd bzstr+ return $! Right $! Initial $ BZStream bzstr++mkDecompress :: DecompressParams -> IO (Either BZipParamsException Initial)+mkDecompress (DecompressParams small _) = do+ bzstr <- mallocForeignPtrBytes #{size bz_stream}+ withForeignPtr bzstr $ \bzptr -> do+ memset (castPtr bzptr) 0 #{size bz_stream}+ decompressInit bzptr verboseLevel (if small then 0 else 1) `finally`+ addForeignPtrFinalizer decompressEnd bzstr+ return $! Right $! Initial $ BZStream bzstr++-- User-related code++-- | Compress the input and send to inner iteratee.+enumCompress :: MonadIO m+ => CompressParams -- ^ Parameters of compression+ -> Enumerator ByteString m a+enumCompress cp@(CompressParams _ _ size) iter = do+ cmp <- liftIO $ mkCompress cp+ case cmp of+ Left err -> enumErr err iter+ Right init -> insertOut size compress' init iter++-- | Decompress the input and send to inner iteratee. If there is end of+-- zlib stream it is left unprocessed.+enumDecompress :: MonadIO m+ => DecompressParams+ -> Enumerator ByteString m a+enumDecompress dp@(DecompressParams _ size) iter = do+ dcmp <- liftIO $ mkDecompress dp+ case dcmp of+ Left err -> enumErr err iter+ Right init -> insertOut size decompress' init iter
iteratee-compress.cabal view
@@ -1,5 +1,5 @@ Name: iteratee-compress-Version: 0.1.2.1+Version: 0.2.0.0 Synopsis: An enumerators for compressing and decompressing streams Description: An enumerators for compressing and decompressing streams License: BSD3@@ -14,23 +14,24 @@ Flag Debug Description: Enable debug support- Default: False+ Default: True Library- Exposed-modules: Data.Iteratee.ZLib+ Exposed-modules: Data.Iteratee.BZip,+ Data.Iteratee.ZLib Build-depends: base >= 4 && < 5, bytestring >= 0.9 && < 0.10,- iteratee >= 0.4 && < 0.7,- monads-fd >= 0.1 && < 0.2+ iteratee >= 0.4 && < 0.9,+ mtl >= 2.0 && < 2.1 Build-tools: c2hs Extensions: CPP, DeriveDataTypeable, ForeignFunctionInterface, ScopedTypeVariables- Extra-libraries: z+ Extra-libraries: z, bz2 if flag(debug) CPP-Options: -DDEBUG Source-Repository head- Type: darcs- Location: http://code.haskell.org/iteratee-compress/+ Type: git+ Location: git://gitorious.org/iteratee-compress/iteratee-compress.git