Switch from zbuff to stream interface

- using the recommended buffersizes from zstd lib
- compile also an codec dll with support for legacy versions
This commit is contained in:
Tino Reichardt
2016-09-04 13:37:51 +02:00
parent b7963b68e9
commit 2512b6593c
16 changed files with 379 additions and 578 deletions
+92 -134
View File
@@ -1,50 +1,39 @@
// ZstdEncoder.cpp
// (C) 2016 Rich Geldreich, Tino Reichardt
// (C) 2016 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() * 30),
_outBufSize (ZBUFF_recommendedCOutSize() * 30),
_inSizeProcessed (0),
_outSizeProcessed (0)
_cstream(NULL),
_buffIn(NULL),
_buffOut(NULL),
_buffInSize(0),
_buffOutSize(0),
_processedIn(0),
_processedOut(0)
{
_props.clear ();
_props.clear();
}
CEncoder::~CEncoder ()
CEncoder::~CEncoder()
{
if (_state)
ZBUFF_freeCCtx(_state);
if (_cstream)
ZSTD_freeCStream(_cstream);
MyFree (_inBuf);
MyFree (_outBuf);
MyFree(_buffIn);
MyFree(_buffOut);
_buffIn = 0;
_buffOut = 0;
}
STDMETHODIMP CEncoder::SetCoderProperties (const PROPID * propIDs,
const PROPVARIANT * coderProps, UInt32 numProps)
STDMETHODIMP CEncoder::SetCoderProperties(const PROPID * propIDs, const PROPVARIANT * coderProps, UInt32 numProps)
{
_props.clear ();
_props.clear();
for (UInt32 i = 0; i < numProps; i++)
{
@@ -54,136 +43,105 @@ STDMETHODIMP CEncoder::SetCoderProperties (const PROPID * propIDs,
{
case NCoderPropID::kLevel:
{
if (prop.vt != VT_UI4)
return E_INVALIDARG;
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;
/* level 1..22 */
_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;
break;
}
default:
{
break;
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;
}
_processedIn = 0;
_processedOut = 0;
return S_OK;
}
HRESULT CEncoder::CreateCompressor ()
STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream * outStream)
{
if (!_state) {
_state = ZBUFF_createCCtx();
if (!_state)
return S_FALSE;
return WriteStream(outStream, &_props, sizeof (_props));
}
STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UInt64 * /* inSize */ ,
const UInt64 * /* outSize */ , ICompressProgressInfo *progress)
{
size_t result;
/* init only once in beginning */
if (!_cstream) {
/* allocate stream */
_cstream = ZSTD_createCStream();
if (!_cstream)
return E_OUTOFMEMORY;
/* allocate buffers */
_buffInSize = ZSTD_CStreamInSize();
_buffIn = MyAlloc(_buffInSize);
if (!_buffIn)
return E_OUTOFMEMORY;
_buffOutSize = ZSTD_CStreamOutSize();
_buffOut = MyAlloc(_buffOutSize);
if (!_buffOut)
return E_OUTOFMEMORY;
}
if (ZBUFF_compressInit(_state, _props._level))
/* init or re-init stream */
result = ZSTD_initCStream(_cstream, _props._level);
if (ZSTD_isError(result))
return S_FALSE;
return S_OK;
}
UInt32 read, toRead = static_cast < UInt32 > (_buffInSize);
for(;;) {
STDMETHODIMP CEncoder::Code (ISequentialInStream * inStream,
ISequentialOutStream * outStream, const UInt64 * /* inSize */ ,
const UInt64 * /* outSize */ , ICompressProgressInfo * progress)
{
RINOK (CreateCompressor());
RINOK (CreateBuffers());
/* read input */
RINOK(inStream->Read(_buffIn, toRead, &read));
size_t InSize = static_cast < size_t > (read);
_processedIn += InSize;
UInt64 startInProgress = _inSizeProcessed;
UInt64 startOutProgress = _outSizeProcessed;
if (InSize == 0) {
for (;;)
{
bool eofFlag = false;
if (_inPos == _inSize)
{
_inPos = _inSize = 0;
RINOK (inStream->Read (_inBuf, _inBufSizeAllocated, &_inSize));
if (!_inSize)
eofFlag = true;
/* @eof */
ZSTD_outBuffer output = { _buffOut, _buffOutSize, 0 };
result = ZSTD_endStream(_cstream, &output);
if (ZSTD_isError(result))
return S_FALSE;
if (output.pos) {
/* write last compressed bytes and update progress */
RINOK(WriteStream(outStream, _buffOut, output.pos));
_processedOut += output.pos;
RINOK(progress->SetRatioInfo(&_processedIn, &_processedOut));
}
return S_OK;
}
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));
/* compress input */
ZSTD_inBuffer input = { _buffIn, InSize, 0 };
while (input.pos < input.size) {
ZSTD_outBuffer output = { _buffOut, _buffOutSize, 0 };
result = ZSTD_compressStream(_cstream, &output , &input);
if (ZSTD_isError(result))
return S_FALSE;
/* write compressed stream and update progress */
RINOK(WriteStream(outStream, _buffOut, output.pos));
_processedOut += output.pos;
RINOK(progress->SetRatioInfo(&_processedIn, &_processedOut));
}
}
return S_OK;
}
}}