Exemplo n.º 1
0
        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);
        }
Exemplo n.º 2
0
 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();
 }
Exemplo n.º 3
0
        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);
        }
Exemplo n.º 4
0
            /* 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);
            }
Exemplo n.º 5
0
 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_);