Exemple #1
0
void Inflator::OutputPast(unsigned int length, unsigned int distance)
{
    size_t start;
    if (distance <= m_current)
        start = m_current - distance;
    else if (m_wrappedAround && distance <= m_window.size())
        start = m_current + m_window.size() - distance;
    else
        throw BadBlockErr();

    if (start + length > m_window.size())
    {
        for (; start < m_window.size(); start++, length--)
            OutputByte(m_window[start]);
        start = 0;
    }

    if (start + length > m_current || m_current + length >= m_window.size())
    {
        while (length--)
            OutputByte(m_window[start++]);
    }
    else
    {
        memcpy(m_window + m_current, m_window + start, length);
        m_current += length;
    }
}
Exemple #2
0
void Inflator::OutputPast(unsigned int length, unsigned int distance)
{
	if (distance > m_maxDistance)
		throw BadBlockErr();
	unsigned int start;
	if (m_current > distance)
		start = m_current - distance;
	else
		start = m_current + m_window.size - distance;

	if (start + length > m_window.size)
	{
		for (; start < m_window.size; start++, length--)
			OutputByte(m_window[start]);
		start = 0;
	}

	if (start + length > m_current || m_current + length >= m_window.size)
	{
		while (length--)
			OutputByte(m_window[start++]);
	}
	else
	{
		memcpy(m_window + m_current, m_window + start, length);
		m_current += length;
		m_maxDistance = STDMIN(m_window.size, m_maxDistance + length);
	}
}
Exemple #3
0
bool Inflator::DecodeBody()
{
    bool blockEnd = false;
    switch (m_blockType)
    {
    case 0:	// stored
        assert(m_reader.BitsBuffered() == 0);
        while (!m_inQueue.IsEmpty() && !blockEnd)
        {
            size_t size;
            const byte *block = m_inQueue.Spy(size);
            size = UnsignedMin(m_storedLen, size);
            OutputString(block, size);
            m_inQueue.Skip(size);
            m_storedLen -= (word16)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;
}
Exemple #4
0
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;
}