Ejemplo n.º 1
0
        private static unsafe void BrotliCreateHqZopfliBackwardReferences(
            ref MemoryManager m, size_t num_bytes,
            size_t position, byte *ringbuffer, size_t ringbuffer_mask,
            BrotliEncoderParams *params_, HasherHandle hasher, int *dist_cache,
            size_t *last_insert_len, Command *commands, size_t *num_commands,
            size_t *num_literals)
        {
            size_t max_backward_limit = BROTLI_MAX_BACKWARD_LIMIT(params_->lgwin);
            uint * num_matches        = (uint *)BrotliAllocate(ref m, num_bytes * sizeof(uint));
            size_t matches_size       = 4 * num_bytes;
            Hasher h         = kHashers[10];
            size_t store_end = num_bytes >= h.StoreLookahead()
                ? position + num_bytes - h.StoreLookahead() + 1
                : position;
            size_t          cur_match_pos = 0;
            size_t          i;
            size_t          orig_num_literals;
            size_t          orig_last_insert_len;
            int *           orig_dist_cache = stackalloc int[4];
            size_t          orig_num_commands;
            ZopfliCostModel model;
            ZopfliNode *    nodes;
            BackwardMatch * matches = (BackwardMatch *)BrotliAllocate(ref m, matches_size * sizeof(BackwardMatch));

            for (i = 0; i + h.HashTypeLength() - 1 < num_bytes; ++i)
            {
                size_t pos          = position + i;
                size_t max_distance = Math.Min(pos, max_backward_limit);
                size_t max_length   = num_bytes - i;
                size_t num_found_matches;
                size_t cur_match_end;
                /* Ensure that we have enough free slots. */
                BrotliEnsureCapacity(ref m, sizeof(BackwardMatch), (void **)&matches, &matches_size, cur_match_pos + MAX_NUM_MATCHES_H10);
                num_found_matches = HashToBinaryTreeH10.FindAllMatches(hasher, ringbuffer,
                                                                       ringbuffer_mask, pos, max_length, max_distance, params_,
                                                                       &matches[cur_match_pos]);
                cur_match_end  = cur_match_pos + num_found_matches;
                num_matches[i] = (uint)num_found_matches;
                if (num_found_matches > 0)
                {
                    size_t match_len = BackwardMatchLength(&matches[cur_match_end - 1]);
                    if (match_len > MAX_ZOPFLI_LEN_QUALITY_11)
                    {
                        size_t skip = match_len - 1;
                        matches[cur_match_pos++] = matches[cur_match_end - 1];
                        num_matches[i]           = 1;
                        /* Add the tail of the copy to the hasher. */
                        h.StoreRange(hasher, ringbuffer, ringbuffer_mask, pos + 1,
                                     Math.Min(pos + match_len, store_end));
                        memset(&num_matches[i + 1], 0, skip * sizeof(uint));
                        i += skip;
                    }
                    else
                    {
                        cur_match_pos = cur_match_end;
                    }
                }
            }
            orig_num_literals    = *num_literals;
            orig_last_insert_len = *last_insert_len;
            memcpy(orig_dist_cache, dist_cache, 4 * sizeof(int));
            orig_num_commands = *num_commands;
            nodes             = (ZopfliNode *)BrotliAllocate(ref m, (num_bytes + 1) * sizeof(ZopfliNode));
            InitZopfliCostModel(ref m, &model, num_bytes);
            for (i = 0; i < 2; i++)
            {
                BrotliInitZopfliNodes(nodes, num_bytes + 1);
                if (i == 0)
                {
                    ZopfliCostModelSetFromLiteralCosts(
                        &model, position, ringbuffer, ringbuffer_mask);
                }
                else
                {
                    ZopfliCostModelSetFromCommands(&model, position, ringbuffer,
                                                   ringbuffer_mask, commands, *num_commands - orig_num_commands,
                                                   orig_last_insert_len);
                }
                *num_commands    = orig_num_commands;
                *num_literals    = orig_num_literals;
                *last_insert_len = orig_last_insert_len;
                memcpy(dist_cache, orig_dist_cache, 4 * sizeof(int));
                *num_commands += ZopfliIterate(num_bytes, position, ringbuffer,
                                               ringbuffer_mask, params_, max_backward_limit, dist_cache,
                                               &model, num_matches, matches, nodes);
                BrotliZopfliCreateCommands(num_bytes, position, max_backward_limit,
                                           nodes, dist_cache, last_insert_len, commands, num_literals);
            }
            CleanupZopfliCostModel(ref m, &model);
            BrotliFree(ref m, nodes);
            BrotliFree(ref m, matches);
            BrotliFree(ref m, num_matches);
        }
Ejemplo n.º 2
0
        /* REQUIRES: nodes != NULL and len(nodes) >= num_bytes + 1 */
        private static unsafe size_t BrotliZopfliComputeShortestPath(ref MemoryManager m,
                                                                     size_t num_bytes,
                                                                     size_t position,
                                                                     byte *ringbuffer,
                                                                     size_t ringbuffer_mask,
                                                                     BrotliEncoderParams *params_,
                                                                     size_t max_backward_limit,
                                                                     int *dist_cache,
                                                                     HasherHandle hasher,
                                                                     ZopfliNode *nodes)
        {
            size_t              max_zopfli_len = MaxZopfliLen(params_);
            ZopfliCostModel     model;
            StartPosQueue       queue;
            BackwardMatch *     matches   = stackalloc BackwardMatch[MAX_NUM_MATCHES_H10];
            HashToBinaryTreeH10 h10       = (HashToBinaryTreeH10)kHashers[10];
            size_t              store_end = num_bytes >= h10.StoreLookahead()
                ? position + num_bytes - h10.StoreLookahead() + 1
                : position;
            size_t i;

            nodes[0].length = 0;
            nodes[0].u.cost = 0;
            InitZopfliCostModel(ref m, &model, num_bytes);
            ZopfliCostModelSetFromLiteralCosts(
                &model, position, ringbuffer, ringbuffer_mask);
            InitStartPosQueue(&queue);
            for (i = 0; i + h10.HashTypeLength() - 1 < num_bytes; i++)
            {
                size_t pos          = position + i;
                size_t max_distance = Math.Min(pos, max_backward_limit);
                size_t num_matches  = HashToBinaryTreeH10.FindAllMatches(hasher, ringbuffer,
                                                                         ringbuffer_mask, pos, num_bytes - i, max_distance, params_, matches);
                size_t skip;
                if (num_matches > 0 &&
                    BackwardMatchLength(&matches[num_matches - 1]) > max_zopfli_len)
                {
                    matches[0]  = matches[num_matches - 1];
                    num_matches = 1;
                }
                skip = UpdateNodes(num_bytes, position, i, ringbuffer, ringbuffer_mask,
                                   params_, max_backward_limit, dist_cache, num_matches, matches, &model,
                                   &queue, nodes);
                if (skip < BROTLI_LONG_COPY_QUICK_STEP)
                {
                    skip = 0;
                }
                if (num_matches == 1 && BackwardMatchLength(&matches[0]) > max_zopfli_len)
                {
                    skip = Math.Max(BackwardMatchLength(&matches[0]), skip);
                }
                if (skip > 1)
                {
                    /* Add the tail of the copy to the hasher. */
                    h10.StoreRange(hasher, ringbuffer, ringbuffer_mask, pos + 1, Math.Min(
                                       pos + skip, store_end));
                    skip--;
                    while (skip != 0)
                    {
                        i++;
                        if (i + h10.HashTypeLength() - 1 >= num_bytes)
                        {
                            break;
                        }
                        EvaluateNode(
                            position, i, max_backward_limit, dist_cache, &model, &queue, nodes);
                        skip--;
                    }
                }
            }
            CleanupZopfliCostModel(ref m, &model);
            return(ComputeShortestPathFromNodes(num_bytes, nodes));
        }