Mercurial > vba-linux
diff src/win32/7zip/7z/CPP/7zip/Compress/Rar3Decoder.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/Rar3Decoder.cpp Sat Mar 03 10:31:27 2012 -0600 1.3 @@ -0,0 +1,834 @@ 1.4 +// Rar3Decoder.cpp 1.5 +// According to unRAR license, this code may not be used to develop 1.6 +// a program that creates RAR archives 1.7 + 1.8 +#include "StdAfx.h" 1.9 + 1.10 +#include "../Common/StreamUtils.h" 1.11 + 1.12 +#include "Rar3Decoder.h" 1.13 + 1.14 +namespace NCompress { 1.15 +namespace NRar3 { 1.16 + 1.17 +static const UInt32 kNumAlignReps = 15; 1.18 + 1.19 +static const UInt32 kSymbolReadTable = 256; 1.20 +static const UInt32 kSymbolRep = 259; 1.21 +static const UInt32 kSymbolLen2 = kSymbolRep + kNumReps; 1.22 + 1.23 +static const Byte kLenStart[kLenTableSize] = {0,1,2,3,4,5,6,7,8,10,12,14,16,20,24,28,32,40,48,56,64,80,96,112,128,160,192,224}; 1.24 +static const Byte kLenDirectBits[kLenTableSize] = {0,0,0,0,0,0,0,0,1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5}; 1.25 + 1.26 +static const Byte kDistDirectBits[kDistTableSize] = 1.27 + {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15, 1.28 + 16,16,16,16,16,16,16,16,16,16,16,16,16,16, 1.29 + 18,18,18,18,18,18,18,18,18,18,18,18}; 1.30 + 1.31 +static const Byte kLevelDirectBits[kLevelTableSize] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7}; 1.32 + 1.33 +static const Byte kLen2DistStarts[kNumLen2Symbols]={0,4,8,16,32,64,128,192}; 1.34 +static const Byte kLen2DistDirectBits[kNumLen2Symbols]={2,2,3, 4, 5, 6, 6, 6}; 1.35 + 1.36 +static const UInt32 kDistLimit3 = 0x2000 - 2; 1.37 +static const UInt32 kDistLimit4 = 0x40000 - 2; 1.38 + 1.39 +static const UInt32 kNormalMatchMinLen = 3; 1.40 + 1.41 +static const UInt32 kVmDataSizeMax = 1 << 16; 1.42 +static const UInt32 kVmCodeSizeMax = 1 << 16; 1.43 + 1.44 +CDecoder::CDecoder(): 1.45 + _window(0), 1.46 + _winPos(0), 1.47 + _wrPtr(0), 1.48 + _lzSize(0), 1.49 + _writtenFileSize(0), 1.50 + _vmData(0), 1.51 + _vmCode(0), 1.52 + m_IsSolid(false) 1.53 +{ 1.54 +} 1.55 + 1.56 +CDecoder::~CDecoder() 1.57 +{ 1.58 + InitFilters(); 1.59 + ::MidFree(_vmData); 1.60 + ::MidFree(_window); 1.61 +} 1.62 + 1.63 +HRESULT CDecoder::WriteDataToStream(const Byte *data, UInt32 size) 1.64 +{ 1.65 + return WriteStream(_outStream, data, size); 1.66 +} 1.67 + 1.68 +HRESULT CDecoder::WriteData(const Byte *data, UInt32 size) 1.69 +{ 1.70 + HRESULT res = S_OK; 1.71 + if (_writtenFileSize < _unpackSize) 1.72 + { 1.73 + UInt32 curSize = size; 1.74 + UInt64 remain = _unpackSize - _writtenFileSize; 1.75 + if (remain < curSize) 1.76 + curSize = (UInt32)remain; 1.77 + res = WriteDataToStream(data, curSize); 1.78 + } 1.79 + _writtenFileSize += size; 1.80 + return res; 1.81 +} 1.82 + 1.83 +HRESULT CDecoder::WriteArea(UInt32 startPtr, UInt32 endPtr) 1.84 +{ 1.85 + if (startPtr <= endPtr) 1.86 + return WriteData(_window + startPtr, endPtr - startPtr); 1.87 + RINOK(WriteData(_window + startPtr, kWindowSize - startPtr)); 1.88 + return WriteData(_window, endPtr); 1.89 +} 1.90 + 1.91 +void CDecoder::ExecuteFilter(int tempFilterIndex, NVm::CBlockRef &outBlockRef) 1.92 +{ 1.93 + CTempFilter *tempFilter = _tempFilters[tempFilterIndex]; 1.94 + tempFilter->InitR[6] = (UInt32)_writtenFileSize; 1.95 + NVm::SetValue32(&tempFilter->GlobalData[0x24], (UInt32)_writtenFileSize); 1.96 + NVm::SetValue32(&tempFilter->GlobalData[0x28], (UInt32)(_writtenFileSize >> 32)); 1.97 + CFilter *filter = _filters[tempFilter->FilterIndex]; 1.98 + _vm.Execute(filter, tempFilter, outBlockRef, filter->GlobalData); 1.99 + delete tempFilter; 1.100 + _tempFilters[tempFilterIndex] = 0; 1.101 +} 1.102 + 1.103 +HRESULT CDecoder::WriteBuf() 1.104 +{ 1.105 + UInt32 writtenBorder = _wrPtr; 1.106 + UInt32 writeSize = (_winPos - writtenBorder) & kWindowMask; 1.107 + for (int i = 0; i < _tempFilters.Size(); i++) 1.108 + { 1.109 + CTempFilter *filter = _tempFilters[i]; 1.110 + if (filter == NULL) 1.111 + continue; 1.112 + if (filter->NextWindow) 1.113 + { 1.114 + filter->NextWindow = false; 1.115 + continue; 1.116 + } 1.117 + UInt32 blockStart = filter->BlockStart; 1.118 + UInt32 blockSize = filter->BlockSize; 1.119 + if (((blockStart - writtenBorder) & kWindowMask) < writeSize) 1.120 + { 1.121 + if (writtenBorder != blockStart) 1.122 + { 1.123 + RINOK(WriteArea(writtenBorder, blockStart)); 1.124 + writtenBorder = blockStart; 1.125 + writeSize = (_winPos - writtenBorder) & kWindowMask; 1.126 + } 1.127 + if (blockSize <= writeSize) 1.128 + { 1.129 + UInt32 blockEnd = (blockStart + blockSize) & kWindowMask; 1.130 + if (blockStart < blockEnd || blockEnd == 0) 1.131 + _vm.SetMemory(0, _window + blockStart, blockSize); 1.132 + else 1.133 + { 1.134 + UInt32 tailSize = kWindowSize - blockStart; 1.135 + _vm.SetMemory(0, _window + blockStart, tailSize); 1.136 + _vm.SetMemory(tailSize, _window, blockEnd); 1.137 + } 1.138 + NVm::CBlockRef outBlockRef; 1.139 + ExecuteFilter(i, outBlockRef); 1.140 + while (i + 1 < _tempFilters.Size()) 1.141 + { 1.142 + CTempFilter *nextFilter = _tempFilters[i + 1]; 1.143 + if (nextFilter == NULL || nextFilter->BlockStart != blockStart || 1.144 + nextFilter->BlockSize != outBlockRef.Size || nextFilter->NextWindow) 1.145 + break; 1.146 + _vm.SetMemory(0, _vm.GetDataPointer(outBlockRef.Offset), outBlockRef.Size); 1.147 + ExecuteFilter(++i, outBlockRef); 1.148 + } 1.149 + WriteDataToStream(_vm.GetDataPointer(outBlockRef.Offset), outBlockRef.Size); 1.150 + _writtenFileSize += outBlockRef.Size; 1.151 + writtenBorder = blockEnd; 1.152 + writeSize = (_winPos - writtenBorder) & kWindowMask; 1.153 + } 1.154 + else 1.155 + { 1.156 + for (int j = i; j < _tempFilters.Size(); j++) 1.157 + { 1.158 + CTempFilter *filter = _tempFilters[j]; 1.159 + if (filter != NULL && filter->NextWindow) 1.160 + filter->NextWindow = false; 1.161 + } 1.162 + _wrPtr = writtenBorder; 1.163 + return S_OK; // check it 1.164 + } 1.165 + } 1.166 + } 1.167 + 1.168 + _wrPtr = _winPos; 1.169 + return WriteArea(writtenBorder, _winPos); 1.170 +} 1.171 + 1.172 +void CDecoder::InitFilters() 1.173 +{ 1.174 + _lastFilter = 0; 1.175 + int i; 1.176 + for (i = 0; i < _tempFilters.Size(); i++) 1.177 + delete _tempFilters[i]; 1.178 + _tempFilters.Clear(); 1.179 + for (i = 0; i < _filters.Size(); i++) 1.180 + delete _filters[i]; 1.181 + _filters.Clear(); 1.182 +} 1.183 + 1.184 +bool CDecoder::AddVmCode(UInt32 firstByte, UInt32 codeSize) 1.185 +{ 1.186 + CMemBitDecoder inp; 1.187 + inp.Init(_vmData, codeSize); 1.188 + 1.189 + UInt32 filterIndex; 1.190 + if (firstByte & 0x80) 1.191 + { 1.192 + filterIndex = NVm::ReadEncodedUInt32(inp); 1.193 + if (filterIndex == 0) 1.194 + InitFilters(); 1.195 + else 1.196 + filterIndex--; 1.197 + } 1.198 + else 1.199 + filterIndex = _lastFilter; 1.200 + if (filterIndex > (UInt32)_filters.Size()) 1.201 + return false; 1.202 + _lastFilter = filterIndex; 1.203 + bool newFilter = (filterIndex == (UInt32)_filters.Size()); 1.204 + 1.205 + CFilter *filter; 1.206 + if (newFilter) 1.207 + { 1.208 + // check if too many filters 1.209 + if (filterIndex > 1024) 1.210 + return false; 1.211 + filter = new CFilter; 1.212 + _filters.Add(filter); 1.213 + } 1.214 + else 1.215 + { 1.216 + filter = _filters[filterIndex]; 1.217 + filter->ExecCount++; 1.218 + } 1.219 + 1.220 + int numEmptyItems = 0; 1.221 + int i; 1.222 + for (i = 0; i < _tempFilters.Size(); i++) 1.223 + { 1.224 + _tempFilters[i - numEmptyItems] = _tempFilters[i]; 1.225 + if (_tempFilters[i] == NULL) 1.226 + numEmptyItems++; 1.227 + if (numEmptyItems > 0) 1.228 + _tempFilters[i] = NULL; 1.229 + } 1.230 + if (numEmptyItems == 0) 1.231 + { 1.232 + _tempFilters.Add(NULL); 1.233 + numEmptyItems = 1; 1.234 + } 1.235 + CTempFilter *tempFilter = new CTempFilter; 1.236 + _tempFilters[_tempFilters.Size() - numEmptyItems] = tempFilter; 1.237 + tempFilter->FilterIndex = filterIndex; 1.238 + tempFilter->ExecCount = filter->ExecCount; 1.239 + 1.240 + UInt32 blockStart = NVm::ReadEncodedUInt32(inp); 1.241 + if (firstByte & 0x40) 1.242 + blockStart += 258; 1.243 + tempFilter->BlockStart = (blockStart + _winPos) & kWindowMask; 1.244 + if (firstByte & 0x20) 1.245 + filter->BlockSize = NVm::ReadEncodedUInt32(inp); 1.246 + tempFilter->BlockSize = filter->BlockSize; 1.247 + tempFilter->NextWindow = _wrPtr != _winPos && ((_wrPtr - _winPos) & kWindowMask) <= blockStart; 1.248 + 1.249 + memset(tempFilter->InitR, 0, sizeof(tempFilter->InitR)); 1.250 + tempFilter->InitR[3] = NVm::kGlobalOffset; 1.251 + tempFilter->InitR[4] = tempFilter->BlockSize; 1.252 + tempFilter->InitR[5] = tempFilter->ExecCount; 1.253 + if (firstByte & 0x10) 1.254 + { 1.255 + UInt32 initMask = inp.ReadBits(NVm::kNumGpRegs); 1.256 + for (int i = 0; i < NVm::kNumGpRegs; i++) 1.257 + if (initMask & (1 << i)) 1.258 + tempFilter->InitR[i] = NVm::ReadEncodedUInt32(inp); 1.259 + } 1.260 + if (newFilter) 1.261 + { 1.262 + UInt32 vmCodeSize = NVm::ReadEncodedUInt32(inp); 1.263 + if (vmCodeSize >= kVmCodeSizeMax || vmCodeSize == 0) 1.264 + return false; 1.265 + for (UInt32 i = 0; i < vmCodeSize; i++) 1.266 + _vmCode[i] = (Byte)inp.ReadBits(8); 1.267 + _vm.PrepareProgram(_vmCode, vmCodeSize, filter); 1.268 + } 1.269 + 1.270 + tempFilter->AllocateEmptyFixedGlobal(); 1.271 + 1.272 + Byte *globalData = &tempFilter->GlobalData[0]; 1.273 + for (i = 0; i < NVm::kNumGpRegs; i++) 1.274 + NVm::SetValue32(&globalData[i * 4], tempFilter->InitR[i]); 1.275 + NVm::SetValue32(&globalData[NVm::NGlobalOffset::kBlockSize], tempFilter->BlockSize); 1.276 + NVm::SetValue32(&globalData[NVm::NGlobalOffset::kBlockPos], 0); // It was commented. why? 1.277 + NVm::SetValue32(&globalData[NVm::NGlobalOffset::kExecCount], tempFilter->ExecCount); 1.278 + 1.279 + if (firstByte & 8) 1.280 + { 1.281 + UInt32 dataSize = NVm::ReadEncodedUInt32(inp); 1.282 + if (dataSize > NVm::kGlobalSize - NVm::kFixedGlobalSize) 1.283 + return false; 1.284 + CRecordVector<Byte> &globalData = tempFilter->GlobalData; 1.285 + int requredSize = (int)(dataSize + NVm::kFixedGlobalSize); 1.286 + if (globalData.Size() < requredSize) 1.287 + { 1.288 + globalData.Reserve(requredSize); 1.289 + for (; globalData.Size() < requredSize; i++) 1.290 + globalData.Add(0); 1.291 + } 1.292 + for (UInt32 i = 0; i < dataSize; i++) 1.293 + globalData[NVm::kFixedGlobalSize + i] = (Byte)inp.ReadBits(8); 1.294 + } 1.295 + return true; 1.296 +} 1.297 + 1.298 +bool CDecoder::ReadVmCodeLZ() 1.299 +{ 1.300 + UInt32 firstByte = m_InBitStream.ReadBits(8); 1.301 + UInt32 length = (firstByte & 7) + 1; 1.302 + if (length == 7) 1.303 + length = m_InBitStream.ReadBits(8) + 7; 1.304 + else if (length == 8) 1.305 + length = m_InBitStream.ReadBits(16); 1.306 + if (length > kVmDataSizeMax) 1.307 + return false; 1.308 + for (UInt32 i = 0; i < length; i++) 1.309 + _vmData[i] = (Byte)m_InBitStream.ReadBits(8); 1.310 + return AddVmCode(firstByte, length); 1.311 +} 1.312 + 1.313 +bool CDecoder::ReadVmCodePPM() 1.314 +{ 1.315 + int firstByte = DecodePpmSymbol(); 1.316 + if (firstByte == -1) 1.317 + return false; 1.318 + UInt32 length = (firstByte & 7) + 1; 1.319 + if (length == 7) 1.320 + { 1.321 + int b1 = DecodePpmSymbol(); 1.322 + if (b1 == -1) 1.323 + return false; 1.324 + length = b1 + 7; 1.325 + } 1.326 + else if (length == 8) 1.327 + { 1.328 + int b1 = DecodePpmSymbol(); 1.329 + if (b1 == -1) 1.330 + return false; 1.331 + int b2 = DecodePpmSymbol(); 1.332 + if (b2 == -1) 1.333 + return false; 1.334 + length = b1 * 256 + b2; 1.335 + } 1.336 + if (length > kVmDataSizeMax) 1.337 + return false; 1.338 + for (UInt32 i = 0; i < length; i++) 1.339 + { 1.340 + int b = DecodePpmSymbol(); 1.341 + if (b == -1) 1.342 + return false; 1.343 + _vmData[i] = (Byte)b; 1.344 + } 1.345 + return AddVmCode(firstByte, length); 1.346 +} 1.347 + 1.348 +#define RIF(x) { if (!(x)) return S_FALSE; } 1.349 + 1.350 +UInt32 CDecoder::ReadBits(int numBits) { return m_InBitStream.ReadBits(numBits); } 1.351 + 1.352 +///////////////////////////////////////////////// 1.353 +// PPM 1.354 + 1.355 +HRESULT CDecoder::InitPPM() 1.356 +{ 1.357 + Byte maxOrder = (Byte)ReadBits(7); 1.358 + 1.359 + bool reset = ((maxOrder & 0x20) != 0); 1.360 + int maxMB = 0; 1.361 + if (reset) 1.362 + maxMB = (Byte)ReadBits(8); 1.363 + else 1.364 + { 1.365 + if (_ppm.SubAllocator.GetSubAllocatorSize()== 0) 1.366 + return S_FALSE; 1.367 + } 1.368 + if (maxOrder & 0x40) 1.369 + PpmEscChar = (Byte)ReadBits(8); 1.370 + m_InBitStream.InitRangeCoder(); 1.371 + /* 1.372 + if (m_InBitStream.m_BitPos != 0) 1.373 + return S_FALSE; 1.374 + */ 1.375 + if (reset) 1.376 + { 1.377 + maxOrder = (maxOrder & 0x1F) + 1; 1.378 + if (maxOrder > 16) 1.379 + maxOrder = 16 + (maxOrder - 16) * 3; 1.380 + if (maxOrder == 1) 1.381 + { 1.382 + // SubAlloc.StopSubAllocator(); 1.383 + _ppm.SubAllocator.StopSubAllocator(); 1.384 + return S_FALSE; 1.385 + } 1.386 + // SubAlloc.StartSubAllocator(MaxMB+1); 1.387 + // StartModelRare(maxOrder); 1.388 + 1.389 + if (!_ppm.SubAllocator.StartSubAllocator((maxMB + 1) << 20)) 1.390 + return E_OUTOFMEMORY; 1.391 + _ppm.MaxOrder = 0; 1.392 + _ppm.StartModelRare(maxOrder); 1.393 + 1.394 + } 1.395 + // return (minContext != NULL); 1.396 + 1.397 + return S_OK; 1.398 +} 1.399 + 1.400 +int CDecoder::DecodePpmSymbol() { return _ppm.DecodeSymbol(&m_InBitStream); } 1.401 + 1.402 +HRESULT CDecoder::DecodePPM(Int32 num, bool &keepDecompressing) 1.403 +{ 1.404 + keepDecompressing = false; 1.405 + do 1.406 + { 1.407 + if (((_wrPtr - _winPos) & kWindowMask) < 260 && _wrPtr != _winPos) 1.408 + { 1.409 + RINOK(WriteBuf()); 1.410 + if (_writtenFileSize > _unpackSize) 1.411 + { 1.412 + keepDecompressing = false; 1.413 + return S_OK; 1.414 + } 1.415 + } 1.416 + int c = DecodePpmSymbol(); 1.417 + if (c == -1) 1.418 + { 1.419 + // Original code sets PPMError=true here and then it returns S_OK. Why ??? 1.420 + // return S_OK; 1.421 + return S_FALSE; 1.422 + } 1.423 + if (c == PpmEscChar) 1.424 + { 1.425 + int nextCh = DecodePpmSymbol(); 1.426 + if (nextCh == 0) 1.427 + return ReadTables(keepDecompressing); 1.428 + if (nextCh == 2 || nextCh == -1) 1.429 + return S_OK; 1.430 + if (nextCh == 3) 1.431 + { 1.432 + if (!ReadVmCodePPM()) 1.433 + return S_FALSE; 1.434 + continue; 1.435 + } 1.436 + if (nextCh == 4 || nextCh == 5) 1.437 + { 1.438 + UInt32 distance = 0; 1.439 + UInt32 length = 4; 1.440 + if (nextCh == 4) 1.441 + { 1.442 + for (int i = 0; i < 3; i++) 1.443 + { 1.444 + int c = DecodePpmSymbol(); 1.445 + if (c == -1) 1.446 + return S_OK; 1.447 + distance = (distance << 8) + (Byte)c; 1.448 + } 1.449 + distance++; 1.450 + length += 28; 1.451 + } 1.452 + int c = DecodePpmSymbol(); 1.453 + if (c == -1) 1.454 + return S_OK; 1.455 + length += c; 1.456 + if (distance >= _lzSize) 1.457 + return S_FALSE; 1.458 + CopyBlock(distance, length); 1.459 + num -= (Int32)length; 1.460 + continue; 1.461 + } 1.462 + } 1.463 + PutByte((Byte)c); 1.464 + num--; 1.465 + } 1.466 + while (num >= 0); 1.467 + keepDecompressing = true; 1.468 + return S_OK; 1.469 +} 1.470 + 1.471 +///////////////////////////////////////////////// 1.472 +// LZ 1.473 + 1.474 +HRESULT CDecoder::ReadTables(bool &keepDecompressing) 1.475 +{ 1.476 + keepDecompressing = true; 1.477 + ReadBits((8 - m_InBitStream.GetBitPosition()) & 7); 1.478 + if (ReadBits(1) != 0) 1.479 + { 1.480 + _lzMode = false; 1.481 + return InitPPM(); 1.482 + } 1.483 + 1.484 + _lzMode = true; 1.485 + PrevAlignBits = 0; 1.486 + PrevAlignCount = 0; 1.487 + 1.488 + Byte levelLevels[kLevelTableSize]; 1.489 + Byte newLevels[kTablesSizesSum]; 1.490 + 1.491 + if (ReadBits(1) == 0) 1.492 + memset(m_LastLevels, 0, kTablesSizesSum); 1.493 + 1.494 + int i; 1.495 + for (i = 0; i < kLevelTableSize; i++) 1.496 + { 1.497 + UInt32 length = ReadBits(4); 1.498 + if (length == 15) 1.499 + { 1.500 + UInt32 zeroCount = ReadBits(4); 1.501 + if (zeroCount != 0) 1.502 + { 1.503 + zeroCount += 2; 1.504 + while (zeroCount-- > 0 && i < kLevelTableSize) 1.505 + levelLevels[i++]=0; 1.506 + i--; 1.507 + continue; 1.508 + } 1.509 + } 1.510 + levelLevels[i] = (Byte)length; 1.511 + } 1.512 + RIF(m_LevelDecoder.SetCodeLengths(levelLevels)); 1.513 + i = 0; 1.514 + while (i < kTablesSizesSum) 1.515 + { 1.516 + UInt32 number = m_LevelDecoder.DecodeSymbol(&m_InBitStream); 1.517 + if (number < 16) 1.518 + { 1.519 + newLevels[i] = Byte((number + m_LastLevels[i]) & 15); 1.520 + i++; 1.521 + } 1.522 + else if (number > kLevelTableSize) 1.523 + return S_FALSE; 1.524 + else 1.525 + { 1.526 + int num; 1.527 + if (((number - 16) & 1) == 0) 1.528 + num = ReadBits(3) + 3; 1.529 + else 1.530 + num = ReadBits(7) + 11; 1.531 + if (number < 18) 1.532 + { 1.533 + if (i == 0) 1.534 + return S_FALSE; 1.535 + for (; num > 0 && i < kTablesSizesSum; num--, i++) 1.536 + newLevels[i] = newLevels[i - 1]; 1.537 + } 1.538 + else 1.539 + { 1.540 + for (; num > 0 && i < kTablesSizesSum; num--) 1.541 + newLevels[i++] = 0; 1.542 + } 1.543 + } 1.544 + } 1.545 + TablesRead = true; 1.546 + 1.547 + // original code has check here: 1.548 + /* 1.549 + if (InAddr > ReadTop) 1.550 + { 1.551 + keepDecompressing = false; 1.552 + return true; 1.553 + } 1.554 + */ 1.555 + 1.556 + RIF(m_MainDecoder.SetCodeLengths(&newLevels[0])); 1.557 + RIF(m_DistDecoder.SetCodeLengths(&newLevels[kMainTableSize])); 1.558 + RIF(m_AlignDecoder.SetCodeLengths(&newLevels[kMainTableSize + kDistTableSize])); 1.559 + RIF(m_LenDecoder.SetCodeLengths(&newLevels[kMainTableSize + kDistTableSize + kAlignTableSize])); 1.560 + 1.561 + memcpy(m_LastLevels, newLevels, kTablesSizesSum); 1.562 + return S_OK; 1.563 +} 1.564 + 1.565 +class CCoderReleaser 1.566 +{ 1.567 + CDecoder *m_Coder; 1.568 +public: 1.569 + CCoderReleaser(CDecoder *coder): m_Coder(coder) {} 1.570 + ~CCoderReleaser() 1.571 + { 1.572 + // m_Coder->m_OutWindowStream.Flush(); 1.573 + m_Coder->ReleaseStreams(); 1.574 + } 1.575 +}; 1.576 + 1.577 +HRESULT CDecoder::ReadEndOfBlock(bool &keepDecompressing) 1.578 +{ 1.579 + if (ReadBits(1) != 0) 1.580 + { 1.581 + // old file 1.582 + TablesRead = false; 1.583 + return ReadTables(keepDecompressing); 1.584 + } 1.585 + // new file 1.586 + keepDecompressing = false; 1.587 + TablesRead = (ReadBits(1) == 0); 1.588 + return S_OK; 1.589 +} 1.590 + 1.591 +UInt32 kDistStart[kDistTableSize]; 1.592 + 1.593 +class CDistInit 1.594 +{ 1.595 +public: 1.596 + CDistInit() { Init(); } 1.597 + void Init() 1.598 + { 1.599 + UInt32 start = 0; 1.600 + for (UInt32 i = 0; i < kDistTableSize; i++) 1.601 + { 1.602 + kDistStart[i] = start; 1.603 + start += (1 << kDistDirectBits[i]); 1.604 + } 1.605 + } 1.606 +} g_DistInit; 1.607 + 1.608 +HRESULT CDecoder::DecodeLZ(bool &keepDecompressing) 1.609 +{ 1.610 + UInt32 rep0 = _reps[0]; 1.611 + UInt32 rep1 = _reps[1]; 1.612 + UInt32 rep2 = _reps[2]; 1.613 + UInt32 rep3 = _reps[3]; 1.614 + UInt32 length = _lastLength; 1.615 + for (;;) 1.616 + { 1.617 + if (((_wrPtr - _winPos) & kWindowMask) < 260 && _wrPtr != _winPos) 1.618 + { 1.619 + RINOK(WriteBuf()); 1.620 + if (_writtenFileSize > _unpackSize) 1.621 + { 1.622 + keepDecompressing = false; 1.623 + return S_OK; 1.624 + } 1.625 + } 1.626 + UInt32 number = m_MainDecoder.DecodeSymbol(&m_InBitStream); 1.627 + if (number < 256) 1.628 + { 1.629 + PutByte(Byte(number)); 1.630 + 1.631 + continue; 1.632 + } 1.633 + else if (number == kSymbolReadTable) 1.634 + { 1.635 + RINOK(ReadEndOfBlock(keepDecompressing)); 1.636 + break; 1.637 + } 1.638 + else if (number == 257) 1.639 + { 1.640 + if (!ReadVmCodeLZ()) 1.641 + return S_FALSE; 1.642 + continue; 1.643 + } 1.644 + else if (number == 258) 1.645 + { 1.646 + } 1.647 + else if (number < kSymbolRep + 4) 1.648 + { 1.649 + if (number != kSymbolRep) 1.650 + { 1.651 + UInt32 distance; 1.652 + if (number == kSymbolRep + 1) 1.653 + distance = rep1; 1.654 + else 1.655 + { 1.656 + if (number == kSymbolRep + 2) 1.657 + distance = rep2; 1.658 + else 1.659 + { 1.660 + distance = rep3; 1.661 + rep3 = rep2; 1.662 + } 1.663 + rep2 = rep1; 1.664 + } 1.665 + rep1 = rep0; 1.666 + rep0 = distance; 1.667 + } 1.668 + 1.669 + UInt32 number = m_LenDecoder.DecodeSymbol(&m_InBitStream); 1.670 + if (number >= kLenTableSize) 1.671 + return S_FALSE; 1.672 + length = 2 + kLenStart[number] + m_InBitStream.ReadBits(kLenDirectBits[number]); 1.673 + } 1.674 + else 1.675 + { 1.676 + rep3 = rep2; 1.677 + rep2 = rep1; 1.678 + rep1 = rep0; 1.679 + if (number < 271) 1.680 + { 1.681 + number -= 263; 1.682 + rep0 = kLen2DistStarts[number] + m_InBitStream.ReadBits(kLen2DistDirectBits[number]); 1.683 + length = 2; 1.684 + } 1.685 + else if (number < 299) 1.686 + { 1.687 + number -= 271; 1.688 + length = kNormalMatchMinLen + (UInt32)kLenStart[number] + m_InBitStream.ReadBits(kLenDirectBits[number]); 1.689 + UInt32 number = m_DistDecoder.DecodeSymbol(&m_InBitStream); 1.690 + if (number >= kDistTableSize) 1.691 + return S_FALSE; 1.692 + rep0 = kDistStart[number]; 1.693 + int numBits = kDistDirectBits[number]; 1.694 + if (number >= (kNumAlignBits * 2) + 2) 1.695 + { 1.696 + if (numBits > kNumAlignBits) 1.697 + rep0 += (m_InBitStream.ReadBits(numBits - kNumAlignBits) << kNumAlignBits); 1.698 + if (PrevAlignCount > 0) 1.699 + { 1.700 + PrevAlignCount--; 1.701 + rep0 += PrevAlignBits; 1.702 + } 1.703 + else 1.704 + { 1.705 + UInt32 number = m_AlignDecoder.DecodeSymbol(&m_InBitStream); 1.706 + if (number < (1 << kNumAlignBits)) 1.707 + { 1.708 + rep0 += number; 1.709 + PrevAlignBits = number; 1.710 + } 1.711 + else if (number == (1 << kNumAlignBits)) 1.712 + { 1.713 + PrevAlignCount = kNumAlignReps; 1.714 + rep0 += PrevAlignBits; 1.715 + } 1.716 + else 1.717 + return S_FALSE; 1.718 + } 1.719 + } 1.720 + else 1.721 + rep0 += m_InBitStream.ReadBits(numBits); 1.722 + length += ((kDistLimit4 - rep0) >> 31) + ((kDistLimit3 - rep0) >> 31); 1.723 + } 1.724 + else 1.725 + return S_FALSE; 1.726 + } 1.727 + if (rep0 >= _lzSize) 1.728 + return S_FALSE; 1.729 + CopyBlock(rep0, length); 1.730 + } 1.731 + _reps[0] = rep0; 1.732 + _reps[1] = rep1; 1.733 + _reps[2] = rep2; 1.734 + _reps[3] = rep3; 1.735 + _lastLength = length; 1.736 + 1.737 + return S_OK; 1.738 +} 1.739 + 1.740 +HRESULT CDecoder::CodeReal(ICompressProgressInfo *progress) 1.741 +{ 1.742 + _writtenFileSize = 0; 1.743 + if (!m_IsSolid) 1.744 + { 1.745 + _lzSize = 0; 1.746 + _winPos = 0; 1.747 + _wrPtr = 0; 1.748 + for (int i = 0; i < kNumReps; i++) 1.749 + _reps[i] = 0; 1.750 + _lastLength = 0; 1.751 + memset(m_LastLevels, 0, kTablesSizesSum); 1.752 + TablesRead = false; 1.753 + PpmEscChar = 2; 1.754 + InitFilters(); 1.755 + } 1.756 + if (!m_IsSolid || !TablesRead) 1.757 + { 1.758 + bool keepDecompressing; 1.759 + RINOK(ReadTables(keepDecompressing)); 1.760 + if (!keepDecompressing) 1.761 + return S_OK; 1.762 + } 1.763 + 1.764 + for(;;) 1.765 + { 1.766 + bool keepDecompressing; 1.767 + if (_lzMode) 1.768 + { 1.769 + RINOK(DecodeLZ(keepDecompressing)) 1.770 + } 1.771 + else 1.772 + { 1.773 + RINOK(DecodePPM(1 << 18, keepDecompressing)) 1.774 + } 1.775 + UInt64 packSize = m_InBitStream.GetProcessedSize(); 1.776 + RINOK(progress->SetRatioInfo(&packSize, &_writtenFileSize)); 1.777 + if (!keepDecompressing) 1.778 + break; 1.779 + } 1.780 + RINOK(WriteBuf()); 1.781 + if (_writtenFileSize < _unpackSize) 1.782 + return S_FALSE; 1.783 + // return m_OutWindowStream.Flush(); 1.784 + return S_OK; 1.785 +} 1.786 + 1.787 +STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, 1.788 + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) 1.789 +{ 1.790 + try 1.791 + { 1.792 + if (inSize == NULL || outSize == NULL) 1.793 + return E_INVALIDARG; 1.794 + 1.795 + if (_vmData == 0) 1.796 + { 1.797 + _vmData = (Byte *)::MidAlloc(kVmDataSizeMax + kVmCodeSizeMax); 1.798 + if (_vmData == 0) 1.799 + return E_OUTOFMEMORY; 1.800 + _vmCode = _vmData + kVmDataSizeMax; 1.801 + } 1.802 + 1.803 + if (_window == 0) 1.804 + { 1.805 + _window = (Byte *)::MidAlloc(kWindowSize); 1.806 + if (_window == 0) 1.807 + return E_OUTOFMEMORY; 1.808 + } 1.809 + if (!m_InBitStream.Create(1 << 20)) 1.810 + return E_OUTOFMEMORY; 1.811 + if (!_vm.Create()) 1.812 + return E_OUTOFMEMORY; 1.813 + 1.814 + 1.815 + m_InBitStream.SetStream(inStream); 1.816 + m_InBitStream.Init(); 1.817 + _outStream = outStream; 1.818 + 1.819 + CCoderReleaser coderReleaser(this); 1.820 + _unpackSize = *outSize; 1.821 + return CodeReal(progress); 1.822 + } 1.823 + catch(const CInBufferException &e) { return e.ErrorCode; } 1.824 + catch(...) { return S_FALSE; } 1.825 + // CNewException is possible here. But probably CNewException is caused 1.826 + // by error in data stream. 1.827 +} 1.828 + 1.829 +STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size) 1.830 +{ 1.831 + if (size < 1) 1.832 + return E_INVALIDARG; 1.833 + m_IsSolid = (data[0] != 0); 1.834 + return S_OK; 1.835 +} 1.836 + 1.837 +}}