1 // zinflate.cpp - originally written and placed in the public domain by Wei Dai
2 
3 // This is a complete reimplementation of the DEFLATE decompression algorithm.
4 // It should not be affected by any security vulnerabilities in the zlib
5 // compression library. In particular it is not affected by the double free bug
6 // (http://www.kb.cert.org/vuls/id/368819).
7 
8 #include "pch.h"
9 
10 #include "zinflate.h"
11 #include "secblock.h"
12 #include "smartptr.h"
13 
14 NAMESPACE_BEGIN(CryptoPP)
15 
16 struct CodeLessThan
17 {
operator ()CodeLessThan18 	inline bool operator()(CryptoPP::HuffmanDecoder::code_t lhs, const CryptoPP::HuffmanDecoder::CodeInfo &rhs)
19 		{return lhs < rhs.code;}
20 	// needed for MSVC .NET 2005
operator ()CodeLessThan21 	inline bool operator()(const CryptoPP::HuffmanDecoder::CodeInfo &lhs, const CryptoPP::HuffmanDecoder::CodeInfo &rhs)
22 		{return lhs.code < rhs.code;}
23 };
24 
FillBuffer(unsigned int length)25 inline bool LowFirstBitReader::FillBuffer(unsigned int length)
26 {
27 	while (m_bitsBuffered < length)
28 	{
29 		byte b;
30 		if (!m_store.Get(b))
31 			return false;
32 		m_buffer |= (unsigned long)b << m_bitsBuffered;
33 		m_bitsBuffered += 8;
34 	}
35 	CRYPTOPP_ASSERT(m_bitsBuffered <= sizeof(unsigned long)*8);
36 	return true;
37 }
38 
PeekBits(unsigned int length)39 inline unsigned long LowFirstBitReader::PeekBits(unsigned int length)
40 {
41 	bool result = FillBuffer(length);
42 	CRYPTOPP_UNUSED(result); CRYPTOPP_ASSERT(result);
43 	return m_buffer & (((unsigned long)1 << length) - 1);
44 }
45 
SkipBits(unsigned int length)46 inline void LowFirstBitReader::SkipBits(unsigned int length)
47 {
48 	CRYPTOPP_ASSERT(m_bitsBuffered >= length);
49 	m_buffer >>= length;
50 	m_bitsBuffered -= length;
51 }
52 
GetBits(unsigned int length)53 inline unsigned long LowFirstBitReader::GetBits(unsigned int length)
54 {
55 	unsigned long result = PeekBits(length);
56 	SkipBits(length);
57 	return result;
58 }
59 
NormalizeCode(HuffmanDecoder::code_t code,unsigned int codeBits)60 inline HuffmanDecoder::code_t HuffmanDecoder::NormalizeCode(HuffmanDecoder::code_t code, unsigned int codeBits)
61 {
62 	return code << (MAX_CODE_BITS - codeBits);
63 }
64 
Initialize(const unsigned int * codeBits,unsigned int nCodes)65 void HuffmanDecoder::Initialize(const unsigned int *codeBits, unsigned int nCodes)
66 {
67 	// the Huffman codes are represented in 3 ways in this code:
68 	//
69 	// 1. most significant code bit (i.e. top of code tree) in the least significant bit position
70 	// 2. most significant code bit (i.e. top of code tree) in the most significant bit position
71 	// 3. most significant code bit (i.e. top of code tree) in n-th least significant bit position,
72 	//    where n is the maximum code length for this code tree
73 	//
74 	// (1) is the way the codes come in from the deflate stream
75 	// (2) is used to sort codes so they can be binary searched
76 	// (3) is used in this function to compute codes from code lengths
77 	//
78 	// a code in representation (2) is called "normalized" here
79 	// The BitReverse() function is used to convert between (1) and (2)
80 	// The NormalizeCode() function is used to convert from (3) to (2)
81 
82 	if (nCodes == 0)
83 		throw Err("null code");
84 
85 	m_maxCodeBits = *std::max_element(codeBits, codeBits+nCodes);
86 
87 	if (m_maxCodeBits > MAX_CODE_BITS)
88 		throw Err("code length exceeds maximum");
89 
90 	if (m_maxCodeBits == 0)
91 		throw Err("null code");
92 
93 	// count number of codes of each length
94 	SecBlockWithHint<unsigned int, 15+1> blCount(m_maxCodeBits+1);
95 	std::fill(blCount.begin(), blCount.end(), 0);
96 	unsigned int i;
97 	for (i=0; i<nCodes; i++)
98 		blCount[codeBits[i]]++;
99 
100 	// compute the starting code of each length
101 	code_t code = 0;
102 	SecBlockWithHint<code_t, 15+1> nextCode(m_maxCodeBits+1);
103 	nextCode[1] = 0;
104 	for (i=2; i<=m_maxCodeBits; i++)
105 	{
106 		// compute this while checking for overflow: code = (code + blCount[i-1]) << 1
107 		if (code > code + blCount[i-1])
108 			throw Err("codes oversubscribed");
109 		code += blCount[i-1];
110 		if (code > (code << 1))
111 			throw Err("codes oversubscribed");
112 		code <<= 1;
113 		nextCode[i] = code;
114 	}
115 
116 	// MAX_CODE_BITS is 32, m_maxCodeBits may be smaller.
117 	const word64 shiftedMaxCode = ((word64)1 << m_maxCodeBits);
118 	if (code > shiftedMaxCode - blCount[m_maxCodeBits])
119 		throw Err("codes oversubscribed");
120 	else if (m_maxCodeBits != 1 && code < shiftedMaxCode - blCount[m_maxCodeBits])
121 		throw Err("codes incomplete");
122 
123 	// compute a vector of <code, length, value> triples sorted by code
124 	m_codeToValue.resize(nCodes - blCount[0]);
125 	unsigned int j=0;
126 	for (i=0; i<nCodes; i++)
127 	{
128 		unsigned int len = codeBits[i];
129 		if (len != 0)
130 		{
131 			CRYPTOPP_ASSERT(j < m_codeToValue.size());
132 			code = NormalizeCode(nextCode[len]++, len);
133 			m_codeToValue[j].code = code;
134 			m_codeToValue[j].len = len;
135 			m_codeToValue[j].value = i;
136 			j++;
137 		}
138 	}
139 	std::sort(m_codeToValue.begin(), m_codeToValue.end());
140 
141 	// initialize the decoding cache
142 	m_cacheBits = STDMIN(9U, m_maxCodeBits);
143 	m_cacheMask = (1 << m_cacheBits) - 1;
144 	m_normalizedCacheMask = NormalizeCode(m_cacheMask, m_cacheBits);
145 	CRYPTOPP_ASSERT(m_normalizedCacheMask == BitReverse(m_cacheMask));
146 
147 	const word64 shiftedCache = ((word64)1 << m_cacheBits);
148 	CRYPTOPP_ASSERT(shiftedCache <= SIZE_MAX);
149 	if (m_cache.size() != shiftedCache)
150 		m_cache.resize((size_t)shiftedCache);
151 
152 	for (i=0; i<m_cache.size(); i++)
153 		m_cache[i].type = 0;
154 }
155 
FillCacheEntry(LookupEntry & entry,code_t normalizedCode) const156 void HuffmanDecoder::FillCacheEntry(LookupEntry &entry, code_t normalizedCode) const
157 {
158 	normalizedCode &= m_normalizedCacheMask;
159 	const CodeInfo &codeInfo = *(std::upper_bound(m_codeToValue.begin(), m_codeToValue.end(), normalizedCode, CodeLessThan())-1);
160 	if (codeInfo.len <= m_cacheBits)
161 	{
162 		entry.type = 1;
163 		entry.value = codeInfo.value;
164 		entry.len = codeInfo.len;
165 	}
166 	else
167 	{
168 		entry.begin = &codeInfo;
169 		const CodeInfo *last = & *(std::upper_bound(m_codeToValue.begin(), m_codeToValue.end(), normalizedCode + ~m_normalizedCacheMask, CodeLessThan())-1);
170 		if (codeInfo.len == last->len)
171 		{
172 			entry.type = 2;
173 			entry.len = codeInfo.len;
174 		}
175 		else
176 		{
177 			entry.type = 3;
178 			entry.end = last+1;
179 		}
180 	}
181 }
182 
Decode(code_t code,value_t & value) const183 inline unsigned int HuffmanDecoder::Decode(code_t code, /* out */ value_t &value) const
184 {
185 	CRYPTOPP_ASSERT(((int)(code & m_cacheMask)) < (int)m_cache.size());
186 	LookupEntry &entry = m_cache[code & m_cacheMask];
187 
188 	code_t normalizedCode = 0;
189 	if (entry.type != 1)
190 		normalizedCode = BitReverse(code);
191 
192 	if (entry.type == 0)
193 		FillCacheEntry(entry, normalizedCode);
194 
195 	if (entry.type == 1)
196 	{
197 		value = entry.value;
198 		return entry.len;
199 	}
200 	else
201 	{
202 		const CodeInfo &codeInfo = (entry.type == 2)
203 			? entry.begin[(normalizedCode << m_cacheBits) >> (MAX_CODE_BITS - (entry.len - m_cacheBits))]
204 			: *(std::upper_bound(entry.begin, entry.end, normalizedCode, CodeLessThan())-1);
205 		value = codeInfo.value;
206 		return codeInfo.len;
207 	}
208 }
209 
Decode(LowFirstBitReader & reader,value_t & value) const210 bool HuffmanDecoder::Decode(LowFirstBitReader &reader, value_t &value) const
211 {
212 	bool result = reader.FillBuffer(m_maxCodeBits);
213 	CRYPTOPP_UNUSED(result); // CRYPTOPP_ASSERT(result);
214 
215 	unsigned int codeBits = Decode(reader.PeekBuffer(), value);
216 	if (codeBits > reader.BitsBuffered())
217 		return false;
218 	reader.SkipBits(codeBits);
219 	return true;
220 }
221 
222 // *************************************************************
223 
Inflator(BufferedTransformation * attachment,bool repeat,int propagation)224 Inflator::Inflator(BufferedTransformation *attachment, bool repeat, int propagation)
225 	: AutoSignaling<Filter>(propagation)
226 	, m_state(PRE_STREAM), m_repeat(repeat), m_eof(0), m_wrappedAround(0)
227 	, m_blockType(0xff), m_storedLen(0xffff), m_nextDecode(), m_literal(0)
228 	, m_distance(0), m_reader(m_inQueue), m_current(0), m_lastFlush(0)
229 {
230 	Detach(attachment);
231 }
232 
IsolatedInitialize(const NameValuePairs & parameters)233 void Inflator::IsolatedInitialize(const NameValuePairs &parameters)
234 {
235 	m_state = PRE_STREAM;
236 	parameters.GetValue("Repeat", m_repeat);
237 	m_inQueue.Clear();
238 	m_reader.SkipBits(m_reader.BitsBuffered());
239 }
240 
OutputByte(byte b)241 void Inflator::OutputByte(byte b)
242 {
243 	m_window[m_current++] = b;
244 	if (m_current == m_window.size())
245 	{
246 		ProcessDecompressedData(m_window + m_lastFlush, m_window.size() - m_lastFlush);
247 		m_lastFlush = 0;
248 		m_current = 0;
249 		m_wrappedAround = true;
250 	}
251 }
252 
OutputString(const byte * string,size_t length)253 void Inflator::OutputString(const byte *string, size_t length)
254 {
255 	while (length)
256 	{
257 		size_t len = UnsignedMin(length, m_window.size() - m_current);
258 		memcpy(m_window + m_current, string, len);
259 		m_current += len;
260 		if (m_current == m_window.size())
261 		{
262 			ProcessDecompressedData(m_window + m_lastFlush, m_window.size() - m_lastFlush);
263 			m_lastFlush = 0;
264 			m_current = 0;
265 			m_wrappedAround = true;
266 		}
267 		string += len;
268 		length -= len;
269 	}
270 }
271 
OutputPast(unsigned int length,unsigned int distance)272 void Inflator::OutputPast(unsigned int length, unsigned int distance)
273 {
274 	size_t start;
275 	if (distance <= m_current)
276 		start = m_current - distance;
277 	else if (m_wrappedAround && distance <= m_window.size())
278 		start = m_current + m_window.size() - distance;
279 	else
280 		throw BadBlockErr();
281 
282 	if (start + length > m_window.size())
283 	{
284 		for (; start < m_window.size(); start++, length--)
285 			OutputByte(m_window[start]);
286 		start = 0;
287 	}
288 
289 	if (start + length > m_current || m_current + length >= m_window.size())
290 	{
291 		while (length--)
292 			OutputByte(m_window[start++]);
293 	}
294 	else
295 	{
296 		memcpy(m_window + m_current, m_window + start, length);
297 		m_current += length;
298 	}
299 }
300 
Put2(const byte * inString,size_t length,int messageEnd,bool blocking)301 size_t Inflator::Put2(const byte *inString, size_t length, int messageEnd, bool blocking)
302 {
303 	if (!blocking)
304 		throw BlockingInputOnly("Inflator");
305 
306 	LazyPutter lp(m_inQueue, inString, length);
307 	ProcessInput(messageEnd != 0);
308 
309 	if (messageEnd)
310 		if (!(m_state == PRE_STREAM || m_state == AFTER_END))
311 			throw UnexpectedEndErr();
312 
313 	Output(0, NULLPTR, 0, messageEnd, blocking);
314 	return 0;
315 }
316 
IsolatedFlush(bool hardFlush,bool blocking)317 bool Inflator::IsolatedFlush(bool hardFlush, bool blocking)
318 {
319 	if (!blocking)
320 		throw BlockingInputOnly("Inflator");
321 
322 	if (hardFlush)
323 		ProcessInput(true);
324 	FlushOutput();
325 
326 	return false;
327 }
328 
ProcessInput(bool flush)329 void Inflator::ProcessInput(bool flush)
330 {
331 	while (true)
332 	{
333 		switch (m_state)
334 		{
335 		case PRE_STREAM:
336 			if (!flush && m_inQueue.CurrentSize() < MaxPrestreamHeaderSize())
337 				return;
338 			ProcessPrestreamHeader();
339 			m_state = WAIT_HEADER;
340 			m_wrappedAround = false;
341 			m_current = 0;
342 			m_lastFlush = 0;
343 			m_window.New(((size_t) 1) << GetLog2WindowSize());
344 			break;
345 		case WAIT_HEADER:
346 			{
347 			// maximum number of bytes before actual compressed data starts
348 			const size_t MAX_HEADER_SIZE = BitsToBytes(3+5+5+4+19*7+286*15+19*15);
349 			if (m_inQueue.CurrentSize() < (flush ? 1 : MAX_HEADER_SIZE))
350 				return;
351 			DecodeHeader();
352 			break;
353 			}
354 		case DECODING_BODY:
355 			if (!DecodeBody())
356 				return;
357 			break;
358 		case POST_STREAM:
359 			if (!flush && m_inQueue.CurrentSize() < MaxPoststreamTailSize())
360 				return;
361 			ProcessPoststreamTail();
362 			m_state = m_repeat ? PRE_STREAM : AFTER_END;
363 			Output(0, NULLPTR, 0, GetAutoSignalPropagation(), true);	// TODO: non-blocking
364 			if (m_inQueue.IsEmpty())
365 				return;
366 			break;
367 		case AFTER_END:
368 			m_inQueue.TransferTo(*AttachedTransformation());
369 			return;
370 		}
371 	}
372 }
373 
DecodeHeader()374 void Inflator::DecodeHeader()
375 {
376 	if (!m_reader.FillBuffer(3))
377 		throw UnexpectedEndErr();
378 	m_eof = m_reader.GetBits(1) != 0;
379 	m_blockType = (byte)m_reader.GetBits(2);
380 
381 	switch (m_blockType)
382 	{
383 	case 0:	// stored
384 		{
385 		m_reader.SkipBits(m_reader.BitsBuffered() % 8);
386 		if (!m_reader.FillBuffer(32))
387 			throw UnexpectedEndErr();
388 		m_storedLen = (word16)m_reader.GetBits(16);
389 		word16 nlen = (word16)m_reader.GetBits(16);
390 		if (nlen != (word16)~m_storedLen)
391 			throw BadBlockErr();
392 		break;
393 		}
394 	case 1:	// fixed codes
395 		m_nextDecode = LITERAL;
396 		break;
397 	case 2:	// dynamic codes
398 		{
399 		if (!m_reader.FillBuffer(5+5+4))
400 			throw UnexpectedEndErr();
401 		unsigned int hlit = m_reader.GetBits(5);
402 		unsigned int hdist = m_reader.GetBits(5);
403 		unsigned int hclen = m_reader.GetBits(4);
404 		unsigned int i = 0;
405 
406 		FixedSizeSecBlock<unsigned int, 286+32> codeLengths;
407 		static const unsigned int border[] = {    // Order of the bit length code lengths
408 			16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
409 		std::fill(codeLengths.begin(), codeLengths+19, 0);
410 		for (i=0; i<hclen+4; ++i)
411 		{
412 			CRYPTOPP_ASSERT(border[i] < codeLengths.size());
413 			codeLengths[border[i]] = m_reader.GetBits(3);
414 		}
415 
416 		try
417 		{
418 			bool result = false;
419 			unsigned int k=0, count=0, repeater=0;
420 			HuffmanDecoder codeLengthDecoder(codeLengths, 19);
421 			for (i=0; i < hlit+257+hdist+1; )
422 			{
423 				k = 0, count = 0, repeater = 0;
424 				result = codeLengthDecoder.Decode(m_reader, k);
425 				if (!result)
426 					throw UnexpectedEndErr();
427 				if (k <= 15)
428 				{
429 					count = 1;
430 					repeater = k;
431 				}
432 				else switch (k)
433 				{
434 				case 16:
435 					if (!m_reader.FillBuffer(2))
436 						throw UnexpectedEndErr();
437 					count = 3 + m_reader.GetBits(2);
438 					if (i == 0)
439 						throw BadBlockErr();
440 					repeater = codeLengths[i-1];
441 					break;
442 				case 17:
443 					if (!m_reader.FillBuffer(3))
444 						throw UnexpectedEndErr();
445 					count = 3 + m_reader.GetBits(3);
446 					repeater = 0;
447 					break;
448 				case 18:
449 					if (!m_reader.FillBuffer(7))
450 						throw UnexpectedEndErr();
451 					count = 11 + m_reader.GetBits(7);
452 					repeater = 0;
453 					break;
454 				}
455 				if (i + count > hlit+257+hdist+1)
456 					throw BadBlockErr();
457 				std::fill(codeLengths + i, codeLengths + i + count, repeater);
458 				i += count;
459 			}
460 			m_dynamicLiteralDecoder.Initialize(codeLengths, hlit+257);
461 			if (hdist == 0 && codeLengths[hlit+257] == 0)
462 			{
463 				if (hlit != 0)	// a single zero distance code length means all literals
464 					throw BadBlockErr();
465 			}
466 			else
467 				m_dynamicDistanceDecoder.Initialize(codeLengths+hlit+257, hdist+1);
468 			m_nextDecode = LITERAL;
469 		}
470 		catch (HuffmanDecoder::Err &)
471 		{
472 			throw BadBlockErr();
473 		}
474 		break;
475 		}
476 	default:
477 		throw BadBlockErr();	// reserved block type
478 	}
479 	m_state = DECODING_BODY;
480 }
481 
DecodeBody()482 bool Inflator::DecodeBody()
483 {
484 	bool blockEnd = false;
485 	switch (m_blockType)
486 	{
487 	case 0:	// stored
488 		CRYPTOPP_ASSERT(m_reader.BitsBuffered() == 0);
489 		while (!m_inQueue.IsEmpty() && !blockEnd)
490 		{
491 			size_t size;
492 			const byte *block = m_inQueue.Spy(size);
493 			size = UnsignedMin(m_storedLen, size);
494 			CRYPTOPP_ASSERT(size <= 0xffff);
495 
496 			OutputString(block, size);
497 			m_inQueue.Skip(size);
498 			m_storedLen = m_storedLen - (word16)size;
499 			if (m_storedLen == 0)
500 				blockEnd = true;
501 		}
502 		break;
503 	case 1:	// fixed codes
504 	case 2:	// dynamic codes
505 		static const unsigned int lengthStarts[] = {
506 			3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
507 			35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258};
508 		static const unsigned int lengthExtraBits[] = {
509 			0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
510 			3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0};
511 		static const unsigned int distanceStarts[] = {
512 			1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
513 			257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
514 			8193, 12289, 16385, 24577};
515 		static const unsigned int distanceExtraBits[] = {
516 			0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
517 			7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
518 			12, 12, 13, 13};
519 
520 		const HuffmanDecoder& literalDecoder = GetLiteralDecoder();
521 		const HuffmanDecoder& distanceDecoder = GetDistanceDecoder();
522 
523 		switch (m_nextDecode)
524 		{
525 		case LITERAL:
526 			while (true)
527 			{
528 				if (!literalDecoder.Decode(m_reader, m_literal))
529 				{
530 					m_nextDecode = LITERAL;
531 					break;
532 				}
533 				if (m_literal < 256)
534 					OutputByte((byte)m_literal);
535 				else if (m_literal == 256)	// end of block
536 				{
537 					blockEnd = true;
538 					break;
539 				}
540 				else
541 				{
542 					if (m_literal > 285)
543 						throw BadBlockErr();
544 					unsigned int bits;
545 		case LENGTH_BITS:
546 					CRYPTOPP_ASSERT(m_literal-257 < COUNTOF(lengthExtraBits));
547 					bits = lengthExtraBits[m_literal-257];
548 					if (!m_reader.FillBuffer(bits))
549 					{
550 						m_nextDecode = LENGTH_BITS;
551 						break;
552 					}
553 					CRYPTOPP_ASSERT(m_literal-257 < COUNTOF(lengthStarts));
554 					m_literal = m_reader.GetBits(bits) + lengthStarts[m_literal-257];
555 		case DISTANCE:
556 					if (!distanceDecoder.Decode(m_reader, m_distance))
557 					{
558 						m_nextDecode = DISTANCE;
559 						break;
560 					}
561 		case DISTANCE_BITS:
562 					CRYPTOPP_ASSERT(m_distance < COUNTOF(distanceExtraBits));
563 					if (m_distance >= COUNTOF(distanceExtraBits))
564 						throw BadDistanceErr();
565 					bits = distanceExtraBits[m_distance];
566 					if (!m_reader.FillBuffer(bits))
567 					{
568 						m_nextDecode = DISTANCE_BITS;
569 						break;
570 					}
571 					CRYPTOPP_ASSERT(m_distance < COUNTOF(distanceStarts));
572 					if (m_distance >= COUNTOF(distanceStarts))
573 						throw BadDistanceErr();
574 					m_distance = m_reader.GetBits(bits) + distanceStarts[m_distance];
575 					OutputPast(m_literal, m_distance);
576 				}
577 			}
578 			break;
579 		default:
580 			CRYPTOPP_ASSERT(0);
581 		}
582 	}
583 	if (blockEnd)
584 	{
585 		if (m_eof)
586 		{
587 			FlushOutput();
588 			m_reader.SkipBits(m_reader.BitsBuffered()%8);
589 			if (m_reader.BitsBuffered())
590 			{
591 				// undo too much lookahead
592 				SecBlockWithHint<byte, 4> buffer(m_reader.BitsBuffered() / 8);
593 				for (unsigned int i=0; i<buffer.size(); i++)
594 					buffer[i] = (byte)m_reader.GetBits(8);
595 				m_inQueue.Unget(buffer, buffer.size());
596 			}
597 			m_state = POST_STREAM;
598 		}
599 		else
600 			m_state = WAIT_HEADER;
601 	}
602 	return blockEnd;
603 }
604 
FlushOutput()605 void Inflator::FlushOutput()
606 {
607 	if (m_state != PRE_STREAM)
608 	{
609 		CRYPTOPP_ASSERT(m_current >= m_lastFlush);
610 		ProcessDecompressedData(m_window + m_lastFlush, m_current - m_lastFlush);
611 		m_lastFlush = m_current;
612 	}
613 }
614 
CreateFixedLiteralDecoder()615 void Inflator::CreateFixedLiteralDecoder()
616 {
617 	unsigned int codeLengths[288];
618 	std::fill(codeLengths + 0, codeLengths + 144, 8);
619 	std::fill(codeLengths + 144, codeLengths + 256, 9);
620 	std::fill(codeLengths + 256, codeLengths + 280, 7);
621 	std::fill(codeLengths + 280, codeLengths + 288, 8);
622 	m_fixedLiteralDecoder.reset(new HuffmanDecoder);
623 	m_fixedLiteralDecoder->Initialize(codeLengths, 288);
624 }
625 
CreateFixedDistanceDecoder()626 void Inflator::CreateFixedDistanceDecoder()
627 {
628 	unsigned int codeLengths[32];
629 	std::fill(codeLengths + 0, codeLengths + 32, 5);
630 	m_fixedDistanceDecoder.reset(new HuffmanDecoder);
631 	m_fixedDistanceDecoder->Initialize(codeLengths, 32);
632 }
633 
GetLiteralDecoder()634 const HuffmanDecoder& Inflator::GetLiteralDecoder()
635 {
636 	if (m_blockType == 1)
637 	{
638 		if (m_fixedLiteralDecoder.get() == NULLPTR)
639 			CreateFixedLiteralDecoder();
640 		return *m_fixedLiteralDecoder;
641 	}
642 	else
643 	{
644 		return m_dynamicLiteralDecoder;
645 	}
646 }
647 
GetDistanceDecoder()648 const HuffmanDecoder& Inflator::GetDistanceDecoder()
649 {
650 	if (m_blockType == 1)
651 	{
652 		if (m_fixedDistanceDecoder.get() == NULLPTR)
653 			CreateFixedDistanceDecoder();
654 		return *m_fixedDistanceDecoder;
655 	}
656 	else
657 	{
658 		return m_dynamicDistanceDecoder;
659 	}
660 }
661 
662 NAMESPACE_END
663