Files
easy7zip/CPP/7zip/Compress/Lz5Decoder.cpp
Tino Reichardt f98edef556 Add zstd fast levels and update 7z property sizes
- add the "fast compression levels" of zstd via "fast" option (fast=1..64)
- change the 7-Zip property sizes of LZ4, LZ5 and Zstandard to 3
- 3 and 5 byte header are valid now (default is 3)
- update the Methods-Extern.md file, to reflect the property changes
2018-11-25 21:21:04 +01:00

193 lines
3.9 KiB
C++

// (C) 2016 Tino Reichardt
#include "StdAfx.h"
#include "Lz5Decoder.h"
int Lz5Read(void *arg, LZ5MT_Buffer * in)
{
struct Lz5Stream *x = (struct Lz5Stream*)arg;
size_t size = in->size;
HRESULT res = ReadStream(x->inStream, in->buf, &size);
/* catch errors */
switch (res) {
case E_ABORT:
return -2;
case E_OUTOFMEMORY:
return -3;
}
/* some other error -> read_fail */
if (res != S_OK)
return -1;
in->size = size;
*x->processedIn += size;
return 0;
}
int Lz5Write(void *arg, LZ5MT_Buffer * out)
{
struct Lz5Stream *x = (struct Lz5Stream*)arg;
UInt32 todo = (UInt32)out->size;
UInt32 done = 0;
while (todo != 0)
{
UInt32 block;
HRESULT res = x->outStream->Write((char*)out->buf + done, todo, &block);
/* catch errors */
switch (res) {
case E_ABORT:
return -2;
case E_OUTOFMEMORY:
return -3;
}
done += block;
if (res == k_My_HRESULT_WritingWasCut)
break;
/* some other error -> write_fail */
if (res != S_OK)
return -1;
if (block == 0)
return -1;
todo -= block;
}
*x->processedOut += done;
/* we need no lock here, cause only one thread can write... */
if (x->progress)
x->progress->SetRatioInfo(x->processedIn, x->processedOut);
return 0;
}
namespace NCompress {
namespace NLZ5 {
CDecoder::CDecoder():
_processedIn(0),
_processedOut(0),
_inputSize(0),
_numThreads(NWindows::NSystem::GetNumberOfProcessors())
{
_props.clear();
}
CDecoder::~CDecoder()
{
}
STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte * prop, UInt32 size)
{
DProps *pProps = (DProps *)prop;
switch (size) {
case 3:
memcpy(&_props, pProps, 3);
return S_OK;
case 5:
memcpy(&_props, pProps, 5);
return S_OK;
default:
return E_NOTIMPL;
}
}
STDMETHODIMP CDecoder::SetNumberOfThreads(UInt32 numThreads)
{
const UInt32 kNumThreadsMax = LZ5MT_THREAD_MAX;
if (numThreads < 1) numThreads = 1;
if (numThreads > kNumThreadsMax) numThreads = kNumThreadsMax;
_numThreads = numThreads;
return S_OK;
}
HRESULT CDecoder::SetOutStreamSizeResume(const UInt64 * /*outSize*/)
{
_processedOut = 0;
return S_OK;
}
STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 * outSize)
{
_processedIn = 0;
RINOK(SetOutStreamSizeResume(outSize));
return S_OK;
}
HRESULT CDecoder::CodeSpec(ISequentialInStream * inStream,
ISequentialOutStream * outStream, ICompressProgressInfo * progress)
{
LZ5MT_RdWr_t rdwr;
size_t result;
HRESULT res = S_OK;
struct Lz5Stream Rd;
Rd.inStream = inStream;
Rd.processedIn = &_processedIn;
struct Lz5Stream Wr;
Wr.progress = progress;
Wr.outStream = outStream;
Wr.processedIn = &_processedIn;
Wr.processedOut = &_processedOut;
/* 1) setup read/write functions */
rdwr.fn_read = ::Lz5Read;
rdwr.fn_write = ::Lz5Write;
rdwr.arg_read = (void *)&Rd;
rdwr.arg_write = (void *)&Wr;
/* 2) create decompression context */
LZ5MT_DCtx *ctx = LZ5MT_createDCtx(_numThreads, _inputSize);
if (!ctx)
return S_FALSE;
/* 3) decompress */
result = LZ5MT_decompressDCtx(ctx, &rdwr);
if (LZ5MT_isError(result)) {
if (result == (size_t)-LZ5MT_error_canceled)
return E_ABORT;
return E_FAIL;
}
/* 4) free resources */
LZ5MT_freeDCtx(ctx);
return res;
}
STDMETHODIMP CDecoder::Code(ISequentialInStream * inStream, ISequentialOutStream * outStream,
const UInt64 * /*inSize */, const UInt64 *outSize, ICompressProgressInfo * progress)
{
SetOutStreamSize(outSize);
return CodeSpec(inStream, outStream, progress);
}
#ifndef NO_READ_FROM_CODER
STDMETHODIMP CDecoder::SetInStream(ISequentialInStream * inStream)
{
_inStream = inStream;
return S_OK;
}
STDMETHODIMP CDecoder::ReleaseInStream()
{
_inStream.Release();
return S_OK;
}
#endif
HRESULT CDecoder::CodeResume(ISequentialOutStream * outStream, const UInt64 * outSize, ICompressProgressInfo * progress)
{
RINOK(SetOutStreamSizeResume(outSize));
return CodeSpec(_inStream, outStream, progress);
}
}}