Bug Summary

File:out/../deps/brotli/c/enc/./histogram_inc.h
Warning:line 19, column 3
Null pointer passed to 1st parameter expecting 'nonnull'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name metablock.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/home/maurizio/node-v18.6.0/out -resource-dir /usr/local/lib/clang/16.0.0 -D V8_DEPRECATION_WARNINGS -D V8_IMMINENT_DEPRECATION_WARNINGS -D _GLIBCXX_USE_CXX11_ABI=1 -D NODE_OPENSSL_CONF_NAME=nodejs_conf -D NODE_OPENSSL_HAS_QUIC -D __STDC_FORMAT_MACROS -D OPENSSL_NO_PINSHARED -D OPENSSL_THREADS -D OS_LINUX -I ../deps/brotli/c/include -internal-isystem /usr/local/lib/clang/16.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-redhat-linux/8/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O3 -Wno-unused-parameter -fdebug-compilation-dir=/home/maurizio/node-v18.6.0/out -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2022-08-22-142216-507842-1 -x c ../deps/brotli/c/enc/metablock.c

../deps/brotli/c/enc/metablock.c

1/* Copyright 2015 Google Inc. All Rights Reserved.
2
3 Distributed under MIT license.
4 See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
5*/
6
7/* Algorithms for distributing the literals and commands of a metablock between
8 block types and contexts. */
9
10#include "./metablock.h"
11
12#include "../common/constants.h"
13#include "../common/context.h"
14#include "../common/platform.h"
15#include <brotli/types.h>
16#include "./bit_cost.h"
17#include "./block_splitter.h"
18#include "./cluster.h"
19#include "./entropy_encode.h"
20#include "./histogram.h"
21#include "./memory.h"
22#include "./quality.h"
23
24#if defined(__cplusplus) || defined(c_plusplus)
25extern "C" {
26#endif
27
28void BrotliInitDistanceParams(BrotliEncoderParams* params,
29 uint32_t npostfix, uint32_t ndirect) {
30 BrotliDistanceParams* dist_params = &params->dist;
31 uint32_t alphabet_size_max;
32 uint32_t alphabet_size_limit;
33 uint32_t max_distance;
34
35 dist_params->distance_postfix_bits = npostfix;
36 dist_params->num_direct_distance_codes = ndirect;
37
38 alphabet_size_max = BROTLI_DISTANCE_ALPHABET_SIZE(( 16 + (ndirect) + ((24U) << ((npostfix) + 1)))
39 npostfix, ndirect, BROTLI_MAX_DISTANCE_BITS)( 16 + (ndirect) + ((24U) << ((npostfix) + 1)));
40 alphabet_size_limit = alphabet_size_max;
41 max_distance = ndirect + (1U << (BROTLI_MAX_DISTANCE_BITS24U + npostfix + 2)) -
42 (1U << (npostfix + 2));
43
44 if (params->large_window) {
45 BrotliDistanceCodeLimit limit = BrotliCalculateDistanceCodeLimit(
46 BROTLI_MAX_ALLOWED_DISTANCE0x7FFFFFFC, npostfix, ndirect);
47 alphabet_size_max = BROTLI_DISTANCE_ALPHABET_SIZE(( 16 + (ndirect) + ((62U) << ((npostfix) + 1)))
48 npostfix, ndirect, BROTLI_LARGE_MAX_DISTANCE_BITS)( 16 + (ndirect) + ((62U) << ((npostfix) + 1)));
49 alphabet_size_limit = limit.max_alphabet_size;
50 max_distance = limit.max_distance;
51 }
52
53 dist_params->alphabet_size_max = alphabet_size_max;
54 dist_params->alphabet_size_limit = alphabet_size_limit;
55 dist_params->max_distance = max_distance;
56}
57
58static void RecomputeDistancePrefixes(Command* cmds,
59 size_t num_commands,
60 const BrotliDistanceParams* orig_params,
61 const BrotliDistanceParams* new_params) {
62 size_t i;
63
64 if (orig_params->distance_postfix_bits == new_params->distance_postfix_bits &&
65 orig_params->num_direct_distance_codes ==
66 new_params->num_direct_distance_codes) {
67 return;
68 }
69
70 for (i = 0; i < num_commands; ++i) {
71 Command* cmd = &cmds[i];
72 if (CommandCopyLen(cmd) && cmd->cmd_prefix_ >= 128) {
73 PrefixEncodeCopyDistance(CommandRestoreDistanceCode(cmd, orig_params),
74 new_params->num_direct_distance_codes,
75 new_params->distance_postfix_bits,
76 &cmd->dist_prefix_,
77 &cmd->dist_extra_);
78 }
79 }
80}
81
82static BROTLI_BOOLint ComputeDistanceCost(const Command* cmds,
83 size_t num_commands,
84 const BrotliDistanceParams* orig_params,
85 const BrotliDistanceParams* new_params,
86 double* cost) {
87 size_t i;
88 BROTLI_BOOLint equal_params = BROTLI_FALSE0;
89 uint16_t dist_prefix;
90 uint32_t dist_extra;
91 double extra_bits = 0.0;
92 HistogramDistance histo;
93 HistogramClearDistance(&histo);
94
95 if (orig_params->distance_postfix_bits == new_params->distance_postfix_bits &&
96 orig_params->num_direct_distance_codes ==
97 new_params->num_direct_distance_codes) {
98 equal_params = BROTLI_TRUE1;
99 }
100
101 for (i = 0; i < num_commands; i++) {
102 const Command* cmd = &cmds[i];
103 if (CommandCopyLen(cmd) && cmd->cmd_prefix_ >= 128) {
104 if (equal_params) {
105 dist_prefix = cmd->dist_prefix_;
106 } else {
107 uint32_t distance = CommandRestoreDistanceCode(cmd, orig_params);
108 if (distance > new_params->max_distance) {
109 return BROTLI_FALSE0;
110 }
111 PrefixEncodeCopyDistance(distance,
112 new_params->num_direct_distance_codes,
113 new_params->distance_postfix_bits,
114 &dist_prefix,
115 &dist_extra);
116 }
117 HistogramAddDistance(&histo, dist_prefix & 0x3FF);
118 extra_bits += dist_prefix >> 10;
119 }
120 }
121
122 *cost = BrotliPopulationCostDistance(&histo) + extra_bits;
123 return BROTLI_TRUE1;
124}
125
126void BrotliBuildMetaBlock(MemoryManager* m,
127 const uint8_t* ringbuffer,
128 const size_t pos,
129 const size_t mask,
130 BrotliEncoderParams* params,
131 uint8_t prev_byte,
132 uint8_t prev_byte2,
133 Command* cmds,
134 size_t num_commands,
135 ContextType literal_context_mode,
136 MetaBlockSplit* mb) {
137 /* Histogram ids need to fit in one byte. */
138 static const size_t kMaxNumberOfHistograms = 256;
139 HistogramDistance* distance_histograms;
140 HistogramLiteral* literal_histograms;
141 ContextType* literal_context_modes = NULL((void*)0);
142 size_t literal_histograms_size;
143 size_t distance_histograms_size;
144 size_t i;
145 size_t literal_context_multiplier = 1;
146 uint32_t npostfix;
147 uint32_t ndirect_msb = 0;
148 BROTLI_BOOLint check_orig = BROTLI_TRUE1;
149 double best_dist_cost = 1e99;
150 BrotliEncoderParams orig_params = *params;
151 BrotliEncoderParams new_params = *params;
152
153 for (npostfix = 0; npostfix <= BROTLI_MAX_NPOSTFIX3; npostfix++) {
154 for (; ndirect_msb < 16; ndirect_msb++) {
155 uint32_t ndirect = ndirect_msb << npostfix;
156 BROTLI_BOOLint skip;
157 double dist_cost;
158 BrotliInitDistanceParams(&new_params, npostfix, ndirect);
159 if (npostfix == orig_params.dist.distance_postfix_bits &&
160 ndirect == orig_params.dist.num_direct_distance_codes) {
161 check_orig = BROTLI_FALSE0;
162 }
163 skip = !ComputeDistanceCost(
164 cmds, num_commands,
165 &orig_params.dist, &new_params.dist, &dist_cost);
166 if (skip || (dist_cost > best_dist_cost)) {
167 break;
168 }
169 best_dist_cost = dist_cost;
170 params->dist = new_params.dist;
171 }
172 if (ndirect_msb > 0) ndirect_msb--;
173 ndirect_msb /= 2;
174 }
175 if (check_orig) {
176 double dist_cost;
177 ComputeDistanceCost(cmds, num_commands,
178 &orig_params.dist, &orig_params.dist, &dist_cost);
179 if (dist_cost < best_dist_cost) {
180 /* NB: currently unused; uncomment when more param tuning is added. */
181 /* best_dist_cost = dist_cost; */
182 params->dist = orig_params.dist;
183 }
184 }
185 RecomputeDistancePrefixes(cmds, num_commands,
186 &orig_params.dist, &params->dist);
187
188 BrotliSplitBlock(m, cmds, num_commands,
189 ringbuffer, pos, mask, params,
190 &mb->literal_split,
191 &mb->command_split,
192 &mb->distance_split);
193 if (BROTLI_IS_OOM(m)(!!0)) return;
194
195 if (!params->disable_literal_context_modeling) {
196 literal_context_multiplier = 1 << BROTLI_LITERAL_CONTEXT_BITS6;
197 literal_context_modes =
198 BROTLI_ALLOC(m, ContextType, mb->literal_split.num_types)((mb->literal_split.num_types) > 0 ? ((ContextType*)BrotliAllocate
((m), (mb->literal_split.num_types) * sizeof(ContextType))
) : ((void*)0))
;
199 if (BROTLI_IS_OOM(m)(!!0) || BROTLI_IS_NULL(literal_context_modes)(!!0)) return;
200 for (i = 0; i < mb->literal_split.num_types; ++i) {
201 literal_context_modes[i] = literal_context_mode;
202 }
203 }
204
205 literal_histograms_size =
206 mb->literal_split.num_types * literal_context_multiplier;
207 literal_histograms =
208 BROTLI_ALLOC(m, HistogramLiteral, literal_histograms_size)((literal_histograms_size) > 0 ? ((HistogramLiteral*)BrotliAllocate
((m), (literal_histograms_size) * sizeof(HistogramLiteral))) :
((void*)0))
;
209 if (BROTLI_IS_OOM(m)(!!0) || BROTLI_IS_NULL(literal_histograms)(!!0)) return;
210 ClearHistogramsLiteral(literal_histograms, literal_histograms_size);
211
212 distance_histograms_size =
213 mb->distance_split.num_types << BROTLI_DISTANCE_CONTEXT_BITS2;
214 distance_histograms =
215 BROTLI_ALLOC(m, HistogramDistance, distance_histograms_size)((distance_histograms_size) > 0 ? ((HistogramDistance*)BrotliAllocate
((m), (distance_histograms_size) * sizeof(HistogramDistance))
) : ((void*)0))
;
216 if (BROTLI_IS_OOM(m)(!!0) || BROTLI_IS_NULL(distance_histograms)(!!0)) return;
217 ClearHistogramsDistance(distance_histograms, distance_histograms_size);
218
219 BROTLI_DCHECK(mb->command_histograms == 0);
220 mb->command_histograms_size = mb->command_split.num_types;
221 mb->command_histograms =
222 BROTLI_ALLOC(m, HistogramCommand, mb->command_histograms_size)((mb->command_histograms_size) > 0 ? ((HistogramCommand
*)BrotliAllocate((m), (mb->command_histograms_size) * sizeof
(HistogramCommand))) : ((void*)0))
;
223 if (BROTLI_IS_OOM(m)(!!0) || BROTLI_IS_NULL(mb->command_histograms)(!!0)) return;
224 ClearHistogramsCommand(mb->command_histograms, mb->command_histograms_size);
225
226 BrotliBuildHistogramsWithContext(cmds, num_commands,
227 &mb->literal_split, &mb->command_split, &mb->distance_split,
228 ringbuffer, pos, mask, prev_byte, prev_byte2, literal_context_modes,
229 literal_histograms, mb->command_histograms, distance_histograms);
230 BROTLI_FREE(m, literal_context_modes){ BrotliFree((m), (literal_context_modes)); literal_context_modes
= ((void*)0); }
;
231
232 BROTLI_DCHECK(mb->literal_context_map == 0);
233 mb->literal_context_map_size =
234 mb->literal_split.num_types << BROTLI_LITERAL_CONTEXT_BITS6;
235 mb->literal_context_map =
236 BROTLI_ALLOC(m, uint32_t, mb->literal_context_map_size)((mb->literal_context_map_size) > 0 ? ((uint32_t*)BrotliAllocate
((m), (mb->literal_context_map_size) * sizeof(uint32_t))) :
((void*)0))
;
237 if (BROTLI_IS_OOM(m)(!!0) || BROTLI_IS_NULL(mb->literal_context_map)(!!0)) return;
238
239 BROTLI_DCHECK(mb->literal_histograms == 0);
240 mb->literal_histograms_size = mb->literal_context_map_size;
241 mb->literal_histograms =
242 BROTLI_ALLOC(m, HistogramLiteral, mb->literal_histograms_size)((mb->literal_histograms_size) > 0 ? ((HistogramLiteral
*)BrotliAllocate((m), (mb->literal_histograms_size) * sizeof
(HistogramLiteral))) : ((void*)0))
;
243 if (BROTLI_IS_OOM(m)(!!0) || BROTLI_IS_NULL(mb->literal_histograms)(!!0)) return;
244
245 BrotliClusterHistogramsLiteral(m, literal_histograms, literal_histograms_size,
246 kMaxNumberOfHistograms, mb->literal_histograms,
247 &mb->literal_histograms_size, mb->literal_context_map);
248 if (BROTLI_IS_OOM(m)(!!0)) return;
249 BROTLI_FREE(m, literal_histograms){ BrotliFree((m), (literal_histograms)); literal_histograms =
((void*)0); }
;
250
251 if (params->disable_literal_context_modeling) {
252 /* Distribute assignment to all contexts. */
253 for (i = mb->literal_split.num_types; i != 0;) {
254 size_t j = 0;
255 i--;
256 for (; j < (1 << BROTLI_LITERAL_CONTEXT_BITS6); j++) {
257 mb->literal_context_map[(i << BROTLI_LITERAL_CONTEXT_BITS6) + j] =
258 mb->literal_context_map[i];
259 }
260 }
261 }
262
263 BROTLI_DCHECK(mb->distance_context_map == 0);
264 mb->distance_context_map_size =
265 mb->distance_split.num_types << BROTLI_DISTANCE_CONTEXT_BITS2;
266 mb->distance_context_map =
267 BROTLI_ALLOC(m, uint32_t, mb->distance_context_map_size)((mb->distance_context_map_size) > 0 ? ((uint32_t*)BrotliAllocate
((m), (mb->distance_context_map_size) * sizeof(uint32_t)))
: ((void*)0))
;
268 if (BROTLI_IS_OOM(m)(!!0) || BROTLI_IS_NULL(mb->distance_context_map)(!!0)) return;
269
270 BROTLI_DCHECK(mb->distance_histograms == 0);
271 mb->distance_histograms_size = mb->distance_context_map_size;
272 mb->distance_histograms =
273 BROTLI_ALLOC(m, HistogramDistance, mb->distance_histograms_size)((mb->distance_histograms_size) > 0 ? ((HistogramDistance
*)BrotliAllocate((m), (mb->distance_histograms_size) * sizeof
(HistogramDistance))) : ((void*)0))
;
274 if (BROTLI_IS_OOM(m)(!!0) || BROTLI_IS_NULL(mb->distance_histograms)(!!0)) return;
275
276 BrotliClusterHistogramsDistance(m, distance_histograms,
277 mb->distance_context_map_size,
278 kMaxNumberOfHistograms,
279 mb->distance_histograms,
280 &mb->distance_histograms_size,
281 mb->distance_context_map);
282 if (BROTLI_IS_OOM(m)(!!0)) return;
283 BROTLI_FREE(m, distance_histograms){ BrotliFree((m), (distance_histograms)); distance_histograms
= ((void*)0); }
;
284}
285
286#define FN(X) X ## Literal
287#include "./metablock_inc.h" /* NOLINT(build/include) */
288#undef FN
289
290#define FN(X) X ## Command
291#include "./metablock_inc.h" /* NOLINT(build/include) */
292#undef FN
293
294#define FN(X) X ## Distance
295#include "./metablock_inc.h" /* NOLINT(build/include) */
296#undef FN
297
298#define BROTLI_MAX_STATIC_CONTEXTS13 13
299
300/* Greedy block splitter for one block category (literal, command or distance).
301 Gathers histograms for all context buckets. */
302typedef struct ContextBlockSplitter {
303 /* Alphabet size of particular block category. */
304 size_t alphabet_size_;
305 size_t num_contexts_;
306 size_t max_block_types_;
307 /* We collect at least this many symbols for each block. */
308 size_t min_block_size_;
309 /* We merge histograms A and B if
310 entropy(A+B) < entropy(A) + entropy(B) + split_threshold_,
311 where A is the current histogram and B is the histogram of the last or the
312 second last block type. */
313 double split_threshold_;
314
315 size_t num_blocks_;
316 BlockSplit* split_; /* not owned */
317 HistogramLiteral* histograms_; /* not owned */
318 size_t* histograms_size_; /* not owned */
319
320 /* The number of symbols that we want to collect before deciding on whether
321 or not to merge the block with a previous one or emit a new block. */
322 size_t target_block_size_;
323 /* The number of symbols in the current histogram. */
324 size_t block_size_;
325 /* Offset of the current histogram. */
326 size_t curr_histogram_ix_;
327 /* Offset of the histograms of the previous two block types. */
328 size_t last_histogram_ix_[2];
329 /* Entropy of the previous two block types. */
330 double last_entropy_[2 * BROTLI_MAX_STATIC_CONTEXTS13];
331 /* The number of times we merged the current block with the last one. */
332 size_t merge_last_count_;
333} ContextBlockSplitter;
334
335static void InitContextBlockSplitter(
336 MemoryManager* m, ContextBlockSplitter* self, size_t alphabet_size,
337 size_t num_contexts, size_t min_block_size, double split_threshold,
338 size_t num_symbols, BlockSplit* split, HistogramLiteral** histograms,
339 size_t* histograms_size) {
340 size_t max_num_blocks = num_symbols / min_block_size + 1;
341 size_t max_num_types;
342 BROTLI_DCHECK(num_contexts <= BROTLI_MAX_STATIC_CONTEXTS);
343
344 self->alphabet_size_ = alphabet_size;
345 self->num_contexts_ = num_contexts;
346 self->max_block_types_ = BROTLI_MAX_NUMBER_OF_BLOCK_TYPES256 / num_contexts;
347 self->min_block_size_ = min_block_size;
348 self->split_threshold_ = split_threshold;
349 self->num_blocks_ = 0;
350 self->split_ = split;
351 self->histograms_size_ = histograms_size;
352 self->target_block_size_ = min_block_size;
353 self->block_size_ = 0;
354 self->curr_histogram_ix_ = 0;
355 self->merge_last_count_ = 0;
356
357 /* We have to allocate one more histogram than the maximum number of block
358 types for the current histogram when the meta-block is too big. */
359 max_num_types =
360 BROTLI_MIN(size_t, max_num_blocks, self->max_block_types_ + 1)(brotli_min_size_t((max_num_blocks), (self->max_block_types_
+ 1)))
;
361 BROTLI_ENSURE_CAPACITY(m, uint8_t,{ if (split->types_alloc_size < (max_num_blocks)) { size_t
_new_size = (split->types_alloc_size == 0) ? (max_num_blocks
) : split->types_alloc_size; uint8_t* new_array; while (_new_size
< (max_num_blocks)) _new_size *= 2; new_array = ((_new_size
) > 0 ? ((uint8_t*)BrotliAllocate(((m)), (_new_size) * sizeof
(uint8_t))) : ((void*)0)); if (!(!!0) && !(!!0) &&
split->types_alloc_size != 0) memcpy(new_array, split->
types, split->types_alloc_size * sizeof(uint8_t)); { BrotliFree
(((m)), (split->types)); split->types = ((void*)0); }; split
->types = new_array; split->types_alloc_size = _new_size
; } }
362 split->types, split->types_alloc_size, max_num_blocks){ if (split->types_alloc_size < (max_num_blocks)) { size_t
_new_size = (split->types_alloc_size == 0) ? (max_num_blocks
) : split->types_alloc_size; uint8_t* new_array; while (_new_size
< (max_num_blocks)) _new_size *= 2; new_array = ((_new_size
) > 0 ? ((uint8_t*)BrotliAllocate(((m)), (_new_size) * sizeof
(uint8_t))) : ((void*)0)); if (!(!!0) && !(!!0) &&
split->types_alloc_size != 0) memcpy(new_array, split->
types, split->types_alloc_size * sizeof(uint8_t)); { BrotliFree
(((m)), (split->types)); split->types = ((void*)0); }; split
->types = new_array; split->types_alloc_size = _new_size
; } }
;
363 BROTLI_ENSURE_CAPACITY(m, uint32_t,{ if (split->lengths_alloc_size < (max_num_blocks)) { size_t
_new_size = (split->lengths_alloc_size == 0) ? (max_num_blocks
) : split->lengths_alloc_size; uint32_t* new_array; while (
_new_size < (max_num_blocks)) _new_size *= 2; new_array = (
(_new_size) > 0 ? ((uint32_t*)BrotliAllocate(((m)), (_new_size
) * sizeof(uint32_t))) : ((void*)0)); if (!(!!0) && !
(!!0) && split->lengths_alloc_size != 0) memcpy(new_array
, split->lengths, split->lengths_alloc_size * sizeof(uint32_t
)); { BrotliFree(((m)), (split->lengths)); split->lengths
= ((void*)0); }; split->lengths = new_array; split->lengths_alloc_size
= _new_size; } }
364 split->lengths, split->lengths_alloc_size, max_num_blocks){ if (split->lengths_alloc_size < (max_num_blocks)) { size_t
_new_size = (split->lengths_alloc_size == 0) ? (max_num_blocks
) : split->lengths_alloc_size; uint32_t* new_array; while (
_new_size < (max_num_blocks)) _new_size *= 2; new_array = (
(_new_size) > 0 ? ((uint32_t*)BrotliAllocate(((m)), (_new_size
) * sizeof(uint32_t))) : ((void*)0)); if (!(!!0) && !
(!!0) && split->lengths_alloc_size != 0) memcpy(new_array
, split->lengths, split->lengths_alloc_size * sizeof(uint32_t
)); { BrotliFree(((m)), (split->lengths)); split->lengths
= ((void*)0); }; split->lengths = new_array; split->lengths_alloc_size
= _new_size; } }
;
365 if (BROTLI_IS_OOM(m)(!!0)) return;
366 split->num_blocks = max_num_blocks;
367 if (BROTLI_IS_OOM(m)(!!0)) return;
368 BROTLI_DCHECK(*histograms == 0);
369 *histograms_size = max_num_types * num_contexts;
370 *histograms = BROTLI_ALLOC(m, HistogramLiteral, *histograms_size)((*histograms_size) > 0 ? ((HistogramLiteral*)BrotliAllocate
((m), (*histograms_size) * sizeof(HistogramLiteral))) : ((void
*)0))
;
371 self->histograms_ = *histograms;
372 if (BROTLI_IS_OOM(m)(!!0) || BROTLI_IS_NULL(*histograms)(!!0)) return;
373 /* Clear only current histogram. */
374 ClearHistogramsLiteral(&self->histograms_[0], num_contexts);
375 self->last_histogram_ix_[0] = self->last_histogram_ix_[1] = 0;
376}
377
378/* Does either of three things:
379 (1) emits the current block with a new block type;
380 (2) emits the current block with the type of the second last block;
381 (3) merges the current block with the last block. */
382static void ContextBlockSplitterFinishBlock(
383 ContextBlockSplitter* self, MemoryManager* m, BROTLI_BOOLint is_final) {
384 BlockSplit* split = self->split_;
385 const size_t num_contexts = self->num_contexts_;
386 double* last_entropy = self->last_entropy_;
387 HistogramLiteral* histograms = self->histograms_;
388
389 if (self->block_size_ < self->min_block_size_) {
390 self->block_size_ = self->min_block_size_;
391 }
392 if (self->num_blocks_ == 0) {
393 size_t i;
394 /* Create first block. */
395 split->lengths[0] = (uint32_t)self->block_size_;
396 split->types[0] = 0;
397
398 for (i = 0; i < num_contexts; ++i) {
399 last_entropy[i] =
400 BitsEntropy(histograms[i].data_, self->alphabet_size_);
401 last_entropy[num_contexts + i] = last_entropy[i];
402 }
403 ++self->num_blocks_;
404 ++split->num_types;
405 self->curr_histogram_ix_ += num_contexts;
406 if (self->curr_histogram_ix_ < *self->histograms_size_) {
407 ClearHistogramsLiteral(
408 &self->histograms_[self->curr_histogram_ix_], self->num_contexts_);
409 }
410 self->block_size_ = 0;
411 } else if (self->block_size_ > 0) {
412 /* Try merging the set of histograms for the current block type with the
413 respective set of histograms for the last and second last block types.
414 Decide over the split based on the total reduction of entropy across
415 all contexts. */
416 double entropy[BROTLI_MAX_STATIC_CONTEXTS13];
417 HistogramLiteral* combined_histo =
418 BROTLI_ALLOC(m, HistogramLiteral, 2 * num_contexts)((2 * num_contexts) > 0 ? ((HistogramLiteral*)BrotliAllocate
((m), (2 * num_contexts) * sizeof(HistogramLiteral))) : ((void
*)0))
;
419 double combined_entropy[2 * BROTLI_MAX_STATIC_CONTEXTS13];
420 double diff[2] = { 0.0 };
421 size_t i;
422 if (BROTLI_IS_OOM(m)(!!0) || BROTLI_IS_NULL(combined_histo)(!!0)) return;
423 for (i = 0; i < num_contexts; ++i) {
424 size_t curr_histo_ix = self->curr_histogram_ix_ + i;
425 size_t j;
426 entropy[i] = BitsEntropy(histograms[curr_histo_ix].data_,
427 self->alphabet_size_);
428 for (j = 0; j < 2; ++j) {
429 size_t jx = j * num_contexts + i;
430 size_t last_histogram_ix = self->last_histogram_ix_[j] + i;
431 combined_histo[jx] = histograms[curr_histo_ix];
432 HistogramAddHistogramLiteral(&combined_histo[jx],
433 &histograms[last_histogram_ix]);
434 combined_entropy[jx] = BitsEntropy(
435 &combined_histo[jx].data_[0], self->alphabet_size_);
436 diff[j] += combined_entropy[jx] - entropy[i] - last_entropy[jx];
437 }
438 }
439
440 if (split->num_types < self->max_block_types_ &&
441 diff[0] > self->split_threshold_ &&
442 diff[1] > self->split_threshold_) {
443 /* Create new block. */
444 split->lengths[self->num_blocks_] = (uint32_t)self->block_size_;
445 split->types[self->num_blocks_] = (uint8_t)split->num_types;
446 self->last_histogram_ix_[1] = self->last_histogram_ix_[0];
447 self->last_histogram_ix_[0] = split->num_types * num_contexts;
448 for (i = 0; i < num_contexts; ++i) {
449 last_entropy[num_contexts + i] = last_entropy[i];
450 last_entropy[i] = entropy[i];
451 }
452 ++self->num_blocks_;
453 ++split->num_types;
454 self->curr_histogram_ix_ += num_contexts;
455 if (self->curr_histogram_ix_ < *self->histograms_size_) {
456 ClearHistogramsLiteral(
457 &self->histograms_[self->curr_histogram_ix_], self->num_contexts_);
458 }
459 self->block_size_ = 0;
460 self->merge_last_count_ = 0;
461 self->target_block_size_ = self->min_block_size_;
462 } else if (diff[1] < diff[0] - 20.0) {
463 /* Combine this block with second last block. */
464 split->lengths[self->num_blocks_] = (uint32_t)self->block_size_;
465 split->types[self->num_blocks_] = split->types[self->num_blocks_ - 2];
466 BROTLI_SWAP(size_t, self->last_histogram_ix_, 0, 1){ size_t __brotli_swap_tmp = (self->last_histogram_ix_)[(0
)]; (self->last_histogram_ix_)[(0)] = (self->last_histogram_ix_
)[(1)]; (self->last_histogram_ix_)[(1)] = __brotli_swap_tmp
; }
;
467 for (i = 0; i < num_contexts; ++i) {
468 histograms[self->last_histogram_ix_[0] + i] =
469 combined_histo[num_contexts + i];
470 last_entropy[num_contexts + i] = last_entropy[i];
471 last_entropy[i] = combined_entropy[num_contexts + i];
472 HistogramClearLiteral(&histograms[self->curr_histogram_ix_ + i]);
473 }
474 ++self->num_blocks_;
475 self->block_size_ = 0;
476 self->merge_last_count_ = 0;
477 self->target_block_size_ = self->min_block_size_;
478 } else {
479 /* Combine this block with last block. */
480 split->lengths[self->num_blocks_ - 1] += (uint32_t)self->block_size_;
481 for (i = 0; i < num_contexts; ++i) {
482 histograms[self->last_histogram_ix_[0] + i] = combined_histo[i];
483 last_entropy[i] = combined_entropy[i];
484 if (split->num_types == 1) {
485 last_entropy[num_contexts + i] = last_entropy[i];
486 }
487 HistogramClearLiteral(&histograms[self->curr_histogram_ix_ + i]);
488 }
489 self->block_size_ = 0;
490 if (++self->merge_last_count_ > 1) {
491 self->target_block_size_ += self->min_block_size_;
492 }
493 }
494 BROTLI_FREE(m, combined_histo){ BrotliFree((m), (combined_histo)); combined_histo = ((void*
)0); }
;
495 }
496 if (is_final) {
497 *self->histograms_size_ = split->num_types * num_contexts;
498 split->num_blocks = self->num_blocks_;
499 }
500}
501
502/* Adds the next symbol to the current block type and context. When the
503 current block reaches the target size, decides on merging the block. */
504static void ContextBlockSplitterAddSymbol(
505 ContextBlockSplitter* self, MemoryManager* m,
506 size_t symbol, size_t context) {
507 HistogramAddLiteral(&self->histograms_[self->curr_histogram_ix_ + context],
508 symbol);
509 ++self->block_size_;
510 if (self->block_size_ == self->target_block_size_) {
511 ContextBlockSplitterFinishBlock(self, m, /* is_final = */ BROTLI_FALSE0);
512 if (BROTLI_IS_OOM(m)(!!0)) return;
513 }
514}
515
516static void MapStaticContexts(MemoryManager* m,
517 size_t num_contexts,
518 const uint32_t* static_context_map,
519 MetaBlockSplit* mb) {
520 size_t i;
521 BROTLI_DCHECK(mb->literal_context_map == 0);
522 mb->literal_context_map_size =
523 mb->literal_split.num_types << BROTLI_LITERAL_CONTEXT_BITS6;
524 mb->literal_context_map =
525 BROTLI_ALLOC(m, uint32_t, mb->literal_context_map_size)((mb->literal_context_map_size) > 0 ? ((uint32_t*)BrotliAllocate
((m), (mb->literal_context_map_size) * sizeof(uint32_t))) :
((void*)0))
;
526 if (BROTLI_IS_OOM(m)(!!0) || BROTLI_IS_NULL(mb->literal_context_map)(!!0)) return;
527
528 for (i = 0; i < mb->literal_split.num_types; ++i) {
529 uint32_t offset = (uint32_t)(i * num_contexts);
530 size_t j;
531 for (j = 0; j < (1u << BROTLI_LITERAL_CONTEXT_BITS6); ++j) {
532 mb->literal_context_map[(i << BROTLI_LITERAL_CONTEXT_BITS6) + j] =
533 offset + static_context_map[j];
534 }
535 }
536}
537
538static BROTLI_INLINEinline __attribute__((__always_inline__)) void BrotliBuildMetaBlockGreedyInternal(
539 MemoryManager* m, const uint8_t* ringbuffer, size_t pos, size_t mask,
540 uint8_t prev_byte, uint8_t prev_byte2, ContextLut literal_context_lut,
541 const size_t num_contexts, const uint32_t* static_context_map,
542 const Command* commands, size_t n_commands, MetaBlockSplit* mb) {
543 union {
544 BlockSplitterLiteral plain;
545 ContextBlockSplitter ctx;
546 } lit_blocks;
547 BlockSplitterCommand cmd_blocks;
548 BlockSplitterDistance dist_blocks;
549 size_t num_literals = 0;
550 size_t i;
551 for (i = 0; i < n_commands; ++i) {
4
Assuming 'i' is < 'n_commands'
5
Loop condition is true. Entering loop body
6
Assuming 'i' is >= 'n_commands'
7
Loop condition is false. Execution continues on line 555
552 num_literals += commands[i].insert_len_;
553 }
554
555 if (num_contexts
7.1
'num_contexts' is equal to 1
7.1
'num_contexts' is equal to 1
7.1
'num_contexts' is equal to 1
== 1) {
8
Taking true branch
556 InitBlockSplitterLiteral(m, &lit_blocks.plain, 256, 512, 400.0,
9
Calling 'InitBlockSplitterLiteral'
557 num_literals, &mb->literal_split, &mb->literal_histograms,
558 &mb->literal_histograms_size);
559 } else {
560 InitContextBlockSplitter(m, &lit_blocks.ctx, 256, num_contexts, 512, 400.0,
561 num_literals, &mb->literal_split, &mb->literal_histograms,
562 &mb->literal_histograms_size);
563 }
564 if (BROTLI_IS_OOM(m)(!!0)) return;
565 InitBlockSplitterCommand(m, &cmd_blocks, BROTLI_NUM_COMMAND_SYMBOLS704, 1024,
566 500.0, n_commands, &mb->command_split, &mb->command_histograms,
567 &mb->command_histograms_size);
568 if (BROTLI_IS_OOM(m)(!!0)) return;
569 InitBlockSplitterDistance(m, &dist_blocks, 64, 512, 100.0, n_commands,
570 &mb->distance_split, &mb->distance_histograms,
571 &mb->distance_histograms_size);
572 if (BROTLI_IS_OOM(m)(!!0)) return;
573
574 for (i = 0; i < n_commands; ++i) {
575 const Command cmd = commands[i];
576 size_t j;
577 BlockSplitterAddSymbolCommand(&cmd_blocks, cmd.cmd_prefix_);
578 for (j = cmd.insert_len_; j != 0; --j) {
579 uint8_t literal = ringbuffer[pos & mask];
580 if (num_contexts == 1) {
581 BlockSplitterAddSymbolLiteral(&lit_blocks.plain, literal);
582 } else {
583 size_t context =
584 BROTLI_CONTEXT(prev_byte, prev_byte2, literal_context_lut)((literal_context_lut)[prev_byte] | ((literal_context_lut) + 256
)[prev_byte2])
;
585 ContextBlockSplitterAddSymbol(&lit_blocks.ctx, m, literal,
586 static_context_map[context]);
587 if (BROTLI_IS_OOM(m)(!!0)) return;
588 }
589 prev_byte2 = prev_byte;
590 prev_byte = literal;
591 ++pos;
592 }
593 pos += CommandCopyLen(&cmd);
594 if (CommandCopyLen(&cmd)) {
595 prev_byte2 = ringbuffer[(pos - 2) & mask];
596 prev_byte = ringbuffer[(pos - 1) & mask];
597 if (cmd.cmd_prefix_ >= 128) {
598 BlockSplitterAddSymbolDistance(&dist_blocks, cmd.dist_prefix_ & 0x3FF);
599 }
600 }
601 }
602
603 if (num_contexts == 1) {
604 BlockSplitterFinishBlockLiteral(
605 &lit_blocks.plain, /* is_final = */ BROTLI_TRUE1);
606 } else {
607 ContextBlockSplitterFinishBlock(
608 &lit_blocks.ctx, m, /* is_final = */ BROTLI_TRUE1);
609 if (BROTLI_IS_OOM(m)(!!0)) return;
610 }
611 BlockSplitterFinishBlockCommand(&cmd_blocks, /* is_final = */ BROTLI_TRUE1);
612 BlockSplitterFinishBlockDistance(&dist_blocks, /* is_final = */ BROTLI_TRUE1);
613
614 if (num_contexts > 1) {
615 MapStaticContexts(m, num_contexts, static_context_map, mb);
616 }
617}
618
619void BrotliBuildMetaBlockGreedy(MemoryManager* m,
620 const uint8_t* ringbuffer,
621 size_t pos,
622 size_t mask,
623 uint8_t prev_byte,
624 uint8_t prev_byte2,
625 ContextLut literal_context_lut,
626 size_t num_contexts,
627 const uint32_t* static_context_map,
628 const Command* commands,
629 size_t n_commands,
630 MetaBlockSplit* mb) {
631 if (num_contexts == 1) {
1
Assuming 'num_contexts' is equal to 1
2
Taking true branch
632 BrotliBuildMetaBlockGreedyInternal(m, ringbuffer, pos, mask, prev_byte,
3
Calling 'BrotliBuildMetaBlockGreedyInternal'
633 prev_byte2, literal_context_lut, 1, NULL((void*)0), commands, n_commands, mb);
634 } else {
635 BrotliBuildMetaBlockGreedyInternal(m, ringbuffer, pos, mask, prev_byte,
636 prev_byte2, literal_context_lut, num_contexts, static_context_map,
637 commands, n_commands, mb);
638 }
639}
640
641void BrotliOptimizeHistograms(uint32_t num_distance_codes,
642 MetaBlockSplit* mb) {
643 uint8_t good_for_rle[BROTLI_NUM_COMMAND_SYMBOLS704];
644 size_t i;
645 for (i = 0; i < mb->literal_histograms_size; ++i) {
646 BrotliOptimizeHuffmanCountsForRle(256, mb->literal_histograms[i].data_,
647 good_for_rle);
648 }
649 for (i = 0; i < mb->command_histograms_size; ++i) {
650 BrotliOptimizeHuffmanCountsForRle(BROTLI_NUM_COMMAND_SYMBOLS704,
651 mb->command_histograms[i].data_,
652 good_for_rle);
653 }
654 for (i = 0; i < mb->distance_histograms_size; ++i) {
655 BrotliOptimizeHuffmanCountsForRle(num_distance_codes,
656 mb->distance_histograms[i].data_,
657 good_for_rle);
658 }
659}
660
661#if defined(__cplusplus) || defined(c_plusplus)
662} /* extern "C" */
663#endif

../deps/brotli/c/enc/./metablock_inc.h

1/* NOLINT(build/header_guard) */
2/* Copyright 2015 Google Inc. All Rights Reserved.
3
4 Distributed under MIT license.
5 See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
6*/
7
8/* template parameters: FN */
9
10#define HistogramType FN(Histogram)
11
12/* Greedy block splitter for one block category (literal, command or distance).
13*/
14typedef struct FN(BlockSplitter) {
15 /* Alphabet size of particular block category. */
16 size_t alphabet_size_;
17 /* We collect at least this many symbols for each block. */
18 size_t min_block_size_;
19 /* We merge histograms A and B if
20 entropy(A+B) < entropy(A) + entropy(B) + split_threshold_,
21 where A is the current histogram and B is the histogram of the last or the
22 second last block type. */
23 double split_threshold_;
24
25 size_t num_blocks_;
26 BlockSplit* split_; /* not owned */
27 HistogramType* histograms_; /* not owned */
28 size_t* histograms_size_; /* not owned */
29
30 /* The number of symbols that we want to collect before deciding on whether
31 or not to merge the block with a previous one or emit a new block. */
32 size_t target_block_size_;
33 /* The number of symbols in the current histogram. */
34 size_t block_size_;
35 /* Offset of the current histogram. */
36 size_t curr_histogram_ix_;
37 /* Offset of the histograms of the previous two block types. */
38 size_t last_histogram_ix_[2];
39 /* Entropy of the previous two block types. */
40 double last_entropy_[2];
41 /* The number of times we merged the current block with the last one. */
42 size_t merge_last_count_;
43} FN(BlockSplitter);
44
45static void FN(InitBlockSplitter)(
46 MemoryManager* m, FN(BlockSplitter)* self, size_t alphabet_size,
47 size_t min_block_size, double split_threshold, size_t num_symbols,
48 BlockSplit* split, HistogramType** histograms, size_t* histograms_size) {
49 size_t max_num_blocks = num_symbols / min_block_size + 1;
50 /* We have to allocate one more histogram than the maximum number of block
51 types for the current histogram when the meta-block is too big. */
52 size_t max_num_types =
53 BROTLI_MIN(size_t, max_num_blocks, BROTLI_MAX_NUMBER_OF_BLOCK_TYPES + 1)(brotli_min_size_t((max_num_blocks), (256 + 1)));
54 self->alphabet_size_ = alphabet_size;
55 self->min_block_size_ = min_block_size;
56 self->split_threshold_ = split_threshold;
57 self->num_blocks_ = 0;
58 self->split_ = split;
59 self->histograms_size_ = histograms_size;
60 self->target_block_size_ = min_block_size;
61 self->block_size_ = 0;
62 self->curr_histogram_ix_ = 0;
63 self->merge_last_count_ = 0;
64 BROTLI_ENSURE_CAPACITY(m, uint8_t,{ if (split->types_alloc_size < (max_num_blocks)) { size_t
_new_size = (split->types_alloc_size == 0) ? (max_num_blocks
) : split->types_alloc_size; uint8_t* new_array; while (_new_size
< (max_num_blocks)) _new_size *= 2; new_array = ((_new_size
) > 0 ? ((uint8_t*)BrotliAllocate(((m)), (_new_size) * sizeof
(uint8_t))) : ((void*)0)); if (!(!!0) && !(!!0) &&
split->types_alloc_size != 0) memcpy(new_array, split->
types, split->types_alloc_size * sizeof(uint8_t)); { BrotliFree
(((m)), (split->types)); split->types = ((void*)0); }; split
->types = new_array; split->types_alloc_size = _new_size
; } }
10
Assuming 'max_num_blocks' is <= field 'types_alloc_size'
11
Taking false branch
65 split->types, split->types_alloc_size, max_num_blocks){ if (split->types_alloc_size < (max_num_blocks)) { size_t
_new_size = (split->types_alloc_size == 0) ? (max_num_blocks
) : split->types_alloc_size; uint8_t* new_array; while (_new_size
< (max_num_blocks)) _new_size *= 2; new_array = ((_new_size
) > 0 ? ((uint8_t*)BrotliAllocate(((m)), (_new_size) * sizeof
(uint8_t))) : ((void*)0)); if (!(!!0) && !(!!0) &&
split->types_alloc_size != 0) memcpy(new_array, split->
types, split->types_alloc_size * sizeof(uint8_t)); { BrotliFree
(((m)), (split->types)); split->types = ((void*)0); }; split
->types = new_array; split->types_alloc_size = _new_size
; } }
;
66 BROTLI_ENSURE_CAPACITY(m, uint32_t,{ if (split->lengths_alloc_size < (max_num_blocks)) { size_t
_new_size = (split->lengths_alloc_size == 0) ? (max_num_blocks
) : split->lengths_alloc_size; uint32_t* new_array; while (
_new_size < (max_num_blocks)) _new_size *= 2; new_array = (
(_new_size) > 0 ? ((uint32_t*)BrotliAllocate(((m)), (_new_size
) * sizeof(uint32_t))) : ((void*)0)); if (!(!!0) && !
(!!0) && split->lengths_alloc_size != 0) memcpy(new_array
, split->lengths, split->lengths_alloc_size * sizeof(uint32_t
)); { BrotliFree(((m)), (split->lengths)); split->lengths
= ((void*)0); }; split->lengths = new_array; split->lengths_alloc_size
= _new_size; } }
12
Assuming 'max_num_blocks' is <= field 'lengths_alloc_size'
13
Taking false branch
67 split->lengths, split->lengths_alloc_size, max_num_blocks){ if (split->lengths_alloc_size < (max_num_blocks)) { size_t
_new_size = (split->lengths_alloc_size == 0) ? (max_num_blocks
) : split->lengths_alloc_size; uint32_t* new_array; while (
_new_size < (max_num_blocks)) _new_size *= 2; new_array = (
(_new_size) > 0 ? ((uint32_t*)BrotliAllocate(((m)), (_new_size
) * sizeof(uint32_t))) : ((void*)0)); if (!(!!0) && !
(!!0) && split->lengths_alloc_size != 0) memcpy(new_array
, split->lengths, split->lengths_alloc_size * sizeof(uint32_t
)); { BrotliFree(((m)), (split->lengths)); split->lengths
= ((void*)0); }; split->lengths = new_array; split->lengths_alloc_size
= _new_size; } }
;
68 if (BROTLI_IS_OOM(m)(!!0)) return;
14
Taking false branch
69 self->split_->num_blocks = max_num_blocks;
70 BROTLI_DCHECK(*histograms == 0);
71 *histograms_size = max_num_types;
72 *histograms = BROTLI_ALLOC(m, HistogramType, *histograms_size)((*histograms_size) > 0 ? ((HistogramType*)BrotliAllocate(
(m), (*histograms_size) * sizeof(HistogramType))) : ((void*)0
))
;
15
Assuming the condition is false
16
'?' condition is false
73 self->histograms_ = *histograms;
74 if (BROTLI_IS_OOM(m)(!!0) || BROTLI_IS_NULL(*histograms)(!!0)) return;
17
Taking false branch
75 /* Clear only current histogram. */
76 FN(HistogramClear)(&self->histograms_[0]);
18
Calling 'HistogramClearLiteral'
77 self->last_histogram_ix_[0] = self->last_histogram_ix_[1] = 0;
78}
79
80/* Does either of three things:
81 (1) emits the current block with a new block type;
82 (2) emits the current block with the type of the second last block;
83 (3) merges the current block with the last block. */
84static void FN(BlockSplitterFinishBlock)(
85 FN(BlockSplitter)* self, BROTLI_BOOLint is_final) {
86 BlockSplit* split = self->split_;
87 double* last_entropy = self->last_entropy_;
88 HistogramType* histograms = self->histograms_;
89 self->block_size_ =
90 BROTLI_MAX(size_t, self->block_size_, self->min_block_size_)(brotli_max_size_t((self->block_size_), (self->min_block_size_
)))
;
91 if (self->num_blocks_ == 0) {
92 /* Create first block. */
93 split->lengths[0] = (uint32_t)self->block_size_;
94 split->types[0] = 0;
95 last_entropy[0] =
96 BitsEntropy(histograms[0].data_, self->alphabet_size_);
97 last_entropy[1] = last_entropy[0];
98 ++self->num_blocks_;
99 ++split->num_types;
100 ++self->curr_histogram_ix_;
101 if (self->curr_histogram_ix_ < *self->histograms_size_)
102 FN(HistogramClear)(&histograms[self->curr_histogram_ix_]);
103 self->block_size_ = 0;
104 } else if (self->block_size_ > 0) {
105 double entropy = BitsEntropy(histograms[self->curr_histogram_ix_].data_,
106 self->alphabet_size_);
107 HistogramType combined_histo[2];
108 double combined_entropy[2];
109 double diff[2];
110 size_t j;
111 for (j = 0; j < 2; ++j) {
112 size_t last_histogram_ix = self->last_histogram_ix_[j];
113 combined_histo[j] = histograms[self->curr_histogram_ix_];
114 FN(HistogramAddHistogram)(&combined_histo[j],
115 &histograms[last_histogram_ix]);
116 combined_entropy[j] = BitsEntropy(
117 &combined_histo[j].data_[0], self->alphabet_size_);
118 diff[j] = combined_entropy[j] - entropy - last_entropy[j];
119 }
120
121 if (split->num_types < BROTLI_MAX_NUMBER_OF_BLOCK_TYPES256 &&
122 diff[0] > self->split_threshold_ &&
123 diff[1] > self->split_threshold_) {
124 /* Create new block. */
125 split->lengths[self->num_blocks_] = (uint32_t)self->block_size_;
126 split->types[self->num_blocks_] = (uint8_t)split->num_types;
127 self->last_histogram_ix_[1] = self->last_histogram_ix_[0];
128 self->last_histogram_ix_[0] = (uint8_t)split->num_types;
129 last_entropy[1] = last_entropy[0];
130 last_entropy[0] = entropy;
131 ++self->num_blocks_;
132 ++split->num_types;
133 ++self->curr_histogram_ix_;
134 if (self->curr_histogram_ix_ < *self->histograms_size_)
135 FN(HistogramClear)(&histograms[self->curr_histogram_ix_]);
136 self->block_size_ = 0;
137 self->merge_last_count_ = 0;
138 self->target_block_size_ = self->min_block_size_;
139 } else if (diff[1] < diff[0] - 20.0) {
140 /* Combine this block with second last block. */
141 split->lengths[self->num_blocks_] = (uint32_t)self->block_size_;
142 split->types[self->num_blocks_] = split->types[self->num_blocks_ - 2];
143 BROTLI_SWAP(size_t, self->last_histogram_ix_, 0, 1){ size_t __brotli_swap_tmp = (self->last_histogram_ix_)[(0
)]; (self->last_histogram_ix_)[(0)] = (self->last_histogram_ix_
)[(1)]; (self->last_histogram_ix_)[(1)] = __brotli_swap_tmp
; }
;
144 histograms[self->last_histogram_ix_[0]] = combined_histo[1];
145 last_entropy[1] = last_entropy[0];
146 last_entropy[0] = combined_entropy[1];
147 ++self->num_blocks_;
148 self->block_size_ = 0;
149 FN(HistogramClear)(&histograms[self->curr_histogram_ix_]);
150 self->merge_last_count_ = 0;
151 self->target_block_size_ = self->min_block_size_;
152 } else {
153 /* Combine this block with last block. */
154 split->lengths[self->num_blocks_ - 1] += (uint32_t)self->block_size_;
155 histograms[self->last_histogram_ix_[0]] = combined_histo[0];
156 last_entropy[0] = combined_entropy[0];
157 if (split->num_types == 1) {
158 last_entropy[1] = last_entropy[0];
159 }
160 self->block_size_ = 0;
161 FN(HistogramClear)(&histograms[self->curr_histogram_ix_]);
162 if (++self->merge_last_count_ > 1) {
163 self->target_block_size_ += self->min_block_size_;
164 }
165 }
166 }
167 if (is_final) {
168 *self->histograms_size_ = split->num_types;
169 split->num_blocks = self->num_blocks_;
170 }
171}
172
173/* Adds the next symbol to the current histogram. When the current histogram
174 reaches the target size, decides on merging the block. */
175static void FN(BlockSplitterAddSymbol)(FN(BlockSplitter)* self, size_t symbol) {
176 FN(HistogramAdd)(&self->histograms_[self->curr_histogram_ix_], symbol);
177 ++self->block_size_;
178 if (self->block_size_ == self->target_block_size_) {
179 FN(BlockSplitterFinishBlock)(self, /* is_final = */ BROTLI_FALSE0);
180 }
181}
182
183#undef HistogramType

../deps/brotli/c/enc/./histogram_inc.h

1/* NOLINT(build/header_guard) */
2/* Copyright 2013 Google Inc. All Rights Reserved.
3
4 Distributed under MIT license.
5 See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
6*/
7
8/* template parameters: Histogram, DATA_SIZE, DataType */
9
10/* A simple container for histograms of data in blocks. */
11
12typedef struct FN(Histogram) {
13 uint32_t data_[DATA_SIZE];
14 size_t total_count_;
15 double bit_cost_;
16} FN(Histogram);
17
18static BROTLI_INLINEinline __attribute__((__always_inline__)) void FN(HistogramClear)(FN(Histogram)* self) {
19 memset(self->data_, 0, sizeof(self->data_));
19
Null pointer passed to 1st parameter expecting 'nonnull'
20 self->total_count_ = 0;
21 self->bit_cost_ = HUGE_VAL(__builtin_huge_val ());
22}
23
24static BROTLI_INLINEinline __attribute__((__always_inline__)) void FN(ClearHistograms)(
25 FN(Histogram)* array, size_t length) {
26 size_t i;
27 for (i = 0; i < length; ++i) FN(HistogramClear)(array + i);
28}
29
30static BROTLI_INLINEinline __attribute__((__always_inline__)) void FN(HistogramAdd)(FN(Histogram)* self, size_t val) {
31 ++self->data_[val];
32 ++self->total_count_;
33}
34
35static BROTLI_INLINEinline __attribute__((__always_inline__)) void FN(HistogramAddVector)(FN(Histogram)* self,
36 const DataType* p, size_t n) {
37 self->total_count_ += n;
38 n += 1;
39 while (--n) ++self->data_[*p++];
40}
41
42static BROTLI_INLINEinline __attribute__((__always_inline__)) void FN(HistogramAddHistogram)(FN(Histogram)* self,
43 const FN(Histogram)* v) {
44 size_t i;
45 self->total_count_ += v->total_count_;
46 for (i = 0; i < DATA_SIZE; ++i) {
47 self->data_[i] += v->data_[i];
48 }
49}
50
51static BROTLI_INLINEinline __attribute__((__always_inline__)) size_t FN(HistogramDataSize)(void) { return DATA_SIZE; }