Mercurial > vba-linux
view src/win32/7zip/7z/CPP/7zip/Compress/PpmdDecoder.cpp @ 1:f9f4f1b99eed
importing src directory
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 03 Mar 2012 10:31:27 -0600 |
parents | |
children |
line wrap: on
line source
1 // PpmdDecoder.cpp3 #include "StdAfx.h"5 #include "Common/Defs.h"6 #include "Windows/Defs.h"8 #include "PpmdDecoder.h"10 namespace NCompress {11 namespace NPpmd {13 const int kLenIdFinished = -1;14 const int kLenIdNeedInit = -2;16 STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *properties, UInt32 size)17 {18 if (size < 5)19 return E_INVALIDARG;20 _order = properties[0];21 _usedMemorySize = 0;22 for (int i = 0; i < 4; i++)23 _usedMemorySize += ((UInt32)(properties[1 + i])) << (i * 8);25 if (_usedMemorySize > kMaxMemBlockSize)26 return E_NOTIMPL;28 if (!_rangeDecoder.Create(1 << 20))29 return E_OUTOFMEMORY;30 if (!_info.SubAllocator.StartSubAllocator(_usedMemorySize))31 return E_OUTOFMEMORY;33 return S_OK;34 }36 class CDecoderFlusher37 {38 CDecoder *_coder;39 public:40 bool NeedFlush;41 CDecoderFlusher(CDecoder *coder): _coder(coder), NeedFlush(true) {}42 ~CDecoderFlusher()43 {44 if (NeedFlush)45 _coder->Flush();46 _coder->ReleaseStreams();47 }48 };50 HRESULT CDecoder::CodeSpec(UInt32 size, Byte *memStream)51 {52 if (_outSizeDefined)53 {54 const UInt64 rem = _outSize - _processedSize;55 if (size > rem)56 size = (UInt32)rem;57 }58 const UInt32 startSize = size;60 if (_remainLen == kLenIdFinished)61 return S_OK;62 if (_remainLen == kLenIdNeedInit)63 {64 _rangeDecoder.Init();65 _remainLen = 0;66 _info.MaxOrder = 0;67 _info.StartModelRare(_order);68 }69 while (size != 0)70 {71 int symbol = _info.DecodeSymbol(&_rangeDecoder);72 if (symbol < 0)73 {74 _remainLen = kLenIdFinished;75 break;76 }77 if (memStream != 0)78 *memStream++ = (Byte)symbol;79 else80 _outStream.WriteByte((Byte)symbol);81 size--;82 }83 _processedSize += startSize - size;84 return S_OK;85 }87 STDMETHODIMP CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream,88 const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress)89 {90 if (!_outStream.Create(1 << 20))91 return E_OUTOFMEMORY;93 SetInStream(inStream);94 _outStream.SetStream(outStream);95 SetOutStreamSize(outSize);96 CDecoderFlusher flusher(this);98 for (;;)99 {100 _processedSize = _outStream.GetProcessedSize();101 UInt32 curSize = (1 << 18);102 RINOK(CodeSpec(curSize, NULL));103 if (_remainLen == kLenIdFinished)104 break;105 if (progress != NULL)106 {107 UInt64 inSize = _rangeDecoder.GetProcessedSize();108 RINOK(progress->SetRatioInfo(&inSize, &_processedSize));109 }110 if (_outSizeDefined)111 if (_outStream.GetProcessedSize() >= _outSize)112 break;113 }114 flusher.NeedFlush = false;115 return Flush();116 }118 #ifdef _NO_EXCEPTIONS120 #define PPMD_TRY_BEGIN121 #define PPMD_TRY_END123 #else125 #define PPMD_TRY_BEGIN try {126 #define PPMD_TRY_END } \127 catch(const CInBufferException &e) { return e.ErrorCode; } \128 catch(const COutBufferException &e) { return e.ErrorCode; } \129 catch(...) { return S_FALSE; }131 #endif134 STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,135 const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)136 {137 PPMD_TRY_BEGIN138 return CodeReal(inStream, outStream, inSize, outSize, progress);139 PPMD_TRY_END140 }142 STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream)143 {144 _rangeDecoder.SetStream(inStream);145 return S_OK;146 }148 STDMETHODIMP CDecoder::ReleaseInStream()149 {150 _rangeDecoder.ReleaseStream();151 return S_OK;152 }154 STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize)155 {156 _outSizeDefined = (outSize != NULL);157 if (_outSizeDefined)158 _outSize = *outSize;159 _processedSize = 0;160 _remainLen = kLenIdNeedInit;161 _outStream.Init();162 return S_OK;163 }165 #ifndef NO_READ_FROM_CODER167 STDMETHODIMP CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize)168 {169 PPMD_TRY_BEGIN170 if (processedSize)171 *processedSize = 0;172 const UInt64 startPos = _processedSize;173 RINOK(CodeSpec(size, (Byte *)data));174 if (processedSize)175 *processedSize = (UInt32)(_processedSize - startPos);176 return Flush();177 PPMD_TRY_END178 }180 #endif182 }}