Mercurial > vba-linux
diff src/win32/7zip/7z/CPP/7zip/Compress/Rar2Decoder.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/Rar2Decoder.cpp Sat Mar 03 10:31:27 2012 -0600 1.3 @@ -0,0 +1,389 @@ 1.4 +// Rar2Decoder.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 "Rar2Decoder.h" 1.11 + 1.12 +namespace NCompress { 1.13 +namespace NRar2 { 1.14 + 1.15 +namespace NMultimedia { 1.16 + 1.17 +Byte CFilter::Decode(int &channelDelta, Byte deltaByte) 1.18 +{ 1.19 + D4 = D3; 1.20 + D3 = D2; 1.21 + D2 = LastDelta - D1; 1.22 + D1 = LastDelta; 1.23 + int predictedValue = ((8 * LastChar + K1 * D1 + K2 * D2 + K3 * D3 + K4 * D4 + K5 * channelDelta) >> 3); 1.24 + 1.25 + Byte realValue = (Byte)(predictedValue - deltaByte); 1.26 + int i = ((int)(signed char)deltaByte) << 3; 1.27 + 1.28 + Dif[0] += abs(i); 1.29 + Dif[1] += abs(i - D1); 1.30 + Dif[2] += abs(i + D1); 1.31 + Dif[3] += abs(i - D2); 1.32 + Dif[4] += abs(i + D2); 1.33 + Dif[5] += abs(i - D3); 1.34 + Dif[6] += abs(i + D3); 1.35 + Dif[7] += abs(i - D4); 1.36 + Dif[8] += abs(i + D4); 1.37 + Dif[9] += abs(i - channelDelta); 1.38 + Dif[10] += abs(i + channelDelta); 1.39 + 1.40 + channelDelta = LastDelta = (signed char)(realValue - LastChar); 1.41 + LastChar = realValue; 1.42 + 1.43 + if (((++ByteCount) & 0x1F) == 0) 1.44 + { 1.45 + UInt32 minDif = Dif[0]; 1.46 + UInt32 numMinDif = 0; 1.47 + Dif[0] = 0; 1.48 + for (i = 1; i < sizeof(Dif) / sizeof(Dif[0]); i++) 1.49 + { 1.50 + if (Dif[i] < minDif) 1.51 + { 1.52 + minDif = Dif[i]; 1.53 + numMinDif = i; 1.54 + } 1.55 + Dif[i] = 0; 1.56 + } 1.57 + switch(numMinDif) 1.58 + { 1.59 + case 1: if (K1 >= -16) K1--; break; 1.60 + case 2: if (K1 < 16) K1++; break; 1.61 + case 3: if (K2 >= -16) K2--; break; 1.62 + case 4: if (K2 < 16) K2++; break; 1.63 + case 5: if (K3 >= -16) K3--; break; 1.64 + case 6: if (K3 < 16) K3++; break; 1.65 + case 7: if (K4 >= -16) K4--; break; 1.66 + case 8: if (K4 < 16) K4++; break; 1.67 + case 9: if (K5 >= -16) K5--; break; 1.68 + case 10:if (K5 < 16) K5++; break; 1.69 + } 1.70 + } 1.71 + return realValue; 1.72 +} 1.73 +} 1.74 + 1.75 +static const char *kNumberErrorMessage = "Number error"; 1.76 + 1.77 +static const UInt32 kHistorySize = 1 << 20; 1.78 + 1.79 +static const int kNumStats = 11; 1.80 + 1.81 +static const UInt32 kWindowReservSize = (1 << 22) + 256; 1.82 + 1.83 +CDecoder::CDecoder(): 1.84 + m_IsSolid(false) 1.85 +{ 1.86 +} 1.87 + 1.88 +void CDecoder::InitStructures() 1.89 +{ 1.90 + m_MmFilter.Init(); 1.91 + for(int i = 0; i < kNumRepDists; i++) 1.92 + m_RepDists[i] = 0; 1.93 + m_RepDistPtr = 0; 1.94 + m_LastLength = 0; 1.95 + memset(m_LastLevels, 0, kMaxTableSize); 1.96 +} 1.97 + 1.98 +UInt32 CDecoder::ReadBits(int numBits) { return m_InBitStream.ReadBits(numBits); } 1.99 + 1.100 +#define RIF(x) { if (!(x)) return false; } 1.101 + 1.102 +bool CDecoder::ReadTables(void) 1.103 +{ 1.104 + Byte levelLevels[kLevelTableSize]; 1.105 + Byte newLevels[kMaxTableSize]; 1.106 + m_AudioMode = (ReadBits(1) == 1); 1.107 + 1.108 + if (ReadBits(1) == 0) 1.109 + memset(m_LastLevels, 0, kMaxTableSize); 1.110 + int numLevels; 1.111 + if (m_AudioMode) 1.112 + { 1.113 + m_NumChannels = ReadBits(2) + 1; 1.114 + if (m_MmFilter.CurrentChannel >= m_NumChannels) 1.115 + m_MmFilter.CurrentChannel = 0; 1.116 + numLevels = m_NumChannels * kMMTableSize; 1.117 + } 1.118 + else 1.119 + numLevels = kHeapTablesSizesSum; 1.120 + 1.121 + int i; 1.122 + for (i = 0; i < kLevelTableSize; i++) 1.123 + levelLevels[i] = (Byte)ReadBits(4); 1.124 + RIF(m_LevelDecoder.SetCodeLengths(levelLevels)); 1.125 + i = 0; 1.126 + while (i < numLevels) 1.127 + { 1.128 + UInt32 number = m_LevelDecoder.DecodeSymbol(&m_InBitStream); 1.129 + if (number < kTableDirectLevels) 1.130 + { 1.131 + newLevels[i] = (Byte)((number + m_LastLevels[i]) & kLevelMask); 1.132 + i++; 1.133 + } 1.134 + else 1.135 + { 1.136 + if (number == kTableLevelRepNumber) 1.137 + { 1.138 + int t = ReadBits(2) + 3; 1.139 + for (int reps = t; reps > 0 && i < numLevels ; reps--, i++) 1.140 + newLevels[i] = newLevels[i - 1]; 1.141 + } 1.142 + else 1.143 + { 1.144 + int num; 1.145 + if (number == kTableLevel0Number) 1.146 + num = ReadBits(3) + 3; 1.147 + else if (number == kTableLevel0Number2) 1.148 + num = ReadBits(7) + 11; 1.149 + else 1.150 + return false; 1.151 + for (;num > 0 && i < numLevels; num--) 1.152 + newLevels[i++] = 0; 1.153 + } 1.154 + } 1.155 + } 1.156 + if (m_AudioMode) 1.157 + for (i = 0; i < m_NumChannels; i++) 1.158 + { 1.159 + RIF(m_MMDecoders[i].SetCodeLengths(&newLevels[i * kMMTableSize])); 1.160 + } 1.161 + else 1.162 + { 1.163 + RIF(m_MainDecoder.SetCodeLengths(&newLevels[0])); 1.164 + RIF(m_DistDecoder.SetCodeLengths(&newLevels[kMainTableSize])); 1.165 + RIF(m_LenDecoder.SetCodeLengths(&newLevels[kMainTableSize + kDistTableSize])); 1.166 + } 1.167 + memcpy(m_LastLevels, newLevels, kMaxTableSize); 1.168 + return true; 1.169 +} 1.170 + 1.171 +bool CDecoder::ReadLastTables() 1.172 +{ 1.173 + // it differs a little from pure RAR sources; 1.174 + // UInt64 ttt = m_InBitStream.GetProcessedSize() + 2; 1.175 + // + 2 works for: return 0xFF; in CInBuffer::ReadByte. 1.176 + if (m_InBitStream.GetProcessedSize() + 7 <= m_PackSize) // test it: probably incorrect; 1.177 + // if (m_InBitStream.GetProcessedSize() + 2 <= m_PackSize) // test it: probably incorrect; 1.178 + if (m_AudioMode) 1.179 + { 1.180 + UInt32 symbol = m_MMDecoders[m_MmFilter.CurrentChannel].DecodeSymbol(&m_InBitStream); 1.181 + if (symbol == 256) 1.182 + return ReadTables(); 1.183 + if (symbol >= kMMTableSize) 1.184 + return false; 1.185 + } 1.186 + else 1.187 + { 1.188 + UInt32 number = m_MainDecoder.DecodeSymbol(&m_InBitStream); 1.189 + if (number == kReadTableNumber) 1.190 + return ReadTables(); 1.191 + if (number >= kMainTableSize) 1.192 + return false; 1.193 + } 1.194 + return true; 1.195 +} 1.196 + 1.197 +class CCoderReleaser 1.198 +{ 1.199 + CDecoder *m_Coder; 1.200 +public: 1.201 + CCoderReleaser(CDecoder *coder): m_Coder(coder) {} 1.202 + ~CCoderReleaser() 1.203 + { 1.204 + m_Coder->ReleaseStreams(); 1.205 + } 1.206 +}; 1.207 + 1.208 +bool CDecoder::DecodeMm(UInt32 pos) 1.209 +{ 1.210 + while (pos-- > 0) 1.211 + { 1.212 + UInt32 symbol = m_MMDecoders[m_MmFilter.CurrentChannel].DecodeSymbol(&m_InBitStream); 1.213 + if (symbol == 256) 1.214 + return true; 1.215 + if (symbol >= kMMTableSize) 1.216 + return false; 1.217 + /* 1.218 + Byte byPredict = m_Predictor.Predict(); 1.219 + Byte byReal = (Byte)(byPredict - (Byte)symbol); 1.220 + m_Predictor.Update(byReal, byPredict); 1.221 + */ 1.222 + Byte byReal = m_MmFilter.Decode((Byte)symbol); 1.223 + m_OutWindowStream.PutByte(byReal); 1.224 + if (++m_MmFilter.CurrentChannel == m_NumChannels) 1.225 + m_MmFilter.CurrentChannel = 0; 1.226 + } 1.227 + return true; 1.228 +} 1.229 + 1.230 +bool CDecoder::DecodeLz(Int32 pos) 1.231 +{ 1.232 + while (pos > 0) 1.233 + { 1.234 + UInt32 number = m_MainDecoder.DecodeSymbol(&m_InBitStream); 1.235 + UInt32 length, distance; 1.236 + if (number < 256) 1.237 + { 1.238 + m_OutWindowStream.PutByte(Byte(number)); 1.239 + pos--; 1.240 + continue; 1.241 + } 1.242 + else if (number >= kMatchNumber) 1.243 + { 1.244 + number -= kMatchNumber; 1.245 + length = kNormalMatchMinLen + UInt32(kLenStart[number]) + 1.246 + m_InBitStream.ReadBits(kLenDirectBits[number]); 1.247 + number = m_DistDecoder.DecodeSymbol(&m_InBitStream); 1.248 + if (number >= kDistTableSize) 1.249 + return false; 1.250 + distance = kDistStart[number] + m_InBitStream.ReadBits(kDistDirectBits[number]); 1.251 + if (distance >= kDistLimit3) 1.252 + { 1.253 + length += 2 - ((distance - kDistLimit4) >> 31); 1.254 + // length++; 1.255 + // if (distance >= kDistLimit4) 1.256 + // length++; 1.257 + } 1.258 + } 1.259 + else if (number == kRepBothNumber) 1.260 + { 1.261 + length = m_LastLength; 1.262 + distance = m_RepDists[(m_RepDistPtr + 4 - 1) & 3]; 1.263 + } 1.264 + else if (number < kLen2Number) 1.265 + { 1.266 + distance = m_RepDists[(m_RepDistPtr - (number - kRepNumber + 1)) & 3]; 1.267 + number = m_LenDecoder.DecodeSymbol(&m_InBitStream); 1.268 + if (number >= kLenTableSize) 1.269 + return false; 1.270 + length = 2 + kLenStart[number] + m_InBitStream.ReadBits(kLenDirectBits[number]); 1.271 + if (distance >= kDistLimit2) 1.272 + { 1.273 + length++; 1.274 + if (distance >= kDistLimit3) 1.275 + { 1.276 + length += 2 - ((distance - kDistLimit4) >> 31); 1.277 + // length++; 1.278 + // if (distance >= kDistLimit4) 1.279 + // length++; 1.280 + } 1.281 + } 1.282 + } 1.283 + else if (number < kReadTableNumber) 1.284 + { 1.285 + number -= kLen2Number; 1.286 + distance = kLen2DistStarts[number] + 1.287 + m_InBitStream.ReadBits(kLen2DistDirectBits[number]); 1.288 + length = 2; 1.289 + } 1.290 + else if (number == kReadTableNumber) 1.291 + return true; 1.292 + else 1.293 + return false; 1.294 + m_RepDists[m_RepDistPtr++ & 3] = distance; 1.295 + m_LastLength = length; 1.296 + if (!m_OutWindowStream.CopyBlock(distance, length)) 1.297 + return false; 1.298 + pos -= length; 1.299 + } 1.300 + return true; 1.301 +} 1.302 + 1.303 +HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, 1.304 + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) 1.305 +{ 1.306 + if (inSize == NULL || outSize == NULL) 1.307 + return E_INVALIDARG; 1.308 + 1.309 + if (!m_OutWindowStream.Create(kHistorySize)) 1.310 + return E_OUTOFMEMORY; 1.311 + if (!m_InBitStream.Create(1 << 20)) 1.312 + return E_OUTOFMEMORY; 1.313 + 1.314 + m_PackSize = *inSize; 1.315 + 1.316 + UInt64 pos = 0, unPackSize = *outSize; 1.317 + 1.318 + m_OutWindowStream.SetStream(outStream); 1.319 + m_OutWindowStream.Init(m_IsSolid); 1.320 + m_InBitStream.SetStream(inStream); 1.321 + m_InBitStream.Init(); 1.322 + 1.323 + CCoderReleaser coderReleaser(this); 1.324 + if (!m_IsSolid) 1.325 + { 1.326 + InitStructures(); 1.327 + if (unPackSize == 0) 1.328 + { 1.329 + if (m_InBitStream.GetProcessedSize() + 2 <= m_PackSize) // test it: probably incorrect; 1.330 + if (!ReadTables()) 1.331 + return S_FALSE; 1.332 + return S_OK; 1.333 + } 1.334 + if (!ReadTables()) 1.335 + return S_FALSE; 1.336 + } 1.337 + 1.338 + UInt64 startPos = m_OutWindowStream.GetProcessedSize(); 1.339 + while(pos < unPackSize) 1.340 + { 1.341 + UInt32 blockSize = 1 << 20; 1.342 + if (blockSize > unPackSize - pos) 1.343 + blockSize = (UInt32)(unPackSize - pos); 1.344 + UInt64 blockStartPos = m_OutWindowStream.GetProcessedSize(); 1.345 + if (m_AudioMode) 1.346 + { 1.347 + if (!DecodeMm(blockSize)) 1.348 + return S_FALSE; 1.349 + } 1.350 + else 1.351 + { 1.352 + if (!DecodeLz((Int32)blockSize)) 1.353 + return S_FALSE; 1.354 + } 1.355 + UInt64 globalPos = m_OutWindowStream.GetProcessedSize(); 1.356 + pos = globalPos - blockStartPos; 1.357 + if (pos < blockSize) 1.358 + if (!ReadTables()) 1.359 + return S_FALSE; 1.360 + pos = globalPos - startPos; 1.361 + if (progress != 0) 1.362 + { 1.363 + UInt64 packSize = m_InBitStream.GetProcessedSize(); 1.364 + RINOK(progress->SetRatioInfo(&packSize, &pos)); 1.365 + } 1.366 + } 1.367 + if (pos > unPackSize) 1.368 + return S_FALSE; 1.369 + 1.370 + if (!ReadLastTables()) 1.371 + return S_FALSE; 1.372 + return m_OutWindowStream.Flush(); 1.373 +} 1.374 + 1.375 +STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, 1.376 + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) 1.377 +{ 1.378 + try { return CodeReal(inStream, outStream, inSize, outSize, progress); } 1.379 + catch(const CInBufferException &e) { return e.ErrorCode; } 1.380 + catch(const CLzOutWindowException &e) { return e.ErrorCode; } 1.381 + catch(...) { return S_FALSE; } 1.382 +} 1.383 + 1.384 +STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size) 1.385 +{ 1.386 + if (size < 1) 1.387 + return E_INVALIDARG; 1.388 + m_IsSolid = (data[0] != 0); 1.389 + return S_OK; 1.390 +} 1.391 + 1.392 +}}