Ejemplo n.º 1
0
 public FastEncoder(bool doGZip) {
     this.usingGzip = doGZip;
     this.inputWindow = new FastEncoderWindow();
     this.inputBuffer = new DeflateInput();
     this.output = new Output();
     this.currentMatch = new Match();
 }
Ejemplo n.º 2
0
        public override void Close()
        {
            if (stream != null)
            {
                if (mode == CompressionMode.Decompress)
                {
                    readBuf = null;
                }
                else
                {
                    int maxByteCount = 0;
                    for (int i = 0; i < byteCount.Length; i++)
                    {
                        if (byteCount[i] > maxByteCount)
                        {
                            compressByte = (byte)i;
                            maxByteCount = byteCount[i];
                        }
                    }

                    BinaryWriter writer = new BinaryWriter(stream);
                    writer.Write(compressByte);
                    writer.Write((int)writeBuf.Length);

                    byte[] inputBuf = writeBuf.GetBuffer();
                    int bufLength = (int)writeBuf.Length;
                    int windowStart = 0;
                    int windowEnd = 0;
                    for (int i = 0; i < bufLength; )
                    {
                        Match maxMatch = new Match();
                        int maxMatchLength = 0;
                        for (int windowIdx = windowStart; windowIdx < windowEnd; windowIdx++)
                        {
                            int blockSize = 0;
                            int numBlocks = 1;
                            if (inputBuf[i] == inputBuf[windowIdx])
                            {
                                for (int k = 1; k < 0xFF; k++)
                                {
                                    blockSize++;
                                    int offset = i + k;
                                    if ((offset >= bufLength) || ((windowIdx + k) >= windowEnd) || (inputBuf[offset] != inputBuf[windowIdx + k]))
                                    {
                                        break;
                                    }
                                }

                                for (int k = 1; k < 0xFF; k++)
                                {
                                    bool addBlock = true;
                                    for (int m = 0; m < blockSize; m++)
                                    {
                                        int offset = i + (blockSize * k) + m;
                                        if ((offset >= bufLength) || (inputBuf[offset] != inputBuf[windowIdx + m]))
                                        {
                                            addBlock = false;
                                            break;
                                        }
                                    }
                                    if (addBlock)
                                    {
                                        numBlocks++;
                                    }
                                    else
                                    {
                                        break;
                                    }
                                }

                                int matchLength = blockSize * numBlocks;
                                if (matchLength > maxMatchLength)
                                {
                                    maxMatch.blockSize = blockSize;
                                    maxMatch.numBlocks = numBlocks;
                                    maxMatch.distance = i - windowIdx;
                                    maxMatch.length = matchLength;
                                    maxMatchLength = matchLength;
                                }
                            }
                        }

                        int windowOffset = 1;
                        if (maxMatchLength > 4)
                        {
                            writer.Write(compressByte);
                            if (maxMatch.distance == compressByte)
                            {
                                writer.Write((byte)0);
                            }
                            else
                            {
                                writer.Write((byte)maxMatch.distance);
                            }
                            writer.Write((byte)maxMatch.blockSize);
                            writer.Write((byte)maxMatch.numBlocks);
                            i += maxMatch.length;
                            windowOffset = maxMatch.length;
                        }
                        else
                        {
                            WriteSingleByte(writer, inputBuf[i], compressByte);
                            i++;
                        }

                        windowEnd += windowOffset;
                        int windowSize = windowEnd - windowStart;
                        if (windowSize >= 0xFF)
                        {
                            windowStart += windowSize - 0xFF;
                        }
                    }

                    writeBuf.Close();
                    writeBuf = null;
                    byteCount = null;
                }

                if (!leaveOpen)
                {
                    stream.Close();
                }

                stream = null;
            }
        }
Ejemplo n.º 3
0
        //
        // Find out what we should generate next. It can be a symbol, a distance/length pair
        // or a symbol followed by distance/length pair
        //
        internal bool GetNextSymbolOrMatch(Match match)
        {
            Debug.Assert(_bufPos >= FastEncoderWindowSize && _bufPos < (2 * FastEncoderWindowSize), "Invalid Buffer Position!");

            // initialise the value of the hash, no problem if locations bufPos, bufPos+1 
            // are invalid (not enough data), since we will never insert using that hash value
            uint hash = HashValue(0, _window[_bufPos]);
            hash = HashValue(hash, _window[_bufPos + 1]);

            int matchLen;
            int matchPos = 0;

            VerifyHashes();   // Debug only code
            if (_bufEnd - _bufPos <= 3)
            {
                // The hash value becomes corrupt when we get within 3 characters of the end of the
                // input window, since the hash value is based on 3 characters.  We just stop
                // inserting into the hash table at this point, and allow no matches.
                matchLen = 0;
            }
            else
            {
                // insert string into hash table and return most recent location of same hash value
                int search = (int)InsertString(ref hash);

                // did we find a recent location of this hash value?
                if (search != 0)
                {
                    // yes, now find a match at what we'll call position X
                    matchLen = FindMatch(search, out matchPos, SearchDepth, NiceLength);

                    // truncate match if we're too close to the end of the input window
                    if (_bufPos + matchLen > _bufEnd)
                        matchLen = _bufEnd - _bufPos;
                }
                else
                {
                    // no most recent location found
                    matchLen = 0;
                }
            }

            if (matchLen < MinMatch)
            {
                // didn't find a match, so output unmatched char
                match.State = MatchState.HasSymbol;
                match.Symbol = _window[_bufPos];
                _bufPos++;
            }
            else
            {
                // bufPos now points to X+1
                _bufPos++;

                // is this match so good (long) that we should take it automatically without
                // checking X+1 ?
                if (matchLen <= LazyMatchThreshold)
                {
                    int nextMatchLen;
                    int nextMatchPos = 0;

                    // search at position X+1
                    int search = (int)InsertString(ref hash);

                    // no, so check for a better match at X+1
                    if (search != 0)
                    {
                        nextMatchLen = FindMatch(search, out nextMatchPos,
                                                   matchLen < GoodLength ? SearchDepth : (SearchDepth >> 2), NiceLength);

                        // truncate match if we're too close to the end of the window
                        // note: nextMatchLen could now be < MinMatch
                        if (_bufPos + nextMatchLen > _bufEnd)
                        {
                            nextMatchLen = _bufEnd - _bufPos;
                        }
                    }
                    else
                    {
                        nextMatchLen = 0;
                    }

                    // right now X and X+1 are both inserted into the search tree
                    if (nextMatchLen > matchLen)
                    {
                        // since nextMatchLen > matchLen, it can't be < MinMatch here

                        // match at X+1 is better, so output unmatched char at X
                        match.State = MatchState.HasSymbolAndMatch;
                        match.Symbol = _window[_bufPos - 1];
                        match.Position = nextMatchPos;
                        match.Length = nextMatchLen;

                        // insert remainder of second match into search tree            
                        // example: (*=inserted already)
                        //
                        // X      X+1               X+2      X+3     X+4
                        // *      *
                        //        nextmatchlen=3
                        //        bufPos
                        //
                        // If nextMatchLen == 3, we want to perform 2
                        // insertions (at X+2 and X+3).  However, first we must 
                        // inc bufPos.
                        //
                        _bufPos++; // now points to X+2
                        matchLen = nextMatchLen;
                        InsertStrings(ref hash, matchLen);
                    }
                    else
                    {
                        // match at X is better, so take it
                        match.State = MatchState.HasMatch;
                        match.Position = matchPos;
                        match.Length = matchLen;

                        // Insert remainder of first match into search tree, minus the first
                        // two locations, which were inserted by the FindMatch() calls.
                        // 
                        // For example, if matchLen == 3, then we've inserted at X and X+1
                        // already (and bufPos is now pointing at X+1), and now we need to insert 
                        // only at X+2.
                        //
                        matchLen--;
                        _bufPos++; // now bufPos points to X+2
                        InsertStrings(ref hash, matchLen);
                    }
                }
                else
                { // match_length >= good_match 
                    // in assertion: bufPos points to X+1, location X inserted already
                    // first match is so good that we're not even going to check at X+1
                    match.State = MatchState.HasMatch;
                    match.Position = matchPos;
                    match.Length = matchLen;

                    // insert remainder of match at X into search tree
                    InsertStrings(ref hash, matchLen);
                }
            }

            if (_bufPos == 2 * FastEncoderWindowSize)
            {
                MoveWindows();
            }
            return true;
        }
Ejemplo n.º 4
0
 public FastEncoder() {
     inputWindow = new FastEncoderWindow();
     currentMatch = new Match();
 }
 internal bool GetNextSymbolOrMatch(Match match)
 {
     int num2;
     uint hash = this.HashValue(0, this.window[this.bufPos]);
     hash = this.HashValue(hash, this.window[this.bufPos + 1]);
     int matchPos = 0;
     if ((this.bufEnd - this.bufPos) <= 3)
     {
         num2 = 0;
     }
     else
     {
         int search = (int) this.InsertString(ref hash);
         if (search != 0)
         {
             num2 = this.FindMatch(search, out matchPos, 0x20, 0x20);
             if ((this.bufPos + num2) > this.bufEnd)
             {
                 num2 = this.bufEnd - this.bufPos;
             }
         }
         else
         {
             num2 = 0;
         }
     }
     if (num2 < 3)
     {
         match.State = MatchState.HasSymbol;
         match.Symbol = this.window[this.bufPos];
         this.bufPos++;
     }
     else
     {
         this.bufPos++;
         if (num2 <= 6)
         {
             int num5;
             int num6 = 0;
             int num7 = (int) this.InsertString(ref hash);
             if (num7 != 0)
             {
                 num5 = this.FindMatch(num7, out num6, (num2 < 4) ? 0x20 : 8, 0x20);
                 if ((this.bufPos + num5) > this.bufEnd)
                 {
                     num5 = this.bufEnd - this.bufPos;
                 }
             }
             else
             {
                 num5 = 0;
             }
             if (num5 > num2)
             {
                 match.State = MatchState.HasSymbolAndMatch;
                 match.Symbol = this.window[this.bufPos - 1];
                 match.Position = num6;
                 match.Length = num5;
                 this.bufPos++;
                 num2 = num5;
                 this.InsertStrings(ref hash, num2);
             }
             else
             {
                 match.State = MatchState.HasMatch;
                 match.Position = matchPos;
                 match.Length = num2;
                 num2--;
                 this.bufPos++;
                 this.InsertStrings(ref hash, num2);
             }
         }
         else
         {
             match.State = MatchState.HasMatch;
             match.Position = matchPos;
             match.Length = num2;
             this.InsertStrings(ref hash, num2);
         }
     }
     if (this.bufPos == 0x4000)
     {
         this.MoveWindows();
     }
     return true;
 }