Mercurial > vba-linux
diff src/win32/7zip/7z/CPP/7zip/Compress/DeflateDecoder.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/DeflateDecoder.cpp Sat Mar 03 10:31:27 2012 -0600 1.3 @@ -0,0 +1,345 @@ 1.4 +// DeflateDecoder.cpp 1.5 + 1.6 +#include "StdAfx.h" 1.7 + 1.8 +#include "DeflateDecoder.h" 1.9 + 1.10 +namespace NCompress { 1.11 +namespace NDeflate { 1.12 +namespace NDecoder { 1.13 + 1.14 +static const int kLenIdFinished = -1; 1.15 +static const int kLenIdNeedInit = -2; 1.16 + 1.17 +CCoder::CCoder(bool deflate64Mode, bool deflateNSIS): 1.18 + _deflate64Mode(deflate64Mode), 1.19 + _deflateNSIS(deflateNSIS), 1.20 + _keepHistory(false), 1.21 + ZlibMode(false) {} 1.22 + 1.23 +UInt32 CCoder::ReadBits(int numBits) 1.24 +{ 1.25 + return m_InBitStream.ReadBits(numBits); 1.26 +} 1.27 + 1.28 +bool CCoder::DeCodeLevelTable(Byte *values, int numSymbols) 1.29 +{ 1.30 + int i = 0; 1.31 + do 1.32 + { 1.33 + UInt32 number = m_LevelDecoder.DecodeSymbol(&m_InBitStream); 1.34 + if (number < kTableDirectLevels) 1.35 + values[i++] = (Byte)number; 1.36 + else if (number < kLevelTableSize) 1.37 + { 1.38 + if (number == kTableLevelRepNumber) 1.39 + { 1.40 + if (i == 0) 1.41 + return false; 1.42 + int num = ReadBits(2) + 3; 1.43 + for (; num > 0 && i < numSymbols; num--, i++) 1.44 + values[i] = values[i - 1]; 1.45 + } 1.46 + else 1.47 + { 1.48 + int num; 1.49 + if (number == kTableLevel0Number) 1.50 + num = ReadBits(3) + 3; 1.51 + else 1.52 + num = ReadBits(7) + 11; 1.53 + for (;num > 0 && i < numSymbols; num--) 1.54 + values[i++] = 0; 1.55 + } 1.56 + } 1.57 + else 1.58 + return false; 1.59 + } 1.60 + while(i < numSymbols); 1.61 + return true; 1.62 +} 1.63 + 1.64 +#define RIF(x) { if (!(x)) return false; } 1.65 + 1.66 +bool CCoder::ReadTables(void) 1.67 +{ 1.68 + m_FinalBlock = (ReadBits(kFinalBlockFieldSize) == NFinalBlockField::kFinalBlock); 1.69 + UInt32 blockType = ReadBits(kBlockTypeFieldSize); 1.70 + if (blockType > NBlockType::kDynamicHuffman) 1.71 + return false; 1.72 + 1.73 + if (blockType == NBlockType::kStored) 1.74 + { 1.75 + m_StoredMode = true; 1.76 + UInt32 currentBitPosition = m_InBitStream.GetBitPosition(); 1.77 + int numBitsForAlign = (int)(currentBitPosition > 0 ? (8 - currentBitPosition): 0); 1.78 + ReadBits(numBitsForAlign); 1.79 + m_StoredBlockSize = ReadBits(kStoredBlockLengthFieldSize); 1.80 + if (_deflateNSIS) 1.81 + return true; 1.82 + return (m_StoredBlockSize == (UInt16)~ReadBits(kStoredBlockLengthFieldSize)); 1.83 + } 1.84 + 1.85 + m_StoredMode = false; 1.86 + 1.87 + CLevels levels; 1.88 + if (blockType == NBlockType::kFixedHuffman) 1.89 + { 1.90 + levels.SetFixedLevels(); 1.91 + _numDistLevels = _deflate64Mode ? kDistTableSize64 : kDistTableSize32; 1.92 + } 1.93 + else 1.94 + { 1.95 + int numLitLenLevels = ReadBits(kNumLenCodesFieldSize) + kNumLitLenCodesMin; 1.96 + _numDistLevels = ReadBits(kNumDistCodesFieldSize) + kNumDistCodesMin; 1.97 + int numLevelCodes = ReadBits(kNumLevelCodesFieldSize) + kNumLevelCodesMin; 1.98 + 1.99 + if (!_deflate64Mode) 1.100 + if (_numDistLevels > kDistTableSize32) 1.101 + return false; 1.102 + 1.103 + Byte levelLevels[kLevelTableSize]; 1.104 + for (int i = 0; i < kLevelTableSize; i++) 1.105 + { 1.106 + int position = kCodeLengthAlphabetOrder[i]; 1.107 + if(i < numLevelCodes) 1.108 + levelLevels[position] = (Byte)ReadBits(kLevelFieldSize); 1.109 + else 1.110 + levelLevels[position] = 0; 1.111 + } 1.112 + 1.113 + RIF(m_LevelDecoder.SetCodeLengths(levelLevels)); 1.114 + 1.115 + Byte tmpLevels[kFixedMainTableSize + kFixedDistTableSize]; 1.116 + if (!DeCodeLevelTable(tmpLevels, numLitLenLevels + _numDistLevels)) 1.117 + return false; 1.118 + 1.119 + levels.SubClear(); 1.120 + memcpy(levels.litLenLevels, tmpLevels, numLitLenLevels); 1.121 + memcpy(levels.distLevels, tmpLevels + numLitLenLevels, _numDistLevels); 1.122 + } 1.123 + RIF(m_MainDecoder.SetCodeLengths(levels.litLenLevels)); 1.124 + return m_DistDecoder.SetCodeLengths(levels.distLevels); 1.125 +} 1.126 + 1.127 +HRESULT CCoder::CodeSpec(UInt32 curSize) 1.128 +{ 1.129 + if (_remainLen == kLenIdFinished) 1.130 + return S_OK; 1.131 + if (_remainLen == kLenIdNeedInit) 1.132 + { 1.133 + if (!_keepHistory) 1.134 + if (!m_OutWindowStream.Create(_deflate64Mode ? kHistorySize64: kHistorySize32)) 1.135 + return E_OUTOFMEMORY; 1.136 + if (!m_InBitStream.Create(1 << 17)) 1.137 + return E_OUTOFMEMORY; 1.138 + m_OutWindowStream.Init(_keepHistory); 1.139 + m_InBitStream.Init(); 1.140 + m_FinalBlock = false; 1.141 + _remainLen = 0; 1.142 + _needReadTable = true; 1.143 + } 1.144 + 1.145 + if (curSize == 0) 1.146 + return S_OK; 1.147 + 1.148 + while(_remainLen > 0 && curSize > 0) 1.149 + { 1.150 + _remainLen--; 1.151 + Byte b = m_OutWindowStream.GetByte(_rep0); 1.152 + m_OutWindowStream.PutByte(b); 1.153 + curSize--; 1.154 + } 1.155 + 1.156 + while(curSize > 0) 1.157 + { 1.158 + if (_needReadTable) 1.159 + { 1.160 + if (m_FinalBlock) 1.161 + { 1.162 + _remainLen = kLenIdFinished; 1.163 + break; 1.164 + } 1.165 + if (!ReadTables()) 1.166 + return S_FALSE; 1.167 + _needReadTable = false; 1.168 + } 1.169 + 1.170 + if(m_StoredMode) 1.171 + { 1.172 + for (; m_StoredBlockSize > 0 && curSize > 0; m_StoredBlockSize--, curSize--) 1.173 + m_OutWindowStream.PutByte((Byte)m_InBitStream.ReadBits(8)); 1.174 + _needReadTable = (m_StoredBlockSize == 0); 1.175 + continue; 1.176 + } 1.177 + while(curSize > 0) 1.178 + { 1.179 + if (m_InBitStream.NumExtraBytes > 4) 1.180 + return S_FALSE; 1.181 + 1.182 + UInt32 number = m_MainDecoder.DecodeSymbol(&m_InBitStream); 1.183 + if (number < 0x100) 1.184 + { 1.185 + m_OutWindowStream.PutByte((Byte)number); 1.186 + curSize--; 1.187 + continue; 1.188 + } 1.189 + else if (number == kSymbolEndOfBlock) 1.190 + { 1.191 + _needReadTable = true; 1.192 + break; 1.193 + } 1.194 + else if (number < kMainTableSize) 1.195 + { 1.196 + number -= kSymbolMatch; 1.197 + UInt32 len; 1.198 + { 1.199 + int numBits; 1.200 + if (_deflate64Mode) 1.201 + { 1.202 + len = kLenStart64[number]; 1.203 + numBits = kLenDirectBits64[number]; 1.204 + } 1.205 + else 1.206 + { 1.207 + len = kLenStart32[number]; 1.208 + numBits = kLenDirectBits32[number]; 1.209 + } 1.210 + len += kMatchMinLen + m_InBitStream.ReadBits(numBits); 1.211 + } 1.212 + UInt32 locLen = len; 1.213 + if (locLen > curSize) 1.214 + locLen = (UInt32)curSize; 1.215 + number = m_DistDecoder.DecodeSymbol(&m_InBitStream); 1.216 + if (number >= _numDistLevels) 1.217 + return S_FALSE; 1.218 + UInt32 distance = kDistStart[number] + m_InBitStream.ReadBits(kDistDirectBits[number]); 1.219 + if (!m_OutWindowStream.CopyBlock(distance, locLen)) 1.220 + return S_FALSE; 1.221 + curSize -= locLen; 1.222 + len -= locLen; 1.223 + if (len != 0) 1.224 + { 1.225 + _remainLen = (Int32)len; 1.226 + _rep0 = distance; 1.227 + break; 1.228 + } 1.229 + } 1.230 + else 1.231 + return S_FALSE; 1.232 + } 1.233 + } 1.234 + return S_OK; 1.235 +} 1.236 + 1.237 +HRESULT CCoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, 1.238 + const UInt64 *, const UInt64 *outSize, ICompressProgressInfo *progress) 1.239 +{ 1.240 + SetInStream(inStream); 1.241 + m_OutWindowStream.SetStream(outStream); 1.242 + SetOutStreamSize(outSize); 1.243 + CCoderReleaser flusher(this); 1.244 + 1.245 + const UInt64 start = m_OutWindowStream.GetProcessedSize(); 1.246 + for (;;) 1.247 + { 1.248 + UInt32 curSize = 1 << 18; 1.249 + if (outSize != 0) 1.250 + { 1.251 + const UInt64 rem = *outSize - (m_OutWindowStream.GetProcessedSize() - start); 1.252 + if (curSize > rem) 1.253 + curSize = (UInt32)rem; 1.254 + } 1.255 + if (curSize == 0) 1.256 + break; 1.257 + RINOK(CodeSpec(curSize)); 1.258 + if (_remainLen == kLenIdFinished) 1.259 + break; 1.260 + if (progress != NULL) 1.261 + { 1.262 + const UInt64 inSize = m_InBitStream.GetProcessedSize(); 1.263 + const UInt64 nowPos64 = m_OutWindowStream.GetProcessedSize() - start; 1.264 + RINOK(progress->SetRatioInfo(&inSize, &nowPos64)); 1.265 + } 1.266 + } 1.267 + if (_remainLen == kLenIdFinished && ZlibMode) 1.268 + { 1.269 + UInt32 currentBitPosition = m_InBitStream.GetBitPosition(); 1.270 + int numBitsForAlign = (int)(currentBitPosition > 0 ? (8 - currentBitPosition): 0); 1.271 + ReadBits(numBitsForAlign); 1.272 + for (int i = 0; i < 4; i++) 1.273 + ZlibFooter[i] = (Byte)m_InBitStream.ReadBits(8); 1.274 + } 1.275 + flusher.NeedFlush = false; 1.276 + return Flush(); 1.277 +} 1.278 + 1.279 + 1.280 +#ifdef _NO_EXCEPTIONS 1.281 + 1.282 +#define DEFLATE_TRY_BEGIN 1.283 +#define DEFLATE_TRY_END 1.284 + 1.285 +#else 1.286 + 1.287 +#define DEFLATE_TRY_BEGIN try { 1.288 +#define DEFLATE_TRY_END } \ 1.289 + catch(const CInBufferException &e) { return e.ErrorCode; } \ 1.290 + catch(const CLzOutWindowException &e) { return e.ErrorCode; } \ 1.291 + catch(...) { return S_FALSE; } 1.292 + 1.293 +#endif 1.294 + 1.295 +HRESULT CCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, 1.296 + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) 1.297 +{ 1.298 + DEFLATE_TRY_BEGIN 1.299 + return CodeReal(inStream, outStream, inSize, outSize, progress); 1.300 + DEFLATE_TRY_END 1.301 +} 1.302 + 1.303 +STDMETHODIMP CCoder::GetInStreamProcessedSize(UInt64 *value) 1.304 +{ 1.305 + if (value == NULL) 1.306 + return E_INVALIDARG; 1.307 + *value = m_InBitStream.GetProcessedSize(); 1.308 + return S_OK; 1.309 +} 1.310 + 1.311 +STDMETHODIMP CCoder::SetInStream(ISequentialInStream *inStream) 1.312 +{ 1.313 + m_InBitStream.SetStream(inStream); 1.314 + return S_OK; 1.315 +} 1.316 + 1.317 +STDMETHODIMP CCoder::ReleaseInStream() 1.318 +{ 1.319 + m_InBitStream.ReleaseStream(); 1.320 + return S_OK; 1.321 +} 1.322 + 1.323 +STDMETHODIMP CCoder::SetOutStreamSize(const UInt64 * /* outSize */) 1.324 +{ 1.325 + _remainLen = kLenIdNeedInit; 1.326 + m_OutWindowStream.Init(_keepHistory); 1.327 + return S_OK; 1.328 +} 1.329 + 1.330 +#ifndef NO_READ_FROM_CODER 1.331 + 1.332 +STDMETHODIMP CCoder::Read(void *data, UInt32 size, UInt32 *processedSize) 1.333 +{ 1.334 + DEFLATE_TRY_BEGIN 1.335 + if (processedSize) 1.336 + *processedSize = 0; 1.337 + const UInt64 startPos = m_OutWindowStream.GetProcessedSize(); 1.338 + m_OutWindowStream.SetMemStream((Byte *)data); 1.339 + RINOK(CodeSpec(size)); 1.340 + if (processedSize) 1.341 + *processedSize = (UInt32)(m_OutWindowStream.GetProcessedSize() - startPos); 1.342 + return Flush(); 1.343 + DEFLATE_TRY_END 1.344 +} 1.345 + 1.346 +#endif 1.347 + 1.348 +}}}