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 }}}
|