mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-07 13:15:04 -06:00
- made an extra zstd.mak file - removed Format7zZStd - SFXSetup also has zstd now - the big 7z.dll is backward compatible to: 0.5 .. 0.7 - the small 7za.dll has only support for zstd 0.8
191 lines
3.8 KiB
C++
191 lines
3.8 KiB
C++
// ZstdEncoder.cpp
|
|
// (C) 2016 Rich Geldreich, Tino Reichardt
|
|
|
|
#include "StdAfx.h"
|
|
#include "ZstdEncoder.h"
|
|
|
|
// #define SHOW_DEBUG_INFO
|
|
#ifdef SHOW_DEBUG_INFO
|
|
#include <stdio.h>
|
|
#define PRF(x) x
|
|
#else
|
|
#define PRF(x)
|
|
#endif
|
|
|
|
#ifndef EXTRACT_ONLY
|
|
namespace NCompress {
|
|
namespace NZSTD {
|
|
|
|
CEncoder::CEncoder():
|
|
_state (NULL),
|
|
_inBuf (NULL),
|
|
_outBuf (NULL),
|
|
_inPos (0),
|
|
_inSize (0),
|
|
_inBufSizeAllocated (0),
|
|
_outBufSizeAllocated (0),
|
|
_inBufSize (ZBUFF_recommendedCInSize()),
|
|
_outBufSize (ZBUFF_recommendedCOutSize()),
|
|
_inSizeProcessed (0),
|
|
_outSizeProcessed (0)
|
|
{
|
|
_props.clear ();
|
|
}
|
|
|
|
CEncoder::~CEncoder ()
|
|
{
|
|
if (_state)
|
|
ZBUFF_freeCCtx(_state);
|
|
|
|
MyFree (_inBuf);
|
|
MyFree (_outBuf);
|
|
}
|
|
|
|
STDMETHODIMP CEncoder::SetCoderProperties (const PROPID * propIDs,
|
|
const PROPVARIANT * coderProps, UInt32 numProps)
|
|
{
|
|
_props.clear ();
|
|
|
|
for (UInt32 i = 0; i < numProps; i++)
|
|
{
|
|
const PROPVARIANT & prop = coderProps[i];
|
|
PROPID propID = propIDs[i];
|
|
switch (propID)
|
|
{
|
|
case NCoderPropID::kLevel:
|
|
{
|
|
if (prop.vt != VT_UI4)
|
|
return E_INVALIDARG;
|
|
|
|
_props._level = static_cast < Byte > (prop.ulVal);
|
|
Byte zstd_level = static_cast < Byte > (ZSTD_maxCLevel());
|
|
if (_props._level > zstd_level)
|
|
_props._level = zstd_level;
|
|
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CEncoder::WriteCoderProperties (ISequentialOutStream * outStream)
|
|
{
|
|
return WriteStream (outStream, &_props, sizeof (_props));
|
|
}
|
|
|
|
HRESULT CEncoder::CreateBuffers ()
|
|
{
|
|
if (_inBuf == 0 || _inBufSize != _inBufSizeAllocated)
|
|
{
|
|
MyFree (_inBuf);
|
|
_inBuf = (Byte *) MyAlloc (_inBufSize);
|
|
if (_inBuf == 0)
|
|
return E_OUTOFMEMORY;
|
|
_inBufSizeAllocated = (UInt32)_inBufSize;
|
|
}
|
|
|
|
if (_outBuf == 0 || _outBufSize != _outBufSizeAllocated)
|
|
{
|
|
MyFree (_outBuf);
|
|
_outBuf = (Byte *) MyAlloc (_outBufSize);
|
|
if (_outBuf == 0)
|
|
return E_OUTOFMEMORY;
|
|
_outBufSizeAllocated = (UInt32)_outBufSize;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CEncoder::CreateCompressor ()
|
|
{
|
|
if (!_state) {
|
|
_state = ZBUFF_createCCtx();
|
|
if (!_state)
|
|
return S_FALSE;
|
|
}
|
|
|
|
if (ZBUFF_compressInit(_state, _props._level))
|
|
return S_FALSE;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CEncoder::Code (ISequentialInStream * inStream,
|
|
ISequentialOutStream * outStream, const UInt64 * /* inSize */ ,
|
|
const UInt64 * /* outSize */ , ICompressProgressInfo * progress)
|
|
{
|
|
RINOK (CreateCompressor());
|
|
RINOK (CreateBuffers());
|
|
|
|
UInt64 startInProgress = _inSizeProcessed;
|
|
UInt64 startOutProgress = _outSizeProcessed;
|
|
|
|
for (;;)
|
|
{
|
|
bool eofFlag = false;
|
|
if (_inPos == _inSize)
|
|
{
|
|
_inPos = _inSize = 0;
|
|
RINOK (inStream->Read (_inBuf, _inBufSizeAllocated, &_inSize));
|
|
if (!_inSize)
|
|
eofFlag = true;
|
|
}
|
|
|
|
Byte *pIn_bytes = _inBuf + _inPos;
|
|
size_t num_in_bytes = _inSize - _inPos;
|
|
Byte *pOut_bytes = _outBuf;
|
|
size_t num_out_bytes = _outBufSize;
|
|
|
|
size_t comp_status;
|
|
bool comp_finished = false;
|
|
|
|
if (eofFlag)
|
|
{
|
|
comp_status = ZBUFF_compressEnd (_state, pOut_bytes, &num_out_bytes);
|
|
comp_finished = (comp_status == 0);
|
|
}
|
|
else
|
|
{
|
|
comp_status = ZBUFF_compressContinue(_state, pOut_bytes, &num_out_bytes, pIn_bytes, &num_in_bytes);
|
|
}
|
|
|
|
bool comp_failed = ZBUFF_isError (comp_status) != 0;
|
|
|
|
if (num_in_bytes)
|
|
{
|
|
_inPos += (UInt32) num_in_bytes;
|
|
_inSizeProcessed += (UInt32) num_in_bytes;
|
|
}
|
|
|
|
if (num_out_bytes)
|
|
{
|
|
_outSizeProcessed += num_out_bytes;
|
|
RINOK (WriteStream (outStream, _outBuf, num_out_bytes));
|
|
}
|
|
|
|
if (comp_failed)
|
|
return S_FALSE;
|
|
|
|
if (comp_finished)
|
|
break;
|
|
|
|
UInt64 inSize = _inSizeProcessed - startInProgress;
|
|
UInt64 outSize = _outSizeProcessed - startOutProgress;
|
|
if (progress)
|
|
{
|
|
RINOK (progress->SetRatioInfo (&inSize, &outSize));
|
|
}
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
}}
|
|
#endif
|