private NextStep Trawl(CompressedMetaBlockBuilder builder)
            {
                do
                {
                    uint hash = nextHash;
                    int  bytesBetweenHashLookups = (skip++) >> 5;

                    ip     = nextIp;
                    nextIp = ip + bytesBetweenHashLookups;

                    if (nextIp > ipLimit)
                    {
                        return(NextStep.EmitRemainder);
                    }

                    nextHash  = table.Hash(nextIp);
                    candidate = ip - lastDistance;

                    if (Match.Check(input, ip, candidate, MinMatchLen) && candidate < ip)
                    {
                        table[hash] = ip - baseIp;
                        break;
                    }

                    candidate   = baseIp + table[hash];
                    table[hash] = ip - baseIp;
                }while(!Match.Check(input, ip, candidate, MinMatchLen));

                if (ip - candidate > SupportedWindowSize.Bytes)
                {
                    return(NextStep.Trawl);
                }

                {
                    int @base    = ip;
                    int matched  = MinMatchLen + Match.DetermineLength(input, candidate + MinMatchLen, ip + MinMatchLen, ipEnd - ip - MinMatchLen);
                    int distance = @base - candidate;
                    int insert   = @base - nextEmit;

                    ip += matched;

                    if (insert >= 6210 && ShouldUseUncompressedMode(insert))
                    {
                        outputTo = @base;
                        return(NextStep.OutputUncompressed);
                    }

                    if (distance == lastDistance)
                    {
                        builder.AddInsertCopy(Literal.FromBytes(input, nextEmit, insert), 2, DistanceInfo.ExplicitCodeZero);
                    }
                    else
                    {
                        builder.AddInsertCopy(Literal.FromBytes(input, nextEmit, insert), 2, distance);
                        lastDistance = distance;
                    }

                    builder.AddCopy(matched - 2, distance);

                    nextEmit = ip;

                    if (ip >= ipLimit)
                    {
                        return(NextStep.EmitRemainder);
                    }

                    candidate = table.UpdateAndGetCandidate(ip, baseIp);
                }

                while (Match.Check(input, ip, candidate, MinMatchLen))
                {
                    int @base   = ip;
                    int matched = MinMatchLen + Match.DetermineLength(input, candidate + MinMatchLen, ip + MinMatchLen, ipEnd - ip - MinMatchLen);

                    if (ip - candidate > SupportedWindowSize.Bytes)
                    {
                        break;
                    }

                    ip          += matched;
                    lastDistance = @base - candidate;

                    builder.AddCopy(matched, lastDistance);
                    nextEmit = ip;

                    if (ip >= ipLimit)
                    {
                        return(NextStep.EmitRemainder);
                    }

                    candidate = table.UpdateAndGetCandidate(ip, baseIp);
                }

                nextHash = table.Hash(++ip);
                return(NextStep.EmitCommandsNextHash);
            }
Beispiel #2
0
 internal override int AddCommand(CompressedMetaBlockBuilder builder, IList <Literal> literals)
 {
     builder.AddInsertCopy(literals, OutputLength, Distance);
     return(OutputLength);
 }