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)); } } }
HRESULT CDecoder::CodeSpec(Byte *memStream, UInt32 size) { switch(_status) { case kStatus_Finished: return S_OK; case kStatus_Error: return S_FALSE; case kStatus_NeedInit: _inStream.Init(); if (!Ppmd7z_RangeDec_Init(&_rangeDec)) { _status = kStatus_Error; return S_FALSE; } _status = kStatus_Normal; Ppmd7_Init(&_ppmd, _order); break; } if (_outSizeDefined) { const UInt64 rem = _outSize - _processedSize; if (size > rem) size = (UInt32)rem; } UInt32 i; int sym = 0; for (i = 0; i != size; i++) { sym = Ppmd7_DecodeSymbol(&_ppmd, &_rangeDec.p); if (_inStream.Extra || sym < 0) break; memStream[i] = (Byte)sym; } _processedSize += i; if (_inStream.Extra) { _status = kStatus_Error; return _inStream.Res; } if (sym < 0) _status = (sym < -1) ? kStatus_Error : kStatus_Finished; return S_OK; }