~zooko/cryptopp/trunk

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