let strstart = state.strstart; let wmask = state.w_mask; let window = state.window.filled(); let scan = &window[strstart..]; letmut limit: Pos; let limit_base: Pos; let early_exit: bool;
// Calculate read offset which should only extend an extra byte to find the next best match length. letmut offset = best_len - 1; if best_len >= core::mem::size_of::<u32>() && UNALIGNED_OK {
offset -= 2; if best_len >= core::mem::size_of::<u64>() && UNALIGNED64_OK {
offset -= 4;
}
}
// Don't waste too much time by following a chain if we already have a good match
chain_length = state.max_chain_length; if best_len >= state.good_match {
chain_length >>= 2;
} let nice_match = state.nice_match;
// Stop when cur_match becomes <= limit. To simplify the code, // we prevent matches with the string of window index 0
limit = strstart.saturating_sub(state.max_dist()) as Pos;
// look for a better string offset if SLOW {
limit_base = limit;
// Find a most distant chain starting from scan with index=1 (index=0 corresponds // to cur_match). We cannot use s->prev[strstart+1,...] immediately, because // these strings are not yet inserted into the hash table. let Some([_cur_match, scan1, scan2, scanrest @ ..]) = scan.get(..best_len + 1) else {
panic!("invalid scan");
};
letmut hash = 0;
hash = state.update_hash(hash, *scan1 as u32);
hash = state.update_hash(hash, *scan2 as u32);
for (i, b) in scanrest.iter().enumerate() {
hash = state.update_hash(hash, *b as u32);
/* If we're starting with best_len >= 3, we can use offset search. */
pos = state.head[hash as usize]; if pos < cur_match {
match_offset = (i + 1) as Pos;
cur_match = pos;
}
}
loop { if cur_match as usize >= strstart { break;
}
// Skip to next match if the match length cannot increase or if the match length is // less than 2. Note that the checks below for insufficient lookahead only occur // occasionally for performance reasons. // Therefore uninitialized memory will be accessed and conditional jumps will be made // that depend on those values. However the length of the match is limited to the // lookahead, so the output of deflate is not affected by the uninitialized values.
// # Safety // // The two pointers must be valid for reads of N bytes. #[inline(always)] unsafefn memcmp_n_ptr<const N: usize>(src0: *const u8, src1: *const u8) -> bool { let src0_cmp = core::ptr::read(src0 as *const [u8; N]); let src1_cmp = core::ptr::read(src1 as *const [u8; N]);
src0_cmp == src1_cmp
}
#[inline(always)] unsafefn is_match<const N: usize>(
cur_match: u16,
mbase_start: *const u8,
mbase_end: *const u8,
scan_start: *const u8,
scan_end: *const u8,
) -> bool { let be = mbase_end.wrapping_add(cur_match as usize); let bs = mbase_start.wrapping_add(cur_match as usize);
// first, do a quick check on the start and end bytes. Go to the next item in the chain if // these bytes don't match. unsafe { let scan_start = scan_start.as_ptr(); let scan_end = scan_end.as_ptr();
if UNALIGNED_OK { if best_len < core::mem::size_of::<u32>() { loop { if is_match::<2>(cur_match, mbase_start, mbase_end, scan_start, scan_end) { break;
}
goto_next_in_chain!();
}
}
} else { loop { if memcmp_n_ptr::<2>(mbase_end.wrapping_add(cur_match as usize), scan_end)
&& memcmp_n_ptr::<2>(
mbase_start.wrapping_add(cur_match as usize),
scan.as_ptr(),
)
{ break;
}
goto_next_in_chain!();
}
}
}
// we know that there is at least some match. Now count how many bytes really match let len = { // TODO this just looks so incredibly unsafe! let src1: &[u8; 256] = unsafe { &*mbase_start.wrapping_add(cur_match as usize + 2).cast() };
assert!(
scan.as_ptr() as usize + len <= window.as_ptr() as usize + (state.window_size - 1), "wild scan"
);
if len > best_len {
match_start = (cur_match - match_offset) as usize;
/* Do not look for matches beyond the end of the input. */ if len > lookahead { return (lookahead, match_start);
}
best_len = len; if best_len >= nice_match { return (best_len, match_start);
}
// Look for a better string offset if SLOW && len > STD_MIN_MATCH && match_start + len < strstart { letmut pos: Pos; // uint32_t i, hash; // unsigned char *scan_endstr;
/* Go back to offset 0 */
cur_match -= match_offset;
match_offset = 0; letmut next_pos = cur_match;
for i in0..=len - STD_MIN_MATCH {
pos = state.prev[(cur_match as usize + i) & wmask]; if pos < next_pos { /* Hash chain is more distant, use it */ if pos <= limit_base + i as Pos { return break_matching(state, best_len, match_start);
}
next_pos = pos;
match_offset = i as Pos;
}
} /* Switch cur_match to next_pos chain */
cur_match = next_pos;
/* Try hash head at len-(STD_MIN_MATCH-1) position to see if we could get *abettercur_matchattheendofstring.Using(STD_MIN_MATCH-1)lets *usincludeonemorebyteintohash-thebytewhichwillbechecked *inmainloopnow,andwhichallowstogrowmatchby1.
*/ let [scan0, scan1, scan2, ..] = scan[len - (STD_MIN_MATCH + 1)..] else {
panic!("index out of bounds");
};
letmut hash = 0;
hash = state.update_hash(hash, scan0 as u32);
hash = state.update_hash(hash, scan1 as u32);
hash = state.update_hash(hash, scan2 as u32);
pos = state.head[hash as usize]; if pos < cur_match {
match_offset = (len - (STD_MIN_MATCH + 1)) as Pos; if pos <= limit_base + match_offset { return break_matching(state, best_len, match_start);
}
cur_match = pos;
}
mbase_end = mbase_start.wrapping_add(offset);
} elseif !SLOW && early_exit { // The probability of finding a match later if we here is pretty low, so for // performance it's best to outright stop here for the lower compression levels break;
}
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.