Mercurial > vba-linux
view src/win32/7zip/7z/CPP/7zip/Compress/ImplodeDecoder.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 // Implode/Decoder.cpp3 #include "StdAfx.h"5 #include "ImplodeDecoder.h"6 #include "Common/Defs.h"8 namespace NCompress {9 namespace NImplode {10 namespace NDecoder {12 class CException13 {14 public:15 enum ECauseType16 {17 kData18 } m_Cause;19 CException(ECauseType cause): m_Cause(cause) {}20 };22 static const int kNumDistanceLowDirectBitsForBigDict = 7;23 static const int kNumDistanceLowDirectBitsForSmallDict = 6;25 static const int kNumBitsInByte = 8;27 // static const int kLevelStructuresNumberFieldSize = kNumBitsInByte;28 static const int kLevelStructuresNumberAdditionalValue = 1;30 static const int kNumLevelStructureLevelBits = 4;31 static const int kLevelStructureLevelAdditionalValue = 1;33 static const int kNumLevelStructureRepNumberBits = 4;34 static const int kLevelStructureRepNumberAdditionalValue = 1;37 static const int kLiteralTableSize = (1 << kNumBitsInByte);38 static const int kDistanceTableSize = 64;39 static const int kLengthTableSize = 64;41 static const UInt32 kHistorySize =42 (1 << MyMax(kNumDistanceLowDirectBitsForBigDict,43 kNumDistanceLowDirectBitsForSmallDict)) *44 kDistanceTableSize; // = 8 KB;46 static const int kNumAdditionalLengthBits = 8;48 static const UInt32 kMatchMinLenWhenLiteralsOn = 3;49 static const UInt32 kMatchMinLenWhenLiteralsOff = 2;51 static const UInt32 kMatchMinLenMax = MyMax(kMatchMinLenWhenLiteralsOn,52 kMatchMinLenWhenLiteralsOff); // 354 // static const UInt32 kMatchMaxLenMax = kMatchMinLenMax + (kLengthTableSize - 1) + (1 << kNumAdditionalLengthBits) - 1; // or 256 enum57 {58 kMatchId = 0,59 kLiteralId = 160 };63 CCoder::CCoder():64 m_LiteralDecoder(kLiteralTableSize),65 m_LengthDecoder(kLengthTableSize),66 m_DistanceDecoder(kDistanceTableSize)67 {68 }70 void CCoder::ReleaseStreams()71 {72 m_OutWindowStream.ReleaseStream();73 m_InBitStream.ReleaseStream();74 }76 bool CCoder::ReadLevelItems(NImplode::NHuffman::CDecoder &decoder,77 Byte *levels, int numLevelItems)78 {79 int numCodedStructures = m_InBitStream.ReadBits(kNumBitsInByte) +80 kLevelStructuresNumberAdditionalValue;81 int currentIndex = 0;82 for(int i = 0; i < numCodedStructures; i++)83 {84 int level = m_InBitStream.ReadBits(kNumLevelStructureLevelBits) +85 kLevelStructureLevelAdditionalValue;86 int rep = m_InBitStream.ReadBits(kNumLevelStructureRepNumberBits) +87 kLevelStructureRepNumberAdditionalValue;88 if (currentIndex + rep > numLevelItems)89 throw CException(CException::kData);90 for(int j = 0; j < rep; j++)91 levels[currentIndex++] = (Byte)level;92 }93 if (currentIndex != numLevelItems)94 return false;95 return decoder.SetCodeLengths(levels);96 }99 bool CCoder::ReadTables(void)100 {101 if (m_LiteralsOn)102 {103 Byte literalLevels[kLiteralTableSize];104 if (!ReadLevelItems(m_LiteralDecoder, literalLevels, kLiteralTableSize))105 return false;106 }108 Byte lengthLevels[kLengthTableSize];109 if (!ReadLevelItems(m_LengthDecoder, lengthLevels, kLengthTableSize))110 return false;112 Byte distanceLevels[kDistanceTableSize];113 return ReadLevelItems(m_DistanceDecoder, distanceLevels, kDistanceTableSize);114 }116 class CCoderReleaser117 {118 CCoder *m_Coder;119 public:120 CCoderReleaser(CCoder *coder): m_Coder(coder) {}121 ~CCoderReleaser() { m_Coder->ReleaseStreams(); }122 };124 HRESULT CCoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream,125 const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress)126 {127 if (!m_InBitStream.Create(1 << 20))128 return E_OUTOFMEMORY;129 if (!m_OutWindowStream.Create(kHistorySize))130 return E_OUTOFMEMORY;131 if (outSize == NULL)132 return E_INVALIDARG;133 UInt64 pos = 0, unPackSize = *outSize;135 m_OutWindowStream.SetStream(outStream);136 m_OutWindowStream.Init(false);137 m_InBitStream.SetStream(inStream);138 m_InBitStream.Init();139 CCoderReleaser coderReleaser(this);141 if (!ReadTables())142 return S_FALSE;144 while(pos < unPackSize)145 {146 if (progress != NULL && pos % (1 << 16) == 0)147 {148 UInt64 packSize = m_InBitStream.GetProcessedSize();149 RINOK(progress->SetRatioInfo(&packSize, &pos));150 }151 if(m_InBitStream.ReadBits(1) == kMatchId) // match152 {153 UInt32 lowDistBits = m_InBitStream.ReadBits(m_NumDistanceLowDirectBits);154 UInt32 distance = m_DistanceDecoder.DecodeSymbol(&m_InBitStream);155 if (distance >= kDistanceTableSize)156 return S_FALSE;157 distance = (distance << m_NumDistanceLowDirectBits) + lowDistBits;158 UInt32 lengthSymbol = m_LengthDecoder.DecodeSymbol(&m_InBitStream);159 if (lengthSymbol >= kLengthTableSize)160 return S_FALSE;161 UInt32 length = lengthSymbol + m_MinMatchLength;162 if (lengthSymbol == kLengthTableSize - 1) // special symbol = 63163 length += m_InBitStream.ReadBits(kNumAdditionalLengthBits);164 while(distance >= pos && length > 0)165 {166 m_OutWindowStream.PutByte(0);167 pos++;168 length--;169 }170 if (length > 0)171 m_OutWindowStream.CopyBlock(distance, length);172 pos += length;173 }174 else175 {176 Byte b;177 if (m_LiteralsOn)178 {179 UInt32 temp = m_LiteralDecoder.DecodeSymbol(&m_InBitStream);180 if (temp >= kLiteralTableSize)181 return S_FALSE;182 b = (Byte)temp;183 }184 else185 b = (Byte)m_InBitStream.ReadBits(kNumBitsInByte);186 m_OutWindowStream.PutByte(b);187 pos++;188 }189 }190 if (pos > unPackSize)191 return S_FALSE;192 return m_OutWindowStream.Flush();193 }195 STDMETHODIMP CCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,196 const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)197 {198 try { return CodeReal(inStream, outStream, inSize, outSize, progress); }199 catch(const CLzOutWindowException &e) { return e.ErrorCode; }200 catch(...) { return S_FALSE; }201 }203 STDMETHODIMP CCoder::SetDecoderProperties2(const Byte *data, UInt32 size)204 {205 if (size < 1)206 return E_INVALIDARG;207 Byte flag = data[0];208 m_BigDictionaryOn = ((flag & 2) != 0);209 m_NumDistanceLowDirectBits = m_BigDictionaryOn ?210 kNumDistanceLowDirectBitsForBigDict:211 kNumDistanceLowDirectBitsForSmallDict;212 m_LiteralsOn = ((flag & 4) != 0);213 m_MinMatchLength = m_LiteralsOn ?214 kMatchMinLenWhenLiteralsOn :215 kMatchMinLenWhenLiteralsOff;216 return S_OK;217 }219 }}}