Ejemplo n.º 1
0
        private void DecompressAllTags()
        {
            Pointer ip = _ip;

            // We could have put this refill fragment only at the beginning of the loop.
            // However, duplicating it at the end of each branch gives the compiler more
            // scope to optimize the <ip_limit_ - ip> expression based on the local
            // context, which overall increases speed.
            Func <bool> maybeRefill = () =>
            {
                if (_ipLimit - ip < 5)
                {
                    _ip = ip;
                    if (!RefillTag())
                    {
                        return(false);
                    }

                    ip = _ip;
                }

                return(true);
            };

            if (!maybeRefill())
            {
                return;
            }

            for (; ;)
            {
                byte c = ip[0];
                ip = ip + 1;

                if ((c & 0x3) == CompressorTag.Literal)
                {
                    int literalLength = ((c >> 2) + 1);
                    if (_output.TryFastAppend(ip, _ipLimit - ip, literalLength))
                    {
                        Debug.Assert(literalLength < 61);
                        ip += literalLength;
                        if (!maybeRefill())
                        {
                            return;
                        }

                        continue;
                    }

                    if (literalLength >= 61)
                    {
                        int longLiteral = literalLength - 60;
                        literalLength = (int)((ip.ToUInt32() & Wordmask[longLiteral]) + 1);
                        ip           += longLiteral;
                    }

                    int avail = _ipLimit - ip;
                    while (avail < literalLength)
                    {
                        if (!_output.Append(ip, avail))
                        {
                            return;
                        }
                        literalLength -= avail;

                        Skip(_peeked);
                        int n;
                        ip      = Peek(out n);
                        avail   = n;
                        _peeked = avail;
                        if (avail == 0)
                        {
                            return; // Premature end of input
                        }
                        _ipLimit = ip + avail;
                    }
                    if (!_output.Append(ip, literalLength))
                    {
                        return;
                    }
                    ip += literalLength;
                    if (!maybeRefill())
                    {
                        return;
                    }
                }
                else
                {
                    int entry   = CharTable[c];
                    int trailer = (int)(ip.ToUInt32() & Wordmask[entry >> 11]);
                    int length  = entry & 0xff;
                    ip += entry >> 11;

                    // copy_offset/256 is encoded in bits 8..10.  By just fetching
                    // those bits, we get copy_offset (since the bit-field starts at
                    // bit 8).
                    int copyOffset = entry & 0x700;
                    if (!_output.AppendFromSelf(copyOffset + trailer, length))
                    {
                        return;
                    }
                    if (!maybeRefill())
                    {
                        return;
                    }
                }
            }
        }
Ejemplo n.º 2
0
 private void Skip(int peeked)
 {
     _ip += peeked;
 }