private static unsafe bool SearchInStaticDictionary( ushort *dictionary_hash, HasherHandle handle, byte *data, size_t max_length, size_t max_backward, HasherSearchResult *out_, bool shallow) { size_t key; size_t i; bool is_match_found = false; HasherCommon *self = GetHasherCommon(handle); if (self->dict_num_matches < (self->dict_num_lookups >> 7)) { return(false); } key = Hash14(data) << 1; for (i = 0; i < (shallow ? 1u : 2u); ++i, ++key) { size_t item = dictionary_hash[key]; self->dict_num_lookups++; if (item != 0) { bool item_matches = TestStaticDictionaryItem( item, data, max_length, max_backward, out_); if (item_matches) { self->dict_num_matches++; is_match_found = true; } } } return(is_match_found); }
public override unsafe bool FindLongestMatch(HasherHandle handle, ushort *dictionary_hash, byte *data, size_t ring_buffer_mask, int *distance_cache, size_t cur_ix, size_t max_length, size_t max_backward, HasherSearchResult *out_) { throw new InvalidOperationException(); }
private static unsafe bool TestStaticDictionaryItem( size_t item, byte *data, size_t max_length, size_t max_backward, HasherSearchResult *out_) { size_t len; size_t dist; size_t offset; size_t matchlen; size_t backward; score_t score; len = item & 0x1F; dist = item >> 5; offset = kBrotliDictionaryOffsetsByLength[len] + len * dist; if (len > max_length) { return(false); } fixed(byte *dict = kBrotliDictionary) matchlen = FindMatchLengthWithLimit(data, &dict[offset], len); if (matchlen + kCutoffTransformsCount <= len || matchlen == 0) { return(false); } { size_t cut = len - matchlen; size_t transform_id = (cut << 2) + (size_t)((kCutoffTransforms >> (int)(cut * 6)) & 0x3F); backward = max_backward + dist + 1 + (transform_id << kBrotliDictionarySizeBitsByLength[len]); } score = BackwardReferenceScore(matchlen, backward); if (score < out_->score) { return(false); } out_->len = matchlen; out_->len_x_code = len ^ matchlen; out_->distance = backward; out_->score = score; return(true); }
/* Find a longest backward match of &data[cur_ix] up to the length of * max_length and stores the position cur_ix in the hash table. * * REQUIRES: FN(PrepareDistanceCache) must be invoked for current distance cache * values; if this method is invoked repeatedly with the same distance * cache values, it is enough to invoke FN(PrepareDistanceCache) once. * * Does not look for matches longer than max_length. * Does not look for matches further away than max_backward. * Writes the best match into |out|. * Returns true when match is found, otherwise false. */ public override unsafe bool FindLongestMatch(HasherHandle handle, ushort *dictionary_hash, byte *data, size_t ring_buffer_mask, int *distance_cache, size_t cur_ix, size_t max_length, size_t max_backward, HasherSearchResult *out_) { HasherCommon * common = GetHasherCommon(handle); HashLongestMatch *self = Self(handle); ushort * num = Num(self); uint * buckets = Buckets(self); size_t cur_ix_masked = cur_ix & ring_buffer_mask; bool is_match_found = false; /* Don't accept a short copy from far away. */ score_t best_score = out_->score; size_t best_len = out_->len; size_t i; out_->len = 0; out_->len_x_code = 0; /* Try last distance first. */ for (i = 0; i < (size_t)common->params_.num_last_distances_to_check; ++i) { size_t backward = (size_t)distance_cache[i]; size_t prev_ix = (size_t)(cur_ix - backward); if (prev_ix >= cur_ix) { continue; } if ((backward > max_backward)) { continue; } prev_ix &= ring_buffer_mask; if (cur_ix_masked + best_len > ring_buffer_mask || prev_ix + best_len > ring_buffer_mask || data[cur_ix_masked + best_len] != data[prev_ix + best_len]) { continue; } { size_t len = FindMatchLengthWithLimit(&data[prev_ix], &data[cur_ix_masked], max_length); if (len >= 3 || (len == 2 && i < 2)) { /* Comparing for >= 2 does not change the semantics, but just saves for * a few unnecessary binary logarithms in backward reference score, * since we are not interested in such short matches. */ score_t score = BackwardReferenceScoreUsingLastDistance(len); if (best_score < score) { if (i != 0) { score -= BackwardReferencePenaltyUsingLastDistance(i); } if (best_score < score) { best_score = score; best_len = len; out_->len = best_len; out_->distance = backward; out_->score = best_score; is_match_found = true; } } } } } { uint key = HashBytes(&data[cur_ix_masked], self->hash_shift_); uint *bucket = &buckets[key << common->params_.block_bits]; size_t down = (num[key] > self->block_size_) ? (num[key] - self->block_size_) : 0; for (i = num[key]; i > down;) { size_t prev_ix = bucket[--i & self->block_mask_]; size_t backward = cur_ix - prev_ix; if ((backward > max_backward)) { break; } prev_ix &= ring_buffer_mask; if (cur_ix_masked + best_len > ring_buffer_mask || prev_ix + best_len > ring_buffer_mask || data[cur_ix_masked + best_len] != data[prev_ix + best_len]) { continue; } { size_t len = FindMatchLengthWithLimit(&data[prev_ix], &data[cur_ix_masked], max_length); if (len >= 4) { /* Comparing for >= 3 does not change the semantics, but just saves * for a few unnecessary binary logarithms in backward reference * score, since we are not interested in such short matches. */ score_t score = BackwardReferenceScore(len, backward); if (best_score < score) { best_score = score; best_len = len; out_->len = best_len; out_->distance = backward; out_->score = best_score; is_match_found = true; } } } } bucket[num[key] & self->block_mask_] = (uint)cur_ix; ++num[key]; } if (!is_match_found) { is_match_found = SearchInStaticDictionary(dictionary_hash, handle, &data[cur_ix_masked], max_length, max_backward, out_, false); } return(is_match_found); }
public abstract bool FindLongestMatch(HasherHandle handle, ushort *dictionary_hash, byte *data, size_t ring_buffer_mask, int *distance_cache, size_t cur_ix, size_t max_length, size_t max_backward, HasherSearchResult *out_);