1 /* Copyright 2013 Google Inc. All Rights Reserved.
3 Distributed under MIT license.
4 See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
7 /* Build per-context histograms of literals, commands and distance codes. */
9 #include "./histogram.h"
11 #include "./block_splitter.h"
12 #include "./command.h"
13 #include "./context.h"
15 #if defined(__cplusplus) || defined(c_plusplus)
19 typedef struct BlockSplitIterator
{
20 const BlockSplit
* split_
; /* Not owned. */
26 static void InitBlockSplitIterator(BlockSplitIterator
* self
,
27 const BlockSplit
* split
) {
31 self
->length_
= split
->lengths
? split
->lengths
[0] : 0;
34 static void BlockSplitIteratorNext(BlockSplitIterator
* self
) {
35 if (self
->length_
== 0) {
37 self
->type_
= self
->split_
->types
[self
->idx_
];
38 self
->length_
= self
->split_
->lengths
[self
->idx_
];
43 void BrotliBuildHistogramsWithContext(
44 const Command
* cmds
, const size_t num_commands
,
45 const BlockSplit
* literal_split
, const BlockSplit
* insert_and_copy_split
,
46 const BlockSplit
* dist_split
, const uint8_t* ringbuffer
, size_t start_pos
,
47 size_t mask
, uint8_t prev_byte
, uint8_t prev_byte2
,
48 const ContextType
* context_modes
, HistogramLiteral
* literal_histograms
,
49 HistogramCommand
* insert_and_copy_histograms
,
50 HistogramDistance
* copy_dist_histograms
) {
51 size_t pos
= start_pos
;
52 BlockSplitIterator literal_it
;
53 BlockSplitIterator insert_and_copy_it
;
54 BlockSplitIterator dist_it
;
57 InitBlockSplitIterator(&literal_it
, literal_split
);
58 InitBlockSplitIterator(&insert_and_copy_it
, insert_and_copy_split
);
59 InitBlockSplitIterator(&dist_it
, dist_split
);
60 for (i
= 0; i
< num_commands
; ++i
) {
61 const Command
* cmd
= &cmds
[i
];
63 BlockSplitIteratorNext(&insert_and_copy_it
);
64 HistogramAddCommand(&insert_and_copy_histograms
[insert_and_copy_it
.type_
],
66 for (j
= cmd
->insert_len_
; j
!= 0; --j
) {
68 BlockSplitIteratorNext(&literal_it
);
69 context
= (literal_it
.type_
<< BROTLI_LITERAL_CONTEXT_BITS
) +
70 Context(prev_byte
, prev_byte2
, context_modes
[literal_it
.type_
]);
71 HistogramAddLiteral(&literal_histograms
[context
],
72 ringbuffer
[pos
& mask
]);
73 prev_byte2
= prev_byte
;
74 prev_byte
= ringbuffer
[pos
& mask
];
77 pos
+= CommandCopyLen(cmd
);
78 if (CommandCopyLen(cmd
)) {
79 prev_byte2
= ringbuffer
[(pos
- 2) & mask
];
80 prev_byte
= ringbuffer
[(pos
- 1) & mask
];
81 if (cmd
->cmd_prefix_
>= 128) {
83 BlockSplitIteratorNext(&dist_it
);
84 context
= (dist_it
.type_
<< BROTLI_DISTANCE_CONTEXT_BITS
) +
85 CommandDistanceContext(cmd
);
86 HistogramAddDistance(©_dist_histograms
[context
],
93 #if defined(__cplusplus) || defined(c_plusplus)