Mercurial > vba-linux
comparison 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 |
comparison
equal
deleted
inserted
replaced
0:8ced16adf2e1 | 1:f9f4f1b99eed |
---|---|
1 // DeflateDecoder.cpp | |
2 | |
3 #include "StdAfx.h" | |
4 | |
5 #include "DeflateDecoder.h" | |
6 | |
7 namespace NCompress { | |
8 namespace NDeflate { | |
9 namespace NDecoder { | |
10 | |
11 static const int kLenIdFinished = -1; | |
12 static const int kLenIdNeedInit = -2; | |
13 | |
14 CCoder::CCoder(bool deflate64Mode, bool deflateNSIS): | |
15 _deflate64Mode(deflate64Mode), | |
16 _deflateNSIS(deflateNSIS), | |
17 _keepHistory(false), | |
18 ZlibMode(false) {} | |
19 | |
20 UInt32 CCoder::ReadBits(int numBits) | |
21 { | |
22 return m_InBitStream.ReadBits(numBits); | |
23 } | |
24 | |
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 } | |
60 | |
61 #define RIF(x) { if (!(x)) return false; } | |
62 | |
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; | |
69 | |
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 } | |
81 | |
82 m_StoredMode = false; | |
83 | |
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; | |
95 | |
96 if (!_deflate64Mode) | |
97 if (_numDistLevels > kDistTableSize32) | |
98 return false; | |
99 | |
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 } | |
109 | |
110 RIF(m_LevelDecoder.SetCodeLengths(levelLevels)); | |
111 | |
112 Byte tmpLevels[kFixedMainTableSize + kFixedDistTableSize]; | |
113 if (!DeCodeLevelTable(tmpLevels, numLitLenLevels + _numDistLevels)) | |
114 return false; | |
115 | |
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 } | |
123 | |
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 } | |
141 | |
142 if (curSize == 0) | |
143 return S_OK; | |
144 | |
145 while(_remainLen > 0 && curSize > 0) | |
146 { | |
147 _remainLen--; | |
148 Byte b = m_OutWindowStream.GetByte(_rep0); | |
149 m_OutWindowStream.PutByte(b); | |
150 curSize--; | |
151 } | |
152 | |
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 } | |
166 | |
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; | |
178 | |
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 } | |
233 | |
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); | |
241 | |
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 } | |
275 | |
276 | |
277 #ifdef _NO_EXCEPTIONS | |
278 | |
279 #define DEFLATE_TRY_BEGIN | |
280 #define DEFLATE_TRY_END | |
281 | |
282 #else | |
283 | |
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; } | |
289 | |
290 #endif | |
291 | |
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 } | |
299 | |
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 } | |
307 | |
308 STDMETHODIMP CCoder::SetInStream(ISequentialInStream *inStream) | |
309 { | |
310 m_InBitStream.SetStream(inStream); | |
311 return S_OK; | |
312 } | |
313 | |
314 STDMETHODIMP CCoder::ReleaseInStream() | |
315 { | |
316 m_InBitStream.ReleaseStream(); | |
317 return S_OK; | |
318 } | |
319 | |
320 STDMETHODIMP CCoder::SetOutStreamSize(const UInt64 * /* outSize */) | |
321 { | |
322 _remainLen = kLenIdNeedInit; | |
323 m_OutWindowStream.Init(_keepHistory); | |
324 return S_OK; | |
325 } | |
326 | |
327 #ifndef NO_READ_FROM_CODER | |
328 | |
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 } | |
342 | |
343 #endif | |
344 | |
345 }}} |