1370b324cSopenharmony_ci// Lzma2Decoder.cpp
2370b324cSopenharmony_ci
3370b324cSopenharmony_ci#include "StdAfx.h"
4370b324cSopenharmony_ci
5370b324cSopenharmony_ci// #include <stdio.h>
6370b324cSopenharmony_ci
7370b324cSopenharmony_ci#include "../../../C/Alloc.h"
8370b324cSopenharmony_ci// #include "../../../C/CpuTicks.h"
9370b324cSopenharmony_ci
10370b324cSopenharmony_ci#include "../Common/StreamUtils.h"
11370b324cSopenharmony_ci
12370b324cSopenharmony_ci#include "Lzma2Decoder.h"
13370b324cSopenharmony_ci
14370b324cSopenharmony_cinamespace NCompress {
15370b324cSopenharmony_cinamespace NLzma2 {
16370b324cSopenharmony_ci
17370b324cSopenharmony_ciCDecoder::CDecoder():
18370b324cSopenharmony_ci      _dec(NULL)
19370b324cSopenharmony_ci    , _inProcessed(0)
20370b324cSopenharmony_ci    , _prop(0xFF)
21370b324cSopenharmony_ci    , _finishMode(false)
22370b324cSopenharmony_ci    , _inBufSize(1 << 20)
23370b324cSopenharmony_ci    , _outStep(1 << 20)
24370b324cSopenharmony_ci    #ifndef Z7_ST
25370b324cSopenharmony_ci    , _tryMt(1)
26370b324cSopenharmony_ci    , _numThreads(1)
27370b324cSopenharmony_ci    , _memUsage((UInt64)(sizeof(size_t)) << 28)
28370b324cSopenharmony_ci    #endif
29370b324cSopenharmony_ci{}
30370b324cSopenharmony_ci
31370b324cSopenharmony_ciCDecoder::~CDecoder()
32370b324cSopenharmony_ci{
33370b324cSopenharmony_ci  if (_dec)
34370b324cSopenharmony_ci    Lzma2DecMt_Destroy(_dec);
35370b324cSopenharmony_ci}
36370b324cSopenharmony_ci
37370b324cSopenharmony_ciZ7_COM7F_IMF(CDecoder::SetInBufSize(UInt32 , UInt32 size)) { _inBufSize = size; return S_OK; }
38370b324cSopenharmony_ciZ7_COM7F_IMF(CDecoder::SetOutBufSize(UInt32 , UInt32 size)) { _outStep = size; return S_OK; }
39370b324cSopenharmony_ci
40370b324cSopenharmony_ciZ7_COM7F_IMF(CDecoder::SetDecoderProperties2(const Byte *prop, UInt32 size))
41370b324cSopenharmony_ci{
42370b324cSopenharmony_ci  if (size != 1)
43370b324cSopenharmony_ci    return E_NOTIMPL;
44370b324cSopenharmony_ci  if (prop[0] > 40)
45370b324cSopenharmony_ci    return E_NOTIMPL;
46370b324cSopenharmony_ci  _prop = prop[0];
47370b324cSopenharmony_ci  return S_OK;
48370b324cSopenharmony_ci}
49370b324cSopenharmony_ci
50370b324cSopenharmony_ci
51370b324cSopenharmony_ciZ7_COM7F_IMF(CDecoder::SetFinishMode(UInt32 finishMode))
52370b324cSopenharmony_ci{
53370b324cSopenharmony_ci  _finishMode = (finishMode != 0);
54370b324cSopenharmony_ci  return S_OK;
55370b324cSopenharmony_ci}
56370b324cSopenharmony_ci
57370b324cSopenharmony_ci
58370b324cSopenharmony_ci
59370b324cSopenharmony_ci#ifndef Z7_ST
60370b324cSopenharmony_ci
61370b324cSopenharmony_cistatic UInt64 Get_ExpectedBlockSize_From_Dict(UInt32 dictSize)
62370b324cSopenharmony_ci{
63370b324cSopenharmony_ci  const UInt32 kMinSize = (UInt32)1 << 20;
64370b324cSopenharmony_ci  const UInt32 kMaxSize = (UInt32)1 << 28;
65370b324cSopenharmony_ci  UInt64 blockSize = (UInt64)dictSize << 2;
66370b324cSopenharmony_ci  if (blockSize < kMinSize) blockSize = kMinSize;
67370b324cSopenharmony_ci  if (blockSize > kMaxSize) blockSize = kMaxSize;
68370b324cSopenharmony_ci  if (blockSize < dictSize) blockSize = dictSize;
69370b324cSopenharmony_ci  blockSize += (kMinSize - 1);
70370b324cSopenharmony_ci  blockSize &= ~(UInt64)(kMinSize - 1);
71370b324cSopenharmony_ci  return blockSize;
72370b324cSopenharmony_ci}
73370b324cSopenharmony_ci
74370b324cSopenharmony_ci#define LZMA2_DIC_SIZE_FROM_PROP_FULL(p) ((p) == 40 ? 0xFFFFFFFF : (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11)))
75370b324cSopenharmony_ci
76370b324cSopenharmony_ci#endif
77370b324cSopenharmony_ci
78370b324cSopenharmony_ci#define RET_IF_WRAP_ERROR_CONFIRMED(wrapRes, sRes, sResErrorCode) \
79370b324cSopenharmony_ci  if (wrapRes != S_OK && sRes == sResErrorCode) return wrapRes;
80370b324cSopenharmony_ci
81370b324cSopenharmony_ci#define RET_IF_WRAP_ERROR(wrapRes, sRes, sResErrorCode) \
82370b324cSopenharmony_ci  if (wrapRes != S_OK /* && (sRes == SZ_OK || sRes == sResErrorCode) */) return wrapRes;
83370b324cSopenharmony_ci
84370b324cSopenharmony_ciZ7_COM7F_IMF(CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
85370b324cSopenharmony_ci    const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress))
86370b324cSopenharmony_ci{
87370b324cSopenharmony_ci  _inProcessed = 0;
88370b324cSopenharmony_ci
89370b324cSopenharmony_ci  if (!_dec)
90370b324cSopenharmony_ci  {
91370b324cSopenharmony_ci    _dec = Lzma2DecMt_Create(
92370b324cSopenharmony_ci      // &g_AlignedAlloc,
93370b324cSopenharmony_ci      &g_Alloc,
94370b324cSopenharmony_ci      &g_MidAlloc);
95370b324cSopenharmony_ci    if (!_dec)
96370b324cSopenharmony_ci      return E_OUTOFMEMORY;
97370b324cSopenharmony_ci  }
98370b324cSopenharmony_ci
99370b324cSopenharmony_ci  CLzma2DecMtProps props;
100370b324cSopenharmony_ci  Lzma2DecMtProps_Init(&props);
101370b324cSopenharmony_ci
102370b324cSopenharmony_ci  props.inBufSize_ST = _inBufSize;
103370b324cSopenharmony_ci  props.outStep_ST = _outStep;
104370b324cSopenharmony_ci
105370b324cSopenharmony_ci  #ifndef Z7_ST
106370b324cSopenharmony_ci  {
107370b324cSopenharmony_ci    props.numThreads = 1;
108370b324cSopenharmony_ci    UInt32 numThreads = _numThreads;
109370b324cSopenharmony_ci
110370b324cSopenharmony_ci    if (_tryMt && numThreads >= 1)
111370b324cSopenharmony_ci    {
112370b324cSopenharmony_ci      const UInt64 useLimit = _memUsage;
113370b324cSopenharmony_ci      const UInt32 dictSize = LZMA2_DIC_SIZE_FROM_PROP_FULL(_prop);
114370b324cSopenharmony_ci      const UInt64 expectedBlockSize64 = Get_ExpectedBlockSize_From_Dict(dictSize);
115370b324cSopenharmony_ci      const size_t expectedBlockSize = (size_t)expectedBlockSize64;
116370b324cSopenharmony_ci      const size_t inBlockMax = expectedBlockSize + expectedBlockSize / 16;
117370b324cSopenharmony_ci      if (expectedBlockSize == expectedBlockSize64 && inBlockMax >= expectedBlockSize)
118370b324cSopenharmony_ci      {
119370b324cSopenharmony_ci        props.outBlockMax = expectedBlockSize;
120370b324cSopenharmony_ci        props.inBlockMax = inBlockMax;
121370b324cSopenharmony_ci        const size_t kOverheadSize = props.inBufSize_MT + (1 << 16);
122370b324cSopenharmony_ci        const UInt64 okThreads = useLimit / (props.outBlockMax + props.inBlockMax + kOverheadSize);
123370b324cSopenharmony_ci        if (numThreads > okThreads)
124370b324cSopenharmony_ci          numThreads = (UInt32)okThreads;
125370b324cSopenharmony_ci        if (numThreads == 0)
126370b324cSopenharmony_ci          numThreads = 1;
127370b324cSopenharmony_ci        props.numThreads = numThreads;
128370b324cSopenharmony_ci      }
129370b324cSopenharmony_ci    }
130370b324cSopenharmony_ci  }
131370b324cSopenharmony_ci  #endif
132370b324cSopenharmony_ci
133370b324cSopenharmony_ci  CSeqInStreamWrap inWrap;
134370b324cSopenharmony_ci  CSeqOutStreamWrap outWrap;
135370b324cSopenharmony_ci  CCompressProgressWrap progressWrap;
136370b324cSopenharmony_ci
137370b324cSopenharmony_ci  inWrap.Init(inStream);
138370b324cSopenharmony_ci  outWrap.Init(outStream);
139370b324cSopenharmony_ci  progressWrap.Init(progress);
140370b324cSopenharmony_ci
141370b324cSopenharmony_ci  SRes res;
142370b324cSopenharmony_ci
143370b324cSopenharmony_ci  UInt64 inProcessed = 0;
144370b324cSopenharmony_ci  int isMT = False;
145370b324cSopenharmony_ci
146370b324cSopenharmony_ci  #ifndef Z7_ST
147370b324cSopenharmony_ci  isMT = _tryMt;
148370b324cSopenharmony_ci  #endif
149370b324cSopenharmony_ci
150370b324cSopenharmony_ci  // UInt64 cpuTicks = GetCpuTicks();
151370b324cSopenharmony_ci
152370b324cSopenharmony_ci  res = Lzma2DecMt_Decode(_dec, _prop, &props,
153370b324cSopenharmony_ci      &outWrap.vt, outSize, _finishMode,
154370b324cSopenharmony_ci      &inWrap.vt,
155370b324cSopenharmony_ci      &inProcessed,
156370b324cSopenharmony_ci      &isMT,
157370b324cSopenharmony_ci      progress ? &progressWrap.vt : NULL);
158370b324cSopenharmony_ci
159370b324cSopenharmony_ci  /*
160370b324cSopenharmony_ci  cpuTicks = GetCpuTicks() - cpuTicks;
161370b324cSopenharmony_ci  printf("\n             ticks = %10I64u\n", cpuTicks / 1000000);
162370b324cSopenharmony_ci  */
163370b324cSopenharmony_ci
164370b324cSopenharmony_ci
165370b324cSopenharmony_ci  #ifndef Z7_ST
166370b324cSopenharmony_ci  /* we reset _tryMt, only if p->props.numThreads was changed */
167370b324cSopenharmony_ci  if (props.numThreads > 1)
168370b324cSopenharmony_ci    _tryMt = isMT;
169370b324cSopenharmony_ci  #endif
170370b324cSopenharmony_ci
171370b324cSopenharmony_ci  _inProcessed = inProcessed;
172370b324cSopenharmony_ci
173370b324cSopenharmony_ci  RET_IF_WRAP_ERROR(progressWrap.Res, res, SZ_ERROR_PROGRESS)
174370b324cSopenharmony_ci  RET_IF_WRAP_ERROR(outWrap.Res, res, SZ_ERROR_WRITE)
175370b324cSopenharmony_ci  RET_IF_WRAP_ERROR_CONFIRMED(inWrap.Res, res, SZ_ERROR_READ)
176370b324cSopenharmony_ci
177370b324cSopenharmony_ci  if (res == SZ_OK && _finishMode)
178370b324cSopenharmony_ci  {
179370b324cSopenharmony_ci    if (inSize && *inSize != inProcessed)
180370b324cSopenharmony_ci      res = SZ_ERROR_DATA;
181370b324cSopenharmony_ci    if (outSize && *outSize != outWrap.Processed)
182370b324cSopenharmony_ci      res = SZ_ERROR_DATA;
183370b324cSopenharmony_ci  }
184370b324cSopenharmony_ci
185370b324cSopenharmony_ci  return SResToHRESULT(res);
186370b324cSopenharmony_ci}
187370b324cSopenharmony_ci
188370b324cSopenharmony_ci
189370b324cSopenharmony_ciZ7_COM7F_IMF(CDecoder::GetInStreamProcessedSize(UInt64 *value))
190370b324cSopenharmony_ci{
191370b324cSopenharmony_ci  *value = _inProcessed;
192370b324cSopenharmony_ci  return S_OK;
193370b324cSopenharmony_ci}
194370b324cSopenharmony_ci
195370b324cSopenharmony_ci
196370b324cSopenharmony_ci#ifndef Z7_ST
197370b324cSopenharmony_ci
198370b324cSopenharmony_ciZ7_COM7F_IMF(CDecoder::SetNumberOfThreads(UInt32 numThreads))
199370b324cSopenharmony_ci{
200370b324cSopenharmony_ci  _numThreads = numThreads;
201370b324cSopenharmony_ci  return S_OK;
202370b324cSopenharmony_ci}
203370b324cSopenharmony_ci
204370b324cSopenharmony_ciZ7_COM7F_IMF(CDecoder::SetMemLimit(UInt64 memUsage))
205370b324cSopenharmony_ci{
206370b324cSopenharmony_ci  _memUsage = memUsage;
207370b324cSopenharmony_ci  return S_OK;
208370b324cSopenharmony_ci}
209370b324cSopenharmony_ci
210370b324cSopenharmony_ci#endif
211370b324cSopenharmony_ci
212370b324cSopenharmony_ci
213370b324cSopenharmony_ci#ifndef Z7_NO_READ_FROM_CODER
214370b324cSopenharmony_ci
215370b324cSopenharmony_ciZ7_COM7F_IMF(CDecoder::SetOutStreamSize(const UInt64 *outSize))
216370b324cSopenharmony_ci{
217370b324cSopenharmony_ci  CLzma2DecMtProps props;
218370b324cSopenharmony_ci  Lzma2DecMtProps_Init(&props);
219370b324cSopenharmony_ci  props.inBufSize_ST = _inBufSize;
220370b324cSopenharmony_ci  props.outStep_ST = _outStep;
221370b324cSopenharmony_ci
222370b324cSopenharmony_ci  _inProcessed = 0;
223370b324cSopenharmony_ci
224370b324cSopenharmony_ci  if (!_dec)
225370b324cSopenharmony_ci  {
226370b324cSopenharmony_ci    _dec = Lzma2DecMt_Create(&g_AlignedAlloc, &g_MidAlloc);
227370b324cSopenharmony_ci    if (!_dec)
228370b324cSopenharmony_ci      return E_OUTOFMEMORY;
229370b324cSopenharmony_ci  }
230370b324cSopenharmony_ci
231370b324cSopenharmony_ci  _inWrap.Init(_inStream);
232370b324cSopenharmony_ci
233370b324cSopenharmony_ci  const SRes res = Lzma2DecMt_Init(_dec, _prop, &props, outSize, _finishMode, &_inWrap.vt);
234370b324cSopenharmony_ci
235370b324cSopenharmony_ci  if (res != SZ_OK)
236370b324cSopenharmony_ci    return SResToHRESULT(res);
237370b324cSopenharmony_ci  return S_OK;
238370b324cSopenharmony_ci}
239370b324cSopenharmony_ci
240370b324cSopenharmony_ci
241370b324cSopenharmony_ciZ7_COM7F_IMF(CDecoder::SetInStream(ISequentialInStream *inStream))
242370b324cSopenharmony_ci  { _inStream = inStream; return S_OK; }
243370b324cSopenharmony_ciZ7_COM7F_IMF(CDecoder::ReleaseInStream())
244370b324cSopenharmony_ci  { _inStream.Release(); return S_OK; }
245370b324cSopenharmony_ci
246370b324cSopenharmony_ci
247370b324cSopenharmony_ciZ7_COM7F_IMF(CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize))
248370b324cSopenharmony_ci{
249370b324cSopenharmony_ci  if (processedSize)
250370b324cSopenharmony_ci    *processedSize = 0;
251370b324cSopenharmony_ci
252370b324cSopenharmony_ci  size_t size2 = size;
253370b324cSopenharmony_ci  UInt64 inProcessed = 0;
254370b324cSopenharmony_ci
255370b324cSopenharmony_ci  const SRes res = Lzma2DecMt_Read(_dec, (Byte *)data, &size2, &inProcessed);
256370b324cSopenharmony_ci
257370b324cSopenharmony_ci  _inProcessed += inProcessed;
258370b324cSopenharmony_ci  if (processedSize)
259370b324cSopenharmony_ci    *processedSize = (UInt32)size2;
260370b324cSopenharmony_ci  if (res != SZ_OK)
261370b324cSopenharmony_ci    return SResToHRESULT(res);
262370b324cSopenharmony_ci  return S_OK;
263370b324cSopenharmony_ci}
264370b324cSopenharmony_ci
265370b324cSopenharmony_ci#endif
266370b324cSopenharmony_ci
267370b324cSopenharmony_ci}}
268