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