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