Mercurial > vba-linux
diff 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 diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/win32/7zip/7z/CPP/7zip/Compress/ImplodeDecoder.cpp Sat Mar 03 10:31:27 2012 -0600 1.3 @@ -0,0 +1,219 @@ 1.4 +// Implode/Decoder.cpp 1.5 + 1.6 +#include "StdAfx.h" 1.7 + 1.8 +#include "ImplodeDecoder.h" 1.9 +#include "Common/Defs.h" 1.10 + 1.11 +namespace NCompress { 1.12 +namespace NImplode { 1.13 +namespace NDecoder { 1.14 + 1.15 +class CException 1.16 +{ 1.17 +public: 1.18 + enum ECauseType 1.19 + { 1.20 + kData 1.21 + } m_Cause; 1.22 + CException(ECauseType cause): m_Cause(cause) {} 1.23 +}; 1.24 + 1.25 +static const int kNumDistanceLowDirectBitsForBigDict = 7; 1.26 +static const int kNumDistanceLowDirectBitsForSmallDict = 6; 1.27 + 1.28 +static const int kNumBitsInByte = 8; 1.29 + 1.30 +// static const int kLevelStructuresNumberFieldSize = kNumBitsInByte; 1.31 +static const int kLevelStructuresNumberAdditionalValue = 1; 1.32 + 1.33 +static const int kNumLevelStructureLevelBits = 4; 1.34 +static const int kLevelStructureLevelAdditionalValue = 1; 1.35 + 1.36 +static const int kNumLevelStructureRepNumberBits = 4; 1.37 +static const int kLevelStructureRepNumberAdditionalValue = 1; 1.38 + 1.39 + 1.40 +static const int kLiteralTableSize = (1 << kNumBitsInByte); 1.41 +static const int kDistanceTableSize = 64; 1.42 +static const int kLengthTableSize = 64; 1.43 + 1.44 +static const UInt32 kHistorySize = 1.45 + (1 << MyMax(kNumDistanceLowDirectBitsForBigDict, 1.46 + kNumDistanceLowDirectBitsForSmallDict)) * 1.47 + kDistanceTableSize; // = 8 KB; 1.48 + 1.49 +static const int kNumAdditionalLengthBits = 8; 1.50 + 1.51 +static const UInt32 kMatchMinLenWhenLiteralsOn = 3; 1.52 +static const UInt32 kMatchMinLenWhenLiteralsOff = 2; 1.53 + 1.54 +static const UInt32 kMatchMinLenMax = MyMax(kMatchMinLenWhenLiteralsOn, 1.55 + kMatchMinLenWhenLiteralsOff); // 3 1.56 + 1.57 +// static const UInt32 kMatchMaxLenMax = kMatchMinLenMax + (kLengthTableSize - 1) + (1 << kNumAdditionalLengthBits) - 1; // or 2 1.58 + 1.59 +enum 1.60 +{ 1.61 + kMatchId = 0, 1.62 + kLiteralId = 1 1.63 +}; 1.64 + 1.65 + 1.66 +CCoder::CCoder(): 1.67 + m_LiteralDecoder(kLiteralTableSize), 1.68 + m_LengthDecoder(kLengthTableSize), 1.69 + m_DistanceDecoder(kDistanceTableSize) 1.70 +{ 1.71 +} 1.72 + 1.73 +void CCoder::ReleaseStreams() 1.74 +{ 1.75 + m_OutWindowStream.ReleaseStream(); 1.76 + m_InBitStream.ReleaseStream(); 1.77 +} 1.78 + 1.79 +bool CCoder::ReadLevelItems(NImplode::NHuffman::CDecoder &decoder, 1.80 + Byte *levels, int numLevelItems) 1.81 +{ 1.82 + int numCodedStructures = m_InBitStream.ReadBits(kNumBitsInByte) + 1.83 + kLevelStructuresNumberAdditionalValue; 1.84 + int currentIndex = 0; 1.85 + for(int i = 0; i < numCodedStructures; i++) 1.86 + { 1.87 + int level = m_InBitStream.ReadBits(kNumLevelStructureLevelBits) + 1.88 + kLevelStructureLevelAdditionalValue; 1.89 + int rep = m_InBitStream.ReadBits(kNumLevelStructureRepNumberBits) + 1.90 + kLevelStructureRepNumberAdditionalValue; 1.91 + if (currentIndex + rep > numLevelItems) 1.92 + throw CException(CException::kData); 1.93 + for(int j = 0; j < rep; j++) 1.94 + levels[currentIndex++] = (Byte)level; 1.95 + } 1.96 + if (currentIndex != numLevelItems) 1.97 + return false; 1.98 + return decoder.SetCodeLengths(levels); 1.99 +} 1.100 + 1.101 + 1.102 +bool CCoder::ReadTables(void) 1.103 +{ 1.104 + if (m_LiteralsOn) 1.105 + { 1.106 + Byte literalLevels[kLiteralTableSize]; 1.107 + if (!ReadLevelItems(m_LiteralDecoder, literalLevels, kLiteralTableSize)) 1.108 + return false; 1.109 + } 1.110 + 1.111 + Byte lengthLevels[kLengthTableSize]; 1.112 + if (!ReadLevelItems(m_LengthDecoder, lengthLevels, kLengthTableSize)) 1.113 + return false; 1.114 + 1.115 + Byte distanceLevels[kDistanceTableSize]; 1.116 + return ReadLevelItems(m_DistanceDecoder, distanceLevels, kDistanceTableSize); 1.117 +} 1.118 + 1.119 +class CCoderReleaser 1.120 +{ 1.121 + CCoder *m_Coder; 1.122 +public: 1.123 + CCoderReleaser(CCoder *coder): m_Coder(coder) {} 1.124 + ~CCoderReleaser() { m_Coder->ReleaseStreams(); } 1.125 +}; 1.126 + 1.127 +HRESULT CCoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, 1.128 + const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress) 1.129 +{ 1.130 + if (!m_InBitStream.Create(1 << 20)) 1.131 + return E_OUTOFMEMORY; 1.132 + if (!m_OutWindowStream.Create(kHistorySize)) 1.133 + return E_OUTOFMEMORY; 1.134 + if (outSize == NULL) 1.135 + return E_INVALIDARG; 1.136 + UInt64 pos = 0, unPackSize = *outSize; 1.137 + 1.138 + m_OutWindowStream.SetStream(outStream); 1.139 + m_OutWindowStream.Init(false); 1.140 + m_InBitStream.SetStream(inStream); 1.141 + m_InBitStream.Init(); 1.142 + CCoderReleaser coderReleaser(this); 1.143 + 1.144 + if (!ReadTables()) 1.145 + return S_FALSE; 1.146 + 1.147 + while(pos < unPackSize) 1.148 + { 1.149 + if (progress != NULL && pos % (1 << 16) == 0) 1.150 + { 1.151 + UInt64 packSize = m_InBitStream.GetProcessedSize(); 1.152 + RINOK(progress->SetRatioInfo(&packSize, &pos)); 1.153 + } 1.154 + if(m_InBitStream.ReadBits(1) == kMatchId) // match 1.155 + { 1.156 + UInt32 lowDistBits = m_InBitStream.ReadBits(m_NumDistanceLowDirectBits); 1.157 + UInt32 distance = m_DistanceDecoder.DecodeSymbol(&m_InBitStream); 1.158 + if (distance >= kDistanceTableSize) 1.159 + return S_FALSE; 1.160 + distance = (distance << m_NumDistanceLowDirectBits) + lowDistBits; 1.161 + UInt32 lengthSymbol = m_LengthDecoder.DecodeSymbol(&m_InBitStream); 1.162 + if (lengthSymbol >= kLengthTableSize) 1.163 + return S_FALSE; 1.164 + UInt32 length = lengthSymbol + m_MinMatchLength; 1.165 + if (lengthSymbol == kLengthTableSize - 1) // special symbol = 63 1.166 + length += m_InBitStream.ReadBits(kNumAdditionalLengthBits); 1.167 + while(distance >= pos && length > 0) 1.168 + { 1.169 + m_OutWindowStream.PutByte(0); 1.170 + pos++; 1.171 + length--; 1.172 + } 1.173 + if (length > 0) 1.174 + m_OutWindowStream.CopyBlock(distance, length); 1.175 + pos += length; 1.176 + } 1.177 + else 1.178 + { 1.179 + Byte b; 1.180 + if (m_LiteralsOn) 1.181 + { 1.182 + UInt32 temp = m_LiteralDecoder.DecodeSymbol(&m_InBitStream); 1.183 + if (temp >= kLiteralTableSize) 1.184 + return S_FALSE; 1.185 + b = (Byte)temp; 1.186 + } 1.187 + else 1.188 + b = (Byte)m_InBitStream.ReadBits(kNumBitsInByte); 1.189 + m_OutWindowStream.PutByte(b); 1.190 + pos++; 1.191 + } 1.192 + } 1.193 + if (pos > unPackSize) 1.194 + return S_FALSE; 1.195 + return m_OutWindowStream.Flush(); 1.196 +} 1.197 + 1.198 +STDMETHODIMP CCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, 1.199 + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) 1.200 +{ 1.201 + try { return CodeReal(inStream, outStream, inSize, outSize, progress); } 1.202 + catch(const CLzOutWindowException &e) { return e.ErrorCode; } 1.203 + catch(...) { return S_FALSE; } 1.204 +} 1.205 + 1.206 +STDMETHODIMP CCoder::SetDecoderProperties2(const Byte *data, UInt32 size) 1.207 +{ 1.208 + if (size < 1) 1.209 + return E_INVALIDARG; 1.210 + Byte flag = data[0]; 1.211 + m_BigDictionaryOn = ((flag & 2) != 0); 1.212 + m_NumDistanceLowDirectBits = m_BigDictionaryOn ? 1.213 + kNumDistanceLowDirectBitsForBigDict: 1.214 + kNumDistanceLowDirectBitsForSmallDict; 1.215 + m_LiteralsOn = ((flag & 4) != 0); 1.216 + m_MinMatchLength = m_LiteralsOn ? 1.217 + kMatchMinLenWhenLiteralsOn : 1.218 + kMatchMinLenWhenLiteralsOff; 1.219 + return S_OK; 1.220 +} 1.221 + 1.222 +}}}