Mercurial > vba-clojure
diff 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 diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/win32/7zip/7z/CPP/7zip/Compress/PpmdDecoder.cpp Sat Mar 03 10:31:27 2012 -0600 1.3 @@ -0,0 +1,182 @@ 1.4 +// PpmdDecoder.cpp 1.5 + 1.6 +#include "StdAfx.h" 1.7 + 1.8 +#include "Common/Defs.h" 1.9 +#include "Windows/Defs.h" 1.10 + 1.11 +#include "PpmdDecoder.h" 1.12 + 1.13 +namespace NCompress { 1.14 +namespace NPpmd { 1.15 + 1.16 +const int kLenIdFinished = -1; 1.17 +const int kLenIdNeedInit = -2; 1.18 + 1.19 +STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *properties, UInt32 size) 1.20 +{ 1.21 + if (size < 5) 1.22 + return E_INVALIDARG; 1.23 + _order = properties[0]; 1.24 + _usedMemorySize = 0; 1.25 + for (int i = 0; i < 4; i++) 1.26 + _usedMemorySize += ((UInt32)(properties[1 + i])) << (i * 8); 1.27 + 1.28 + if (_usedMemorySize > kMaxMemBlockSize) 1.29 + return E_NOTIMPL; 1.30 + 1.31 + if (!_rangeDecoder.Create(1 << 20)) 1.32 + return E_OUTOFMEMORY; 1.33 + if (!_info.SubAllocator.StartSubAllocator(_usedMemorySize)) 1.34 + return E_OUTOFMEMORY; 1.35 + 1.36 + return S_OK; 1.37 +} 1.38 + 1.39 +class CDecoderFlusher 1.40 +{ 1.41 + CDecoder *_coder; 1.42 +public: 1.43 + bool NeedFlush; 1.44 + CDecoderFlusher(CDecoder *coder): _coder(coder), NeedFlush(true) {} 1.45 + ~CDecoderFlusher() 1.46 + { 1.47 + if (NeedFlush) 1.48 + _coder->Flush(); 1.49 + _coder->ReleaseStreams(); 1.50 + } 1.51 +}; 1.52 + 1.53 +HRESULT CDecoder::CodeSpec(UInt32 size, Byte *memStream) 1.54 +{ 1.55 + if (_outSizeDefined) 1.56 + { 1.57 + const UInt64 rem = _outSize - _processedSize; 1.58 + if (size > rem) 1.59 + size = (UInt32)rem; 1.60 + } 1.61 + const UInt32 startSize = size; 1.62 + 1.63 + if (_remainLen == kLenIdFinished) 1.64 + return S_OK; 1.65 + if (_remainLen == kLenIdNeedInit) 1.66 + { 1.67 + _rangeDecoder.Init(); 1.68 + _remainLen = 0; 1.69 + _info.MaxOrder = 0; 1.70 + _info.StartModelRare(_order); 1.71 + } 1.72 + while (size != 0) 1.73 + { 1.74 + int symbol = _info.DecodeSymbol(&_rangeDecoder); 1.75 + if (symbol < 0) 1.76 + { 1.77 + _remainLen = kLenIdFinished; 1.78 + break; 1.79 + } 1.80 + if (memStream != 0) 1.81 + *memStream++ = (Byte)symbol; 1.82 + else 1.83 + _outStream.WriteByte((Byte)symbol); 1.84 + size--; 1.85 + } 1.86 + _processedSize += startSize - size; 1.87 + return S_OK; 1.88 +} 1.89 + 1.90 +STDMETHODIMP CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, 1.91 + const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress) 1.92 +{ 1.93 + if (!_outStream.Create(1 << 20)) 1.94 + return E_OUTOFMEMORY; 1.95 + 1.96 + SetInStream(inStream); 1.97 + _outStream.SetStream(outStream); 1.98 + SetOutStreamSize(outSize); 1.99 + CDecoderFlusher flusher(this); 1.100 + 1.101 + for (;;) 1.102 + { 1.103 + _processedSize = _outStream.GetProcessedSize(); 1.104 + UInt32 curSize = (1 << 18); 1.105 + RINOK(CodeSpec(curSize, NULL)); 1.106 + if (_remainLen == kLenIdFinished) 1.107 + break; 1.108 + if (progress != NULL) 1.109 + { 1.110 + UInt64 inSize = _rangeDecoder.GetProcessedSize(); 1.111 + RINOK(progress->SetRatioInfo(&inSize, &_processedSize)); 1.112 + } 1.113 + if (_outSizeDefined) 1.114 + if (_outStream.GetProcessedSize() >= _outSize) 1.115 + break; 1.116 + } 1.117 + flusher.NeedFlush = false; 1.118 + return Flush(); 1.119 +} 1.120 + 1.121 +#ifdef _NO_EXCEPTIONS 1.122 + 1.123 +#define PPMD_TRY_BEGIN 1.124 +#define PPMD_TRY_END 1.125 + 1.126 +#else 1.127 + 1.128 +#define PPMD_TRY_BEGIN try { 1.129 +#define PPMD_TRY_END } \ 1.130 + catch(const CInBufferException &e) { return e.ErrorCode; } \ 1.131 + catch(const COutBufferException &e) { return e.ErrorCode; } \ 1.132 + catch(...) { return S_FALSE; } 1.133 + 1.134 +#endif 1.135 + 1.136 + 1.137 +STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, 1.138 + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) 1.139 +{ 1.140 + PPMD_TRY_BEGIN 1.141 + return CodeReal(inStream, outStream, inSize, outSize, progress); 1.142 + PPMD_TRY_END 1.143 +} 1.144 + 1.145 +STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream) 1.146 +{ 1.147 + _rangeDecoder.SetStream(inStream); 1.148 + return S_OK; 1.149 +} 1.150 + 1.151 +STDMETHODIMP CDecoder::ReleaseInStream() 1.152 +{ 1.153 + _rangeDecoder.ReleaseStream(); 1.154 + return S_OK; 1.155 +} 1.156 + 1.157 +STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize) 1.158 +{ 1.159 + _outSizeDefined = (outSize != NULL); 1.160 + if (_outSizeDefined) 1.161 + _outSize = *outSize; 1.162 + _processedSize = 0; 1.163 + _remainLen = kLenIdNeedInit; 1.164 + _outStream.Init(); 1.165 + return S_OK; 1.166 +} 1.167 + 1.168 +#ifndef NO_READ_FROM_CODER 1.169 + 1.170 +STDMETHODIMP CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize) 1.171 +{ 1.172 + PPMD_TRY_BEGIN 1.173 + if (processedSize) 1.174 + *processedSize = 0; 1.175 + const UInt64 startPos = _processedSize; 1.176 + RINOK(CodeSpec(size, (Byte *)data)); 1.177 + if (processedSize) 1.178 + *processedSize = (UInt32)(_processedSize - startPos); 1.179 + return Flush(); 1.180 + PPMD_TRY_END 1.181 +} 1.182 + 1.183 +#endif 1.184 + 1.185 +}}