summaryrefslogtreecommitdiff
path: root/other-licenses/7zstub/src/CPP/7zip/Compress/Lzma2Decoder.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'other-licenses/7zstub/src/CPP/7zip/Compress/Lzma2Decoder.cpp')
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Compress/Lzma2Decoder.cpp265
1 files changed, 265 insertions, 0 deletions
diff --git a/other-licenses/7zstub/src/CPP/7zip/Compress/Lzma2Decoder.cpp b/other-licenses/7zstub/src/CPP/7zip/Compress/Lzma2Decoder.cpp
new file mode 100644
index 0000000000..bb631c5c59
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Compress/Lzma2Decoder.cpp
@@ -0,0 +1,265 @@
+// Lzma2Decoder.cpp
+
+#include "StdAfx.h"
+
+// #include <stdio.h>
+
+#include "../../../C/Alloc.h"
+// #include "../../../C/CpuTicks.h"
+
+#include "../Common/StreamUtils.h"
+
+#include "Lzma2Decoder.h"
+
+namespace NCompress {
+namespace NLzma2 {
+
+CDecoder::CDecoder():
+ _dec(NULL)
+ , _inProcessed(0)
+ , _prop(0xFF)
+ , _finishMode(false)
+ , _inBufSize(1 << 20)
+ , _outStep(1 << 20)
+ #ifndef _7ZIP_ST
+ , _tryMt(1)
+ , _numThreads(1)
+ , _memUsage((UInt64)(sizeof(size_t)) << 28)
+ #endif
+{}
+
+CDecoder::~CDecoder()
+{
+ if (_dec)
+ Lzma2DecMt_Destroy(_dec);
+}
+
+STDMETHODIMP CDecoder::SetInBufSize(UInt32 , UInt32 size) { _inBufSize = size; return S_OK; }
+STDMETHODIMP CDecoder::SetOutBufSize(UInt32 , UInt32 size) { _outStep = size; return S_OK; }
+
+STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *prop, UInt32 size)
+{
+ if (size != 1)
+ return E_NOTIMPL;
+ if (prop[0] > 40)
+ return E_NOTIMPL;
+ _prop = prop[0];
+ return S_OK;
+}
+
+
+STDMETHODIMP CDecoder::SetFinishMode(UInt32 finishMode)
+{
+ _finishMode = (finishMode != 0);
+ return S_OK;
+}
+
+
+
+#ifndef _7ZIP_ST
+
+static UInt64 Get_ExpectedBlockSize_From_Dict(UInt32 dictSize)
+{
+ const UInt32 kMinSize = (UInt32)1 << 20;
+ const UInt32 kMaxSize = (UInt32)1 << 28;
+ UInt64 blockSize = (UInt64)dictSize << 2;
+ if (blockSize < kMinSize) blockSize = kMinSize;
+ if (blockSize > kMaxSize) blockSize = kMaxSize;
+ if (blockSize < dictSize) blockSize = dictSize;
+ blockSize += (kMinSize - 1);
+ blockSize &= ~(UInt64)(kMinSize - 1);
+ return blockSize;
+}
+
+#define LZMA2_DIC_SIZE_FROM_PROP_FULL(p) ((p) == 40 ? 0xFFFFFFFF : (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11)))
+
+#endif
+
+#define RET_IF_WRAP_ERROR_CONFIRMED(wrapRes, sRes, sResErrorCode) \
+ if (wrapRes != S_OK && sRes == sResErrorCode) return wrapRes;
+
+#define RET_IF_WRAP_ERROR(wrapRes, sRes, sResErrorCode) \
+ if (wrapRes != S_OK /* && (sRes == SZ_OK || sRes == sResErrorCode) */) return wrapRes;
+
+STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
+ const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)
+{
+ _inProcessed = 0;
+
+ if (!_dec)
+ {
+ _dec = Lzma2DecMt_Create(
+ // &g_AlignedAlloc,
+ &g_Alloc,
+ &g_MidAlloc);
+ if (!_dec)
+ return E_OUTOFMEMORY;
+ }
+
+ CLzma2DecMtProps props;
+ Lzma2DecMtProps_Init(&props);
+
+ props.inBufSize_ST = _inBufSize;
+ props.outStep_ST = _outStep;
+
+ #ifndef _7ZIP_ST
+ {
+ props.numThreads = 1;
+ UInt32 numThreads = _numThreads;
+
+ if (_tryMt && numThreads >= 1)
+ {
+ UInt64 useLimit = _memUsage;
+ UInt32 dictSize = LZMA2_DIC_SIZE_FROM_PROP_FULL(_prop);
+ UInt64 expectedBlockSize64 = Get_ExpectedBlockSize_From_Dict(dictSize);
+ size_t expectedBlockSize = (size_t)expectedBlockSize64;
+ size_t inBlockMax = expectedBlockSize + expectedBlockSize / 16;
+ if (expectedBlockSize == expectedBlockSize64 && inBlockMax >= expectedBlockSize)
+ {
+ props.outBlockMax = expectedBlockSize;
+ props.inBlockMax = inBlockMax;
+ const size_t kOverheadSize = props.inBufSize_MT + (1 << 16);
+ UInt64 okThreads = useLimit / (props.outBlockMax + props.inBlockMax + kOverheadSize);
+ if (numThreads > okThreads)
+ numThreads = (UInt32)okThreads;
+ if (numThreads == 0)
+ numThreads = 1;
+ props.numThreads = numThreads;
+ }
+ }
+ }
+ #endif
+
+ CSeqInStreamWrap inWrap;
+ CSeqOutStreamWrap outWrap;
+ CCompressProgressWrap progressWrap;
+
+ inWrap.Init(inStream);
+ outWrap.Init(outStream);
+ progressWrap.Init(progress);
+
+ SRes res;
+
+ UInt64 inProcessed = 0;
+ int isMT = False;
+
+ #ifndef _7ZIP_ST
+ isMT = _tryMt;
+ #endif
+
+ // UInt64 cpuTicks = GetCpuTicks();
+
+ res = Lzma2DecMt_Decode(_dec, _prop, &props,
+ &outWrap.vt, outSize, _finishMode,
+ &inWrap.vt,
+ &inProcessed,
+ &isMT,
+ progress ? &progressWrap.vt : NULL);
+
+ /*
+ cpuTicks = GetCpuTicks() - cpuTicks;
+ printf("\n ticks = %10I64u\n", cpuTicks / 1000000);
+ */
+
+
+ #ifndef _7ZIP_ST
+ /* we reset _tryMt, only if p->props.numThreads was changed */
+ if (props.numThreads > 1)
+ _tryMt = isMT;
+ #endif
+
+ _inProcessed = inProcessed;
+
+ RET_IF_WRAP_ERROR(progressWrap.Res, res, SZ_ERROR_PROGRESS)
+ RET_IF_WRAP_ERROR(outWrap.Res, res, SZ_ERROR_WRITE)
+ RET_IF_WRAP_ERROR_CONFIRMED(inWrap.Res, res, SZ_ERROR_READ)
+
+ if (res == SZ_OK && _finishMode)
+ {
+ if (inSize && *inSize != inProcessed)
+ res = SZ_ERROR_DATA;
+ if (outSize && *outSize != outWrap.Processed)
+ res = SZ_ERROR_DATA;
+ }
+
+ return SResToHRESULT(res);
+}
+
+
+STDMETHODIMP CDecoder::GetInStreamProcessedSize(UInt64 *value)
+{
+ *value = _inProcessed;
+ return S_OK;
+}
+
+
+#ifndef _7ZIP_ST
+
+STDMETHODIMP CDecoder::SetNumberOfThreads(UInt32 numThreads)
+{
+ _numThreads = numThreads;
+ return S_OK;
+}
+
+STDMETHODIMP CDecoder::SetMemLimit(UInt64 memUsage)
+{
+ _memUsage = memUsage;
+ return S_OK;
+}
+
+#endif
+
+
+#ifndef NO_READ_FROM_CODER
+
+STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize)
+{
+ CLzma2DecMtProps props;
+ Lzma2DecMtProps_Init(&props);
+ props.inBufSize_ST = _inBufSize;
+ props.outStep_ST = _outStep;
+
+ _inProcessed = 0;
+
+ if (!_dec)
+ {
+ _dec = Lzma2DecMt_Create(&g_AlignedAlloc, &g_MidAlloc);
+ if (!_dec)
+ return E_OUTOFMEMORY;
+ }
+
+ _inWrap.Init(_inStream);
+
+ SRes res = Lzma2DecMt_Init(_dec, _prop, &props, outSize, _finishMode, &_inWrap.vt);
+
+ if (res != SZ_OK)
+ return SResToHRESULT(res);
+ return S_OK;
+}
+
+
+STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream) { _inStream = inStream; return S_OK; }
+STDMETHODIMP CDecoder::ReleaseInStream() { _inStream.Release(); return S_OK; }
+
+
+STDMETHODIMP CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+ if (processedSize)
+ *processedSize = 0;
+
+ size_t size2 = size;
+ UInt64 inProcessed = 0;
+
+ SRes res = Lzma2DecMt_Read(_dec, (Byte *)data, &size2, &inProcessed);
+
+ _inProcessed += inProcessed;
+ if (processedSize)
+ *processedSize = (UInt32)size2;
+ if (res != SZ_OK)
+ return SResToHRESULT(res);
+ return S_OK;
+}
+
+#endif
+
+}}