1370b324cSopenharmony_ci// PpmdDecoder.cpp
2370b324cSopenharmony_ci
3370b324cSopenharmony_ci#include "StdAfx.h"
4370b324cSopenharmony_ci
5370b324cSopenharmony_ci#include "../../../C/Alloc.h"
6370b324cSopenharmony_ci#include "../../../C/CpuArch.h"
7370b324cSopenharmony_ci
8370b324cSopenharmony_ci#include "../Common/StreamUtils.h"
9370b324cSopenharmony_ci
10370b324cSopenharmony_ci#include "PpmdDecoder.h"
11370b324cSopenharmony_ci
12370b324cSopenharmony_cinamespace NCompress {
13370b324cSopenharmony_cinamespace NPpmd {
14370b324cSopenharmony_ci
15370b324cSopenharmony_cistatic const UInt32 kBufSize = (1 << 16);
16370b324cSopenharmony_ci
17370b324cSopenharmony_cienum
18370b324cSopenharmony_ci{
19370b324cSopenharmony_ci  kStatus_NeedInit,
20370b324cSopenharmony_ci  kStatus_Normal,
21370b324cSopenharmony_ci  kStatus_Finished_With_Mark,
22370b324cSopenharmony_ci  kStatus_Error
23370b324cSopenharmony_ci};
24370b324cSopenharmony_ci
25370b324cSopenharmony_ciCDecoder::~CDecoder()
26370b324cSopenharmony_ci{
27370b324cSopenharmony_ci  ::MidFree(_outBuf);
28370b324cSopenharmony_ci  Ppmd7_Free(&_ppmd, &g_BigAlloc);
29370b324cSopenharmony_ci}
30370b324cSopenharmony_ci
31370b324cSopenharmony_ciZ7_COM7F_IMF(CDecoder::SetDecoderProperties2(const Byte *props, UInt32 size))
32370b324cSopenharmony_ci{
33370b324cSopenharmony_ci  if (size < 5)
34370b324cSopenharmony_ci    return E_INVALIDARG;
35370b324cSopenharmony_ci  _order = props[0];
36370b324cSopenharmony_ci  const UInt32 memSize = GetUi32(props + 1);
37370b324cSopenharmony_ci  if (_order < PPMD7_MIN_ORDER ||
38370b324cSopenharmony_ci      _order > PPMD7_MAX_ORDER ||
39370b324cSopenharmony_ci      memSize < PPMD7_MIN_MEM_SIZE ||
40370b324cSopenharmony_ci      memSize > PPMD7_MAX_MEM_SIZE)
41370b324cSopenharmony_ci    return E_NOTIMPL;
42370b324cSopenharmony_ci  if (!_inStream.Alloc(1 << 20))
43370b324cSopenharmony_ci    return E_OUTOFMEMORY;
44370b324cSopenharmony_ci  if (!Ppmd7_Alloc(&_ppmd, memSize, &g_BigAlloc))
45370b324cSopenharmony_ci    return E_OUTOFMEMORY;
46370b324cSopenharmony_ci  return S_OK;
47370b324cSopenharmony_ci}
48370b324cSopenharmony_ci
49370b324cSopenharmony_ci#define MY_rangeDec  _ppmd.rc.dec
50370b324cSopenharmony_ci
51370b324cSopenharmony_ci#define CHECK_EXTRA_ERROR \
52370b324cSopenharmony_ci    if (_inStream.Extra) { \
53370b324cSopenharmony_ci      _status = kStatus_Error; \
54370b324cSopenharmony_ci      return (_res = (_inStream.Res != SZ_OK ? _inStream.Res: S_FALSE)); }
55370b324cSopenharmony_ci
56370b324cSopenharmony_ci
57370b324cSopenharmony_ciHRESULT CDecoder::CodeSpec(Byte *memStream, UInt32 size)
58370b324cSopenharmony_ci{
59370b324cSopenharmony_ci  if (_res != S_OK)
60370b324cSopenharmony_ci    return _res;
61370b324cSopenharmony_ci
62370b324cSopenharmony_ci  switch (_status)
63370b324cSopenharmony_ci  {
64370b324cSopenharmony_ci    case kStatus_Finished_With_Mark: return S_OK;
65370b324cSopenharmony_ci    case kStatus_Error: return S_FALSE;
66370b324cSopenharmony_ci    case kStatus_NeedInit:
67370b324cSopenharmony_ci      _inStream.Init();
68370b324cSopenharmony_ci      if (!Ppmd7z_RangeDec_Init(&MY_rangeDec))
69370b324cSopenharmony_ci      {
70370b324cSopenharmony_ci        _status = kStatus_Error;
71370b324cSopenharmony_ci        return (_res = S_FALSE);
72370b324cSopenharmony_ci      }
73370b324cSopenharmony_ci      CHECK_EXTRA_ERROR
74370b324cSopenharmony_ci      _status = kStatus_Normal;
75370b324cSopenharmony_ci      Ppmd7_Init(&_ppmd, _order);
76370b324cSopenharmony_ci      break;
77370b324cSopenharmony_ci  }
78370b324cSopenharmony_ci
79370b324cSopenharmony_ci  if (_outSizeDefined)
80370b324cSopenharmony_ci  {
81370b324cSopenharmony_ci    const UInt64 rem = _outSize - _processedSize;
82370b324cSopenharmony_ci    if (size > rem)
83370b324cSopenharmony_ci      size = (UInt32)rem;
84370b324cSopenharmony_ci  }
85370b324cSopenharmony_ci
86370b324cSopenharmony_ci  int sym = 0;
87370b324cSopenharmony_ci  {
88370b324cSopenharmony_ci    Byte *buf = memStream;
89370b324cSopenharmony_ci    const Byte *lim = buf + size;
90370b324cSopenharmony_ci    for (; buf != lim; buf++)
91370b324cSopenharmony_ci    {
92370b324cSopenharmony_ci      sym = Ppmd7z_DecodeSymbol(&_ppmd);
93370b324cSopenharmony_ci      if (_inStream.Extra || sym < 0)
94370b324cSopenharmony_ci        break;
95370b324cSopenharmony_ci      *buf = (Byte)sym;
96370b324cSopenharmony_ci    }
97370b324cSopenharmony_ci    /*
98370b324cSopenharmony_ci    buf = Ppmd7z_DecodeSymbols(&_ppmd, buf, lim);
99370b324cSopenharmony_ci    sym = _ppmd.LastSymbol;
100370b324cSopenharmony_ci    */
101370b324cSopenharmony_ci    _processedSize += (size_t)(buf - memStream);
102370b324cSopenharmony_ci  }
103370b324cSopenharmony_ci
104370b324cSopenharmony_ci  CHECK_EXTRA_ERROR
105370b324cSopenharmony_ci
106370b324cSopenharmony_ci  if (sym >= 0)
107370b324cSopenharmony_ci  {
108370b324cSopenharmony_ci    if (!FinishStream
109370b324cSopenharmony_ci        || !_outSizeDefined
110370b324cSopenharmony_ci        || _outSize != _processedSize
111370b324cSopenharmony_ci        || MY_rangeDec.Code == 0)
112370b324cSopenharmony_ci      return S_OK;
113370b324cSopenharmony_ci    /*
114370b324cSopenharmony_ci    // We can decode additional End Marker here:
115370b324cSopenharmony_ci    sym = Ppmd7z_DecodeSymbol(&_ppmd);
116370b324cSopenharmony_ci    CHECK_EXTRA_ERROR
117370b324cSopenharmony_ci    */
118370b324cSopenharmony_ci  }
119370b324cSopenharmony_ci
120370b324cSopenharmony_ci  if (sym != PPMD7_SYM_END || MY_rangeDec.Code != 0)
121370b324cSopenharmony_ci  {
122370b324cSopenharmony_ci    _status = kStatus_Error;
123370b324cSopenharmony_ci    return (_res = S_FALSE);
124370b324cSopenharmony_ci  }
125370b324cSopenharmony_ci
126370b324cSopenharmony_ci  _status = kStatus_Finished_With_Mark;
127370b324cSopenharmony_ci  return S_OK;
128370b324cSopenharmony_ci}
129370b324cSopenharmony_ci
130370b324cSopenharmony_ci
131370b324cSopenharmony_ci
132370b324cSopenharmony_ciZ7_COM7F_IMF(CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
133370b324cSopenharmony_ci    const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress))
134370b324cSopenharmony_ci{
135370b324cSopenharmony_ci  if (!_outBuf)
136370b324cSopenharmony_ci  {
137370b324cSopenharmony_ci    _outBuf = (Byte *)::MidAlloc(kBufSize);
138370b324cSopenharmony_ci    if (!_outBuf)
139370b324cSopenharmony_ci      return E_OUTOFMEMORY;
140370b324cSopenharmony_ci  }
141370b324cSopenharmony_ci
142370b324cSopenharmony_ci  _inStream.Stream = inStream;
143370b324cSopenharmony_ci  SetOutStreamSize(outSize);
144370b324cSopenharmony_ci
145370b324cSopenharmony_ci  do
146370b324cSopenharmony_ci  {
147370b324cSopenharmony_ci    const UInt64 startPos = _processedSize;
148370b324cSopenharmony_ci    const HRESULT res = CodeSpec(_outBuf, kBufSize);
149370b324cSopenharmony_ci    const size_t processed = (size_t)(_processedSize - startPos);
150370b324cSopenharmony_ci    RINOK(WriteStream(outStream, _outBuf, processed))
151370b324cSopenharmony_ci    RINOK(res)
152370b324cSopenharmony_ci    if (_status == kStatus_Finished_With_Mark)
153370b324cSopenharmony_ci      break;
154370b324cSopenharmony_ci    if (progress)
155370b324cSopenharmony_ci    {
156370b324cSopenharmony_ci      const UInt64 inProcessed = _inStream.GetProcessed();
157370b324cSopenharmony_ci      RINOK(progress->SetRatioInfo(&inProcessed, &_processedSize))
158370b324cSopenharmony_ci    }
159370b324cSopenharmony_ci  }
160370b324cSopenharmony_ci  while (!_outSizeDefined || _processedSize < _outSize);
161370b324cSopenharmony_ci
162370b324cSopenharmony_ci  if (FinishStream && inSize && *inSize != _inStream.GetProcessed())
163370b324cSopenharmony_ci    return S_FALSE;
164370b324cSopenharmony_ci
165370b324cSopenharmony_ci  return S_OK;
166370b324cSopenharmony_ci}
167370b324cSopenharmony_ci
168370b324cSopenharmony_ci
169370b324cSopenharmony_ciZ7_COM7F_IMF(CDecoder::SetOutStreamSize(const UInt64 *outSize))
170370b324cSopenharmony_ci{
171370b324cSopenharmony_ci  _outSizeDefined = (outSize != NULL);
172370b324cSopenharmony_ci  if (_outSizeDefined)
173370b324cSopenharmony_ci    _outSize = *outSize;
174370b324cSopenharmony_ci  _processedSize = 0;
175370b324cSopenharmony_ci  _status = kStatus_NeedInit;
176370b324cSopenharmony_ci  _res = SZ_OK;
177370b324cSopenharmony_ci  return S_OK;
178370b324cSopenharmony_ci}
179370b324cSopenharmony_ci
180370b324cSopenharmony_ciZ7_COM7F_IMF(CDecoder::SetFinishMode(UInt32 finishMode))
181370b324cSopenharmony_ci{
182370b324cSopenharmony_ci  FinishStream = (finishMode != 0);
183370b324cSopenharmony_ci  return S_OK;
184370b324cSopenharmony_ci}
185370b324cSopenharmony_ci
186370b324cSopenharmony_ciZ7_COM7F_IMF(CDecoder::GetInStreamProcessedSize(UInt64 *value))
187370b324cSopenharmony_ci{
188370b324cSopenharmony_ci  *value = _inStream.GetProcessed();
189370b324cSopenharmony_ci  return S_OK;
190370b324cSopenharmony_ci}
191370b324cSopenharmony_ci
192370b324cSopenharmony_ci#ifndef Z7_NO_READ_FROM_CODER
193370b324cSopenharmony_ci
194370b324cSopenharmony_ciZ7_COM7F_IMF(CDecoder::SetInStream(ISequentialInStream *inStream))
195370b324cSopenharmony_ci{
196370b324cSopenharmony_ci  InSeqStream = inStream;
197370b324cSopenharmony_ci  _inStream.Stream = inStream;
198370b324cSopenharmony_ci  return S_OK;
199370b324cSopenharmony_ci}
200370b324cSopenharmony_ci
201370b324cSopenharmony_ciZ7_COM7F_IMF(CDecoder::ReleaseInStream())
202370b324cSopenharmony_ci{
203370b324cSopenharmony_ci  InSeqStream.Release();
204370b324cSopenharmony_ci  return S_OK;
205370b324cSopenharmony_ci}
206370b324cSopenharmony_ci
207370b324cSopenharmony_ciZ7_COM7F_IMF(CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize))
208370b324cSopenharmony_ci{
209370b324cSopenharmony_ci  const UInt64 startPos = _processedSize;
210370b324cSopenharmony_ci  const HRESULT res = CodeSpec((Byte *)data, size);
211370b324cSopenharmony_ci  if (processedSize)
212370b324cSopenharmony_ci    *processedSize = (UInt32)(_processedSize - startPos);
213370b324cSopenharmony_ci  return res;
214370b324cSopenharmony_ci}
215370b324cSopenharmony_ci
216370b324cSopenharmony_ci#endif
217370b324cSopenharmony_ci
218370b324cSopenharmony_ci}}
219