packages feed

lz4-0.1.0.0: src/Codec/Compression/LZ4.hs

module Codec.Compression.LZ4 (compress, compressHC, uncompress) where
import Codec.Compression.LZ4.Foreign
import Foreign
import Data.ByteString
import Debug.Trace
import Data.ByteString.Unsafe

-- Following zlib's lead, we pretend to be pure on Bytestrings
-- errors may be thrown for bad formats. I'm not entirely comfortable with this.

-- we use unsafeUseAsCStringLen because the underlying files may be large, and
-- we trust lz4 not to tamper with the input buffer.

-- TODO: use a standard chunk size & support lazy Bytestrings
-- TODO: load files from disk: we don't currently support the full file format with
--       magic archive numbers etc.

-- compressHC = compressWorker c_LZ4_compressHC
-- compress   = compressWorker c_LZ4_compress

-- for some reason, when I factor this out in the obvious way, I get link errors. Very confusing. FIXME
compressHC x = unsafePerformIO $ unsafeUseAsCStringLen x $ \(input,len) ->
  let outLen = c_LZ4_compressBound len in
  allocaBytes (1+outLen) $ \out -> do    
    written <- c_LZ4_compressHC input out (fromIntegral len)
    if written == 0
      then error "compression failed"
      else packCStringLen (out, written) --  `doTrace` ("compress", x, len, outLen, written)

compress x = unsafePerformIO $ unsafeUseAsCStringLen x $ \(input,len) ->
  let outLen = c_LZ4_compressBound len in
  allocaBytes (1+outLen) $ \out -> do    
    written <- c_LZ4_compress input out (fromIntegral len)
    if written == 0
      then error "compression failed"
      else packCStringLen (out, written) --  `doTrace` ("compress", x, len, outLen, written)

uncompress :: ByteString -> ByteString
uncompress x = unsafePerformIO $ unsafeUseAsCStringLen x $ \(input,len) ->
  -- this is a complete punt. let's say we use 5*len for the moment,
  -- and extend to lazy bytestrings later.
  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)