ref: cf20fb934e9af13b64c2365cbf95d974f30b5c9d
dir: /lib/System/Compress.hs/
module System.Compress(compress, decompress) where
import Prelude(); import MiniPrelude
import Data.Function
import Foreign.Ptr
import Foreign.C.String
import Foreign.C.Types
import Foreign.Marshal.Alloc
import Foreign.Marshal.Utils
import Foreign.Ptr
import Foreign.Storable
import System.IO
import System.IO.Internal
import System.IO.Unsafe
type PBFILE = Ptr BFILE
type Transducer = PBFILE -> IO PBFILE
foreign import ccall "openb_wr_buf" c_openb_wr_buf :: IO PBFILE
foreign import ccall "openb_rd_buf" c_openb_rd_buf :: Ptr Char -> Int -> IO PBFILE
foreign import ccall "add_lz77_compressor" c_add_lz77_compressor :: Transducer
foreign import ccall "add_lz77_decompressor" c_add_lz77_decompressor :: Transducer
foreign import ccall "add_rle_compressor" c_add_rle_compressor :: Transducer
foreign import ccall "add_rle_decompressor" c_add_rle_decompressor :: Transducer
foreign import ccall "add_bwt_compressor" c_add_bwt_compressor :: Transducer
foreign import ccall "add_bwt_decompressor" c_add_bwt_decompressor :: Transducer
foreign import ccall "putb" c_putb :: Int -> PBFILE -> IO ()
foreign import ccall "getb" c_getb :: PBFILE -> IO Int
foreign import ccall "get_buf" c_get_buf :: PBFILE -> Ptr (Ptr Char) -> Ptr Int -> IO ()
foreign import ccall "closeb" c_close :: PBFILE -> IO ()
foreign import ccall "flushb" c_flush :: PBFILE -> IO ()
withPutTransducer :: Transducer -> [Char] -> [Char]
withPutTransducer trans file = unsafePerformIO $ do
bf <- c_openb_wr_buf -- create a buffer
cbf <- trans bf -- and add transducer (e.g., a compressor)
mapM_ (flip c_putb cbf . ord) file -- copy all the bytes
c_flush cbf -- do compression and write to buffer
with nullPtr $ \ bufp ->
with 0 $ \ lenp -> do
c_get_buf bf bufp lenp -- get buffer and length
buf <- peek bufp
len <- peek lenp
res <- peekCAStringLen (buf, len) -- encode as a string
free buf -- free owned memory
c_close cbf -- and close everything
return res
withGetTransducer :: Transducer -> [Char] -> [Char]
withGetTransducer trans file = unsafePerformIO $ do
(ptr, len) <- newCAStringLen file -- make memory buffer
bf <- c_openb_rd_buf ptr len -- open it for reading
cbf <- trans bf -- and add transducer (e.g., decompressor)
h <- mkHandle "withGetTransducer" cbf HRead
cs <- hGetContents h -- get contents
seq (length cs) (return ()) -- force it all so ptr is no longer in use
hClose h
return cs
compress :: [Char] -> [Char]
compress = withPutTransducer c_add_lz77_compressor
decompress :: [Char] -> [Char]
decompress = withGetTransducer c_add_lz77_decompressor
compressRLE :: [Char] -> [Char]
compressRLE = withPutTransducer c_add_rle_compressor
decompressRLE :: [Char] -> [Char]
decompressRLE = withGetTransducer c_add_rle_decompressor
compressBWT :: [Char] -> [Char]
compressBWT = withPutTransducer c_add_bwt_compressor
decompressBWT :: [Char] -> [Char]
decompressBWT = withGetTransducer c_add_bwt_decompressor
compressBWTRLE :: [Char] -> [Char]
compressBWTRLE = withPutTransducer (c_add_bwt_compressor <=< c_add_rle_compressor <=< c_add_lz77_compressor)
decompressBWTRLE :: [Char] -> [Char]
decompressBWTRLE = withGetTransducer (c_add_bwt_decompressor <=< c_add_rle_decompressor <=< c_add_lz77_decompressor)
{-
main :: IO ()
main = do
putStrLn "compress"
haa <- openBinaryFile "aa" ReadMode
aa <- hGetContents haa
let bb = compressBWTRLE aa
hbb <- openBinaryFile "bb" WriteMode
hPutStr hbb bb
hClose hbb
hClose haa
putStrLn "decompress"
hbb' <- openBinaryFile "bb" ReadMode
bb' <- hGetContents hbb'
let aa' = decompressBWTRLE bb'
hcc <- openBinaryFile "cc" WriteMode
hPutStr hcc aa'
hClose hbb'
hClose hcc
-}