static SRes SzDecodePpmd(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream, Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain) { CPpmd7 ppmd; CByteInToLook s; SRes res = SZ_OK; s.p.Read = ReadByte; s.inStream = inStream; s.begin = s.end = s.cur = NULL; s.extra = False; s.res = SZ_OK; s.processed = 0; if (coder->Props.size != 5) return SZ_ERROR_UNSUPPORTED; { unsigned order = coder->Props.data[0]; UInt32 memSize = GetUi32(coder->Props.data + 1); if (order < PPMD7_MIN_ORDER || order > PPMD7_MAX_ORDER || memSize < PPMD7_MIN_MEM_SIZE || memSize > PPMD7_MAX_MEM_SIZE) return SZ_ERROR_UNSUPPORTED; Ppmd7_Construct(&ppmd); if (!Ppmd7_Alloc(&ppmd, memSize, allocMain)) return SZ_ERROR_MEM; Ppmd7_Init(&ppmd, order); } { CPpmd7z_RangeDec rc; Ppmd7z_RangeDec_CreateVTable(&rc); rc.Stream = &s.p; if (!Ppmd7z_RangeDec_Init(&rc)) res = SZ_ERROR_DATA; else if (s.extra) res = (s.res != SZ_OK ? s.res : SZ_ERROR_DATA); else { SizeT i; for (i = 0; i < outSize; i++) { int sym = Ppmd7_DecodeSymbol(&ppmd, &rc.p); if (s.extra || sym < 0) break; outBuffer[i] = (Byte)sym; } if (i != outSize) res = (s.res != SZ_OK ? s.res : SZ_ERROR_DATA); else if (s.processed + (s.cur - s.begin) != inSize || !Ppmd7z_RangeDec_IsFinishedOK(&rc)) res = SZ_ERROR_DATA; } } Ppmd7_Free(&ppmd, allocMain); return res; }
STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *props, UInt32 size) { if (size < 5) return E_INVALIDARG; _order = props[0]; UInt32 memSize = GetUi32(props + 1); if (_order < PPMD7_MIN_ORDER || _order > PPMD7_MAX_ORDER || memSize < PPMD7_MIN_MEM_SIZE || memSize > PPMD7_MAX_MEM_SIZE) return E_NOTIMPL; if (!_inStream.Alloc(1 << 20)) return E_OUTOFMEMORY; if (!Ppmd7_Alloc(&_ppmd, memSize, &g_BigAlloc)) return E_OUTOFMEMORY; return S_OK; }
HRESULT CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress) { if (!_inBuf) { _inBuf = (Byte *)::MidAlloc(kBufSize); if (!_inBuf) return E_OUTOFMEMORY; } if (!_outStream.Alloc(1 << 20)) return E_OUTOFMEMORY; if (!Ppmd7_Alloc(&_ppmd, _props.MemSize, &g_BigAlloc)) return E_OUTOFMEMORY; _outStream.Stream = outStream; _outStream.Init(); Ppmd7z_RangeEnc_Init(&_rangeEnc); Ppmd7_Init(&_ppmd, _props.Order); UInt64 processed = 0; for (;;) { UInt32 size; RINOK(inStream->Read(_inBuf, kBufSize, &size)); if (size == 0) { // We don't write EndMark in PPMD-7z. // Ppmd7_EncodeSymbol(&_ppmd, &_rangeEnc, -1); Ppmd7z_RangeEnc_FlushData(&_rangeEnc); return _outStream.Flush(); } for (UInt32 i = 0; i < size; i++) { Ppmd7_EncodeSymbol(&_ppmd, &_rangeEnc, _inBuf[i]); RINOK(_outStream.Res); } processed += size; if (progress) { UInt64 outSize = _outStream.GetProcessed(); RINOK(progress->SetRatioInfo(&processed, &outSize)); } } }