pubfn deflate_slow(stream: &mut DeflateStream, flush: DeflateFlush) -> BlockState { letmut hash_head; /* head of hash chain */ letmut bflush; /* set if current block must be flushed */ letmut dist; letmut match_len;
let use_longest_match_slow = stream.state.max_chain_length > 1024; let valid_distance_range = 1..=stream.state.max_dist() as isize;
/* Process the input block. */ loop { /* Make sure that we always have enough lookahead, except *attheendoftheinputfile.WeneedSTD_MAX_MATCHbytes *forthenextmatch,plusWANT_MIN_MATCHbytestoinsertthe *stringfollowingthenextmatch.
*/ if stream.state.lookahead < MIN_LOOKAHEAD {
fill_window(stream); if stream.state.lookahead < MIN_LOOKAHEAD && flush == DeflateFlush::NoFlush { return BlockState::NeedMore;
}
if stream.state.lookahead == 0 { break; /* flush the current block */
}
}
let state = &mut stream.state;
/* Insert the string window[strstart .. strstart+2] in the *dictionary,andsethash_headtotheheadofthehashchain:
*/
hash_head = if state.lookahead >= WANT_MIN_MATCH {
state.quick_insert_string(state.strstart)
} else { 0
};
// Find the longest match, discarding those <= prev_length.
state.prev_match = state.match_start as u16;
match_len = STD_MIN_MATCH - 1;
dist = state.strstart as isize - hash_head as isize;
if valid_distance_range.contains(&dist)
&& state.prev_length < state.max_lazy_match
&& hash_head != 0
{ // To simplify the code, we prevent matches with the string // of window index 0 (in particular we have to avoid a match // of the string with itself at the start of the input file).
(match_len, state.match_start) = if use_longest_match_slow { crate::deflate::longest_match::longest_match_slow(state, hash_head)
} else { crate::deflate::longest_match::longest_match(state, hash_head)
};
if match_len <= 5 && (state.strategy == Strategy::Filtered) { /* If prev_match is also WANT_MIN_MATCH, match_start is garbage *butwewillignorethecurrentmatchanyway.
*/
match_len = STD_MIN_MATCH - 1;
}
}
// If there was a match at the previous step and the current // match is not better, output the previous match: if state.prev_length >= STD_MIN_MATCH && match_len <= state.prev_length { let max_insert = state.strstart + state.lookahead - STD_MIN_MATCH; /* Do not insert strings in hash table beyond this. */
/* Insert in hash table all strings up to the end of the match. *strstart-1andstrstartarealreadyinserted.Ifthereisnot *enoughlookahead,thelasttwostringsarenotinsertedin *thehashtable.
*/
state.prev_length -= 1;
state.lookahead -= state.prev_length;
if bflush {
flush_block!(stream, false);
}
} elseif match_available { // If there was no match at the previous position, output a // single literal. If there was a match but the current match // is longer, truncate the previous match to a single literal. let lc = state.window.filled()[state.strstart - 1];
bflush = state.tally_lit(lc); if bflush {
flush_block_only(stream, false);
}
stream.state.prev_length = match_len;
stream.state.strstart += 1;
stream.state.lookahead -= 1; if stream.avail_out == 0 { return BlockState::NeedMore;
}
} else { // There is no previous match to compare with, wait for // the next step to decide.
state.prev_length = match_len;
state.match_available = true;
match_available = true;
state.strstart += 1;
state.lookahead -= 1;
}
}
assert_ne!(flush, DeflateFlush::NoFlush, "no flush?");
let state = &mut stream.state;
if state.match_available { let lc = state.window.filled()[state.strstart - 1]; let _ = state.tally_lit(lc);
state.match_available = false;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.