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.cpp
3 #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 do
29 {
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 else
44 {
45 int num;
46 if (number == kTableLevel0Number)
47 num = ReadBits(3) + 3;
48 else
49 num = ReadBits(7) + 11;
50 for (;num > 0 && i < numSymbols; num--)
51 values[i++] = 0;
52 }
53 }
54 else
55 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 else
91 {
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 else
107 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 else
203 {
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 else
228 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_EXCEPTIONS
279 #define DEFLATE_TRY_BEGIN
280 #define DEFLATE_TRY_END
282 #else
284 #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 #endif
292 HRESULT CCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
293 const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)
294 {
295 DEFLATE_TRY_BEGIN
296 return CodeReal(inStream, outStream, inSize, outSize, progress);
297 DEFLATE_TRY_END
298 }
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_CODER
329 STDMETHODIMP CCoder::Read(void *data, UInt32 size, UInt32 *processedSize)
330 {
331 DEFLATE_TRY_BEGIN
332 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_END
341 }
343 #endif
345 }}}