Exemplo n.º 1
0
        private bool _needsEob;          // indicates whether or not we have compressed any data

        public FastEncoder(bool doGZip)
        {
            _usingGzip = doGZip;
            _inputWindow = new FastEncoderWindow();
            _inputBuffer = new DeflateInput();
            _output = new Output();
            _currentMatch = new Match();
        }
Exemplo n.º 2
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;
        }