annotate 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
rev   line source
rlm@1 1 // DeflateDecoder.cpp
rlm@1 2
rlm@1 3 #include "StdAfx.h"
rlm@1 4
rlm@1 5 #include "DeflateDecoder.h"
rlm@1 6
rlm@1 7 namespace NCompress {
rlm@1 8 namespace NDeflate {
rlm@1 9 namespace NDecoder {
rlm@1 10
rlm@1 11 static const int kLenIdFinished = -1;
rlm@1 12 static const int kLenIdNeedInit = -2;
rlm@1 13
rlm@1 14 CCoder::CCoder(bool deflate64Mode, bool deflateNSIS):
rlm@1 15 _deflate64Mode(deflate64Mode),
rlm@1 16 _deflateNSIS(deflateNSIS),
rlm@1 17 _keepHistory(false),
rlm@1 18 ZlibMode(false) {}
rlm@1 19
rlm@1 20 UInt32 CCoder::ReadBits(int numBits)
rlm@1 21 {
rlm@1 22 return m_InBitStream.ReadBits(numBits);
rlm@1 23 }
rlm@1 24
rlm@1 25 bool CCoder::DeCodeLevelTable(Byte *values, int numSymbols)
rlm@1 26 {
rlm@1 27 int i = 0;
rlm@1 28 do
rlm@1 29 {
rlm@1 30 UInt32 number = m_LevelDecoder.DecodeSymbol(&m_InBitStream);
rlm@1 31 if (number < kTableDirectLevels)
rlm@1 32 values[i++] = (Byte)number;
rlm@1 33 else if (number < kLevelTableSize)
rlm@1 34 {
rlm@1 35 if (number == kTableLevelRepNumber)
rlm@1 36 {
rlm@1 37 if (i == 0)
rlm@1 38 return false;
rlm@1 39 int num = ReadBits(2) + 3;
rlm@1 40 for (; num > 0 && i < numSymbols; num--, i++)
rlm@1 41 values[i] = values[i - 1];
rlm@1 42 }
rlm@1 43 else
rlm@1 44 {
rlm@1 45 int num;
rlm@1 46 if (number == kTableLevel0Number)
rlm@1 47 num = ReadBits(3) + 3;
rlm@1 48 else
rlm@1 49 num = ReadBits(7) + 11;
rlm@1 50 for (;num > 0 && i < numSymbols; num--)
rlm@1 51 values[i++] = 0;
rlm@1 52 }
rlm@1 53 }
rlm@1 54 else
rlm@1 55 return false;
rlm@1 56 }
rlm@1 57 while(i < numSymbols);
rlm@1 58 return true;
rlm@1 59 }
rlm@1 60
rlm@1 61 #define RIF(x) { if (!(x)) return false; }
rlm@1 62
rlm@1 63 bool CCoder::ReadTables(void)
rlm@1 64 {
rlm@1 65 m_FinalBlock = (ReadBits(kFinalBlockFieldSize) == NFinalBlockField::kFinalBlock);
rlm@1 66 UInt32 blockType = ReadBits(kBlockTypeFieldSize);
rlm@1 67 if (blockType > NBlockType::kDynamicHuffman)
rlm@1 68 return false;
rlm@1 69
rlm@1 70 if (blockType == NBlockType::kStored)
rlm@1 71 {
rlm@1 72 m_StoredMode = true;
rlm@1 73 UInt32 currentBitPosition = m_InBitStream.GetBitPosition();
rlm@1 74 int numBitsForAlign = (int)(currentBitPosition > 0 ? (8 - currentBitPosition): 0);
rlm@1 75 ReadBits(numBitsForAlign);
rlm@1 76 m_StoredBlockSize = ReadBits(kStoredBlockLengthFieldSize);
rlm@1 77 if (_deflateNSIS)
rlm@1 78 return true;
rlm@1 79 return (m_StoredBlockSize == (UInt16)~ReadBits(kStoredBlockLengthFieldSize));
rlm@1 80 }
rlm@1 81
rlm@1 82 m_StoredMode = false;
rlm@1 83
rlm@1 84 CLevels levels;
rlm@1 85 if (blockType == NBlockType::kFixedHuffman)
rlm@1 86 {
rlm@1 87 levels.SetFixedLevels();
rlm@1 88 _numDistLevels = _deflate64Mode ? kDistTableSize64 : kDistTableSize32;
rlm@1 89 }
rlm@1 90 else
rlm@1 91 {
rlm@1 92 int numLitLenLevels = ReadBits(kNumLenCodesFieldSize) + kNumLitLenCodesMin;
rlm@1 93 _numDistLevels = ReadBits(kNumDistCodesFieldSize) + kNumDistCodesMin;
rlm@1 94 int numLevelCodes = ReadBits(kNumLevelCodesFieldSize) + kNumLevelCodesMin;
rlm@1 95
rlm@1 96 if (!_deflate64Mode)
rlm@1 97 if (_numDistLevels > kDistTableSize32)
rlm@1 98 return false;
rlm@1 99
rlm@1 100 Byte levelLevels[kLevelTableSize];
rlm@1 101 for (int i = 0; i < kLevelTableSize; i++)
rlm@1 102 {
rlm@1 103 int position = kCodeLengthAlphabetOrder[i];
rlm@1 104 if(i < numLevelCodes)
rlm@1 105 levelLevels[position] = (Byte)ReadBits(kLevelFieldSize);
rlm@1 106 else
rlm@1 107 levelLevels[position] = 0;
rlm@1 108 }
rlm@1 109
rlm@1 110 RIF(m_LevelDecoder.SetCodeLengths(levelLevels));
rlm@1 111
rlm@1 112 Byte tmpLevels[kFixedMainTableSize + kFixedDistTableSize];
rlm@1 113 if (!DeCodeLevelTable(tmpLevels, numLitLenLevels + _numDistLevels))
rlm@1 114 return false;
rlm@1 115
rlm@1 116 levels.SubClear();
rlm@1 117 memcpy(levels.litLenLevels, tmpLevels, numLitLenLevels);
rlm@1 118 memcpy(levels.distLevels, tmpLevels + numLitLenLevels, _numDistLevels);
rlm@1 119 }
rlm@1 120 RIF(m_MainDecoder.SetCodeLengths(levels.litLenLevels));
rlm@1 121 return m_DistDecoder.SetCodeLengths(levels.distLevels);
rlm@1 122 }
rlm@1 123
rlm@1 124 HRESULT CCoder::CodeSpec(UInt32 curSize)
rlm@1 125 {
rlm@1 126 if (_remainLen == kLenIdFinished)
rlm@1 127 return S_OK;
rlm@1 128 if (_remainLen == kLenIdNeedInit)
rlm@1 129 {
rlm@1 130 if (!_keepHistory)
rlm@1 131 if (!m_OutWindowStream.Create(_deflate64Mode ? kHistorySize64: kHistorySize32))
rlm@1 132 return E_OUTOFMEMORY;
rlm@1 133 if (!m_InBitStream.Create(1 << 17))
rlm@1 134 return E_OUTOFMEMORY;
rlm@1 135 m_OutWindowStream.Init(_keepHistory);
rlm@1 136 m_InBitStream.Init();
rlm@1 137 m_FinalBlock = false;
rlm@1 138 _remainLen = 0;
rlm@1 139 _needReadTable = true;
rlm@1 140 }
rlm@1 141
rlm@1 142 if (curSize == 0)
rlm@1 143 return S_OK;
rlm@1 144
rlm@1 145 while(_remainLen > 0 && curSize > 0)
rlm@1 146 {
rlm@1 147 _remainLen--;
rlm@1 148 Byte b = m_OutWindowStream.GetByte(_rep0);
rlm@1 149 m_OutWindowStream.PutByte(b);
rlm@1 150 curSize--;
rlm@1 151 }
rlm@1 152
rlm@1 153 while(curSize > 0)
rlm@1 154 {
rlm@1 155 if (_needReadTable)
rlm@1 156 {
rlm@1 157 if (m_FinalBlock)
rlm@1 158 {
rlm@1 159 _remainLen = kLenIdFinished;
rlm@1 160 break;
rlm@1 161 }
rlm@1 162 if (!ReadTables())
rlm@1 163 return S_FALSE;
rlm@1 164 _needReadTable = false;
rlm@1 165 }
rlm@1 166
rlm@1 167 if(m_StoredMode)
rlm@1 168 {
rlm@1 169 for (; m_StoredBlockSize > 0 && curSize > 0; m_StoredBlockSize--, curSize--)
rlm@1 170 m_OutWindowStream.PutByte((Byte)m_InBitStream.ReadBits(8));
rlm@1 171 _needReadTable = (m_StoredBlockSize == 0);
rlm@1 172 continue;
rlm@1 173 }
rlm@1 174 while(curSize > 0)
rlm@1 175 {
rlm@1 176 if (m_InBitStream.NumExtraBytes > 4)
rlm@1 177 return S_FALSE;
rlm@1 178
rlm@1 179 UInt32 number = m_MainDecoder.DecodeSymbol(&m_InBitStream);
rlm@1 180 if (number < 0x100)
rlm@1 181 {
rlm@1 182 m_OutWindowStream.PutByte((Byte)number);
rlm@1 183 curSize--;
rlm@1 184 continue;
rlm@1 185 }
rlm@1 186 else if (number == kSymbolEndOfBlock)
rlm@1 187 {
rlm@1 188 _needReadTable = true;
rlm@1 189 break;
rlm@1 190 }
rlm@1 191 else if (number < kMainTableSize)
rlm@1 192 {
rlm@1 193 number -= kSymbolMatch;
rlm@1 194 UInt32 len;
rlm@1 195 {
rlm@1 196 int numBits;
rlm@1 197 if (_deflate64Mode)
rlm@1 198 {
rlm@1 199 len = kLenStart64[number];
rlm@1 200 numBits = kLenDirectBits64[number];
rlm@1 201 }
rlm@1 202 else
rlm@1 203 {
rlm@1 204 len = kLenStart32[number];
rlm@1 205 numBits = kLenDirectBits32[number];
rlm@1 206 }
rlm@1 207 len += kMatchMinLen + m_InBitStream.ReadBits(numBits);
rlm@1 208 }
rlm@1 209 UInt32 locLen = len;
rlm@1 210 if (locLen > curSize)
rlm@1 211 locLen = (UInt32)curSize;
rlm@1 212 number = m_DistDecoder.DecodeSymbol(&m_InBitStream);
rlm@1 213 if (number >= _numDistLevels)
rlm@1 214 return S_FALSE;
rlm@1 215 UInt32 distance = kDistStart[number] + m_InBitStream.ReadBits(kDistDirectBits[number]);
rlm@1 216 if (!m_OutWindowStream.CopyBlock(distance, locLen))
rlm@1 217 return S_FALSE;
rlm@1 218 curSize -= locLen;
rlm@1 219 len -= locLen;
rlm@1 220 if (len != 0)
rlm@1 221 {
rlm@1 222 _remainLen = (Int32)len;
rlm@1 223 _rep0 = distance;
rlm@1 224 break;
rlm@1 225 }
rlm@1 226 }
rlm@1 227 else
rlm@1 228 return S_FALSE;
rlm@1 229 }
rlm@1 230 }
rlm@1 231 return S_OK;
rlm@1 232 }
rlm@1 233
rlm@1 234 HRESULT CCoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream,
rlm@1 235 const UInt64 *, const UInt64 *outSize, ICompressProgressInfo *progress)
rlm@1 236 {
rlm@1 237 SetInStream(inStream);
rlm@1 238 m_OutWindowStream.SetStream(outStream);
rlm@1 239 SetOutStreamSize(outSize);
rlm@1 240 CCoderReleaser flusher(this);
rlm@1 241
rlm@1 242 const UInt64 start = m_OutWindowStream.GetProcessedSize();
rlm@1 243 for (;;)
rlm@1 244 {
rlm@1 245 UInt32 curSize = 1 << 18;
rlm@1 246 if (outSize != 0)
rlm@1 247 {
rlm@1 248 const UInt64 rem = *outSize - (m_OutWindowStream.GetProcessedSize() - start);
rlm@1 249 if (curSize > rem)
rlm@1 250 curSize = (UInt32)rem;
rlm@1 251 }
rlm@1 252 if (curSize == 0)
rlm@1 253 break;
rlm@1 254 RINOK(CodeSpec(curSize));
rlm@1 255 if (_remainLen == kLenIdFinished)
rlm@1 256 break;
rlm@1 257 if (progress != NULL)
rlm@1 258 {
rlm@1 259 const UInt64 inSize = m_InBitStream.GetProcessedSize();
rlm@1 260 const UInt64 nowPos64 = m_OutWindowStream.GetProcessedSize() - start;
rlm@1 261 RINOK(progress->SetRatioInfo(&inSize, &nowPos64));
rlm@1 262 }
rlm@1 263 }
rlm@1 264 if (_remainLen == kLenIdFinished && ZlibMode)
rlm@1 265 {
rlm@1 266 UInt32 currentBitPosition = m_InBitStream.GetBitPosition();
rlm@1 267 int numBitsForAlign = (int)(currentBitPosition > 0 ? (8 - currentBitPosition): 0);
rlm@1 268 ReadBits(numBitsForAlign);
rlm@1 269 for (int i = 0; i < 4; i++)
rlm@1 270 ZlibFooter[i] = (Byte)m_InBitStream.ReadBits(8);
rlm@1 271 }
rlm@1 272 flusher.NeedFlush = false;
rlm@1 273 return Flush();
rlm@1 274 }
rlm@1 275
rlm@1 276
rlm@1 277 #ifdef _NO_EXCEPTIONS
rlm@1 278
rlm@1 279 #define DEFLATE_TRY_BEGIN
rlm@1 280 #define DEFLATE_TRY_END
rlm@1 281
rlm@1 282 #else
rlm@1 283
rlm@1 284 #define DEFLATE_TRY_BEGIN try {
rlm@1 285 #define DEFLATE_TRY_END } \
rlm@1 286 catch(const CInBufferException &e) { return e.ErrorCode; } \
rlm@1 287 catch(const CLzOutWindowException &e) { return e.ErrorCode; } \
rlm@1 288 catch(...) { return S_FALSE; }
rlm@1 289
rlm@1 290 #endif
rlm@1 291
rlm@1 292 HRESULT CCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
rlm@1 293 const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)
rlm@1 294 {
rlm@1 295 DEFLATE_TRY_BEGIN
rlm@1 296 return CodeReal(inStream, outStream, inSize, outSize, progress);
rlm@1 297 DEFLATE_TRY_END
rlm@1 298 }
rlm@1 299
rlm@1 300 STDMETHODIMP CCoder::GetInStreamProcessedSize(UInt64 *value)
rlm@1 301 {
rlm@1 302 if (value == NULL)
rlm@1 303 return E_INVALIDARG;
rlm@1 304 *value = m_InBitStream.GetProcessedSize();
rlm@1 305 return S_OK;
rlm@1 306 }
rlm@1 307
rlm@1 308 STDMETHODIMP CCoder::SetInStream(ISequentialInStream *inStream)
rlm@1 309 {
rlm@1 310 m_InBitStream.SetStream(inStream);
rlm@1 311 return S_OK;
rlm@1 312 }
rlm@1 313
rlm@1 314 STDMETHODIMP CCoder::ReleaseInStream()
rlm@1 315 {
rlm@1 316 m_InBitStream.ReleaseStream();
rlm@1 317 return S_OK;
rlm@1 318 }
rlm@1 319
rlm@1 320 STDMETHODIMP CCoder::SetOutStreamSize(const UInt64 * /* outSize */)
rlm@1 321 {
rlm@1 322 _remainLen = kLenIdNeedInit;
rlm@1 323 m_OutWindowStream.Init(_keepHistory);
rlm@1 324 return S_OK;
rlm@1 325 }
rlm@1 326
rlm@1 327 #ifndef NO_READ_FROM_CODER
rlm@1 328
rlm@1 329 STDMETHODIMP CCoder::Read(void *data, UInt32 size, UInt32 *processedSize)
rlm@1 330 {
rlm@1 331 DEFLATE_TRY_BEGIN
rlm@1 332 if (processedSize)
rlm@1 333 *processedSize = 0;
rlm@1 334 const UInt64 startPos = m_OutWindowStream.GetProcessedSize();
rlm@1 335 m_OutWindowStream.SetMemStream((Byte *)data);
rlm@1 336 RINOK(CodeSpec(size));
rlm@1 337 if (processedSize)
rlm@1 338 *processedSize = (UInt32)(m_OutWindowStream.GetProcessedSize() - startPos);
rlm@1 339 return Flush();
rlm@1 340 DEFLATE_TRY_END
rlm@1 341 }
rlm@1 342
rlm@1 343 #endif
rlm@1 344
rlm@1 345 }}}