📄 zinflate.cpp
字号:
return false;
}
void Inflator::ProcessInput(bool flush)
{
while (true)
{
switch (m_state)
{
case PRE_STREAM:
if (!flush && m_inQueue.CurrentSize() < MaxPrestreamHeaderSize())
return;
ProcessPrestreamHeader();
m_state = WAIT_HEADER;
m_wrappedAround = false;
m_current = 0;
m_lastFlush = 0;
m_window.New(1 << GetLog2WindowSize());
break;
case WAIT_HEADER:
{
// maximum number of bytes before actual compressed data starts
const unsigned int MAX_HEADER_SIZE = BitsToBytes(3+5+5+4+19*7+286*15+19*15);
if (m_inQueue.CurrentSize() < (flush ? 1 : MAX_HEADER_SIZE))
return;
DecodeHeader();
break;
}
case DECODING_BODY:
if (!DecodeBody())
return;
break;
case POST_STREAM:
if (!flush && m_inQueue.CurrentSize() < MaxPoststreamTailSize())
return;
ProcessPoststreamTail();
m_state = m_repeat ? PRE_STREAM : AFTER_END;
Output(0, NULL, 0, GetAutoSignalPropagation(), true); // TODO: non-blocking
if (m_inQueue.IsEmpty())
return;
break;
case AFTER_END:
m_inQueue.TransferTo(*AttachedTransformation());
return;
}
}
}
void Inflator::DecodeHeader()
{
if (!m_reader.FillBuffer(3))
throw UnexpectedEndErr();
m_eof = m_reader.GetBits(1) != 0;
m_blockType = (byte)m_reader.GetBits(2);
switch (m_blockType)
{
case 0: // stored
{
m_reader.SkipBits(m_reader.BitsBuffered() % 8);
if (!m_reader.FillBuffer(32))
throw UnexpectedEndErr();
m_storedLen = (word16)m_reader.GetBits(16);
word16 nlen = (word16)m_reader.GetBits(16);
if (nlen != (word16)~m_storedLen)
throw BadBlockErr();
break;
}
case 1: // fixed codes
m_nextDecode = LITERAL;
break;
case 2: // dynamic codes
{
if (!m_reader.FillBuffer(5+5+4))
throw UnexpectedEndErr();
unsigned int hlit = m_reader.GetBits(5);
unsigned int hdist = m_reader.GetBits(5);
unsigned int hclen = m_reader.GetBits(4);
FixedSizeSecBlock<unsigned int, 286+32> codeLengths;
unsigned int i;
static const unsigned int border[] = { // Order of the bit length code lengths
16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
std::fill(codeLengths.begin(), codeLengths+19, 0);
for (i=0; i<hclen+4; i++)
codeLengths[border[i]] = m_reader.GetBits(3);
try
{
HuffmanDecoder codeLengthDecoder(codeLengths, 19);
for (i = 0; i < hlit+257+hdist+1; )
{
unsigned int k, count, repeater;
bool result = codeLengthDecoder.Decode(m_reader, k);
if (!result)
throw UnexpectedEndErr();
if (k <= 15)
{
count = 1;
repeater = k;
}
else switch (k)
{
case 16:
if (!m_reader.FillBuffer(2))
throw UnexpectedEndErr();
count = 3 + m_reader.GetBits(2);
if (i == 0)
throw BadBlockErr();
repeater = codeLengths[i-1];
break;
case 17:
if (!m_reader.FillBuffer(3))
throw UnexpectedEndErr();
count = 3 + m_reader.GetBits(3);
repeater = 0;
break;
case 18:
if (!m_reader.FillBuffer(7))
throw UnexpectedEndErr();
count = 11 + m_reader.GetBits(7);
repeater = 0;
break;
}
if (i + count > hlit+257+hdist+1)
throw BadBlockErr();
std::fill(codeLengths + i, codeLengths + i + count, repeater);
i += count;
}
m_dynamicLiteralDecoder.Initialize(codeLengths, hlit+257);
if (hdist == 0 && codeLengths[hlit+257] == 0)
{
if (hlit != 0) // a single zero distance code length means all literals
throw BadBlockErr();
}
else
m_dynamicDistanceDecoder.Initialize(codeLengths+hlit+257, hdist+1);
m_nextDecode = LITERAL;
}
catch (HuffmanDecoder::Err &)
{
throw BadBlockErr();
}
break;
}
default:
throw BadBlockErr(); // reserved block type
}
m_state = DECODING_BODY;
}
bool Inflator::DecodeBody()
{
bool blockEnd = false;
switch (m_blockType)
{
case 0: // stored
assert(m_reader.BitsBuffered() == 0);
while (!m_inQueue.IsEmpty() && !blockEnd)
{
unsigned int size;
const byte *block = m_inQueue.Spy(size);
size = STDMIN(size, (unsigned int)m_storedLen);
OutputString(block, size);
m_inQueue.Skip(size);
m_storedLen -= size;
if (m_storedLen == 0)
blockEnd = true;
}
break;
case 1: // fixed codes
case 2: // dynamic codes
static const unsigned int lengthStarts[] = {
3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258};
static const unsigned int lengthExtraBits[] = {
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0};
static const unsigned int distanceStarts[] = {
1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
8193, 12289, 16385, 24577};
static const unsigned int distanceExtraBits[] = {
0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
12, 12, 13, 13};
const HuffmanDecoder& literalDecoder = GetLiteralDecoder();
const HuffmanDecoder& distanceDecoder = GetDistanceDecoder();
switch (m_nextDecode)
{
case LITERAL:
while (true)
{
if (!literalDecoder.Decode(m_reader, m_literal))
{
m_nextDecode = LITERAL;
break;
}
if (m_literal < 256)
OutputByte((byte)m_literal);
else if (m_literal == 256) // end of block
{
blockEnd = true;
break;
}
else
{
if (m_literal > 285)
throw BadBlockErr();
unsigned int bits;
case LENGTH_BITS:
bits = lengthExtraBits[m_literal-257];
if (!m_reader.FillBuffer(bits))
{
m_nextDecode = LENGTH_BITS;
break;
}
m_literal = m_reader.GetBits(bits) + lengthStarts[m_literal-257];
case DISTANCE:
if (!distanceDecoder.Decode(m_reader, m_distance))
{
m_nextDecode = DISTANCE;
break;
}
case DISTANCE_BITS:
bits = distanceExtraBits[m_distance];
if (!m_reader.FillBuffer(bits))
{
m_nextDecode = DISTANCE_BITS;
break;
}
m_distance = m_reader.GetBits(bits) + distanceStarts[m_distance];
OutputPast(m_literal, m_distance);
}
}
}
}
if (blockEnd)
{
if (m_eof)
{
FlushOutput();
m_reader.SkipBits(m_reader.BitsBuffered()%8);
if (m_reader.BitsBuffered())
{
// undo too much lookahead
SecBlockWithHint<byte, 4> buffer(m_reader.BitsBuffered() / 8);
for (unsigned int i=0; i<buffer.size(); i++)
buffer[i] = (byte)m_reader.GetBits(8);
m_inQueue.Unget(buffer, buffer.size());
}
m_state = POST_STREAM;
}
else
m_state = WAIT_HEADER;
}
return blockEnd;
}
void Inflator::FlushOutput()
{
if (m_state != PRE_STREAM)
{
assert(m_current >= m_lastFlush);
ProcessDecompressedData(m_window + m_lastFlush, m_current - m_lastFlush);
m_lastFlush = m_current;
}
}
struct NewFixedLiteralDecoder
{
HuffmanDecoder * operator()() const
{
unsigned int codeLengths[288];
std::fill(codeLengths + 0, codeLengths + 144, 8);
std::fill(codeLengths + 144, codeLengths + 256, 9);
std::fill(codeLengths + 256, codeLengths + 280, 7);
std::fill(codeLengths + 280, codeLengths + 288, 8);
std::auto_ptr<HuffmanDecoder> pDecoder(new HuffmanDecoder);
pDecoder->Initialize(codeLengths, 288);
return pDecoder.release();
}
};
struct NewFixedDistanceDecoder
{
HuffmanDecoder * operator()() const
{
unsigned int codeLengths[32];
std::fill(codeLengths + 0, codeLengths + 32, 5);
std::auto_ptr<HuffmanDecoder> pDecoder(new HuffmanDecoder);
pDecoder->Initialize(codeLengths, 32);
return pDecoder.release();
}
};
const HuffmanDecoder& Inflator::GetLiteralDecoder() const
{
return m_blockType == 1 ? Singleton<HuffmanDecoder, NewFixedLiteralDecoder>().Ref() : m_dynamicLiteralDecoder;
}
const HuffmanDecoder& Inflator::GetDistanceDecoder() const
{
return m_blockType == 1 ? Singleton<HuffmanDecoder, NewFixedDistanceDecoder>().Ref() : m_dynamicDistanceDecoder;
}
NAMESPACE_END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -