Esempio n. 1
0
 public abstract void CreateBackwardReferences(
     ushort *dictionary_hash,
     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);
Esempio n. 2
0
 private static unsafe void BrotliBuildMetaBlockGreedy(ref MemoryManager m,
                                                       byte *ringbuffer,
                                                       size_t pos,
                                                       size_t mask,
                                                       byte prev_byte,
                                                       byte prev_byte2,
                                                       ContextType literal_context_mode,
                                                       size_t num_contexts,
                                                       uint *static_context_map,
                                                       Command *commands,
                                                       size_t n_commands,
                                                       MetaBlockSplit *mb)
 {
     if (num_contexts == 1)
     {
         BrotliBuildMetaBlockGreedyInternal(ref m, ringbuffer, pos, mask, prev_byte,
                                            prev_byte2, literal_context_mode, 1, null, commands, n_commands, mb);
     }
     else
     {
         BrotliBuildMetaBlockGreedyInternal(ref m, ringbuffer, pos, mask, prev_byte,
                                            prev_byte2, literal_context_mode, num_contexts, static_context_map,
                                            commands, n_commands, mb);
     }
 }
Esempio n. 3
0
        private static unsafe void CopyLiteralsToByteArray(Command *cmds,
                                                           size_t num_commands,
                                                           byte *data,
                                                           size_t offset,
                                                           size_t mask,
                                                           byte *literals)
        {
            size_t pos      = 0;
            size_t from_pos = offset & mask;
            size_t i;

            for (i = 0; i < num_commands; ++i)
            {
                size_t insert_len = cmds[i].insert_len_;
                if (from_pos + insert_len > mask)
                {
                    size_t head_size = mask + 1 - from_pos;
                    memcpy(literals + pos, data + from_pos, head_size);
                    from_pos    = 0;
                    pos        += head_size;
                    insert_len -= head_size;
                }
                if (insert_len > 0)
                {
                    memcpy(literals + pos, data + from_pos, insert_len);
                    pos += insert_len;
                }
                from_pos = (from_pos + insert_len + CommandCopyLen(&cmds[i])) & mask;
            }
        }
Esempio n. 4
0
        private static unsafe void BrotliCreateBackwardReferences(
            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)
        {
            switch (params_->hasher.type)
            {
            case 2:
            case 3:
            case 4:
            case 5:
            case 6:
            case 40:
            case 41:
            case 42:
            case 54:
                fixed(ushort *ksdh = kStaticDictionaryHash)
                kHashers[params_->hasher.type].CreateBackwardReferences(ksdh, num_bytes,
                                                                        position, ringbuffer, ringbuffer_mask, params_, hasher, dist_cache,
                                                                        last_insert_len, commands, num_commands, num_literals);

                break;
            }
        }
Esempio n. 5
0
 private static unsafe void InitInsertCommand(Command *self, size_t insertlen)
 {
     self->insert_len_  = (uint)insertlen;
     self->copy_len_    = 4 << 24;
     self->dist_extra_  = 0;
     self->dist_prefix_ = BROTLI_NUM_DISTANCE_SHORT_CODES;
     GetLengthCode(insertlen, 4, false, &self->cmd_prefix_);
 }
Esempio n. 6
0
        private static unsafe void BrotliBuildHistogramsWithContext(
            Command *cmds, size_t num_commands,
            BlockSplit *literal_split, BlockSplit *insert_and_copy_split,
            BlockSplit *dist_split, byte *ringbuffer, size_t start_pos,
            size_t mask, byte prev_byte, byte prev_byte2,
            ContextType *context_modes, HistogramLiteral *literal_histograms,
            HistogramCommand *insert_and_copy_histograms,
            HistogramDistance *copy_dist_histograms)
        {
            size_t             pos = start_pos;
            BlockSplitIterator literal_it;
            BlockSplitIterator insert_and_copy_it;
            BlockSplitIterator dist_it;
            size_t             i;

            InitBlockSplitIterator(&literal_it, literal_split);
            InitBlockSplitIterator(&insert_and_copy_it, insert_and_copy_split);
            InitBlockSplitIterator(&dist_it, dist_split);
            for (i = 0; i < num_commands; ++i)
            {
                Command *cmd = &cmds[i];
                size_t   j;
                BlockSplitIteratorNext(&insert_and_copy_it);
                HistogramCommand.HistogramAdd(&insert_and_copy_histograms[insert_and_copy_it.type_],
                                              cmd->cmd_prefix_);
                for (j = cmd->insert_len_; j != 0; --j)
                {
                    size_t context;
                    BlockSplitIteratorNext(&literal_it);
                    context = context_modes != null ?
                              ((literal_it.type_ << BROTLI_LITERAL_CONTEXT_BITS) +
                               Context(prev_byte, prev_byte2, context_modes[literal_it.type_])) :
                              literal_it.type_;
                    HistogramLiteral.HistogramAdd(&literal_histograms[context],
                                                  ringbuffer[pos & mask]);
                    prev_byte2 = prev_byte;
                    prev_byte  = ringbuffer[pos & mask];
                    ++pos;
                }
                pos += CommandCopyLen(cmd);
                if (CommandCopyLen(cmd) != 0)
                {
                    prev_byte2 = ringbuffer[(pos - 2) & mask];
                    prev_byte  = ringbuffer[(pos - 1) & mask];
                    if (cmd->cmd_prefix_ >= 128)
                    {
                        size_t context;
                        BlockSplitIteratorNext(&dist_it);
                        context = (dist_it.type_ << BROTLI_DISTANCE_CONTEXT_BITS) +
                                  CommandDistanceContext(cmd);
                        HistogramDistance.HistogramAdd(&copy_dist_histograms[context],
                                                       cmd->dist_prefix_);
                    }
                }
            }
        }
Esempio n. 7
0
        private static unsafe uint CommandDistanceContext(Command *self)
        {
            uint r = (uint)(self->cmd_prefix_ >> 6);
            uint c = (uint)(self->cmd_prefix_ & 7);

            if ((r == 0 || r == 2 || r == 4 || r == 7) && (c <= 2))
            {
                return(c);
            }
            return(3);
        }
Esempio n. 8
0
        private static unsafe size_t CountLiterals(Command *cmds, size_t num_commands)
        {
            /* Count how many we have. */
            size_t total_length = 0;
            size_t i;

            for (i = 0; i < num_commands; ++i)
            {
                total_length += cmds[i].insert_len_;
            }
            return(total_length);
        }
Esempio n. 9
0
        /* REQUIRES: nodes != NULL and len(nodes) >= num_bytes + 1 */
        private static unsafe void BrotliZopfliCreateCommands(size_t num_bytes,
                                                              size_t block_start,
                                                              size_t max_backward_limit,
                                                              ZopfliNode *nodes,
                                                              int *dist_cache,
                                                              size_t *last_insert_len,
                                                              Command *commands,
                                                              size_t *num_literals)
        {
            size_t pos    = 0;
            uint   offset = nodes[0].u.next;
            size_t i;

            for (i = 0; offset != uint.MaxValue; i++)
            {
                ZopfliNode *next          = &nodes[pos + offset];
                size_t      copy_length   = ZopfliNodeCopyLength(next);
                size_t      insert_length = next->insert_length;
                pos   += insert_length;
                offset = next->u.next;
                if (i == 0)
                {
                    insert_length += *last_insert_len;
                    *last_insert_len = 0;
                }
                {
                    size_t distance     = ZopfliNodeCopyDistance(next);
                    size_t len_code     = ZopfliNodeLengthCode(next);
                    size_t max_distance =
                        Math.Min(block_start + pos, max_backward_limit);
                    bool   is_dictionary = (distance > max_distance);
                    size_t dist_code     = ZopfliNodeDistanceCode(next);

                    InitCommand(
                        &commands[i], insert_length, copy_length, len_code, dist_code);

                    if (!is_dictionary && dist_code > 0)
                    {
                        dist_cache[3] = dist_cache[2];
                        dist_cache[2] = dist_cache[1];
                        dist_cache[1] = dist_cache[0];
                        dist_cache[0] = (int)distance;
                    }
                }

                *num_literals += insert_length;
                pos += copy_length;
            }
            *last_insert_len += num_bytes - pos;
        }
Esempio n. 10
0
        /* distance_code is e.g. 0 for same-as-last short code, or 16 for offset 1. */
        private static unsafe void InitCommand(Command *self, size_t insertlen,
                                               size_t copylen, size_t copylen_code, size_t distance_code)
        {
            self->insert_len_ = (uint)insertlen;
            self->copy_len_   = (uint)(copylen | ((copylen_code ^ copylen) << 24));

            /* The distance prefix and extra bits are stored in this Command as if
             * npostfix and ndirect were 0, they are only recomputed later after the
             * clustering if needed. */
            PrefixEncodeCopyDistance(
                distance_code, 0, 0, &self->dist_prefix_, &self->dist_extra_);
            GetLengthCode(
                insertlen, copylen_code, (self->dist_prefix_ == 0),
                &self->cmd_prefix_);
        }
Esempio n. 11
0
        private static unsafe void BrotliCreateZopfliBackwardReferences(
            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);
            ZopfliNode *nodes;

            nodes = (ZopfliNode *)BrotliAllocate(ref m, (num_bytes + 1) * sizeof(ZopfliNode));
            BrotliInitZopfliNodes(nodes, num_bytes + 1);
            *num_commands += BrotliZopfliComputeShortestPath(ref m, num_bytes,
                                                             position, ringbuffer, ringbuffer_mask, params_, max_backward_limit,
                                                             dist_cache, hasher, nodes);
            BrotliZopfliCreateCommands(num_bytes, position, max_backward_limit, nodes,
                                       dist_cache, last_insert_len, commands, num_literals);
            BrotliFree(ref m, nodes);
        }
Esempio n. 12
0
        private static unsafe uint CommandRestoreDistanceCode(Command *self)
        {
            if (self->dist_prefix_ < BROTLI_NUM_DISTANCE_SHORT_CODES)
            {
                return(self->dist_prefix_);
            }
            else
            {
                uint nbits = self->dist_extra_ >> 24;
                uint extra = self->dist_extra_ & 0xffffff;

                /* It is assumed that the distance was first encoded with NPOSTFIX = 0 and
                 * NDIRECT = 0, so the code itself is of this form:
                 *   BROTLI_NUM_DISTANCE_SHORT_CODES + 2 * (nbits - 1) + prefix_bit
                 * Therefore, the following expression results in (2 + prefix_bit). */
                uint prefix =
                    self->dist_prefix_ + 4u - BROTLI_NUM_DISTANCE_SHORT_CODES - 2u * nbits;

                /* Subtract 4 for offset (Chapter 4.) and
                 * increase by BROTLI_NUM_DISTANCE_SHORT_CODES - 1  */
                return((prefix << (int)nbits) + extra + BROTLI_NUM_DISTANCE_SHORT_CODES - 4u);
            }
        }
Esempio n. 13
0
            public override unsafe void CreateBackwardReferences(
                ushort *dictionary_hash,
                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)
            {
                /* Set maximum distance, see section 9.1. of the spec. */
                size_t max_backward_limit = BROTLI_MAX_BACKWARD_LIMIT(params_->lgwin);

                Command *orig_commands = commands;
                size_t   insert_length = *last_insert_len;
                size_t   pos_end       = position + num_bytes;
                size_t   store_end     = num_bytes >= StoreLookahead()
                    ? position + num_bytes - StoreLookahead() + 1
                    : position;

                /* For speed up heuristics for random data. */
                size_t random_heuristics_window_size =
                    LiteralSpreeLengthForSparseSearch(params_);
                size_t apply_random_heuristics = position + random_heuristics_window_size;

                /* Minimum score to accept a backward reference. */
                score_t kMinScore = BROTLI_SCORE_BASE + 100;

                PrepareDistanceCache(hasher, dist_cache);

                while (position + HashTypeLength() < pos_end)
                {
                    size_t             max_length   = pos_end - position;
                    size_t             max_distance = Math.Min(position, max_backward_limit);
                    HasherSearchResult sr           = new HasherSearchResult();
                    sr.len        = 0;
                    sr.len_x_code = 0;
                    sr.distance   = 0;
                    sr.score      = kMinScore;
                    if (FindLongestMatch(hasher, dictionary_hash,
                                         ringbuffer, ringbuffer_mask, dist_cache,
                                         position, max_length, max_distance, &sr))
                    {
                        /* Found a match. Let's look for something even better ahead. */
                        int delayed_backward_references_in_row = 0;
                        --max_length;
                        for (;; --max_length)
                        {
                            score_t            cost_diff_lazy = 175;
                            bool               is_match_found;
                            HasherSearchResult sr2;
                            sr2.len = params_->quality < MIN_QUALITY_FOR_EXTENSIVE_REFERENCE_SEARCH
                                ? Math.Min(sr.len - 1, max_length)
                                : 0;

                            sr2.len_x_code = 0;
                            sr2.distance   = 0;
                            sr2.score      = kMinScore;
                            max_distance   = Math.Min(position + 1, max_backward_limit);
                            is_match_found = FindLongestMatch(hasher,
                                                              dictionary_hash, ringbuffer, ringbuffer_mask, dist_cache,
                                                              position + 1, max_length, max_distance, &sr2);
                            if (is_match_found && sr2.score >= sr.score + cost_diff_lazy)
                            {
                                /* Ok, let's just write one byte for now and start a match from the
                                 * next byte. */
                                ++position;
                                ++insert_length;
                                sr = sr2;
                                if (++delayed_backward_references_in_row < 4 &&
                                    position + HashTypeLength() < pos_end)
                                {
                                    continue;
                                }
                            }
                            break;
                        }
                        apply_random_heuristics =
                            position + 2 * sr.len + random_heuristics_window_size;
                        max_distance = Math.Min(position, max_backward_limit);
                        {
                            /* The first 16 codes are special short-codes,
                             * and the minimum offset is 1. */
                            size_t distance_code =
                                ComputeDistanceCode(sr.distance, max_distance, dist_cache);
                            if (sr.distance <= max_distance && distance_code > 0)
                            {
                                dist_cache[3] = dist_cache[2];
                                dist_cache[2] = dist_cache[1];
                                dist_cache[1] = dist_cache[0];
                                dist_cache[0] = (int)sr.distance;
                                PrepareDistanceCache(hasher, dist_cache);
                            }
                            InitCommand(commands++, insert_length, sr.len, sr.len ^ sr.len_x_code,
                                        distance_code);
                        }
                        *num_literals += insert_length;
                        insert_length = 0;

                        /* Put the hash keys into the table, if there are enough bytes left.
                         * Depending on the hasher implementation, it can push all positions
                         * in the given range or only a subset of them. */
                        StoreRange(hasher, ringbuffer, ringbuffer_mask, position + 2,
                                   Math.Min(position + sr.len, store_end));
                        position += sr.len;
                    }
                    else
                    {
                        ++insert_length;
                        ++position;

                        /* If we have not seen matches for a long time, we can skip some
                         * match lookups. Unsuccessful match lookups are very very expensive
                         * and this kind of a heuristic speeds up compression quite
                         * a lot. */
                        if (position > apply_random_heuristics)
                        {
                            /* Going through uncompressible data, jump. */
                            if (position >
                                apply_random_heuristics + 4 * random_heuristics_window_size)
                            {
                                /* It is quite a long time since we saw a copy, so we assume
                                 * that this data is not compressible, and store hashes less
                                 * often. Hashes of non compressible data are less likely to
                                 * turn out to be useful in the future, too, so we store less of
                                 * them to not to flood out the hash table of good compressible
                                 * data. */
                                size_t kMargin =
                                    Math.Max(StoreLookahead() - 1, 4);
                                size_t pos_jump =
                                    Math.Min(position + 16, pos_end - kMargin);
                                for (; position < pos_jump; position += 4)
                                {
                                    Store(hasher, ringbuffer, ringbuffer_mask, position);
                                    insert_length += 4;
                                }
                            }
                            else
                            {
                                size_t kMargin =
                                    Math.Max(StoreLookahead() - 1, 2);
                                size_t pos_jump =
                                    Math.Min(position + 8, pos_end - kMargin);
                                for (; position < pos_jump; position += 2)
                                {
                                    Store(hasher, ringbuffer, ringbuffer_mask, position);
                                    insert_length += 2;
                                }
                            }
                        }
                    }
                }
                insert_length += pos_end - position;
                *last_insert_len = insert_length;
                *num_commands   += (size_t)(commands - orig_commands);
            }
Esempio n. 14
0
        private static unsafe void BrotliBuildMetaBlock(ref MemoryManager m,
                                                        byte *ringbuffer,
                                                        size_t pos,
                                                        size_t mask,
                                                        BrotliEncoderParams *params_,
                                                        byte prev_byte,
                                                        byte prev_byte2,
                                                        Command *cmds,
                                                        size_t num_commands,
                                                        ContextType literal_context_mode,
                                                        MetaBlockSplit *mb)
        {
            /* Histogram ids need to fit in one byte. */
            size_t             kMaxNumberOfHistograms = 256;
            HistogramDistance *distance_histograms;
            HistogramLiteral * literal_histograms;
            ContextType *      literal_context_modes = null;
            size_t             literal_histograms_size;
            size_t             distance_histograms_size;
            size_t             i;
            size_t             literal_context_multiplier = 1;

            BrotliSplitBlock(ref m, cmds, num_commands,
                             ringbuffer, pos, mask, params_,
                             &mb->literal_split,
                             &mb->command_split,
                             &mb->distance_split);

            if (!params_->disable_literal_context_modeling)
            {
                literal_context_multiplier = 1 << BROTLI_LITERAL_CONTEXT_BITS;
                literal_context_modes      =
                    (ContextType *)BrotliAllocate(ref m, mb->literal_split.num_types * sizeof(ContextType));
                for (i = 0; i < mb->literal_split.num_types; ++i)
                {
                    literal_context_modes[i] = literal_context_mode;
                }
            }

            literal_histograms_size =
                mb->literal_split.num_types * literal_context_multiplier;
            literal_histograms =
                (HistogramLiteral *)BrotliAllocate(ref m, literal_histograms_size * sizeof(HistogramLiteral));
            HistogramLiteral.ClearHistograms(literal_histograms, literal_histograms_size);

            distance_histograms_size =
                mb->distance_split.num_types << BROTLI_DISTANCE_CONTEXT_BITS;
            distance_histograms =
                (HistogramDistance *)BrotliAllocate(ref m, distance_histograms_size * sizeof(HistogramDistance));
            HistogramDistance.ClearHistograms(distance_histograms, distance_histograms_size);

            mb->command_histograms_size = mb->command_split.num_types;
            mb->command_histograms      =
                (HistogramCommand *)BrotliAllocate(ref m, mb->command_histograms_size * sizeof(HistogramCommand));
            HistogramCommand.ClearHistograms(mb->command_histograms, mb->command_histograms_size);

            BrotliBuildHistogramsWithContext(cmds, num_commands,
                                             &mb->literal_split, &mb->command_split, &mb->distance_split,
                                             ringbuffer, pos, mask, prev_byte, prev_byte2, literal_context_modes,
                                             literal_histograms, mb->command_histograms, distance_histograms);
            BrotliFree(ref m, literal_context_modes);

            mb->literal_context_map_size =
                mb->literal_split.num_types << BROTLI_LITERAL_CONTEXT_BITS;
            mb->literal_context_map =
                (uint *)BrotliAllocate(ref m, mb->literal_context_map_size * sizeof(uint));

            mb->literal_histograms_size = mb->literal_context_map_size;
            mb->literal_histograms      =
                (HistogramLiteral *)BrotliAllocate(ref m, mb->literal_histograms_size * sizeof(HistogramLiteral));

            ClusterLiteral.BrotliClusterHistograms(ref m, literal_histograms, literal_histograms_size,
                                                   kMaxNumberOfHistograms, mb->literal_histograms,
                                                   &mb->literal_histograms_size, mb->literal_context_map);
            BrotliFree(ref m, literal_histograms);

            if (params_->disable_literal_context_modeling)
            {
                /* Distribute assignment to all contexts. */
                for (i = mb->literal_split.num_types; i != 0;)
                {
                    size_t j = 0;
                    i--;
                    for (; j < (1 << BROTLI_LITERAL_CONTEXT_BITS); j++)
                    {
                        mb->literal_context_map[(i << BROTLI_LITERAL_CONTEXT_BITS) + j] =
                            mb->literal_context_map[i];
                    }
                }
            }

            mb->distance_context_map_size =
                mb->distance_split.num_types << BROTLI_DISTANCE_CONTEXT_BITS;
            mb->distance_context_map =
                (uint *)BrotliAllocate(ref m, mb->distance_context_map_size * sizeof(uint));

            mb->distance_histograms_size = mb->distance_context_map_size;
            mb->distance_histograms      =
                (HistogramDistance *)BrotliAllocate(ref m, mb->distance_histograms_size * sizeof(HistogramDistance));

            ClusterDistance.BrotliClusterHistograms(ref m, distance_histograms,
                                                    mb->distance_context_map_size,
                                                    kMaxNumberOfHistograms,
                                                    mb->distance_histograms,
                                                    &mb->distance_histograms_size,
                                                    mb->distance_context_map);
            BrotliFree(ref m, distance_histograms);
        }
Esempio n. 15
0
        private static unsafe void BrotliSplitBlock(ref MemoryManager m,
                                                    Command *cmds,
                                                    size_t num_commands,
                                                    byte *data,
                                                    size_t pos,
                                                    size_t mask,
                                                    BrotliEncoderParams *params_,
                                                    BlockSplit *literal_split,
                                                    BlockSplit *insert_and_copy_split,
                                                    BlockSplit *dist_split)
        {
            {
                size_t literals_count = CountLiterals(cmds, num_commands);
                byte * literals       = (byte *)BrotliAllocate(ref m, literals_count * sizeof(byte));

                /* Create a continuous array of literals. */
                CopyLiteralsToByteArray(cmds, num_commands, data, pos, mask, literals);

                /* Create the block split on the array of literals.
                 * Literal histograms have alphabet size 256. */
                BlockSplitterLiteral.SplitByteVector(
                    ref m, literals, literals_count,
                    kSymbolsPerLiteralHistogram, kMaxLiteralHistograms,
                    kLiteralStrideLength, kLiteralBlockSwitchCost, params_,
                    literal_split);

                BrotliFree(ref m, literals);
            }

            {
                /* Compute prefix codes for commands. */
                ushort *insert_and_copy_codes = (ushort *)BrotliAllocate(ref m, num_commands * sizeof(ushort));
                size_t  i;

                for (i = 0; i < num_commands; ++i)
                {
                    insert_and_copy_codes[i] = cmds[i].cmd_prefix_;
                }
                /* Create the block split on the array of command prefixes. */
                BlockSplitterCommand.SplitByteVector(
                    ref m, insert_and_copy_codes, num_commands,
                    kSymbolsPerCommandHistogram, kMaxCommandHistograms,
                    kCommandStrideLength, kCommandBlockSwitchCost, params_,
                    insert_and_copy_split);

                /* TODO: reuse for distances? */
                BrotliFree(ref m, insert_and_copy_codes);
            }

            {
                /* Create a continuous array of distance prefixes. */
                ushort *distance_prefixes = (ushort *)BrotliAllocate(ref m, num_commands * sizeof(ushort));
                size_t  j = 0;
                size_t  i;

                for (i = 0; i < num_commands; ++i)
                {
                    Command *cmd = &cmds[i];
                    if (CommandCopyLen(cmd) != 0 && cmd->cmd_prefix_ >= 128)
                    {
                        distance_prefixes[j++] = cmd->dist_prefix_;
                    }
                }
                /* Create the block split on the array of distance prefixes. */
                BlockSplitterDistance.SplitByteVector(
                    ref m, distance_prefixes, j,
                    kSymbolsPerDistanceHistogram, kMaxCommandHistograms,
                    kCommandStrideLength, kDistanceBlockSwitchCost, params_,
                    dist_split);

                BrotliFree(ref m, distance_prefixes);
            }
        }
Esempio n. 16
0
        private static unsafe void BrotliBuildMetaBlockGreedyInternal(
            ref MemoryManager m, byte *ringbuffer, size_t pos, size_t mask,
            byte prev_byte, byte prev_byte2, ContextType literal_context_mode,
            size_t num_contexts, uint *static_context_map,
            Command *commands, size_t n_commands, MetaBlockSplit *mb)
        {
            lit_blocks_union      lit_blocks = new lit_blocks_union();
            BlockSplitterCommand  cmd_blocks;
            BlockSplitterDistance dist_blocks;
            size_t num_literals = 0;
            size_t i;

            for (i = 0; i < n_commands; ++i)
            {
                num_literals += commands[i].insert_len_;
            }

            if (num_contexts == 1)
            {
                BlockSplitterLiteral.InitBlockSplitter(ref m, (BlockSplitterLiteral *)&lit_blocks, 256, 512, 400.0,
                                                       num_literals, &mb->literal_split, &mb->literal_histograms,
                                                       &mb->literal_histograms_size);
            }
            else
            {
                InitContextBlockSplitter(ref m, &lit_blocks.ctx, 256, num_contexts, 512, 400.0,
                                         num_literals, &mb->literal_split, &mb->literal_histograms,
                                         &mb->literal_histograms_size);
            }
            BlockSplitterCommand.InitBlockSplitter(ref m, &cmd_blocks, BROTLI_NUM_COMMAND_SYMBOLS, 1024,
                                                   500.0, n_commands, &mb->command_split, &mb->command_histograms,
                                                   &mb->command_histograms_size);
            BlockSplitterDistance.InitBlockSplitter(ref m, &dist_blocks, 64, 512, 100.0, n_commands,
                                                    &mb->distance_split, &mb->distance_histograms,
                                                    &mb->distance_histograms_size);

            for (i = 0; i < n_commands; ++i)
            {
                Command cmd = commands[i];
                size_t  j;
                BlockSplitterCommand.BlockSplitterAddSymbol(&cmd_blocks, cmd.cmd_prefix_);
                for (j = cmd.insert_len_; j != 0; --j)
                {
                    byte literal = ringbuffer[pos & mask];
                    if (num_contexts == 1)
                    {
                        BlockSplitterLiteral.BlockSplitterAddSymbol((BlockSplitterLiteral *)&lit_blocks, literal);
                    }
                    else
                    {
                        size_t context = Context(prev_byte, prev_byte2, literal_context_mode);
                        ContextBlockSplitterAddSymbol(&lit_blocks.ctx, ref m, literal,
                                                      static_context_map[context]);
                    }
                    prev_byte2 = prev_byte;
                    prev_byte  = literal;
                    ++pos;
                }
                pos += CommandCopyLen(&cmd);
                if (CommandCopyLen(&cmd) != 0)
                {
                    prev_byte2 = ringbuffer[(pos - 2) & mask];
                    prev_byte  = ringbuffer[(pos - 1) & mask];
                    if (cmd.cmd_prefix_ >= 128)
                    {
                        BlockSplitterDistance.BlockSplitterAddSymbol(&dist_blocks, cmd.dist_prefix_);
                    }
                }
            }

            if (num_contexts == 1)
            {
                BlockSplitterLiteral.BlockSplitterFinishBlock(
                    (BlockSplitterLiteral *)&lit_blocks, /* is_final = */ true);
            }
            else
            {
                ContextBlockSplitterFinishBlock(
                    &lit_blocks.ctx, ref m, /* is_final = */ true);
            }
            BlockSplitterCommand.BlockSplitterFinishBlock(&cmd_blocks, /* is_final = */ true);
            BlockSplitterDistance.BlockSplitterFinishBlock(&dist_blocks, /* is_final = */ true);

            if (num_contexts > 1)
            {
                MapStaticContexts(ref m, num_contexts, static_context_map, mb);
            }
        }
Esempio n. 17
0
 private static unsafe uint CommandCopyLen(Command *self)
 {
     return(self->copy_len_ & 0xFFFFFF);
 }
Esempio n. 18
0
 private static unsafe uint CommandCopyLenCode(Command *self)
 {
     return((self->copy_len_ & 0xFFFFFF) ^ (self->copy_len_ >> 24));
 }
Esempio n. 19
0
 public override unsafe void CreateBackwardReferences(ushort *dictionary_hash, 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)
 {
     throw new InvalidOperationException();
 }
Esempio n. 20
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);
        }
Esempio n. 21
0
        private static unsafe void ZopfliCostModelSetFromCommands(ZopfliCostModel *self,
                                                                  size_t position,
                                                                  byte *ringbuffer,
                                                                  size_t ringbuffer_mask,
                                                                  Command *commands,
                                                                  size_t num_commands,
                                                                  size_t last_insert_len)
        {
            uint * histogram_literal = stackalloc uint[BROTLI_NUM_LITERAL_SYMBOLS];
            uint * histogram_cmd     = stackalloc uint[BROTLI_NUM_COMMAND_SYMBOLS];
            uint * histogram_dist    = stackalloc uint[BROTLI_NUM_DISTANCE_SYMBOLS];
            float *cost_literal      = stackalloc float[BROTLI_NUM_LITERAL_SYMBOLS];
            size_t pos          = position - last_insert_len;
            float  min_cost_cmd = kInfinity;
            size_t i;
            float *cost_cmd = self->cost_cmd_;

            memset(histogram_literal, 0, BROTLI_NUM_LITERAL_SYMBOLS * sizeof(uint));
            memset(histogram_cmd, 0, BROTLI_NUM_COMMAND_SYMBOLS * sizeof(uint));
            memset(histogram_dist, 0, BROTLI_NUM_DISTANCE_SYMBOLS * sizeof(uint));

            for (i = 0; i < num_commands; i++)
            {
                size_t inslength  = commands[i].insert_len_;
                size_t copylength = CommandCopyLen(&commands[i]);
                size_t distcode   = commands[i].dist_prefix_;
                size_t cmdcode    = commands[i].cmd_prefix_;
                size_t j;

                histogram_cmd[cmdcode]++;
                if (cmdcode >= 128)
                {
                    histogram_dist[distcode]++;
                }

                for (j = 0; j < inslength; j++)
                {
                    histogram_literal[ringbuffer[(pos + j) & ringbuffer_mask]]++;
                }

                pos += inslength + copylength;
            }

            SetCost(histogram_literal, BROTLI_NUM_LITERAL_SYMBOLS, cost_literal);
            SetCost(histogram_cmd, BROTLI_NUM_COMMAND_SYMBOLS, cost_cmd);
            SetCost(histogram_dist, BROTLI_NUM_DISTANCE_SYMBOLS, self->cost_dist_);

            for (i = 0; i < BROTLI_NUM_COMMAND_SYMBOLS; ++i)
            {
                min_cost_cmd = Math.Min(min_cost_cmd, cost_cmd[i]);
            }
            self->min_cost_cmd_ = min_cost_cmd;

            {
                float *literal_costs = self->literal_costs_;
                size_t num_bytes     = self->num_bytes_;
                literal_costs[0] = 0.0f;
                for (i = 0; i < num_bytes; ++i)
                {
                    literal_costs[i + 1] = literal_costs[i] +
                                           cost_literal[ringbuffer[(position + i) & ringbuffer_mask]];
                }
            }
        }