1cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky// PpmdDecoder.cpp 2cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky// 2009-03-11 : Igor Pavlov : Public domain 3cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky 4cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky#include "StdAfx.h" 5cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky 6cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky#include "../../../C/Alloc.h" 7cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky#include "../../../C/CpuArch.h" 8cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky 9cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky#include "../Common/StreamUtils.h" 10cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky 11cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky#include "PpmdDecoder.h" 12cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky 13cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbeckynamespace NCompress { 14cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbeckynamespace NPpmd { 15cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky 16cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbeckystatic const UInt32 kBufSize = (1 << 20); 17cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky 18cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbeckyenum 19cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky{ 20cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky kStatus_NeedInit, 21cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky kStatus_Normal, 22cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky kStatus_Finished, 23cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky kStatus_Error 24cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky}; 25cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky 26cd66d540cead3f8200b0c73bad9c276d67896c3dDavid SrbeckyCDecoder::~CDecoder() 27cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky{ 28cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky ::MidFree(_outBuf); 29cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky Ppmd7_Free(&_ppmd, &g_BigAlloc); 30cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky} 31cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky 32cd66d540cead3f8200b0c73bad9c276d67896c3dDavid SrbeckySTDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *props, UInt32 size) 33cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky{ 34cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky if (size < 5) 35cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky return E_INVALIDARG; 36cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky _order = props[0]; 37cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky UInt32 memSize = GetUi32(props + 1); 38cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky if (_order < PPMD7_MIN_ORDER || 39cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky _order > PPMD7_MAX_ORDER || 40cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky memSize < PPMD7_MIN_MEM_SIZE || 41cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky memSize > PPMD7_MAX_MEM_SIZE) 42cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky return E_NOTIMPL; 43cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky if (!_inStream.Alloc(1 << 20)) 44cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky return E_OUTOFMEMORY; 45cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky if (!Ppmd7_Alloc(&_ppmd, memSize, &g_BigAlloc)) 46cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky return E_OUTOFMEMORY; 47cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky return S_OK; 48cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky} 49cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky 50cd66d540cead3f8200b0c73bad9c276d67896c3dDavid SrbeckyHRESULT CDecoder::CodeSpec(Byte *memStream, UInt32 size) 51cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky{ 52f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka switch (_status) 53cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky { 54cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky case kStatus_Finished: return S_OK; 55cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky case kStatus_Error: return S_FALSE; 56cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky case kStatus_NeedInit: 57cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky _inStream.Init(); 58cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky if (!Ppmd7z_RangeDec_Init(&_rangeDec)) 59cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky { 60cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky _status = kStatus_Error; 61cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky return S_FALSE; 62cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky } 63cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky _status = kStatus_Normal; 64cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky Ppmd7_Init(&_ppmd, _order); 65cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky break; 66cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky } 67cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky if (_outSizeDefined) 68cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky { 69cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky const UInt64 rem = _outSize - _processedSize; 70cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky if (size > rem) 71cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky size = (UInt32)rem; 72cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky } 73cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky 74cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky UInt32 i; 75cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky int sym = 0; 76cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky for (i = 0; i != size; i++) 77cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky { 78cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky sym = Ppmd7_DecodeSymbol(&_ppmd, &_rangeDec.p); 79cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky if (_inStream.Extra || sym < 0) 80cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky break; 81cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky memStream[i] = (Byte)sym; 82cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky } 83cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky 84cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky _processedSize += i; 85cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky if (_inStream.Extra) 86cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky { 87cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky _status = kStatus_Error; 88cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky return _inStream.Res; 89cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky } 90cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky if (sym < 0) 91cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky _status = (sym < -1) ? kStatus_Error : kStatus_Finished; 92cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky return S_OK; 93cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky} 94cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky 95cd66d540cead3f8200b0c73bad9c276d67896c3dDavid SrbeckySTDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, 96cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress) 97cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky{ 98cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky if (!_outBuf) 99cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky { 100cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky _outBuf = (Byte *)::MidAlloc(kBufSize); 101cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky if (!_outBuf) 102cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky return E_OUTOFMEMORY; 103cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky } 104cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky 105cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky _inStream.Stream = inStream; 106cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky SetOutStreamSize(outSize); 107cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky 108cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky do 109cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky { 110cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky const UInt64 startPos = _processedSize; 111cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky HRESULT res = CodeSpec(_outBuf, kBufSize); 112cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky size_t processed = (size_t)(_processedSize - startPos); 113cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky RINOK(WriteStream(outStream, _outBuf, processed)); 114cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky RINOK(res); 115cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky if (_status == kStatus_Finished) 116cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky break; 117cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky if (progress) 118cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky { 119cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky UInt64 inSize = _inStream.GetProcessed(); 120cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky RINOK(progress->SetRatioInfo(&inSize, &_processedSize)); 121cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky } 122cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky } 123cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky while (!_outSizeDefined || _processedSize < _outSize); 124cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky return S_OK; 125cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky} 126cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky 127cd66d540cead3f8200b0c73bad9c276d67896c3dDavid SrbeckySTDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize) 128cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky{ 129cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky _outSizeDefined = (outSize != NULL); 130cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky if (_outSizeDefined) 131cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky _outSize = *outSize; 132cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky _processedSize = 0; 133cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky _status = kStatus_NeedInit; 134cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky return S_OK; 135cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky} 136cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky 137cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky#ifndef NO_READ_FROM_CODER 138cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky 139cd66d540cead3f8200b0c73bad9c276d67896c3dDavid SrbeckySTDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream) 140cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky{ 141cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky InSeqStream = inStream; 142cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky _inStream.Stream = inStream; 143cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky return S_OK; 144cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky} 145cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky 146cd66d540cead3f8200b0c73bad9c276d67896c3dDavid SrbeckySTDMETHODIMP CDecoder::ReleaseInStream() 147cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky{ 148cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky InSeqStream.Release(); 149cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky return S_OK; 150cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky} 151cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky 152cd66d540cead3f8200b0c73bad9c276d67896c3dDavid SrbeckySTDMETHODIMP CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize) 153cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky{ 154cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky const UInt64 startPos = _processedSize; 155cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky HRESULT res = CodeSpec((Byte *)data, size); 156cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky if (processedSize) 157cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky *processedSize = (UInt32)(_processedSize - startPos); 158cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky return res; 159cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky} 160cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky 161cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky#endif 162cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky 163cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky}} 164