1*f4ee7fbaSAndroid Build Coastguard Worker /* Copyright 2013 Google Inc. All Rights Reserved.
2*f4ee7fbaSAndroid Build Coastguard Worker
3*f4ee7fbaSAndroid Build Coastguard Worker Distributed under MIT license.
4*f4ee7fbaSAndroid Build Coastguard Worker See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
5*f4ee7fbaSAndroid Build Coastguard Worker */
6*f4ee7fbaSAndroid Build Coastguard Worker
7*f4ee7fbaSAndroid Build Coastguard Worker /* Build per-context histograms of literals, commands and distance codes. */
8*f4ee7fbaSAndroid Build Coastguard Worker
9*f4ee7fbaSAndroid Build Coastguard Worker #include "./histogram.h"
10*f4ee7fbaSAndroid Build Coastguard Worker
11*f4ee7fbaSAndroid Build Coastguard Worker #include "../common/context.h"
12*f4ee7fbaSAndroid Build Coastguard Worker #include "./block_splitter.h"
13*f4ee7fbaSAndroid Build Coastguard Worker #include "./command.h"
14*f4ee7fbaSAndroid Build Coastguard Worker
15*f4ee7fbaSAndroid Build Coastguard Worker #if defined(__cplusplus) || defined(c_plusplus)
16*f4ee7fbaSAndroid Build Coastguard Worker extern "C" {
17*f4ee7fbaSAndroid Build Coastguard Worker #endif
18*f4ee7fbaSAndroid Build Coastguard Worker
19*f4ee7fbaSAndroid Build Coastguard Worker typedef struct BlockSplitIterator {
20*f4ee7fbaSAndroid Build Coastguard Worker const BlockSplit* split_; /* Not owned. */
21*f4ee7fbaSAndroid Build Coastguard Worker size_t idx_;
22*f4ee7fbaSAndroid Build Coastguard Worker size_t type_;
23*f4ee7fbaSAndroid Build Coastguard Worker size_t length_;
24*f4ee7fbaSAndroid Build Coastguard Worker } BlockSplitIterator;
25*f4ee7fbaSAndroid Build Coastguard Worker
InitBlockSplitIterator(BlockSplitIterator * self,const BlockSplit * split)26*f4ee7fbaSAndroid Build Coastguard Worker static void InitBlockSplitIterator(BlockSplitIterator* self,
27*f4ee7fbaSAndroid Build Coastguard Worker const BlockSplit* split) {
28*f4ee7fbaSAndroid Build Coastguard Worker self->split_ = split;
29*f4ee7fbaSAndroid Build Coastguard Worker self->idx_ = 0;
30*f4ee7fbaSAndroid Build Coastguard Worker self->type_ = 0;
31*f4ee7fbaSAndroid Build Coastguard Worker self->length_ = split->lengths ? split->lengths[0] : 0;
32*f4ee7fbaSAndroid Build Coastguard Worker }
33*f4ee7fbaSAndroid Build Coastguard Worker
BlockSplitIteratorNext(BlockSplitIterator * self)34*f4ee7fbaSAndroid Build Coastguard Worker static void BlockSplitIteratorNext(BlockSplitIterator* self) {
35*f4ee7fbaSAndroid Build Coastguard Worker if (self->length_ == 0) {
36*f4ee7fbaSAndroid Build Coastguard Worker ++self->idx_;
37*f4ee7fbaSAndroid Build Coastguard Worker self->type_ = self->split_->types[self->idx_];
38*f4ee7fbaSAndroid Build Coastguard Worker self->length_ = self->split_->lengths[self->idx_];
39*f4ee7fbaSAndroid Build Coastguard Worker }
40*f4ee7fbaSAndroid Build Coastguard Worker --self->length_;
41*f4ee7fbaSAndroid Build Coastguard Worker }
42*f4ee7fbaSAndroid Build Coastguard Worker
BrotliBuildHistogramsWithContext(const Command * cmds,const size_t num_commands,const BlockSplit * literal_split,const BlockSplit * insert_and_copy_split,const BlockSplit * dist_split,const uint8_t * ringbuffer,size_t start_pos,size_t mask,uint8_t prev_byte,uint8_t prev_byte2,const ContextType * context_modes,HistogramLiteral * literal_histograms,HistogramCommand * insert_and_copy_histograms,HistogramDistance * copy_dist_histograms)43*f4ee7fbaSAndroid Build Coastguard Worker void BrotliBuildHistogramsWithContext(
44*f4ee7fbaSAndroid Build Coastguard Worker const Command* cmds, const size_t num_commands,
45*f4ee7fbaSAndroid Build Coastguard Worker const BlockSplit* literal_split, const BlockSplit* insert_and_copy_split,
46*f4ee7fbaSAndroid Build Coastguard Worker const BlockSplit* dist_split, const uint8_t* ringbuffer, size_t start_pos,
47*f4ee7fbaSAndroid Build Coastguard Worker size_t mask, uint8_t prev_byte, uint8_t prev_byte2,
48*f4ee7fbaSAndroid Build Coastguard Worker const ContextType* context_modes, HistogramLiteral* literal_histograms,
49*f4ee7fbaSAndroid Build Coastguard Worker HistogramCommand* insert_and_copy_histograms,
50*f4ee7fbaSAndroid Build Coastguard Worker HistogramDistance* copy_dist_histograms) {
51*f4ee7fbaSAndroid Build Coastguard Worker size_t pos = start_pos;
52*f4ee7fbaSAndroid Build Coastguard Worker BlockSplitIterator literal_it;
53*f4ee7fbaSAndroid Build Coastguard Worker BlockSplitIterator insert_and_copy_it;
54*f4ee7fbaSAndroid Build Coastguard Worker BlockSplitIterator dist_it;
55*f4ee7fbaSAndroid Build Coastguard Worker size_t i;
56*f4ee7fbaSAndroid Build Coastguard Worker
57*f4ee7fbaSAndroid Build Coastguard Worker InitBlockSplitIterator(&literal_it, literal_split);
58*f4ee7fbaSAndroid Build Coastguard Worker InitBlockSplitIterator(&insert_and_copy_it, insert_and_copy_split);
59*f4ee7fbaSAndroid Build Coastguard Worker InitBlockSplitIterator(&dist_it, dist_split);
60*f4ee7fbaSAndroid Build Coastguard Worker for (i = 0; i < num_commands; ++i) {
61*f4ee7fbaSAndroid Build Coastguard Worker const Command* cmd = &cmds[i];
62*f4ee7fbaSAndroid Build Coastguard Worker size_t j;
63*f4ee7fbaSAndroid Build Coastguard Worker BlockSplitIteratorNext(&insert_and_copy_it);
64*f4ee7fbaSAndroid Build Coastguard Worker HistogramAddCommand(&insert_and_copy_histograms[insert_and_copy_it.type_],
65*f4ee7fbaSAndroid Build Coastguard Worker cmd->cmd_prefix_);
66*f4ee7fbaSAndroid Build Coastguard Worker /* TODO: unwrap iterator blocks. */
67*f4ee7fbaSAndroid Build Coastguard Worker for (j = cmd->insert_len_; j != 0; --j) {
68*f4ee7fbaSAndroid Build Coastguard Worker size_t context;
69*f4ee7fbaSAndroid Build Coastguard Worker BlockSplitIteratorNext(&literal_it);
70*f4ee7fbaSAndroid Build Coastguard Worker context = literal_it.type_;
71*f4ee7fbaSAndroid Build Coastguard Worker if (context_modes) {
72*f4ee7fbaSAndroid Build Coastguard Worker ContextLut lut = BROTLI_CONTEXT_LUT(context_modes[context]);
73*f4ee7fbaSAndroid Build Coastguard Worker context = (context << BROTLI_LITERAL_CONTEXT_BITS) +
74*f4ee7fbaSAndroid Build Coastguard Worker BROTLI_CONTEXT(prev_byte, prev_byte2, lut);
75*f4ee7fbaSAndroid Build Coastguard Worker }
76*f4ee7fbaSAndroid Build Coastguard Worker HistogramAddLiteral(&literal_histograms[context],
77*f4ee7fbaSAndroid Build Coastguard Worker ringbuffer[pos & mask]);
78*f4ee7fbaSAndroid Build Coastguard Worker prev_byte2 = prev_byte;
79*f4ee7fbaSAndroid Build Coastguard Worker prev_byte = ringbuffer[pos & mask];
80*f4ee7fbaSAndroid Build Coastguard Worker ++pos;
81*f4ee7fbaSAndroid Build Coastguard Worker }
82*f4ee7fbaSAndroid Build Coastguard Worker pos += CommandCopyLen(cmd);
83*f4ee7fbaSAndroid Build Coastguard Worker if (CommandCopyLen(cmd)) {
84*f4ee7fbaSAndroid Build Coastguard Worker prev_byte2 = ringbuffer[(pos - 2) & mask];
85*f4ee7fbaSAndroid Build Coastguard Worker prev_byte = ringbuffer[(pos - 1) & mask];
86*f4ee7fbaSAndroid Build Coastguard Worker if (cmd->cmd_prefix_ >= 128) {
87*f4ee7fbaSAndroid Build Coastguard Worker size_t context;
88*f4ee7fbaSAndroid Build Coastguard Worker BlockSplitIteratorNext(&dist_it);
89*f4ee7fbaSAndroid Build Coastguard Worker context = (dist_it.type_ << BROTLI_DISTANCE_CONTEXT_BITS) +
90*f4ee7fbaSAndroid Build Coastguard Worker CommandDistanceContext(cmd);
91*f4ee7fbaSAndroid Build Coastguard Worker HistogramAddDistance(©_dist_histograms[context],
92*f4ee7fbaSAndroid Build Coastguard Worker cmd->dist_prefix_ & 0x3FF);
93*f4ee7fbaSAndroid Build Coastguard Worker }
94*f4ee7fbaSAndroid Build Coastguard Worker }
95*f4ee7fbaSAndroid Build Coastguard Worker }
96*f4ee7fbaSAndroid Build Coastguard Worker }
97*f4ee7fbaSAndroid Build Coastguard Worker
98*f4ee7fbaSAndroid Build Coastguard Worker #if defined(__cplusplus) || defined(c_plusplus)
99*f4ee7fbaSAndroid Build Coastguard Worker } /* extern "C" */
100*f4ee7fbaSAndroid Build Coastguard Worker #endif
101