{-# LINE 1 "src/LibLzma.hsc" #-}
{-# LANGUAGE RecordWildCards, DeriveDataTypeable #-}
module LibLzma
( LzmaStream
, LzmaRet(..)
, IntegrityCheck(..)
, CompressionLevel(..)
, newDecodeLzmaStream
, DecompressParams(..)
, defaultDecompressParams
, newEncodeLzmaStream
, CompressParams(..)
, defaultCompressParams
, runLzmaStream
, endLzmaStream
, LzmaAction(..)
) where
import Control.Applicative
import Control.Exception
import Control.Monad
import Control.Monad.ST.Strict (ST)
import Control.Monad.ST.Unsafe (unsafeIOToST)
import Data.ByteString (ByteString)
import qualified Data.ByteString as BS
import qualified Data.ByteString.Internal as BS
import qualified Data.ByteString.Unsafe as BS
import Data.Typeable
import Foreign
import Prelude
newtype LzmaStream = LS (ForeignPtr LzmaStream)
data LzmaRet = LzmaRetOK
| LzmaRetStreamEnd
| LzmaRetUnsupportedCheck
| LzmaRetGetCheck
| LzmaRetMemError
| LzmaRetMemlimitError
| LzmaRetFormatError
| LzmaRetOptionsError
| LzmaRetDataError
| LzmaRetBufError
| LzmaRetProgError
deriving (Eq,Ord,Read,Show,Typeable)
instance Exception LzmaRet
toLzmaRet :: Int -> Maybe LzmaRet
toLzmaRet i = case i of
(0) -> Just LzmaRetOK
{-# LINE 66 "src/LibLzma.hsc" #-}
(1) -> Just LzmaRetStreamEnd
{-# LINE 67 "src/LibLzma.hsc" #-}
(3) -> Just LzmaRetUnsupportedCheck
{-# LINE 68 "src/LibLzma.hsc" #-}
(4) -> Just LzmaRetGetCheck
{-# LINE 69 "src/LibLzma.hsc" #-}
(5) -> Just LzmaRetMemError
{-# LINE 70 "src/LibLzma.hsc" #-}
(6) -> Just LzmaRetMemlimitError
{-# LINE 71 "src/LibLzma.hsc" #-}
(7) -> Just LzmaRetFormatError
{-# LINE 72 "src/LibLzma.hsc" #-}
(8) -> Just LzmaRetOptionsError
{-# LINE 73 "src/LibLzma.hsc" #-}
(9) -> Just LzmaRetDataError
{-# LINE 74 "src/LibLzma.hsc" #-}
(10) -> Just LzmaRetBufError
{-# LINE 75 "src/LibLzma.hsc" #-}
(11) -> Just LzmaRetProgError
{-# LINE 76 "src/LibLzma.hsc" #-}
_ -> Nothing
data IntegrityCheck = IntegrityCheckNone
| IntegrityCheckCrc32
| IntegrityCheckCrc64
| IntegrityCheckSha256
deriving (Eq,Ord,Read,Show,Typeable)
fromIntegrityCheck :: IntegrityCheck -> Int
fromIntegrityCheck lc = case lc of
IntegrityCheckNone -> 0
{-# LINE 88 "src/LibLzma.hsc" #-}
IntegrityCheckCrc32 -> 1
{-# LINE 89 "src/LibLzma.hsc" #-}
IntegrityCheckCrc64 -> 4
{-# LINE 90 "src/LibLzma.hsc" #-}
IntegrityCheckSha256 -> 10
{-# LINE 91 "src/LibLzma.hsc" #-}
data CompressionLevel = CompressionLevel0
| CompressionLevel1
| CompressionLevel2
| CompressionLevel3
| CompressionLevel4
| CompressionLevel5
| CompressionLevel6
| CompressionLevel7
| CompressionLevel8
| CompressionLevel9
deriving (Eq,Ord,Read,Show,Enum,Typeable)
data DecompressParams = DecompressParams
{ decompressTellNoCheck :: !Bool
, decompressTellUnsupportedCheck :: !Bool
, decompressTellAnyCheck :: !Bool
, decompressConcatenated :: !Bool
, decompressAutoDecoder :: !Bool
, decompressMemLimit :: !Word64
} deriving (Eq,Show)
defaultDecompressParams :: DecompressParams
defaultDecompressParams = DecompressParams {..}
where
decompressTellNoCheck = False
decompressTellUnsupportedCheck = False
decompressTellAnyCheck = False
decompressConcatenated = True
decompressAutoDecoder = False
decompressMemLimit = maxBound
data CompressParams = CompressParams
{ compressIntegrityCheck :: !IntegrityCheck
, compressLevel :: !CompressionLevel
, compressLevelExtreme :: !Bool
} deriving (Eq,Show)
defaultCompressParams :: CompressParams
defaultCompressParams = CompressParams {..}
where
compressIntegrityCheck = IntegrityCheckCrc64
compressLevel = CompressionLevel6
compressLevelExtreme = False
newDecodeLzmaStream :: DecompressParams -> ST s (Either LzmaRet LzmaStream)
newDecodeLzmaStream (DecompressParams {..}) = unsafeIOToST $ do
fp <- mallocForeignPtrBytes ((136))
{-# LINE 165 "src/LibLzma.hsc" #-}
addForeignPtrFinalizer c_hs_lzma_done_funptr fp
rc <- withForeignPtr fp (\ptr -> c_hs_lzma_init_decoder ptr decompressAutoDecoder decompressMemLimit flags')
rc' <- maybe (fail "newDecodeLzmaStream: invalid return code") pure $ toLzmaRet rc
return $ case rc' of
LzmaRetOK -> Right (LS fp)
_ -> Left rc'
where
flags' =
(if decompressTellNoCheck then (1) else 0) .|.
{-# LINE 175 "src/LibLzma.hsc" #-}
(if decompressTellUnsupportedCheck then (2) else 0) .|.
{-# LINE 176 "src/LibLzma.hsc" #-}
(if decompressTellAnyCheck then (4) else 0) .|.
{-# LINE 177 "src/LibLzma.hsc" #-}
(if decompressConcatenated then (8) else 0)
{-# LINE 178 "src/LibLzma.hsc" #-}
newEncodeLzmaStream :: CompressParams -> ST s (Either LzmaRet LzmaStream)
newEncodeLzmaStream (CompressParams {..}) = unsafeIOToST $ do
fp <- mallocForeignPtrBytes ((136))
{-# LINE 182 "src/LibLzma.hsc" #-}
addForeignPtrFinalizer c_hs_lzma_done_funptr fp
rc <- withForeignPtr fp (\ptr -> c_hs_lzma_init_encoder ptr preset check)
rc' <- maybe (fail "newDecodeLzmaStream: invalid return code") pure $ toLzmaRet rc
return $ case rc' of
LzmaRetOK -> Right (LS fp)
_ -> Left rc'
where
preset = fromIntegral (fromEnum compressLevel) .|.
(if compressLevelExtreme then (2147483648) else 0)
{-# LINE 193 "src/LibLzma.hsc" #-}
check = fromIntegrityCheck compressIntegrityCheck
data LzmaAction = LzmaRun
| LzmaSyncFlush
| LzmaFullFlush
| LzmaFinish
deriving (Eq,Show)
runLzmaStream :: LzmaStream -> ByteString -> LzmaAction -> Int -> ST s (LzmaRet,Int,ByteString)
runLzmaStream (LS ls) ibs action0 buflen
| buflen <= 0 = return (LzmaRetOptionsError,0,BS.empty)
| otherwise = unsafeIOToST $ withForeignPtr ls $ \lsptr ->
BS.unsafeUseAsCStringLen ibs $ \(ibsptr, ibslen) -> do
(obuf,rc) <- BS.createAndTrim' buflen $ \bufptr -> do
rc' <- c_hs_lzma_run lsptr action (castPtr ibsptr) ibslen bufptr buflen
rc'' <- maybe (fail "runLzmaStream: invalid return code") pure $ toLzmaRet rc'
availOut <- ((\hsc_ptr -> peekByteOff hsc_ptr 32)) lsptr
{-# LINE 211 "src/LibLzma.hsc" #-}
unless (buflen >= availOut && availOut >= 0) $
fail "runLzmaStream: invalid avail_out"
let produced = buflen - availOut
return (0, produced, rc'')
availIn <- ((\hsc_ptr -> peekByteOff hsc_ptr 8)) lsptr
{-# LINE 218 "src/LibLzma.hsc" #-}
unless (ibslen >= availIn && availIn >= 0) $
fail "runLzmaStream: invalid avail_in"
let consumed = ibslen - availIn
return (rc, fromIntegral consumed, obuf)
where
action = case action0 of
LzmaRun -> 0
{-# LINE 227 "src/LibLzma.hsc" #-}
LzmaSyncFlush -> 1
{-# LINE 228 "src/LibLzma.hsc" #-}
LzmaFullFlush -> 2
{-# LINE 229 "src/LibLzma.hsc" #-}
LzmaFinish -> 3
{-# LINE 230 "src/LibLzma.hsc" #-}
endLzmaStream :: LzmaStream -> ST s ()
endLzmaStream (LS ls) = unsafeIOToST $ finalizeForeignPtr ls
foreign import ccall "hs_lzma_init_decoder"
c_hs_lzma_init_decoder :: Ptr LzmaStream -> Bool -> Word64 -> Word32 -> IO Int
foreign import ccall "hs_lzma_init_encoder"
c_hs_lzma_init_encoder :: Ptr LzmaStream -> Word32 -> Int -> IO Int
foreign import ccall "hs_lzma_run"
c_hs_lzma_run :: Ptr LzmaStream -> Int -> Ptr Word8 -> Int -> Ptr Word8 -> Int -> IO Int
foreign import ccall "&hs_lzma_done"
c_hs_lzma_done_funptr :: FunPtr (Ptr LzmaStream -> IO ())