lz4-0.1.0.1: src/Codec/Compression/LZ4.hs
-- | This is a binding to the LZ4 library, source of which can be found at
-- http://code.google.com/p/lz4/
--
-- Following zlib's lead, we pretend to be total on Bytestrings
-- errors may be thrown for bad formats. I'm not entirely comfortable with this,
-- but I'd like it to be a drop-in replacement for ease of use.
--
-- TODO: use a standard chunk size & support lazy Bytestrings, pending Yann's
-- publication of a formal standard.
module Codec.Compression.LZ4 (compress, compressHC, uncompress) where
import Codec.Compression.LZ4.Foreign
import System.IO.Unsafe (unsafePerformIO)
import Foreign.Marshal.Alloc(allocaBytes)
import Foreign.C.String
import Data.ByteString
import Data.ByteString.Unsafe
-- import Debug.Trace
-- | Compresses a LZ4-packed String using the slow, better packing.
compressHC :: ByteString -> ByteString
compressHC x = compressWorker c_LZ4_compressHC x
-- | Compresses a LZ4-packed String
compress :: ByteString -> ByteString
compress x = compressWorker c_LZ4_compress x
compressWorker :: Num b => (CString -> CString -> b -> IO Int) -> ByteString -> ByteString
compressWorker compressor x = unsafePerformIO $ unsafeUseAsCStringLen x $ \(input,len) ->
let outLen = c_LZ4_compressBound len in
allocaBytes (1+outLen) $ \out -> do
written <- compressor input out (fromIntegral len)
if written == 0
then error "compression failed"
else packCStringLen (out, written)
-- `doTrace` ("compress", x, len, outLen, written)
-- | Uncompresses a LZ4-packed String
-- No chunking yet - Yann is still working on a framing.
-- As a dirty hack, we assume that it won't decompress to more than 5 times
-- the length of the compressed file - this will go away with a fixed
-- frame size
uncompress :: ByteString -> ByteString
uncompress x = unsafePerformIO $ unsafeUseAsCStringLen x $ \(input,len) ->
let outLen = 5 * len in
allocaBytes (1+outLen) $ \out -> do
written <- c_LZ4_uncompress_unknownOutputSize input out
(fromIntegral len)
(fromIntegral outLen)
if written < 0
then error "decompression failed!"
else packCStringLen (out, written)