Exemplo n.º 1
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;
        }
Exemplo n.º 2
0
 public FastEncoder() {
     inputWindow = new FastEncoderWindow();
     currentMatch = new Match();
 }