xref: /aosp_15_r20/external/cronet/third_party/brotli/enc/encode.c (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker /* Copyright 2013 Google Inc. All Rights Reserved.
2*6777b538SAndroid Build Coastguard Worker 
3*6777b538SAndroid Build Coastguard Worker    Distributed under MIT license.
4*6777b538SAndroid Build Coastguard Worker    See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
5*6777b538SAndroid Build Coastguard Worker */
6*6777b538SAndroid Build Coastguard Worker 
7*6777b538SAndroid Build Coastguard Worker /* Implementation of Brotli compressor. */
8*6777b538SAndroid Build Coastguard Worker 
9*6777b538SAndroid Build Coastguard Worker #include <brotli/encode.h>
10*6777b538SAndroid Build Coastguard Worker 
11*6777b538SAndroid Build Coastguard Worker #include <stdlib.h>  /* free, malloc */
12*6777b538SAndroid Build Coastguard Worker #include <string.h>  /* memcpy, memset */
13*6777b538SAndroid Build Coastguard Worker 
14*6777b538SAndroid Build Coastguard Worker #include "../common/constants.h"
15*6777b538SAndroid Build Coastguard Worker #include "../common/context.h"
16*6777b538SAndroid Build Coastguard Worker #include "../common/platform.h"
17*6777b538SAndroid Build Coastguard Worker #include "../common/version.h"
18*6777b538SAndroid Build Coastguard Worker #include "backward_references.h"
19*6777b538SAndroid Build Coastguard Worker #include "backward_references_hq.h"
20*6777b538SAndroid Build Coastguard Worker #include "bit_cost.h"
21*6777b538SAndroid Build Coastguard Worker #include "brotli_bit_stream.h"
22*6777b538SAndroid Build Coastguard Worker #include "compress_fragment.h"
23*6777b538SAndroid Build Coastguard Worker #include "compress_fragment_two_pass.h"
24*6777b538SAndroid Build Coastguard Worker #include "dictionary_hash.h"
25*6777b538SAndroid Build Coastguard Worker #include "encoder_dict.h"
26*6777b538SAndroid Build Coastguard Worker #include "entropy_encode.h"
27*6777b538SAndroid Build Coastguard Worker #include "fast_log.h"
28*6777b538SAndroid Build Coastguard Worker #include "hash.h"
29*6777b538SAndroid Build Coastguard Worker #include "histogram.h"
30*6777b538SAndroid Build Coastguard Worker #include "memory.h"
31*6777b538SAndroid Build Coastguard Worker #include "metablock.h"
32*6777b538SAndroid Build Coastguard Worker #include "prefix.h"
33*6777b538SAndroid Build Coastguard Worker #include "quality.h"
34*6777b538SAndroid Build Coastguard Worker #include "ringbuffer.h"
35*6777b538SAndroid Build Coastguard Worker #include "utf8_util.h"
36*6777b538SAndroid Build Coastguard Worker #include "write_bits.h"
37*6777b538SAndroid Build Coastguard Worker 
38*6777b538SAndroid Build Coastguard Worker #if defined(__cplusplus) || defined(c_plusplus)
39*6777b538SAndroid Build Coastguard Worker extern "C" {
40*6777b538SAndroid Build Coastguard Worker #endif
41*6777b538SAndroid Build Coastguard Worker 
42*6777b538SAndroid Build Coastguard Worker #define COPY_ARRAY(dst, src) memcpy(dst, src, sizeof(src));
43*6777b538SAndroid Build Coastguard Worker 
44*6777b538SAndroid Build Coastguard Worker typedef enum BrotliEncoderStreamState {
45*6777b538SAndroid Build Coastguard Worker   /* Default state. */
46*6777b538SAndroid Build Coastguard Worker   BROTLI_STREAM_PROCESSING = 0,
47*6777b538SAndroid Build Coastguard Worker   /* Intermediate state; after next block is emitted, byte-padding should be
48*6777b538SAndroid Build Coastguard Worker      performed before getting back to default state. */
49*6777b538SAndroid Build Coastguard Worker   BROTLI_STREAM_FLUSH_REQUESTED = 1,
50*6777b538SAndroid Build Coastguard Worker   /* Last metablock was produced; no more input is acceptable. */
51*6777b538SAndroid Build Coastguard Worker   BROTLI_STREAM_FINISHED = 2,
52*6777b538SAndroid Build Coastguard Worker   /* Flushing compressed block and writing meta-data block header. */
53*6777b538SAndroid Build Coastguard Worker   BROTLI_STREAM_METADATA_HEAD = 3,
54*6777b538SAndroid Build Coastguard Worker   /* Writing metadata block body. */
55*6777b538SAndroid Build Coastguard Worker   BROTLI_STREAM_METADATA_BODY = 4
56*6777b538SAndroid Build Coastguard Worker } BrotliEncoderStreamState;
57*6777b538SAndroid Build Coastguard Worker 
58*6777b538SAndroid Build Coastguard Worker typedef enum BrotliEncoderFlintState {
59*6777b538SAndroid Build Coastguard Worker   BROTLI_FLINT_NEEDS_2_BYTES = 2,
60*6777b538SAndroid Build Coastguard Worker   BROTLI_FLINT_NEEDS_1_BYTE = 1,
61*6777b538SAndroid Build Coastguard Worker   BROTLI_FLINT_WAITING_FOR_PROCESSING = 0,
62*6777b538SAndroid Build Coastguard Worker   BROTLI_FLINT_WAITING_FOR_FLUSHING = -1,
63*6777b538SAndroid Build Coastguard Worker   BROTLI_FLINT_DONE = -2
64*6777b538SAndroid Build Coastguard Worker } BrotliEncoderFlintState;
65*6777b538SAndroid Build Coastguard Worker 
66*6777b538SAndroid Build Coastguard Worker typedef struct BrotliEncoderStateStruct {
67*6777b538SAndroid Build Coastguard Worker   BrotliEncoderParams params;
68*6777b538SAndroid Build Coastguard Worker 
69*6777b538SAndroid Build Coastguard Worker   MemoryManager memory_manager_;
70*6777b538SAndroid Build Coastguard Worker 
71*6777b538SAndroid Build Coastguard Worker   uint64_t input_pos_;
72*6777b538SAndroid Build Coastguard Worker   RingBuffer ringbuffer_;
73*6777b538SAndroid Build Coastguard Worker   size_t cmd_alloc_size_;
74*6777b538SAndroid Build Coastguard Worker   Command* commands_;
75*6777b538SAndroid Build Coastguard Worker   size_t num_commands_;
76*6777b538SAndroid Build Coastguard Worker   size_t num_literals_;
77*6777b538SAndroid Build Coastguard Worker   size_t last_insert_len_;
78*6777b538SAndroid Build Coastguard Worker   uint64_t last_flush_pos_;
79*6777b538SAndroid Build Coastguard Worker   uint64_t last_processed_pos_;
80*6777b538SAndroid Build Coastguard Worker   int dist_cache_[BROTLI_NUM_DISTANCE_SHORT_CODES];
81*6777b538SAndroid Build Coastguard Worker   int saved_dist_cache_[4];
82*6777b538SAndroid Build Coastguard Worker   uint16_t last_bytes_;
83*6777b538SAndroid Build Coastguard Worker   uint8_t last_bytes_bits_;
84*6777b538SAndroid Build Coastguard Worker   /* "Flint" is a tiny uncompressed block emitted before the continuation
85*6777b538SAndroid Build Coastguard Worker      block to unwire literal context from previous data. Despite being int8_t,
86*6777b538SAndroid Build Coastguard Worker      field is actually BrotliEncoderFlintState enum. */
87*6777b538SAndroid Build Coastguard Worker   int8_t flint_;
88*6777b538SAndroid Build Coastguard Worker   uint8_t prev_byte_;
89*6777b538SAndroid Build Coastguard Worker   uint8_t prev_byte2_;
90*6777b538SAndroid Build Coastguard Worker   size_t storage_size_;
91*6777b538SAndroid Build Coastguard Worker   uint8_t* storage_;
92*6777b538SAndroid Build Coastguard Worker 
93*6777b538SAndroid Build Coastguard Worker   Hasher hasher_;
94*6777b538SAndroid Build Coastguard Worker 
95*6777b538SAndroid Build Coastguard Worker   /* Hash table for FAST_ONE_PASS_COMPRESSION_QUALITY mode. */
96*6777b538SAndroid Build Coastguard Worker   int small_table_[1 << 10];  /* 4KiB */
97*6777b538SAndroid Build Coastguard Worker   int* large_table_;          /* Allocated only when needed */
98*6777b538SAndroid Build Coastguard Worker   size_t large_table_size_;
99*6777b538SAndroid Build Coastguard Worker 
100*6777b538SAndroid Build Coastguard Worker   BrotliOnePassArena* one_pass_arena_;
101*6777b538SAndroid Build Coastguard Worker   BrotliTwoPassArena* two_pass_arena_;
102*6777b538SAndroid Build Coastguard Worker 
103*6777b538SAndroid Build Coastguard Worker   /* Command and literal buffers for FAST_TWO_PASS_COMPRESSION_QUALITY. */
104*6777b538SAndroid Build Coastguard Worker   uint32_t* command_buf_;
105*6777b538SAndroid Build Coastguard Worker   uint8_t* literal_buf_;
106*6777b538SAndroid Build Coastguard Worker 
107*6777b538SAndroid Build Coastguard Worker   uint8_t* next_out_;
108*6777b538SAndroid Build Coastguard Worker   size_t available_out_;
109*6777b538SAndroid Build Coastguard Worker   size_t total_out_;
110*6777b538SAndroid Build Coastguard Worker   /* Temporary buffer for padding flush bits or metadata block header / body. */
111*6777b538SAndroid Build Coastguard Worker   union {
112*6777b538SAndroid Build Coastguard Worker     uint64_t u64[2];
113*6777b538SAndroid Build Coastguard Worker     uint8_t u8[16];
114*6777b538SAndroid Build Coastguard Worker   } tiny_buf_;
115*6777b538SAndroid Build Coastguard Worker   uint32_t remaining_metadata_bytes_;
116*6777b538SAndroid Build Coastguard Worker   BrotliEncoderStreamState stream_state_;
117*6777b538SAndroid Build Coastguard Worker 
118*6777b538SAndroid Build Coastguard Worker   BROTLI_BOOL is_last_block_emitted_;
119*6777b538SAndroid Build Coastguard Worker   BROTLI_BOOL is_initialized_;
120*6777b538SAndroid Build Coastguard Worker } BrotliEncoderStateStruct;
121*6777b538SAndroid Build Coastguard Worker 
InputBlockSize(BrotliEncoderState * s)122*6777b538SAndroid Build Coastguard Worker static size_t InputBlockSize(BrotliEncoderState* s) {
123*6777b538SAndroid Build Coastguard Worker   return (size_t)1 << s->params.lgblock;
124*6777b538SAndroid Build Coastguard Worker }
125*6777b538SAndroid Build Coastguard Worker 
UnprocessedInputSize(BrotliEncoderState * s)126*6777b538SAndroid Build Coastguard Worker static uint64_t UnprocessedInputSize(BrotliEncoderState* s) {
127*6777b538SAndroid Build Coastguard Worker   return s->input_pos_ - s->last_processed_pos_;
128*6777b538SAndroid Build Coastguard Worker }
129*6777b538SAndroid Build Coastguard Worker 
RemainingInputBlockSize(BrotliEncoderState * s)130*6777b538SAndroid Build Coastguard Worker static size_t RemainingInputBlockSize(BrotliEncoderState* s) {
131*6777b538SAndroid Build Coastguard Worker   const uint64_t delta = UnprocessedInputSize(s);
132*6777b538SAndroid Build Coastguard Worker   size_t block_size = InputBlockSize(s);
133*6777b538SAndroid Build Coastguard Worker   if (delta >= block_size) return 0;
134*6777b538SAndroid Build Coastguard Worker   return block_size - (size_t)delta;
135*6777b538SAndroid Build Coastguard Worker }
136*6777b538SAndroid Build Coastguard Worker 
BrotliEncoderSetParameter(BrotliEncoderState * state,BrotliEncoderParameter p,uint32_t value)137*6777b538SAndroid Build Coastguard Worker BROTLI_BOOL BrotliEncoderSetParameter(
138*6777b538SAndroid Build Coastguard Worker     BrotliEncoderState* state, BrotliEncoderParameter p, uint32_t value) {
139*6777b538SAndroid Build Coastguard Worker   /* Changing parameters on the fly is not implemented yet. */
140*6777b538SAndroid Build Coastguard Worker   if (state->is_initialized_) return BROTLI_FALSE;
141*6777b538SAndroid Build Coastguard Worker   /* TODO(eustas): Validate/clamp parameters here. */
142*6777b538SAndroid Build Coastguard Worker   switch (p) {
143*6777b538SAndroid Build Coastguard Worker     case BROTLI_PARAM_MODE:
144*6777b538SAndroid Build Coastguard Worker       state->params.mode = (BrotliEncoderMode)value;
145*6777b538SAndroid Build Coastguard Worker       return BROTLI_TRUE;
146*6777b538SAndroid Build Coastguard Worker 
147*6777b538SAndroid Build Coastguard Worker     case BROTLI_PARAM_QUALITY:
148*6777b538SAndroid Build Coastguard Worker       state->params.quality = (int)value;
149*6777b538SAndroid Build Coastguard Worker       return BROTLI_TRUE;
150*6777b538SAndroid Build Coastguard Worker 
151*6777b538SAndroid Build Coastguard Worker     case BROTLI_PARAM_LGWIN:
152*6777b538SAndroid Build Coastguard Worker       state->params.lgwin = (int)value;
153*6777b538SAndroid Build Coastguard Worker       return BROTLI_TRUE;
154*6777b538SAndroid Build Coastguard Worker 
155*6777b538SAndroid Build Coastguard Worker     case BROTLI_PARAM_LGBLOCK:
156*6777b538SAndroid Build Coastguard Worker       state->params.lgblock = (int)value;
157*6777b538SAndroid Build Coastguard Worker       return BROTLI_TRUE;
158*6777b538SAndroid Build Coastguard Worker 
159*6777b538SAndroid Build Coastguard Worker     case BROTLI_PARAM_DISABLE_LITERAL_CONTEXT_MODELING:
160*6777b538SAndroid Build Coastguard Worker       if ((value != 0) && (value != 1)) return BROTLI_FALSE;
161*6777b538SAndroid Build Coastguard Worker       state->params.disable_literal_context_modeling = TO_BROTLI_BOOL(!!value);
162*6777b538SAndroid Build Coastguard Worker       return BROTLI_TRUE;
163*6777b538SAndroid Build Coastguard Worker 
164*6777b538SAndroid Build Coastguard Worker     case BROTLI_PARAM_SIZE_HINT:
165*6777b538SAndroid Build Coastguard Worker       state->params.size_hint = value;
166*6777b538SAndroid Build Coastguard Worker       return BROTLI_TRUE;
167*6777b538SAndroid Build Coastguard Worker 
168*6777b538SAndroid Build Coastguard Worker     case BROTLI_PARAM_LARGE_WINDOW:
169*6777b538SAndroid Build Coastguard Worker       state->params.large_window = TO_BROTLI_BOOL(!!value);
170*6777b538SAndroid Build Coastguard Worker       return BROTLI_TRUE;
171*6777b538SAndroid Build Coastguard Worker 
172*6777b538SAndroid Build Coastguard Worker     case BROTLI_PARAM_NPOSTFIX:
173*6777b538SAndroid Build Coastguard Worker       state->params.dist.distance_postfix_bits = value;
174*6777b538SAndroid Build Coastguard Worker       return BROTLI_TRUE;
175*6777b538SAndroid Build Coastguard Worker 
176*6777b538SAndroid Build Coastguard Worker     case BROTLI_PARAM_NDIRECT:
177*6777b538SAndroid Build Coastguard Worker       state->params.dist.num_direct_distance_codes = value;
178*6777b538SAndroid Build Coastguard Worker       return BROTLI_TRUE;
179*6777b538SAndroid Build Coastguard Worker 
180*6777b538SAndroid Build Coastguard Worker     case BROTLI_PARAM_STREAM_OFFSET:
181*6777b538SAndroid Build Coastguard Worker       if (value > (1u << 30)) return BROTLI_FALSE;
182*6777b538SAndroid Build Coastguard Worker       state->params.stream_offset = value;
183*6777b538SAndroid Build Coastguard Worker       return BROTLI_TRUE;
184*6777b538SAndroid Build Coastguard Worker 
185*6777b538SAndroid Build Coastguard Worker     default: return BROTLI_FALSE;
186*6777b538SAndroid Build Coastguard Worker   }
187*6777b538SAndroid Build Coastguard Worker }
188*6777b538SAndroid Build Coastguard Worker 
189*6777b538SAndroid Build Coastguard Worker /* Wraps 64-bit input position to 32-bit ring-buffer position preserving
190*6777b538SAndroid Build Coastguard Worker    "not-a-first-lap" feature. */
WrapPosition(uint64_t position)191*6777b538SAndroid Build Coastguard Worker static uint32_t WrapPosition(uint64_t position) {
192*6777b538SAndroid Build Coastguard Worker   uint32_t result = (uint32_t)position;
193*6777b538SAndroid Build Coastguard Worker   uint64_t gb = position >> 30;
194*6777b538SAndroid Build Coastguard Worker   if (gb > 2) {
195*6777b538SAndroid Build Coastguard Worker     /* Wrap every 2GiB; The first 3GB are continuous. */
196*6777b538SAndroid Build Coastguard Worker     result = (result & ((1u << 30) - 1)) | ((uint32_t)((gb - 1) & 1) + 1) << 30;
197*6777b538SAndroid Build Coastguard Worker   }
198*6777b538SAndroid Build Coastguard Worker   return result;
199*6777b538SAndroid Build Coastguard Worker }
200*6777b538SAndroid Build Coastguard Worker 
GetBrotliStorage(BrotliEncoderState * s,size_t size)201*6777b538SAndroid Build Coastguard Worker static uint8_t* GetBrotliStorage(BrotliEncoderState* s, size_t size) {
202*6777b538SAndroid Build Coastguard Worker   MemoryManager* m = &s->memory_manager_;
203*6777b538SAndroid Build Coastguard Worker   if (s->storage_size_ < size) {
204*6777b538SAndroid Build Coastguard Worker     BROTLI_FREE(m, s->storage_);
205*6777b538SAndroid Build Coastguard Worker     s->storage_ = BROTLI_ALLOC(m, uint8_t, size);
206*6777b538SAndroid Build Coastguard Worker     if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(s->storage_)) return NULL;
207*6777b538SAndroid Build Coastguard Worker     s->storage_size_ = size;
208*6777b538SAndroid Build Coastguard Worker   }
209*6777b538SAndroid Build Coastguard Worker   return s->storage_;
210*6777b538SAndroid Build Coastguard Worker }
211*6777b538SAndroid Build Coastguard Worker 
HashTableSize(size_t max_table_size,size_t input_size)212*6777b538SAndroid Build Coastguard Worker static size_t HashTableSize(size_t max_table_size, size_t input_size) {
213*6777b538SAndroid Build Coastguard Worker   size_t htsize = 256;
214*6777b538SAndroid Build Coastguard Worker   while (htsize < max_table_size && htsize < input_size) {
215*6777b538SAndroid Build Coastguard Worker     htsize <<= 1;
216*6777b538SAndroid Build Coastguard Worker   }
217*6777b538SAndroid Build Coastguard Worker   return htsize;
218*6777b538SAndroid Build Coastguard Worker }
219*6777b538SAndroid Build Coastguard Worker 
GetHashTable(BrotliEncoderState * s,int quality,size_t input_size,size_t * table_size)220*6777b538SAndroid Build Coastguard Worker static int* GetHashTable(BrotliEncoderState* s, int quality,
221*6777b538SAndroid Build Coastguard Worker                          size_t input_size, size_t* table_size) {
222*6777b538SAndroid Build Coastguard Worker   /* Use smaller hash table when input.size() is smaller, since we
223*6777b538SAndroid Build Coastguard Worker      fill the table, incurring O(hash table size) overhead for
224*6777b538SAndroid Build Coastguard Worker      compression, and if the input is short, we won't need that
225*6777b538SAndroid Build Coastguard Worker      many hash table entries anyway. */
226*6777b538SAndroid Build Coastguard Worker   MemoryManager* m = &s->memory_manager_;
227*6777b538SAndroid Build Coastguard Worker   const size_t max_table_size = MaxHashTableSize(quality);
228*6777b538SAndroid Build Coastguard Worker   size_t htsize = HashTableSize(max_table_size, input_size);
229*6777b538SAndroid Build Coastguard Worker   int* table;
230*6777b538SAndroid Build Coastguard Worker   BROTLI_DCHECK(max_table_size >= 256);
231*6777b538SAndroid Build Coastguard Worker   if (quality == FAST_ONE_PASS_COMPRESSION_QUALITY) {
232*6777b538SAndroid Build Coastguard Worker     /* Only odd shifts are supported by fast-one-pass. */
233*6777b538SAndroid Build Coastguard Worker     if ((htsize & 0xAAAAA) == 0) {
234*6777b538SAndroid Build Coastguard Worker       htsize <<= 1;
235*6777b538SAndroid Build Coastguard Worker     }
236*6777b538SAndroid Build Coastguard Worker   }
237*6777b538SAndroid Build Coastguard Worker 
238*6777b538SAndroid Build Coastguard Worker   if (htsize <= sizeof(s->small_table_) / sizeof(s->small_table_[0])) {
239*6777b538SAndroid Build Coastguard Worker     table = s->small_table_;
240*6777b538SAndroid Build Coastguard Worker   } else {
241*6777b538SAndroid Build Coastguard Worker     if (htsize > s->large_table_size_) {
242*6777b538SAndroid Build Coastguard Worker       s->large_table_size_ = htsize;
243*6777b538SAndroid Build Coastguard Worker       BROTLI_FREE(m, s->large_table_);
244*6777b538SAndroid Build Coastguard Worker       s->large_table_ = BROTLI_ALLOC(m, int, htsize);
245*6777b538SAndroid Build Coastguard Worker       if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(s->large_table_)) return 0;
246*6777b538SAndroid Build Coastguard Worker     }
247*6777b538SAndroid Build Coastguard Worker     table = s->large_table_;
248*6777b538SAndroid Build Coastguard Worker   }
249*6777b538SAndroid Build Coastguard Worker 
250*6777b538SAndroid Build Coastguard Worker   *table_size = htsize;
251*6777b538SAndroid Build Coastguard Worker   memset(table, 0, htsize * sizeof(*table));
252*6777b538SAndroid Build Coastguard Worker   return table;
253*6777b538SAndroid Build Coastguard Worker }
254*6777b538SAndroid Build Coastguard Worker 
EncodeWindowBits(int lgwin,BROTLI_BOOL large_window,uint16_t * last_bytes,uint8_t * last_bytes_bits)255*6777b538SAndroid Build Coastguard Worker static void EncodeWindowBits(int lgwin, BROTLI_BOOL large_window,
256*6777b538SAndroid Build Coastguard Worker     uint16_t* last_bytes, uint8_t* last_bytes_bits) {
257*6777b538SAndroid Build Coastguard Worker   if (large_window) {
258*6777b538SAndroid Build Coastguard Worker     *last_bytes = (uint16_t)(((lgwin & 0x3F) << 8) | 0x11);
259*6777b538SAndroid Build Coastguard Worker     *last_bytes_bits = 14;
260*6777b538SAndroid Build Coastguard Worker   } else {
261*6777b538SAndroid Build Coastguard Worker     if (lgwin == 16) {
262*6777b538SAndroid Build Coastguard Worker       *last_bytes = 0;
263*6777b538SAndroid Build Coastguard Worker       *last_bytes_bits = 1;
264*6777b538SAndroid Build Coastguard Worker     } else if (lgwin == 17) {
265*6777b538SAndroid Build Coastguard Worker       *last_bytes = 1;
266*6777b538SAndroid Build Coastguard Worker       *last_bytes_bits = 7;
267*6777b538SAndroid Build Coastguard Worker     } else if (lgwin > 17) {
268*6777b538SAndroid Build Coastguard Worker       *last_bytes = (uint16_t)(((lgwin - 17) << 1) | 0x01);
269*6777b538SAndroid Build Coastguard Worker       *last_bytes_bits = 4;
270*6777b538SAndroid Build Coastguard Worker     } else {
271*6777b538SAndroid Build Coastguard Worker       *last_bytes = (uint16_t)(((lgwin - 8) << 4) | 0x01);
272*6777b538SAndroid Build Coastguard Worker       *last_bytes_bits = 7;
273*6777b538SAndroid Build Coastguard Worker     }
274*6777b538SAndroid Build Coastguard Worker   }
275*6777b538SAndroid Build Coastguard Worker }
276*6777b538SAndroid Build Coastguard Worker 
277*6777b538SAndroid Build Coastguard Worker /* TODO(eustas): move to compress_fragment.c? */
278*6777b538SAndroid Build Coastguard Worker /* Initializes the command and distance prefix codes for the first block. */
InitCommandPrefixCodes(BrotliOnePassArena * s)279*6777b538SAndroid Build Coastguard Worker static void InitCommandPrefixCodes(BrotliOnePassArena* s) {
280*6777b538SAndroid Build Coastguard Worker   static const uint8_t kDefaultCommandDepths[128] = {
281*6777b538SAndroid Build Coastguard Worker     0, 4, 4, 5, 6, 6, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8,
282*6777b538SAndroid Build Coastguard Worker     0, 0, 0, 4, 4, 4, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7,
283*6777b538SAndroid Build Coastguard Worker     7, 7, 10, 10, 10, 10, 10, 10, 0, 4, 4, 5, 5, 5, 6, 6,
284*6777b538SAndroid Build Coastguard Worker     7, 8, 8, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
285*6777b538SAndroid Build Coastguard Worker     5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
286*6777b538SAndroid Build Coastguard Worker     6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4,
287*6777b538SAndroid Build Coastguard Worker     4, 4, 4, 5, 5, 5, 5, 5, 5, 6, 6, 7, 7, 7, 8, 10,
288*6777b538SAndroid Build Coastguard Worker     12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
289*6777b538SAndroid Build Coastguard Worker   };
290*6777b538SAndroid Build Coastguard Worker   static const uint16_t kDefaultCommandBits[128] = {
291*6777b538SAndroid Build Coastguard Worker     0,   0,   8,   9,   3,  35,   7,   71,
292*6777b538SAndroid Build Coastguard Worker     39, 103,  23,  47, 175, 111, 239,   31,
293*6777b538SAndroid Build Coastguard Worker     0,   0,   0,   4,  12,   2,  10,    6,
294*6777b538SAndroid Build Coastguard Worker     13,  29,  11,  43,  27,  59,  87,   55,
295*6777b538SAndroid Build Coastguard Worker     15,  79, 319, 831, 191, 703, 447,  959,
296*6777b538SAndroid Build Coastguard Worker     0,  14,   1,  25,   5,  21,  19,   51,
297*6777b538SAndroid Build Coastguard Worker     119, 159,  95, 223, 479, 991,  63,  575,
298*6777b538SAndroid Build Coastguard Worker     127, 639, 383, 895, 255, 767, 511, 1023,
299*6777b538SAndroid Build Coastguard Worker     14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
300*6777b538SAndroid Build Coastguard Worker     27, 59, 7, 39, 23, 55, 30, 1, 17, 9, 25, 5, 0, 8, 4, 12,
301*6777b538SAndroid Build Coastguard Worker     2, 10, 6, 21, 13, 29, 3, 19, 11, 15, 47, 31, 95, 63, 127, 255,
302*6777b538SAndroid Build Coastguard Worker     767, 2815, 1791, 3839, 511, 2559, 1535, 3583, 1023, 3071, 2047, 4095,
303*6777b538SAndroid Build Coastguard Worker   };
304*6777b538SAndroid Build Coastguard Worker   static const uint8_t kDefaultCommandCode[] = {
305*6777b538SAndroid Build Coastguard Worker     0xff, 0x77, 0xd5, 0xbf, 0xe7, 0xde, 0xea, 0x9e, 0x51, 0x5d, 0xde, 0xc6,
306*6777b538SAndroid Build Coastguard Worker     0x70, 0x57, 0xbc, 0x58, 0x58, 0x58, 0xd8, 0xd8, 0x58, 0xd5, 0xcb, 0x8c,
307*6777b538SAndroid Build Coastguard Worker     0xea, 0xe0, 0xc3, 0x87, 0x1f, 0x83, 0xc1, 0x60, 0x1c, 0x67, 0xb2, 0xaa,
308*6777b538SAndroid Build Coastguard Worker     0x06, 0x83, 0xc1, 0x60, 0x30, 0x18, 0xcc, 0xa1, 0xce, 0x88, 0x54, 0x94,
309*6777b538SAndroid Build Coastguard Worker     0x46, 0xe1, 0xb0, 0xd0, 0x4e, 0xb2, 0xf7, 0x04, 0x00,
310*6777b538SAndroid Build Coastguard Worker   };
311*6777b538SAndroid Build Coastguard Worker   static const size_t kDefaultCommandCodeNumBits = 448;
312*6777b538SAndroid Build Coastguard Worker   COPY_ARRAY(s->cmd_depth, kDefaultCommandDepths);
313*6777b538SAndroid Build Coastguard Worker   COPY_ARRAY(s->cmd_bits, kDefaultCommandBits);
314*6777b538SAndroid Build Coastguard Worker 
315*6777b538SAndroid Build Coastguard Worker   /* Initialize the pre-compressed form of the command and distance prefix
316*6777b538SAndroid Build Coastguard Worker      codes. */
317*6777b538SAndroid Build Coastguard Worker   COPY_ARRAY(s->cmd_code, kDefaultCommandCode);
318*6777b538SAndroid Build Coastguard Worker   s->cmd_code_numbits = kDefaultCommandCodeNumBits;
319*6777b538SAndroid Build Coastguard Worker }
320*6777b538SAndroid Build Coastguard Worker 
321*6777b538SAndroid Build Coastguard Worker /* Decide about the context map based on the ability of the prediction
322*6777b538SAndroid Build Coastguard Worker    ability of the previous byte UTF8-prefix on the next byte. The
323*6777b538SAndroid Build Coastguard Worker    prediction ability is calculated as Shannon entropy. Here we need
324*6777b538SAndroid Build Coastguard Worker    Shannon entropy instead of 'BitsEntropy' since the prefix will be
325*6777b538SAndroid Build Coastguard Worker    encoded with the remaining 6 bits of the following byte, and
326*6777b538SAndroid Build Coastguard Worker    BitsEntropy will assume that symbol to be stored alone using Huffman
327*6777b538SAndroid Build Coastguard Worker    coding. */
ChooseContextMap(int quality,uint32_t * bigram_histo,size_t * num_literal_contexts,const uint32_t ** literal_context_map)328*6777b538SAndroid Build Coastguard Worker static void ChooseContextMap(int quality,
329*6777b538SAndroid Build Coastguard Worker                              uint32_t* bigram_histo,
330*6777b538SAndroid Build Coastguard Worker                              size_t* num_literal_contexts,
331*6777b538SAndroid Build Coastguard Worker                              const uint32_t** literal_context_map) {
332*6777b538SAndroid Build Coastguard Worker   static const uint32_t kStaticContextMapContinuation[64] = {
333*6777b538SAndroid Build Coastguard Worker     1, 1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
334*6777b538SAndroid Build Coastguard Worker     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
335*6777b538SAndroid Build Coastguard Worker     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
336*6777b538SAndroid Build Coastguard Worker     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
337*6777b538SAndroid Build Coastguard Worker   };
338*6777b538SAndroid Build Coastguard Worker   static const uint32_t kStaticContextMapSimpleUTF8[64] = {
339*6777b538SAndroid Build Coastguard Worker     0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
340*6777b538SAndroid Build Coastguard Worker     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
341*6777b538SAndroid Build Coastguard Worker     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
342*6777b538SAndroid Build Coastguard Worker     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
343*6777b538SAndroid Build Coastguard Worker   };
344*6777b538SAndroid Build Coastguard Worker 
345*6777b538SAndroid Build Coastguard Worker   uint32_t monogram_histo[3] = { 0 };
346*6777b538SAndroid Build Coastguard Worker   uint32_t two_prefix_histo[6] = { 0 };
347*6777b538SAndroid Build Coastguard Worker   size_t total;
348*6777b538SAndroid Build Coastguard Worker   size_t i;
349*6777b538SAndroid Build Coastguard Worker   size_t dummy;
350*6777b538SAndroid Build Coastguard Worker   double entropy[4];
351*6777b538SAndroid Build Coastguard Worker   for (i = 0; i < 9; ++i) {
352*6777b538SAndroid Build Coastguard Worker     monogram_histo[i % 3] += bigram_histo[i];
353*6777b538SAndroid Build Coastguard Worker     two_prefix_histo[i % 6] += bigram_histo[i];
354*6777b538SAndroid Build Coastguard Worker   }
355*6777b538SAndroid Build Coastguard Worker   entropy[1] = ShannonEntropy(monogram_histo, 3, &dummy);
356*6777b538SAndroid Build Coastguard Worker   entropy[2] = (ShannonEntropy(two_prefix_histo, 3, &dummy) +
357*6777b538SAndroid Build Coastguard Worker                 ShannonEntropy(two_prefix_histo + 3, 3, &dummy));
358*6777b538SAndroid Build Coastguard Worker   entropy[3] = 0;
359*6777b538SAndroid Build Coastguard Worker   for (i = 0; i < 3; ++i) {
360*6777b538SAndroid Build Coastguard Worker     entropy[3] += ShannonEntropy(bigram_histo + 3 * i, 3, &dummy);
361*6777b538SAndroid Build Coastguard Worker   }
362*6777b538SAndroid Build Coastguard Worker 
363*6777b538SAndroid Build Coastguard Worker   total = monogram_histo[0] + monogram_histo[1] + monogram_histo[2];
364*6777b538SAndroid Build Coastguard Worker   BROTLI_DCHECK(total != 0);
365*6777b538SAndroid Build Coastguard Worker   entropy[0] = 1.0 / (double)total;
366*6777b538SAndroid Build Coastguard Worker   entropy[1] *= entropy[0];
367*6777b538SAndroid Build Coastguard Worker   entropy[2] *= entropy[0];
368*6777b538SAndroid Build Coastguard Worker   entropy[3] *= entropy[0];
369*6777b538SAndroid Build Coastguard Worker 
370*6777b538SAndroid Build Coastguard Worker   if (quality < MIN_QUALITY_FOR_HQ_CONTEXT_MODELING) {
371*6777b538SAndroid Build Coastguard Worker     /* 3 context models is a bit slower, don't use it at lower qualities. */
372*6777b538SAndroid Build Coastguard Worker     entropy[3] = entropy[1] * 10;
373*6777b538SAndroid Build Coastguard Worker   }
374*6777b538SAndroid Build Coastguard Worker   /* If expected savings by symbol are less than 0.2 bits, skip the
375*6777b538SAndroid Build Coastguard Worker      context modeling -- in exchange for faster decoding speed. */
376*6777b538SAndroid Build Coastguard Worker   if (entropy[1] - entropy[2] < 0.2 &&
377*6777b538SAndroid Build Coastguard Worker       entropy[1] - entropy[3] < 0.2) {
378*6777b538SAndroid Build Coastguard Worker     *num_literal_contexts = 1;
379*6777b538SAndroid Build Coastguard Worker   } else if (entropy[2] - entropy[3] < 0.02) {
380*6777b538SAndroid Build Coastguard Worker     *num_literal_contexts = 2;
381*6777b538SAndroid Build Coastguard Worker     *literal_context_map = kStaticContextMapSimpleUTF8;
382*6777b538SAndroid Build Coastguard Worker   } else {
383*6777b538SAndroid Build Coastguard Worker     *num_literal_contexts = 3;
384*6777b538SAndroid Build Coastguard Worker     *literal_context_map = kStaticContextMapContinuation;
385*6777b538SAndroid Build Coastguard Worker   }
386*6777b538SAndroid Build Coastguard Worker }
387*6777b538SAndroid Build Coastguard Worker 
388*6777b538SAndroid Build Coastguard Worker /* Decide if we want to use a more complex static context map containing 13
389*6777b538SAndroid Build Coastguard Worker    context values, based on the entropy reduction of histograms over the
390*6777b538SAndroid Build Coastguard Worker    first 5 bits of literals. */
ShouldUseComplexStaticContextMap(const uint8_t * input,size_t start_pos,size_t length,size_t mask,int quality,size_t size_hint,size_t * num_literal_contexts,const uint32_t ** literal_context_map,uint32_t * arena)391*6777b538SAndroid Build Coastguard Worker static BROTLI_BOOL ShouldUseComplexStaticContextMap(const uint8_t* input,
392*6777b538SAndroid Build Coastguard Worker     size_t start_pos, size_t length, size_t mask, int quality, size_t size_hint,
393*6777b538SAndroid Build Coastguard Worker     size_t* num_literal_contexts, const uint32_t** literal_context_map,
394*6777b538SAndroid Build Coastguard Worker     uint32_t* arena) {
395*6777b538SAndroid Build Coastguard Worker   static const uint32_t kStaticContextMapComplexUTF8[64] = {
396*6777b538SAndroid Build Coastguard Worker     11, 11, 12, 12, /* 0 special */
397*6777b538SAndroid Build Coastguard Worker     0, 0, 0, 0, /* 4 lf */
398*6777b538SAndroid Build Coastguard Worker     1, 1, 9, 9, /* 8 space */
399*6777b538SAndroid Build Coastguard Worker     2, 2, 2, 2, /* !, first after space/lf and after something else. */
400*6777b538SAndroid Build Coastguard Worker     1, 1, 1, 1, /* " */
401*6777b538SAndroid Build Coastguard Worker     8, 3, 3, 3, /* % */
402*6777b538SAndroid Build Coastguard Worker     1, 1, 1, 1, /* ({[ */
403*6777b538SAndroid Build Coastguard Worker     2, 2, 2, 2, /* }]) */
404*6777b538SAndroid Build Coastguard Worker     8, 4, 4, 4, /* :; */
405*6777b538SAndroid Build Coastguard Worker     8, 7, 4, 4, /* . */
406*6777b538SAndroid Build Coastguard Worker     8, 0, 0, 0, /* > */
407*6777b538SAndroid Build Coastguard Worker     3, 3, 3, 3, /* [0..9] */
408*6777b538SAndroid Build Coastguard Worker     5, 5, 10, 5, /* [A-Z] */
409*6777b538SAndroid Build Coastguard Worker     5, 5, 10, 5,
410*6777b538SAndroid Build Coastguard Worker     6, 6, 6, 6, /* [a-z] */
411*6777b538SAndroid Build Coastguard Worker     6, 6, 6, 6,
412*6777b538SAndroid Build Coastguard Worker   };
413*6777b538SAndroid Build Coastguard Worker   BROTLI_UNUSED(quality);
414*6777b538SAndroid Build Coastguard Worker   /* Try the more complex static context map only for long data. */
415*6777b538SAndroid Build Coastguard Worker   if (size_hint < (1 << 20)) {
416*6777b538SAndroid Build Coastguard Worker     return BROTLI_FALSE;
417*6777b538SAndroid Build Coastguard Worker   } else {
418*6777b538SAndroid Build Coastguard Worker     const size_t end_pos = start_pos + length;
419*6777b538SAndroid Build Coastguard Worker     /* To make entropy calculations faster, we collect histograms
420*6777b538SAndroid Build Coastguard Worker        over the 5 most significant bits of literals. One histogram
421*6777b538SAndroid Build Coastguard Worker        without context and 13 additional histograms for each context value. */
422*6777b538SAndroid Build Coastguard Worker     uint32_t* BROTLI_RESTRICT const combined_histo = arena;
423*6777b538SAndroid Build Coastguard Worker     uint32_t* BROTLI_RESTRICT const context_histo = arena + 32;
424*6777b538SAndroid Build Coastguard Worker     uint32_t total = 0;
425*6777b538SAndroid Build Coastguard Worker     double entropy[3];
426*6777b538SAndroid Build Coastguard Worker     size_t dummy;
427*6777b538SAndroid Build Coastguard Worker     size_t i;
428*6777b538SAndroid Build Coastguard Worker     ContextLut utf8_lut = BROTLI_CONTEXT_LUT(CONTEXT_UTF8);
429*6777b538SAndroid Build Coastguard Worker     memset(arena, 0, sizeof(arena[0]) * 32 * 14);
430*6777b538SAndroid Build Coastguard Worker     for (; start_pos + 64 <= end_pos; start_pos += 4096) {
431*6777b538SAndroid Build Coastguard Worker       const size_t stride_end_pos = start_pos + 64;
432*6777b538SAndroid Build Coastguard Worker       uint8_t prev2 = input[start_pos & mask];
433*6777b538SAndroid Build Coastguard Worker       uint8_t prev1 = input[(start_pos + 1) & mask];
434*6777b538SAndroid Build Coastguard Worker       size_t pos;
435*6777b538SAndroid Build Coastguard Worker       /* To make the analysis of the data faster we only examine 64 byte long
436*6777b538SAndroid Build Coastguard Worker          strides at every 4kB intervals. */
437*6777b538SAndroid Build Coastguard Worker       for (pos = start_pos + 2; pos < stride_end_pos; ++pos) {
438*6777b538SAndroid Build Coastguard Worker         const uint8_t literal = input[pos & mask];
439*6777b538SAndroid Build Coastguard Worker         const uint8_t context = (uint8_t)kStaticContextMapComplexUTF8[
440*6777b538SAndroid Build Coastguard Worker             BROTLI_CONTEXT(prev1, prev2, utf8_lut)];
441*6777b538SAndroid Build Coastguard Worker         ++total;
442*6777b538SAndroid Build Coastguard Worker         ++combined_histo[literal >> 3];
443*6777b538SAndroid Build Coastguard Worker         ++context_histo[(context << 5) + (literal >> 3)];
444*6777b538SAndroid Build Coastguard Worker         prev2 = prev1;
445*6777b538SAndroid Build Coastguard Worker         prev1 = literal;
446*6777b538SAndroid Build Coastguard Worker       }
447*6777b538SAndroid Build Coastguard Worker     }
448*6777b538SAndroid Build Coastguard Worker     entropy[1] = ShannonEntropy(combined_histo, 32, &dummy);
449*6777b538SAndroid Build Coastguard Worker     entropy[2] = 0;
450*6777b538SAndroid Build Coastguard Worker     for (i = 0; i < 13; ++i) {
451*6777b538SAndroid Build Coastguard Worker       entropy[2] += ShannonEntropy(context_histo + (i << 5), 32, &dummy);
452*6777b538SAndroid Build Coastguard Worker     }
453*6777b538SAndroid Build Coastguard Worker     entropy[0] = 1.0 / (double)total;
454*6777b538SAndroid Build Coastguard Worker     entropy[1] *= entropy[0];
455*6777b538SAndroid Build Coastguard Worker     entropy[2] *= entropy[0];
456*6777b538SAndroid Build Coastguard Worker     /* The triggering heuristics below were tuned by compressing the individual
457*6777b538SAndroid Build Coastguard Worker        files of the silesia corpus. If we skip this kind of context modeling
458*6777b538SAndroid Build Coastguard Worker        for not very well compressible input (i.e. entropy using context modeling
459*6777b538SAndroid Build Coastguard Worker        is 60% of maximal entropy) or if expected savings by symbol are less
460*6777b538SAndroid Build Coastguard Worker        than 0.2 bits, then in every case when it triggers, the final compression
461*6777b538SAndroid Build Coastguard Worker        ratio is improved. Note however that this heuristics might be too strict
462*6777b538SAndroid Build Coastguard Worker        for some cases and could be tuned further. */
463*6777b538SAndroid Build Coastguard Worker     if (entropy[2] > 3.0 || entropy[1] - entropy[2] < 0.2) {
464*6777b538SAndroid Build Coastguard Worker       return BROTLI_FALSE;
465*6777b538SAndroid Build Coastguard Worker     } else {
466*6777b538SAndroid Build Coastguard Worker       *num_literal_contexts = 13;
467*6777b538SAndroid Build Coastguard Worker       *literal_context_map = kStaticContextMapComplexUTF8;
468*6777b538SAndroid Build Coastguard Worker       return BROTLI_TRUE;
469*6777b538SAndroid Build Coastguard Worker     }
470*6777b538SAndroid Build Coastguard Worker   }
471*6777b538SAndroid Build Coastguard Worker }
472*6777b538SAndroid Build Coastguard Worker 
DecideOverLiteralContextModeling(const uint8_t * input,size_t start_pos,size_t length,size_t mask,int quality,size_t size_hint,size_t * num_literal_contexts,const uint32_t ** literal_context_map,uint32_t * arena)473*6777b538SAndroid Build Coastguard Worker static void DecideOverLiteralContextModeling(const uint8_t* input,
474*6777b538SAndroid Build Coastguard Worker     size_t start_pos, size_t length, size_t mask, int quality, size_t size_hint,
475*6777b538SAndroid Build Coastguard Worker     size_t* num_literal_contexts, const uint32_t** literal_context_map,
476*6777b538SAndroid Build Coastguard Worker     uint32_t* arena) {
477*6777b538SAndroid Build Coastguard Worker   if (quality < MIN_QUALITY_FOR_CONTEXT_MODELING || length < 64) {
478*6777b538SAndroid Build Coastguard Worker     return;
479*6777b538SAndroid Build Coastguard Worker   } else if (ShouldUseComplexStaticContextMap(
480*6777b538SAndroid Build Coastguard Worker       input, start_pos, length, mask, quality, size_hint,
481*6777b538SAndroid Build Coastguard Worker       num_literal_contexts, literal_context_map, arena)) {
482*6777b538SAndroid Build Coastguard Worker     /* Context map was already set, nothing else to do. */
483*6777b538SAndroid Build Coastguard Worker   } else {
484*6777b538SAndroid Build Coastguard Worker     /* Gather bi-gram data of the UTF8 byte prefixes. To make the analysis of
485*6777b538SAndroid Build Coastguard Worker        UTF8 data faster we only examine 64 byte long strides at every 4kB
486*6777b538SAndroid Build Coastguard Worker        intervals. */
487*6777b538SAndroid Build Coastguard Worker     const size_t end_pos = start_pos + length;
488*6777b538SAndroid Build Coastguard Worker     uint32_t* BROTLI_RESTRICT const bigram_prefix_histo = arena;
489*6777b538SAndroid Build Coastguard Worker     memset(bigram_prefix_histo, 0, sizeof(arena[0]) * 9);
490*6777b538SAndroid Build Coastguard Worker     for (; start_pos + 64 <= end_pos; start_pos += 4096) {
491*6777b538SAndroid Build Coastguard Worker       static const int lut[4] = { 0, 0, 1, 2 };
492*6777b538SAndroid Build Coastguard Worker       const size_t stride_end_pos = start_pos + 64;
493*6777b538SAndroid Build Coastguard Worker       int prev = lut[input[start_pos & mask] >> 6] * 3;
494*6777b538SAndroid Build Coastguard Worker       size_t pos;
495*6777b538SAndroid Build Coastguard Worker       for (pos = start_pos + 1; pos < stride_end_pos; ++pos) {
496*6777b538SAndroid Build Coastguard Worker         const uint8_t literal = input[pos & mask];
497*6777b538SAndroid Build Coastguard Worker         ++bigram_prefix_histo[prev + lut[literal >> 6]];
498*6777b538SAndroid Build Coastguard Worker         prev = lut[literal >> 6] * 3;
499*6777b538SAndroid Build Coastguard Worker       }
500*6777b538SAndroid Build Coastguard Worker     }
501*6777b538SAndroid Build Coastguard Worker     ChooseContextMap(quality, &bigram_prefix_histo[0], num_literal_contexts,
502*6777b538SAndroid Build Coastguard Worker                      literal_context_map);
503*6777b538SAndroid Build Coastguard Worker   }
504*6777b538SAndroid Build Coastguard Worker }
505*6777b538SAndroid Build Coastguard Worker 
ShouldCompress(const uint8_t * data,const size_t mask,const uint64_t last_flush_pos,const size_t bytes,const size_t num_literals,const size_t num_commands)506*6777b538SAndroid Build Coastguard Worker static BROTLI_BOOL ShouldCompress(
507*6777b538SAndroid Build Coastguard Worker     const uint8_t* data, const size_t mask, const uint64_t last_flush_pos,
508*6777b538SAndroid Build Coastguard Worker     const size_t bytes, const size_t num_literals, const size_t num_commands) {
509*6777b538SAndroid Build Coastguard Worker   /* TODO(eustas): find more precise minimal block overhead. */
510*6777b538SAndroid Build Coastguard Worker   if (bytes <= 2) return BROTLI_FALSE;
511*6777b538SAndroid Build Coastguard Worker   if (num_commands < (bytes >> 8) + 2) {
512*6777b538SAndroid Build Coastguard Worker     if ((double)num_literals > 0.99 * (double)bytes) {
513*6777b538SAndroid Build Coastguard Worker       uint32_t literal_histo[256] = { 0 };
514*6777b538SAndroid Build Coastguard Worker       static const uint32_t kSampleRate = 13;
515*6777b538SAndroid Build Coastguard Worker       static const double kMinEntropy = 7.92;
516*6777b538SAndroid Build Coastguard Worker       const double bit_cost_threshold =
517*6777b538SAndroid Build Coastguard Worker           (double)bytes * kMinEntropy / kSampleRate;
518*6777b538SAndroid Build Coastguard Worker       size_t t = (bytes + kSampleRate - 1) / kSampleRate;
519*6777b538SAndroid Build Coastguard Worker       uint32_t pos = (uint32_t)last_flush_pos;
520*6777b538SAndroid Build Coastguard Worker       size_t i;
521*6777b538SAndroid Build Coastguard Worker       for (i = 0; i < t; i++) {
522*6777b538SAndroid Build Coastguard Worker         ++literal_histo[data[pos & mask]];
523*6777b538SAndroid Build Coastguard Worker         pos += kSampleRate;
524*6777b538SAndroid Build Coastguard Worker       }
525*6777b538SAndroid Build Coastguard Worker       if (BitsEntropy(literal_histo, 256) > bit_cost_threshold) {
526*6777b538SAndroid Build Coastguard Worker         return BROTLI_FALSE;
527*6777b538SAndroid Build Coastguard Worker       }
528*6777b538SAndroid Build Coastguard Worker     }
529*6777b538SAndroid Build Coastguard Worker   }
530*6777b538SAndroid Build Coastguard Worker   return BROTLI_TRUE;
531*6777b538SAndroid Build Coastguard Worker }
532*6777b538SAndroid Build Coastguard Worker 
533*6777b538SAndroid Build Coastguard Worker /* Chooses the literal context mode for a metablock */
ChooseContextMode(const BrotliEncoderParams * params,const uint8_t * data,const size_t pos,const size_t mask,const size_t length)534*6777b538SAndroid Build Coastguard Worker static ContextType ChooseContextMode(const BrotliEncoderParams* params,
535*6777b538SAndroid Build Coastguard Worker     const uint8_t* data, const size_t pos, const size_t mask,
536*6777b538SAndroid Build Coastguard Worker     const size_t length) {
537*6777b538SAndroid Build Coastguard Worker   /* We only do the computation for the option of something else than
538*6777b538SAndroid Build Coastguard Worker      CONTEXT_UTF8 for the highest qualities */
539*6777b538SAndroid Build Coastguard Worker   if (params->quality >= MIN_QUALITY_FOR_HQ_BLOCK_SPLITTING &&
540*6777b538SAndroid Build Coastguard Worker       !BrotliIsMostlyUTF8(data, pos, mask, length, kMinUTF8Ratio)) {
541*6777b538SAndroid Build Coastguard Worker     return CONTEXT_SIGNED;
542*6777b538SAndroid Build Coastguard Worker   }
543*6777b538SAndroid Build Coastguard Worker   return CONTEXT_UTF8;
544*6777b538SAndroid Build Coastguard Worker }
545*6777b538SAndroid Build Coastguard Worker 
WriteMetaBlockInternal(MemoryManager * m,const uint8_t * data,const size_t mask,const uint64_t last_flush_pos,const size_t bytes,const BROTLI_BOOL is_last,ContextType literal_context_mode,const BrotliEncoderParams * params,const uint8_t prev_byte,const uint8_t prev_byte2,const size_t num_literals,const size_t num_commands,Command * commands,const int * saved_dist_cache,int * dist_cache,size_t * storage_ix,uint8_t * storage)546*6777b538SAndroid Build Coastguard Worker static void WriteMetaBlockInternal(MemoryManager* m,
547*6777b538SAndroid Build Coastguard Worker                                    const uint8_t* data,
548*6777b538SAndroid Build Coastguard Worker                                    const size_t mask,
549*6777b538SAndroid Build Coastguard Worker                                    const uint64_t last_flush_pos,
550*6777b538SAndroid Build Coastguard Worker                                    const size_t bytes,
551*6777b538SAndroid Build Coastguard Worker                                    const BROTLI_BOOL is_last,
552*6777b538SAndroid Build Coastguard Worker                                    ContextType literal_context_mode,
553*6777b538SAndroid Build Coastguard Worker                                    const BrotliEncoderParams* params,
554*6777b538SAndroid Build Coastguard Worker                                    const uint8_t prev_byte,
555*6777b538SAndroid Build Coastguard Worker                                    const uint8_t prev_byte2,
556*6777b538SAndroid Build Coastguard Worker                                    const size_t num_literals,
557*6777b538SAndroid Build Coastguard Worker                                    const size_t num_commands,
558*6777b538SAndroid Build Coastguard Worker                                    Command* commands,
559*6777b538SAndroid Build Coastguard Worker                                    const int* saved_dist_cache,
560*6777b538SAndroid Build Coastguard Worker                                    int* dist_cache,
561*6777b538SAndroid Build Coastguard Worker                                    size_t* storage_ix,
562*6777b538SAndroid Build Coastguard Worker                                    uint8_t* storage) {
563*6777b538SAndroid Build Coastguard Worker   const uint32_t wrapped_last_flush_pos = WrapPosition(last_flush_pos);
564*6777b538SAndroid Build Coastguard Worker   uint16_t last_bytes;
565*6777b538SAndroid Build Coastguard Worker   uint8_t last_bytes_bits;
566*6777b538SAndroid Build Coastguard Worker   ContextLut literal_context_lut = BROTLI_CONTEXT_LUT(literal_context_mode);
567*6777b538SAndroid Build Coastguard Worker   BrotliEncoderParams block_params = *params;
568*6777b538SAndroid Build Coastguard Worker 
569*6777b538SAndroid Build Coastguard Worker   if (bytes == 0) {
570*6777b538SAndroid Build Coastguard Worker     /* Write the ISLAST and ISEMPTY bits. */
571*6777b538SAndroid Build Coastguard Worker     BrotliWriteBits(2, 3, storage_ix, storage);
572*6777b538SAndroid Build Coastguard Worker     *storage_ix = (*storage_ix + 7u) & ~7u;
573*6777b538SAndroid Build Coastguard Worker     return;
574*6777b538SAndroid Build Coastguard Worker   }
575*6777b538SAndroid Build Coastguard Worker 
576*6777b538SAndroid Build Coastguard Worker   if (!ShouldCompress(data, mask, last_flush_pos, bytes,
577*6777b538SAndroid Build Coastguard Worker                       num_literals, num_commands)) {
578*6777b538SAndroid Build Coastguard Worker     /* Restore the distance cache, as its last update by
579*6777b538SAndroid Build Coastguard Worker        CreateBackwardReferences is now unused. */
580*6777b538SAndroid Build Coastguard Worker     memcpy(dist_cache, saved_dist_cache, 4 * sizeof(dist_cache[0]));
581*6777b538SAndroid Build Coastguard Worker     BrotliStoreUncompressedMetaBlock(is_last, data,
582*6777b538SAndroid Build Coastguard Worker                                      wrapped_last_flush_pos, mask, bytes,
583*6777b538SAndroid Build Coastguard Worker                                      storage_ix, storage);
584*6777b538SAndroid Build Coastguard Worker     return;
585*6777b538SAndroid Build Coastguard Worker   }
586*6777b538SAndroid Build Coastguard Worker 
587*6777b538SAndroid Build Coastguard Worker   BROTLI_DCHECK(*storage_ix <= 14);
588*6777b538SAndroid Build Coastguard Worker   last_bytes = (uint16_t)((storage[1] << 8) | storage[0]);
589*6777b538SAndroid Build Coastguard Worker   last_bytes_bits = (uint8_t)(*storage_ix);
590*6777b538SAndroid Build Coastguard Worker   if (params->quality <= MAX_QUALITY_FOR_STATIC_ENTROPY_CODES) {
591*6777b538SAndroid Build Coastguard Worker     BrotliStoreMetaBlockFast(m, data, wrapped_last_flush_pos,
592*6777b538SAndroid Build Coastguard Worker                              bytes, mask, is_last, params,
593*6777b538SAndroid Build Coastguard Worker                              commands, num_commands,
594*6777b538SAndroid Build Coastguard Worker                              storage_ix, storage);
595*6777b538SAndroid Build Coastguard Worker     if (BROTLI_IS_OOM(m)) return;
596*6777b538SAndroid Build Coastguard Worker   } else if (params->quality < MIN_QUALITY_FOR_BLOCK_SPLIT) {
597*6777b538SAndroid Build Coastguard Worker     BrotliStoreMetaBlockTrivial(m, data, wrapped_last_flush_pos,
598*6777b538SAndroid Build Coastguard Worker                                 bytes, mask, is_last, params,
599*6777b538SAndroid Build Coastguard Worker                                 commands, num_commands,
600*6777b538SAndroid Build Coastguard Worker                                 storage_ix, storage);
601*6777b538SAndroid Build Coastguard Worker     if (BROTLI_IS_OOM(m)) return;
602*6777b538SAndroid Build Coastguard Worker   } else {
603*6777b538SAndroid Build Coastguard Worker     MetaBlockSplit mb;
604*6777b538SAndroid Build Coastguard Worker     InitMetaBlockSplit(&mb);
605*6777b538SAndroid Build Coastguard Worker     if (params->quality < MIN_QUALITY_FOR_HQ_BLOCK_SPLITTING) {
606*6777b538SAndroid Build Coastguard Worker       size_t num_literal_contexts = 1;
607*6777b538SAndroid Build Coastguard Worker       const uint32_t* literal_context_map = NULL;
608*6777b538SAndroid Build Coastguard Worker       if (!params->disable_literal_context_modeling) {
609*6777b538SAndroid Build Coastguard Worker         /* TODO(eustas): pull to higher level and reuse. */
610*6777b538SAndroid Build Coastguard Worker         uint32_t* arena = BROTLI_ALLOC(m, uint32_t, 14 * 32);
611*6777b538SAndroid Build Coastguard Worker         if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(arena)) return;
612*6777b538SAndroid Build Coastguard Worker         DecideOverLiteralContextModeling(
613*6777b538SAndroid Build Coastguard Worker             data, wrapped_last_flush_pos, bytes, mask, params->quality,
614*6777b538SAndroid Build Coastguard Worker             params->size_hint, &num_literal_contexts,
615*6777b538SAndroid Build Coastguard Worker             &literal_context_map, arena);
616*6777b538SAndroid Build Coastguard Worker         BROTLI_FREE(m, arena);
617*6777b538SAndroid Build Coastguard Worker       }
618*6777b538SAndroid Build Coastguard Worker       BrotliBuildMetaBlockGreedy(m, data, wrapped_last_flush_pos, mask,
619*6777b538SAndroid Build Coastguard Worker           prev_byte, prev_byte2, literal_context_lut, num_literal_contexts,
620*6777b538SAndroid Build Coastguard Worker           literal_context_map, commands, num_commands, &mb);
621*6777b538SAndroid Build Coastguard Worker       if (BROTLI_IS_OOM(m)) return;
622*6777b538SAndroid Build Coastguard Worker     } else {
623*6777b538SAndroid Build Coastguard Worker       BrotliBuildMetaBlock(m, data, wrapped_last_flush_pos, mask, &block_params,
624*6777b538SAndroid Build Coastguard Worker                            prev_byte, prev_byte2,
625*6777b538SAndroid Build Coastguard Worker                            commands, num_commands,
626*6777b538SAndroid Build Coastguard Worker                            literal_context_mode,
627*6777b538SAndroid Build Coastguard Worker                            &mb);
628*6777b538SAndroid Build Coastguard Worker       if (BROTLI_IS_OOM(m)) return;
629*6777b538SAndroid Build Coastguard Worker     }
630*6777b538SAndroid Build Coastguard Worker     if (params->quality >= MIN_QUALITY_FOR_OPTIMIZE_HISTOGRAMS) {
631*6777b538SAndroid Build Coastguard Worker       /* The number of distance symbols effectively used for distance
632*6777b538SAndroid Build Coastguard Worker          histograms. It might be less than distance alphabet size
633*6777b538SAndroid Build Coastguard Worker          for "Large Window Brotli" (32-bit). */
634*6777b538SAndroid Build Coastguard Worker       BrotliOptimizeHistograms(block_params.dist.alphabet_size_limit, &mb);
635*6777b538SAndroid Build Coastguard Worker     }
636*6777b538SAndroid Build Coastguard Worker     BrotliStoreMetaBlock(m, data, wrapped_last_flush_pos, bytes, mask,
637*6777b538SAndroid Build Coastguard Worker                          prev_byte, prev_byte2,
638*6777b538SAndroid Build Coastguard Worker                          is_last,
639*6777b538SAndroid Build Coastguard Worker                          &block_params,
640*6777b538SAndroid Build Coastguard Worker                          literal_context_mode,
641*6777b538SAndroid Build Coastguard Worker                          commands, num_commands,
642*6777b538SAndroid Build Coastguard Worker                          &mb,
643*6777b538SAndroid Build Coastguard Worker                          storage_ix, storage);
644*6777b538SAndroid Build Coastguard Worker     if (BROTLI_IS_OOM(m)) return;
645*6777b538SAndroid Build Coastguard Worker     DestroyMetaBlockSplit(m, &mb);
646*6777b538SAndroid Build Coastguard Worker   }
647*6777b538SAndroid Build Coastguard Worker   if (bytes + 4 < (*storage_ix >> 3)) {
648*6777b538SAndroid Build Coastguard Worker     /* Restore the distance cache and last byte. */
649*6777b538SAndroid Build Coastguard Worker     memcpy(dist_cache, saved_dist_cache, 4 * sizeof(dist_cache[0]));
650*6777b538SAndroid Build Coastguard Worker     storage[0] = (uint8_t)last_bytes;
651*6777b538SAndroid Build Coastguard Worker     storage[1] = (uint8_t)(last_bytes >> 8);
652*6777b538SAndroid Build Coastguard Worker     *storage_ix = last_bytes_bits;
653*6777b538SAndroid Build Coastguard Worker     BrotliStoreUncompressedMetaBlock(is_last, data,
654*6777b538SAndroid Build Coastguard Worker                                      wrapped_last_flush_pos, mask,
655*6777b538SAndroid Build Coastguard Worker                                      bytes, storage_ix, storage);
656*6777b538SAndroid Build Coastguard Worker   }
657*6777b538SAndroid Build Coastguard Worker }
658*6777b538SAndroid Build Coastguard Worker 
ChooseDistanceParams(BrotliEncoderParams * params)659*6777b538SAndroid Build Coastguard Worker static void ChooseDistanceParams(BrotliEncoderParams* params) {
660*6777b538SAndroid Build Coastguard Worker   uint32_t distance_postfix_bits = 0;
661*6777b538SAndroid Build Coastguard Worker   uint32_t num_direct_distance_codes = 0;
662*6777b538SAndroid Build Coastguard Worker 
663*6777b538SAndroid Build Coastguard Worker   if (params->quality >= MIN_QUALITY_FOR_NONZERO_DISTANCE_PARAMS) {
664*6777b538SAndroid Build Coastguard Worker     uint32_t ndirect_msb;
665*6777b538SAndroid Build Coastguard Worker     if (params->mode == BROTLI_MODE_FONT) {
666*6777b538SAndroid Build Coastguard Worker       distance_postfix_bits = 1;
667*6777b538SAndroid Build Coastguard Worker       num_direct_distance_codes = 12;
668*6777b538SAndroid Build Coastguard Worker     } else {
669*6777b538SAndroid Build Coastguard Worker       distance_postfix_bits = params->dist.distance_postfix_bits;
670*6777b538SAndroid Build Coastguard Worker       num_direct_distance_codes = params->dist.num_direct_distance_codes;
671*6777b538SAndroid Build Coastguard Worker     }
672*6777b538SAndroid Build Coastguard Worker     ndirect_msb = (num_direct_distance_codes >> distance_postfix_bits) & 0x0F;
673*6777b538SAndroid Build Coastguard Worker     if (distance_postfix_bits > BROTLI_MAX_NPOSTFIX ||
674*6777b538SAndroid Build Coastguard Worker         num_direct_distance_codes > BROTLI_MAX_NDIRECT ||
675*6777b538SAndroid Build Coastguard Worker         (ndirect_msb << distance_postfix_bits) != num_direct_distance_codes) {
676*6777b538SAndroid Build Coastguard Worker       distance_postfix_bits = 0;
677*6777b538SAndroid Build Coastguard Worker       num_direct_distance_codes = 0;
678*6777b538SAndroid Build Coastguard Worker     }
679*6777b538SAndroid Build Coastguard Worker   }
680*6777b538SAndroid Build Coastguard Worker 
681*6777b538SAndroid Build Coastguard Worker   BrotliInitDistanceParams(&params->dist, distance_postfix_bits,
682*6777b538SAndroid Build Coastguard Worker                            num_direct_distance_codes, params->large_window);
683*6777b538SAndroid Build Coastguard Worker }
684*6777b538SAndroid Build Coastguard Worker 
EnsureInitialized(BrotliEncoderState * s)685*6777b538SAndroid Build Coastguard Worker static BROTLI_BOOL EnsureInitialized(BrotliEncoderState* s) {
686*6777b538SAndroid Build Coastguard Worker   MemoryManager* m = &s->memory_manager_;
687*6777b538SAndroid Build Coastguard Worker   if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;
688*6777b538SAndroid Build Coastguard Worker   if (s->is_initialized_) return BROTLI_TRUE;
689*6777b538SAndroid Build Coastguard Worker 
690*6777b538SAndroid Build Coastguard Worker   s->last_bytes_bits_ = 0;
691*6777b538SAndroid Build Coastguard Worker   s->last_bytes_ = 0;
692*6777b538SAndroid Build Coastguard Worker   s->flint_ = BROTLI_FLINT_DONE;
693*6777b538SAndroid Build Coastguard Worker   s->remaining_metadata_bytes_ = BROTLI_UINT32_MAX;
694*6777b538SAndroid Build Coastguard Worker 
695*6777b538SAndroid Build Coastguard Worker   SanitizeParams(&s->params);
696*6777b538SAndroid Build Coastguard Worker   s->params.lgblock = ComputeLgBlock(&s->params);
697*6777b538SAndroid Build Coastguard Worker   ChooseDistanceParams(&s->params);
698*6777b538SAndroid Build Coastguard Worker 
699*6777b538SAndroid Build Coastguard Worker   if (s->params.stream_offset != 0) {
700*6777b538SAndroid Build Coastguard Worker     s->flint_ = BROTLI_FLINT_NEEDS_2_BYTES;
701*6777b538SAndroid Build Coastguard Worker     /* Poison the distance cache. -16 +- 3 is still less than zero (invalid). */
702*6777b538SAndroid Build Coastguard Worker     s->dist_cache_[0] = -16;
703*6777b538SAndroid Build Coastguard Worker     s->dist_cache_[1] = -16;
704*6777b538SAndroid Build Coastguard Worker     s->dist_cache_[2] = -16;
705*6777b538SAndroid Build Coastguard Worker     s->dist_cache_[3] = -16;
706*6777b538SAndroid Build Coastguard Worker     memcpy(s->saved_dist_cache_, s->dist_cache_, sizeof(s->saved_dist_cache_));
707*6777b538SAndroid Build Coastguard Worker   }
708*6777b538SAndroid Build Coastguard Worker 
709*6777b538SAndroid Build Coastguard Worker   RingBufferSetup(&s->params, &s->ringbuffer_);
710*6777b538SAndroid Build Coastguard Worker 
711*6777b538SAndroid Build Coastguard Worker   /* Initialize last byte with stream header. */
712*6777b538SAndroid Build Coastguard Worker   {
713*6777b538SAndroid Build Coastguard Worker     int lgwin = s->params.lgwin;
714*6777b538SAndroid Build Coastguard Worker     if (s->params.quality == FAST_ONE_PASS_COMPRESSION_QUALITY ||
715*6777b538SAndroid Build Coastguard Worker         s->params.quality == FAST_TWO_PASS_COMPRESSION_QUALITY) {
716*6777b538SAndroid Build Coastguard Worker       lgwin = BROTLI_MAX(int, lgwin, 18);
717*6777b538SAndroid Build Coastguard Worker     }
718*6777b538SAndroid Build Coastguard Worker     if (s->params.stream_offset == 0) {
719*6777b538SAndroid Build Coastguard Worker       EncodeWindowBits(lgwin, s->params.large_window,
720*6777b538SAndroid Build Coastguard Worker                        &s->last_bytes_, &s->last_bytes_bits_);
721*6777b538SAndroid Build Coastguard Worker     } else {
722*6777b538SAndroid Build Coastguard Worker       /* Bigger values have the same effect, but could cause overflows. */
723*6777b538SAndroid Build Coastguard Worker       s->params.stream_offset = BROTLI_MIN(size_t,
724*6777b538SAndroid Build Coastguard Worker           s->params.stream_offset, BROTLI_MAX_BACKWARD_LIMIT(lgwin));
725*6777b538SAndroid Build Coastguard Worker     }
726*6777b538SAndroid Build Coastguard Worker   }
727*6777b538SAndroid Build Coastguard Worker 
728*6777b538SAndroid Build Coastguard Worker   if (s->params.quality == FAST_ONE_PASS_COMPRESSION_QUALITY) {
729*6777b538SAndroid Build Coastguard Worker     s->one_pass_arena_ = BROTLI_ALLOC(m, BrotliOnePassArena, 1);
730*6777b538SAndroid Build Coastguard Worker     if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;
731*6777b538SAndroid Build Coastguard Worker     InitCommandPrefixCodes(s->one_pass_arena_);
732*6777b538SAndroid Build Coastguard Worker   } else if (s->params.quality == FAST_TWO_PASS_COMPRESSION_QUALITY) {
733*6777b538SAndroid Build Coastguard Worker     s->two_pass_arena_ = BROTLI_ALLOC(m, BrotliTwoPassArena, 1);
734*6777b538SAndroid Build Coastguard Worker     if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;
735*6777b538SAndroid Build Coastguard Worker   }
736*6777b538SAndroid Build Coastguard Worker 
737*6777b538SAndroid Build Coastguard Worker   s->is_initialized_ = BROTLI_TRUE;
738*6777b538SAndroid Build Coastguard Worker   return BROTLI_TRUE;
739*6777b538SAndroid Build Coastguard Worker }
740*6777b538SAndroid Build Coastguard Worker 
BrotliEncoderInitParams(BrotliEncoderParams * params)741*6777b538SAndroid Build Coastguard Worker static void BrotliEncoderInitParams(BrotliEncoderParams* params) {
742*6777b538SAndroid Build Coastguard Worker   params->mode = BROTLI_DEFAULT_MODE;
743*6777b538SAndroid Build Coastguard Worker   params->large_window = BROTLI_FALSE;
744*6777b538SAndroid Build Coastguard Worker   params->quality = BROTLI_DEFAULT_QUALITY;
745*6777b538SAndroid Build Coastguard Worker   params->lgwin = BROTLI_DEFAULT_WINDOW;
746*6777b538SAndroid Build Coastguard Worker   params->lgblock = 0;
747*6777b538SAndroid Build Coastguard Worker   params->stream_offset = 0;
748*6777b538SAndroid Build Coastguard Worker   params->size_hint = 0;
749*6777b538SAndroid Build Coastguard Worker   params->disable_literal_context_modeling = BROTLI_FALSE;
750*6777b538SAndroid Build Coastguard Worker   BrotliInitSharedEncoderDictionary(&params->dictionary);
751*6777b538SAndroid Build Coastguard Worker   params->dist.distance_postfix_bits = 0;
752*6777b538SAndroid Build Coastguard Worker   params->dist.num_direct_distance_codes = 0;
753*6777b538SAndroid Build Coastguard Worker   params->dist.alphabet_size_max =
754*6777b538SAndroid Build Coastguard Worker       BROTLI_DISTANCE_ALPHABET_SIZE(0, 0, BROTLI_MAX_DISTANCE_BITS);
755*6777b538SAndroid Build Coastguard Worker   params->dist.alphabet_size_limit = params->dist.alphabet_size_max;
756*6777b538SAndroid Build Coastguard Worker   params->dist.max_distance = BROTLI_MAX_DISTANCE;
757*6777b538SAndroid Build Coastguard Worker }
758*6777b538SAndroid Build Coastguard Worker 
BrotliEncoderCleanupParams(MemoryManager * m,BrotliEncoderParams * params)759*6777b538SAndroid Build Coastguard Worker static void BrotliEncoderCleanupParams(MemoryManager* m,
760*6777b538SAndroid Build Coastguard Worker     BrotliEncoderParams* params) {
761*6777b538SAndroid Build Coastguard Worker   BrotliCleanupSharedEncoderDictionary(m, &params->dictionary);
762*6777b538SAndroid Build Coastguard Worker }
763*6777b538SAndroid Build Coastguard Worker 
BrotliEncoderInitState(BrotliEncoderState * s)764*6777b538SAndroid Build Coastguard Worker static void BrotliEncoderInitState(BrotliEncoderState* s) {
765*6777b538SAndroid Build Coastguard Worker   BrotliEncoderInitParams(&s->params);
766*6777b538SAndroid Build Coastguard Worker   s->input_pos_ = 0;
767*6777b538SAndroid Build Coastguard Worker   s->num_commands_ = 0;
768*6777b538SAndroid Build Coastguard Worker   s->num_literals_ = 0;
769*6777b538SAndroid Build Coastguard Worker   s->last_insert_len_ = 0;
770*6777b538SAndroid Build Coastguard Worker   s->last_flush_pos_ = 0;
771*6777b538SAndroid Build Coastguard Worker   s->last_processed_pos_ = 0;
772*6777b538SAndroid Build Coastguard Worker   s->prev_byte_ = 0;
773*6777b538SAndroid Build Coastguard Worker   s->prev_byte2_ = 0;
774*6777b538SAndroid Build Coastguard Worker   s->storage_size_ = 0;
775*6777b538SAndroid Build Coastguard Worker   s->storage_ = 0;
776*6777b538SAndroid Build Coastguard Worker   HasherInit(&s->hasher_);
777*6777b538SAndroid Build Coastguard Worker   s->large_table_ = NULL;
778*6777b538SAndroid Build Coastguard Worker   s->large_table_size_ = 0;
779*6777b538SAndroid Build Coastguard Worker   s->one_pass_arena_ = NULL;
780*6777b538SAndroid Build Coastguard Worker   s->two_pass_arena_ = NULL;
781*6777b538SAndroid Build Coastguard Worker   s->command_buf_ = NULL;
782*6777b538SAndroid Build Coastguard Worker   s->literal_buf_ = NULL;
783*6777b538SAndroid Build Coastguard Worker   s->next_out_ = NULL;
784*6777b538SAndroid Build Coastguard Worker   s->available_out_ = 0;
785*6777b538SAndroid Build Coastguard Worker   s->total_out_ = 0;
786*6777b538SAndroid Build Coastguard Worker   s->stream_state_ = BROTLI_STREAM_PROCESSING;
787*6777b538SAndroid Build Coastguard Worker   s->is_last_block_emitted_ = BROTLI_FALSE;
788*6777b538SAndroid Build Coastguard Worker   s->is_initialized_ = BROTLI_FALSE;
789*6777b538SAndroid Build Coastguard Worker 
790*6777b538SAndroid Build Coastguard Worker   RingBufferInit(&s->ringbuffer_);
791*6777b538SAndroid Build Coastguard Worker 
792*6777b538SAndroid Build Coastguard Worker   s->commands_ = 0;
793*6777b538SAndroid Build Coastguard Worker   s->cmd_alloc_size_ = 0;
794*6777b538SAndroid Build Coastguard Worker 
795*6777b538SAndroid Build Coastguard Worker   /* Initialize distance cache. */
796*6777b538SAndroid Build Coastguard Worker   s->dist_cache_[0] = 4;
797*6777b538SAndroid Build Coastguard Worker   s->dist_cache_[1] = 11;
798*6777b538SAndroid Build Coastguard Worker   s->dist_cache_[2] = 15;
799*6777b538SAndroid Build Coastguard Worker   s->dist_cache_[3] = 16;
800*6777b538SAndroid Build Coastguard Worker   /* Save the state of the distance cache in case we need to restore it for
801*6777b538SAndroid Build Coastguard Worker      emitting an uncompressed block. */
802*6777b538SAndroid Build Coastguard Worker   memcpy(s->saved_dist_cache_, s->dist_cache_, sizeof(s->saved_dist_cache_));
803*6777b538SAndroid Build Coastguard Worker }
804*6777b538SAndroid Build Coastguard Worker 
BrotliEncoderCreateInstance(brotli_alloc_func alloc_func,brotli_free_func free_func,void * opaque)805*6777b538SAndroid Build Coastguard Worker BrotliEncoderState* BrotliEncoderCreateInstance(
806*6777b538SAndroid Build Coastguard Worker     brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque) {
807*6777b538SAndroid Build Coastguard Worker   BrotliEncoderState* state = (BrotliEncoderState*)BrotliBootstrapAlloc(
808*6777b538SAndroid Build Coastguard Worker       sizeof(BrotliEncoderState), alloc_func, free_func, opaque);
809*6777b538SAndroid Build Coastguard Worker   if (state == NULL) {
810*6777b538SAndroid Build Coastguard Worker     /* BROTLI_DUMP(); */
811*6777b538SAndroid Build Coastguard Worker     return 0;
812*6777b538SAndroid Build Coastguard Worker   }
813*6777b538SAndroid Build Coastguard Worker   BrotliInitMemoryManager(
814*6777b538SAndroid Build Coastguard Worker       &state->memory_manager_, alloc_func, free_func, opaque);
815*6777b538SAndroid Build Coastguard Worker   BrotliEncoderInitState(state);
816*6777b538SAndroid Build Coastguard Worker   return state;
817*6777b538SAndroid Build Coastguard Worker }
818*6777b538SAndroid Build Coastguard Worker 
BrotliEncoderCleanupState(BrotliEncoderState * s)819*6777b538SAndroid Build Coastguard Worker static void BrotliEncoderCleanupState(BrotliEncoderState* s) {
820*6777b538SAndroid Build Coastguard Worker   MemoryManager* m = &s->memory_manager_;
821*6777b538SAndroid Build Coastguard Worker   if (BROTLI_IS_OOM(m)) {
822*6777b538SAndroid Build Coastguard Worker     BrotliWipeOutMemoryManager(m);
823*6777b538SAndroid Build Coastguard Worker     return;
824*6777b538SAndroid Build Coastguard Worker   }
825*6777b538SAndroid Build Coastguard Worker   BROTLI_FREE(m, s->storage_);
826*6777b538SAndroid Build Coastguard Worker   BROTLI_FREE(m, s->commands_);
827*6777b538SAndroid Build Coastguard Worker   RingBufferFree(m, &s->ringbuffer_);
828*6777b538SAndroid Build Coastguard Worker   DestroyHasher(m, &s->hasher_);
829*6777b538SAndroid Build Coastguard Worker   BROTLI_FREE(m, s->large_table_);
830*6777b538SAndroid Build Coastguard Worker   BROTLI_FREE(m, s->one_pass_arena_);
831*6777b538SAndroid Build Coastguard Worker   BROTLI_FREE(m, s->two_pass_arena_);
832*6777b538SAndroid Build Coastguard Worker   BROTLI_FREE(m, s->command_buf_);
833*6777b538SAndroid Build Coastguard Worker   BROTLI_FREE(m, s->literal_buf_);
834*6777b538SAndroid Build Coastguard Worker   BrotliEncoderCleanupParams(m, &s->params);
835*6777b538SAndroid Build Coastguard Worker }
836*6777b538SAndroid Build Coastguard Worker 
837*6777b538SAndroid Build Coastguard Worker /* Deinitializes and frees BrotliEncoderState instance. */
BrotliEncoderDestroyInstance(BrotliEncoderState * state)838*6777b538SAndroid Build Coastguard Worker void BrotliEncoderDestroyInstance(BrotliEncoderState* state) {
839*6777b538SAndroid Build Coastguard Worker   if (!state) {
840*6777b538SAndroid Build Coastguard Worker     return;
841*6777b538SAndroid Build Coastguard Worker   } else {
842*6777b538SAndroid Build Coastguard Worker     BrotliEncoderCleanupState(state);
843*6777b538SAndroid Build Coastguard Worker     BrotliBootstrapFree(state, &state->memory_manager_);
844*6777b538SAndroid Build Coastguard Worker   }
845*6777b538SAndroid Build Coastguard Worker }
846*6777b538SAndroid Build Coastguard Worker 
847*6777b538SAndroid Build Coastguard Worker /*
848*6777b538SAndroid Build Coastguard Worker    Copies the given input data to the internal ring buffer of the compressor.
849*6777b538SAndroid Build Coastguard Worker    No processing of the data occurs at this time and this function can be
850*6777b538SAndroid Build Coastguard Worker    called multiple times before calling WriteBrotliData() to process the
851*6777b538SAndroid Build Coastguard Worker    accumulated input. At most input_block_size() bytes of input data can be
852*6777b538SAndroid Build Coastguard Worker    copied to the ring buffer, otherwise the next WriteBrotliData() will fail.
853*6777b538SAndroid Build Coastguard Worker  */
CopyInputToRingBuffer(BrotliEncoderState * s,const size_t input_size,const uint8_t * input_buffer)854*6777b538SAndroid Build Coastguard Worker static void CopyInputToRingBuffer(BrotliEncoderState* s,
855*6777b538SAndroid Build Coastguard Worker                                   const size_t input_size,
856*6777b538SAndroid Build Coastguard Worker                                   const uint8_t* input_buffer) {
857*6777b538SAndroid Build Coastguard Worker   RingBuffer* ringbuffer_ = &s->ringbuffer_;
858*6777b538SAndroid Build Coastguard Worker   MemoryManager* m = &s->memory_manager_;
859*6777b538SAndroid Build Coastguard Worker   RingBufferWrite(m, input_buffer, input_size, ringbuffer_);
860*6777b538SAndroid Build Coastguard Worker   if (BROTLI_IS_OOM(m)) return;
861*6777b538SAndroid Build Coastguard Worker   s->input_pos_ += input_size;
862*6777b538SAndroid Build Coastguard Worker 
863*6777b538SAndroid Build Coastguard Worker   /* TL;DR: If needed, initialize 7 more bytes in the ring buffer to make the
864*6777b538SAndroid Build Coastguard Worker      hashing not depend on uninitialized data. This makes compression
865*6777b538SAndroid Build Coastguard Worker      deterministic and it prevents uninitialized memory warnings in Valgrind.
866*6777b538SAndroid Build Coastguard Worker      Even without erasing, the output would be valid (but nondeterministic).
867*6777b538SAndroid Build Coastguard Worker 
868*6777b538SAndroid Build Coastguard Worker      Background information: The compressor stores short (at most 8 bytes)
869*6777b538SAndroid Build Coastguard Worker      substrings of the input already read in a hash table, and detects
870*6777b538SAndroid Build Coastguard Worker      repetitions by looking up such substrings in the hash table. If it
871*6777b538SAndroid Build Coastguard Worker      can find a substring, it checks whether the substring is really there
872*6777b538SAndroid Build Coastguard Worker      in the ring buffer (or it's just a hash collision). Should the hash
873*6777b538SAndroid Build Coastguard Worker      table become corrupt, this check makes sure that the output is
874*6777b538SAndroid Build Coastguard Worker      still valid, albeit the compression ratio would be bad.
875*6777b538SAndroid Build Coastguard Worker 
876*6777b538SAndroid Build Coastguard Worker      The compressor populates the hash table from the ring buffer as it's
877*6777b538SAndroid Build Coastguard Worker      reading new bytes from the input. However, at the last few indexes of
878*6777b538SAndroid Build Coastguard Worker      the ring buffer, there are not enough bytes to build full-length
879*6777b538SAndroid Build Coastguard Worker      substrings from. Since the hash table always contains full-length
880*6777b538SAndroid Build Coastguard Worker      substrings, we erase with dummy zeros here to make sure that those
881*6777b538SAndroid Build Coastguard Worker      substrings will contain zeros at the end instead of uninitialized
882*6777b538SAndroid Build Coastguard Worker      data.
883*6777b538SAndroid Build Coastguard Worker 
884*6777b538SAndroid Build Coastguard Worker      Please note that erasing is not necessary (because the
885*6777b538SAndroid Build Coastguard Worker      memory region is already initialized since he ring buffer
886*6777b538SAndroid Build Coastguard Worker      has a `tail' that holds a copy of the beginning,) so we
887*6777b538SAndroid Build Coastguard Worker      skip erasing if we have already gone around at least once in
888*6777b538SAndroid Build Coastguard Worker      the ring buffer.
889*6777b538SAndroid Build Coastguard Worker 
890*6777b538SAndroid Build Coastguard Worker      Only clear during the first round of ring-buffer writes. On
891*6777b538SAndroid Build Coastguard Worker      subsequent rounds data in the ring-buffer would be affected. */
892*6777b538SAndroid Build Coastguard Worker   if (ringbuffer_->pos_ <= ringbuffer_->mask_) {
893*6777b538SAndroid Build Coastguard Worker     /* This is the first time when the ring buffer is being written.
894*6777b538SAndroid Build Coastguard Worker        We clear 7 bytes just after the bytes that have been copied from
895*6777b538SAndroid Build Coastguard Worker        the input buffer.
896*6777b538SAndroid Build Coastguard Worker 
897*6777b538SAndroid Build Coastguard Worker        The ring-buffer has a "tail" that holds a copy of the beginning,
898*6777b538SAndroid Build Coastguard Worker        but only once the ring buffer has been fully written once, i.e.,
899*6777b538SAndroid Build Coastguard Worker        pos <= mask. For the first time, we need to write values
900*6777b538SAndroid Build Coastguard Worker        in this tail (where index may be larger than mask), so that
901*6777b538SAndroid Build Coastguard Worker        we have exactly defined behavior and don't read uninitialized
902*6777b538SAndroid Build Coastguard Worker        memory. Due to performance reasons, hashing reads data using a
903*6777b538SAndroid Build Coastguard Worker        LOAD64, which can go 7 bytes beyond the bytes written in the
904*6777b538SAndroid Build Coastguard Worker        ring-buffer. */
905*6777b538SAndroid Build Coastguard Worker     memset(ringbuffer_->buffer_ + ringbuffer_->pos_, 0, 7);
906*6777b538SAndroid Build Coastguard Worker   }
907*6777b538SAndroid Build Coastguard Worker }
908*6777b538SAndroid Build Coastguard Worker 
909*6777b538SAndroid Build Coastguard Worker /* Marks all input as processed.
910*6777b538SAndroid Build Coastguard Worker    Returns true if position wrapping occurs. */
UpdateLastProcessedPos(BrotliEncoderState * s)911*6777b538SAndroid Build Coastguard Worker static BROTLI_BOOL UpdateLastProcessedPos(BrotliEncoderState* s) {
912*6777b538SAndroid Build Coastguard Worker   uint32_t wrapped_last_processed_pos = WrapPosition(s->last_processed_pos_);
913*6777b538SAndroid Build Coastguard Worker   uint32_t wrapped_input_pos = WrapPosition(s->input_pos_);
914*6777b538SAndroid Build Coastguard Worker   s->last_processed_pos_ = s->input_pos_;
915*6777b538SAndroid Build Coastguard Worker   return TO_BROTLI_BOOL(wrapped_input_pos < wrapped_last_processed_pos);
916*6777b538SAndroid Build Coastguard Worker }
917*6777b538SAndroid Build Coastguard Worker 
ExtendLastCommand(BrotliEncoderState * s,uint32_t * bytes,uint32_t * wrapped_last_processed_pos)918*6777b538SAndroid Build Coastguard Worker static void ExtendLastCommand(BrotliEncoderState* s, uint32_t* bytes,
919*6777b538SAndroid Build Coastguard Worker                               uint32_t* wrapped_last_processed_pos) {
920*6777b538SAndroid Build Coastguard Worker   Command* last_command = &s->commands_[s->num_commands_ - 1];
921*6777b538SAndroid Build Coastguard Worker   const uint8_t* data = s->ringbuffer_.buffer_;
922*6777b538SAndroid Build Coastguard Worker   const uint32_t mask = s->ringbuffer_.mask_;
923*6777b538SAndroid Build Coastguard Worker   uint64_t max_backward_distance =
924*6777b538SAndroid Build Coastguard Worker       (((uint64_t)1) << s->params.lgwin) - BROTLI_WINDOW_GAP;
925*6777b538SAndroid Build Coastguard Worker   uint64_t last_copy_len = last_command->copy_len_ & 0x1FFFFFF;
926*6777b538SAndroid Build Coastguard Worker   uint64_t last_processed_pos = s->last_processed_pos_ - last_copy_len;
927*6777b538SAndroid Build Coastguard Worker   uint64_t max_distance = last_processed_pos < max_backward_distance ?
928*6777b538SAndroid Build Coastguard Worker       last_processed_pos : max_backward_distance;
929*6777b538SAndroid Build Coastguard Worker   uint64_t cmd_dist = (uint64_t)s->dist_cache_[0];
930*6777b538SAndroid Build Coastguard Worker   uint32_t distance_code = CommandRestoreDistanceCode(last_command,
931*6777b538SAndroid Build Coastguard Worker                                                       &s->params.dist);
932*6777b538SAndroid Build Coastguard Worker   const CompoundDictionary* dict = &s->params.dictionary.compound;
933*6777b538SAndroid Build Coastguard Worker   size_t compound_dictionary_size = dict->total_size;
934*6777b538SAndroid Build Coastguard Worker   if (distance_code < BROTLI_NUM_DISTANCE_SHORT_CODES ||
935*6777b538SAndroid Build Coastguard Worker       distance_code - (BROTLI_NUM_DISTANCE_SHORT_CODES - 1) == cmd_dist) {
936*6777b538SAndroid Build Coastguard Worker     if (cmd_dist <= max_distance) {
937*6777b538SAndroid Build Coastguard Worker       while (*bytes != 0 && data[*wrapped_last_processed_pos & mask] ==
938*6777b538SAndroid Build Coastguard Worker              data[(*wrapped_last_processed_pos - cmd_dist) & mask]) {
939*6777b538SAndroid Build Coastguard Worker         last_command->copy_len_++;
940*6777b538SAndroid Build Coastguard Worker         (*bytes)--;
941*6777b538SAndroid Build Coastguard Worker         (*wrapped_last_processed_pos)++;
942*6777b538SAndroid Build Coastguard Worker       }
943*6777b538SAndroid Build Coastguard Worker     } else {
944*6777b538SAndroid Build Coastguard Worker       if ((cmd_dist - max_distance - 1) < compound_dictionary_size &&
945*6777b538SAndroid Build Coastguard Worker           last_copy_len < cmd_dist - max_distance) {
946*6777b538SAndroid Build Coastguard Worker         size_t address =
947*6777b538SAndroid Build Coastguard Worker             compound_dictionary_size - (size_t)(cmd_dist - max_distance) +
948*6777b538SAndroid Build Coastguard Worker             (size_t)last_copy_len;
949*6777b538SAndroid Build Coastguard Worker         size_t br_index = 0;
950*6777b538SAndroid Build Coastguard Worker         size_t br_offset;
951*6777b538SAndroid Build Coastguard Worker         const uint8_t* chunk;
952*6777b538SAndroid Build Coastguard Worker         size_t chunk_length;
953*6777b538SAndroid Build Coastguard Worker         while (address >= dict->chunk_offsets[br_index + 1]) br_index++;
954*6777b538SAndroid Build Coastguard Worker         br_offset = address - dict->chunk_offsets[br_index];
955*6777b538SAndroid Build Coastguard Worker         chunk = dict->chunk_source[br_index];
956*6777b538SAndroid Build Coastguard Worker         chunk_length =
957*6777b538SAndroid Build Coastguard Worker             dict->chunk_offsets[br_index + 1] - dict->chunk_offsets[br_index];
958*6777b538SAndroid Build Coastguard Worker         while (*bytes != 0 && data[*wrapped_last_processed_pos & mask] ==
959*6777b538SAndroid Build Coastguard Worker                chunk[br_offset]) {
960*6777b538SAndroid Build Coastguard Worker           last_command->copy_len_++;
961*6777b538SAndroid Build Coastguard Worker           (*bytes)--;
962*6777b538SAndroid Build Coastguard Worker           (*wrapped_last_processed_pos)++;
963*6777b538SAndroid Build Coastguard Worker           if (++br_offset == chunk_length) {
964*6777b538SAndroid Build Coastguard Worker             br_index++;
965*6777b538SAndroid Build Coastguard Worker             br_offset = 0;
966*6777b538SAndroid Build Coastguard Worker             if (br_index != dict->num_chunks) {
967*6777b538SAndroid Build Coastguard Worker               chunk = dict->chunk_source[br_index];
968*6777b538SAndroid Build Coastguard Worker               chunk_length = dict->chunk_offsets[br_index + 1] -
969*6777b538SAndroid Build Coastguard Worker                   dict->chunk_offsets[br_index];
970*6777b538SAndroid Build Coastguard Worker             } else {
971*6777b538SAndroid Build Coastguard Worker               break;
972*6777b538SAndroid Build Coastguard Worker             }
973*6777b538SAndroid Build Coastguard Worker           }
974*6777b538SAndroid Build Coastguard Worker         }
975*6777b538SAndroid Build Coastguard Worker       }
976*6777b538SAndroid Build Coastguard Worker     }
977*6777b538SAndroid Build Coastguard Worker     /* The copy length is at most the metablock size, and thus expressible. */
978*6777b538SAndroid Build Coastguard Worker     GetLengthCode(last_command->insert_len_,
979*6777b538SAndroid Build Coastguard Worker                   (size_t)((int)(last_command->copy_len_ & 0x1FFFFFF) +
980*6777b538SAndroid Build Coastguard Worker                            (int)(last_command->copy_len_ >> 25)),
981*6777b538SAndroid Build Coastguard Worker                   TO_BROTLI_BOOL((last_command->dist_prefix_ & 0x3FF) == 0),
982*6777b538SAndroid Build Coastguard Worker                   &last_command->cmd_prefix_);
983*6777b538SAndroid Build Coastguard Worker   }
984*6777b538SAndroid Build Coastguard Worker }
985*6777b538SAndroid Build Coastguard Worker 
986*6777b538SAndroid Build Coastguard Worker /*
987*6777b538SAndroid Build Coastguard Worker    Processes the accumulated input data and sets |*out_size| to the length of
988*6777b538SAndroid Build Coastguard Worker    the new output meta-block, or to zero if no new output meta-block has been
989*6777b538SAndroid Build Coastguard Worker    created (in this case the processed input data is buffered internally).
990*6777b538SAndroid Build Coastguard Worker    If |*out_size| is positive, |*output| points to the start of the output
991*6777b538SAndroid Build Coastguard Worker    data. If |is_last| or |force_flush| is BROTLI_TRUE, an output meta-block is
992*6777b538SAndroid Build Coastguard Worker    always created. However, until |is_last| is BROTLI_TRUE encoder may retain up
993*6777b538SAndroid Build Coastguard Worker    to 7 bits of the last byte of output. To force encoder to dump the remaining
994*6777b538SAndroid Build Coastguard Worker    bits use WriteMetadata() to append an empty meta-data block.
995*6777b538SAndroid Build Coastguard Worker    Returns BROTLI_FALSE if the size of the input data is larger than
996*6777b538SAndroid Build Coastguard Worker    input_block_size().
997*6777b538SAndroid Build Coastguard Worker  */
EncodeData(BrotliEncoderState * s,const BROTLI_BOOL is_last,const BROTLI_BOOL force_flush,size_t * out_size,uint8_t ** output)998*6777b538SAndroid Build Coastguard Worker static BROTLI_BOOL EncodeData(
999*6777b538SAndroid Build Coastguard Worker     BrotliEncoderState* s, const BROTLI_BOOL is_last,
1000*6777b538SAndroid Build Coastguard Worker     const BROTLI_BOOL force_flush, size_t* out_size, uint8_t** output) {
1001*6777b538SAndroid Build Coastguard Worker   const uint64_t delta = UnprocessedInputSize(s);
1002*6777b538SAndroid Build Coastguard Worker   uint32_t bytes = (uint32_t)delta;
1003*6777b538SAndroid Build Coastguard Worker   uint32_t wrapped_last_processed_pos = WrapPosition(s->last_processed_pos_);
1004*6777b538SAndroid Build Coastguard Worker   uint8_t* data;
1005*6777b538SAndroid Build Coastguard Worker   uint32_t mask;
1006*6777b538SAndroid Build Coastguard Worker   MemoryManager* m = &s->memory_manager_;
1007*6777b538SAndroid Build Coastguard Worker   ContextType literal_context_mode;
1008*6777b538SAndroid Build Coastguard Worker   ContextLut literal_context_lut;
1009*6777b538SAndroid Build Coastguard Worker 
1010*6777b538SAndroid Build Coastguard Worker   data = s->ringbuffer_.buffer_;
1011*6777b538SAndroid Build Coastguard Worker   mask = s->ringbuffer_.mask_;
1012*6777b538SAndroid Build Coastguard Worker 
1013*6777b538SAndroid Build Coastguard Worker   if (s->params.quality > s->params.dictionary.max_quality) return BROTLI_FALSE;
1014*6777b538SAndroid Build Coastguard Worker   /* Adding more blocks after "last" block is forbidden. */
1015*6777b538SAndroid Build Coastguard Worker   if (s->is_last_block_emitted_) return BROTLI_FALSE;
1016*6777b538SAndroid Build Coastguard Worker   if (is_last) s->is_last_block_emitted_ = BROTLI_TRUE;
1017*6777b538SAndroid Build Coastguard Worker 
1018*6777b538SAndroid Build Coastguard Worker   if (delta > InputBlockSize(s)) {
1019*6777b538SAndroid Build Coastguard Worker     return BROTLI_FALSE;
1020*6777b538SAndroid Build Coastguard Worker   }
1021*6777b538SAndroid Build Coastguard Worker   if (s->params.quality == FAST_TWO_PASS_COMPRESSION_QUALITY &&
1022*6777b538SAndroid Build Coastguard Worker       !s->command_buf_) {
1023*6777b538SAndroid Build Coastguard Worker     s->command_buf_ =
1024*6777b538SAndroid Build Coastguard Worker         BROTLI_ALLOC(m, uint32_t, kCompressFragmentTwoPassBlockSize);
1025*6777b538SAndroid Build Coastguard Worker     s->literal_buf_ =
1026*6777b538SAndroid Build Coastguard Worker         BROTLI_ALLOC(m, uint8_t, kCompressFragmentTwoPassBlockSize);
1027*6777b538SAndroid Build Coastguard Worker     if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(s->command_buf_) ||
1028*6777b538SAndroid Build Coastguard Worker         BROTLI_IS_NULL(s->literal_buf_)) {
1029*6777b538SAndroid Build Coastguard Worker       return BROTLI_FALSE;
1030*6777b538SAndroid Build Coastguard Worker     }
1031*6777b538SAndroid Build Coastguard Worker   }
1032*6777b538SAndroid Build Coastguard Worker 
1033*6777b538SAndroid Build Coastguard Worker   if (s->params.quality == FAST_ONE_PASS_COMPRESSION_QUALITY ||
1034*6777b538SAndroid Build Coastguard Worker       s->params.quality == FAST_TWO_PASS_COMPRESSION_QUALITY) {
1035*6777b538SAndroid Build Coastguard Worker     uint8_t* storage;
1036*6777b538SAndroid Build Coastguard Worker     size_t storage_ix = s->last_bytes_bits_;
1037*6777b538SAndroid Build Coastguard Worker     size_t table_size;
1038*6777b538SAndroid Build Coastguard Worker     int* table;
1039*6777b538SAndroid Build Coastguard Worker 
1040*6777b538SAndroid Build Coastguard Worker     if (delta == 0 && !is_last) {
1041*6777b538SAndroid Build Coastguard Worker       /* We have no new input data and we don't have to finish the stream, so
1042*6777b538SAndroid Build Coastguard Worker          nothing to do. */
1043*6777b538SAndroid Build Coastguard Worker       *out_size = 0;
1044*6777b538SAndroid Build Coastguard Worker       return BROTLI_TRUE;
1045*6777b538SAndroid Build Coastguard Worker     }
1046*6777b538SAndroid Build Coastguard Worker     storage = GetBrotliStorage(s, 2 * bytes + 503);
1047*6777b538SAndroid Build Coastguard Worker     if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;
1048*6777b538SAndroid Build Coastguard Worker     storage[0] = (uint8_t)s->last_bytes_;
1049*6777b538SAndroid Build Coastguard Worker     storage[1] = (uint8_t)(s->last_bytes_ >> 8);
1050*6777b538SAndroid Build Coastguard Worker     table = GetHashTable(s, s->params.quality, bytes, &table_size);
1051*6777b538SAndroid Build Coastguard Worker     if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;
1052*6777b538SAndroid Build Coastguard Worker     if (s->params.quality == FAST_ONE_PASS_COMPRESSION_QUALITY) {
1053*6777b538SAndroid Build Coastguard Worker       BrotliCompressFragmentFast(
1054*6777b538SAndroid Build Coastguard Worker           s->one_pass_arena_, &data[wrapped_last_processed_pos & mask],
1055*6777b538SAndroid Build Coastguard Worker           bytes, is_last,
1056*6777b538SAndroid Build Coastguard Worker           table, table_size,
1057*6777b538SAndroid Build Coastguard Worker           &storage_ix, storage);
1058*6777b538SAndroid Build Coastguard Worker       if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;
1059*6777b538SAndroid Build Coastguard Worker     } else {
1060*6777b538SAndroid Build Coastguard Worker       BrotliCompressFragmentTwoPass(
1061*6777b538SAndroid Build Coastguard Worker           s->two_pass_arena_, &data[wrapped_last_processed_pos & mask],
1062*6777b538SAndroid Build Coastguard Worker           bytes, is_last,
1063*6777b538SAndroid Build Coastguard Worker           s->command_buf_, s->literal_buf_,
1064*6777b538SAndroid Build Coastguard Worker           table, table_size,
1065*6777b538SAndroid Build Coastguard Worker           &storage_ix, storage);
1066*6777b538SAndroid Build Coastguard Worker       if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;
1067*6777b538SAndroid Build Coastguard Worker     }
1068*6777b538SAndroid Build Coastguard Worker     s->last_bytes_ = (uint16_t)(storage[storage_ix >> 3]);
1069*6777b538SAndroid Build Coastguard Worker     s->last_bytes_bits_ = storage_ix & 7u;
1070*6777b538SAndroid Build Coastguard Worker     UpdateLastProcessedPos(s);
1071*6777b538SAndroid Build Coastguard Worker     *output = &storage[0];
1072*6777b538SAndroid Build Coastguard Worker     *out_size = storage_ix >> 3;
1073*6777b538SAndroid Build Coastguard Worker     return BROTLI_TRUE;
1074*6777b538SAndroid Build Coastguard Worker   }
1075*6777b538SAndroid Build Coastguard Worker 
1076*6777b538SAndroid Build Coastguard Worker   {
1077*6777b538SAndroid Build Coastguard Worker     /* Theoretical max number of commands is 1 per 2 bytes. */
1078*6777b538SAndroid Build Coastguard Worker     size_t newsize = s->num_commands_ + bytes / 2 + 1;
1079*6777b538SAndroid Build Coastguard Worker     if (newsize > s->cmd_alloc_size_) {
1080*6777b538SAndroid Build Coastguard Worker       Command* new_commands;
1081*6777b538SAndroid Build Coastguard Worker       /* Reserve a bit more memory to allow merging with a next block
1082*6777b538SAndroid Build Coastguard Worker          without reallocation: that would impact speed. */
1083*6777b538SAndroid Build Coastguard Worker       newsize += (bytes / 4) + 16;
1084*6777b538SAndroid Build Coastguard Worker       s->cmd_alloc_size_ = newsize;
1085*6777b538SAndroid Build Coastguard Worker       new_commands = BROTLI_ALLOC(m, Command, newsize);
1086*6777b538SAndroid Build Coastguard Worker       if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(new_commands)) return BROTLI_FALSE;
1087*6777b538SAndroid Build Coastguard Worker       if (s->commands_) {
1088*6777b538SAndroid Build Coastguard Worker         memcpy(new_commands, s->commands_, sizeof(Command) * s->num_commands_);
1089*6777b538SAndroid Build Coastguard Worker         BROTLI_FREE(m, s->commands_);
1090*6777b538SAndroid Build Coastguard Worker       }
1091*6777b538SAndroid Build Coastguard Worker       s->commands_ = new_commands;
1092*6777b538SAndroid Build Coastguard Worker     }
1093*6777b538SAndroid Build Coastguard Worker   }
1094*6777b538SAndroid Build Coastguard Worker 
1095*6777b538SAndroid Build Coastguard Worker   InitOrStitchToPreviousBlock(m, &s->hasher_, data, mask, &s->params,
1096*6777b538SAndroid Build Coastguard Worker       wrapped_last_processed_pos, bytes, is_last);
1097*6777b538SAndroid Build Coastguard Worker 
1098*6777b538SAndroid Build Coastguard Worker   literal_context_mode = ChooseContextMode(
1099*6777b538SAndroid Build Coastguard Worker       &s->params, data, WrapPosition(s->last_flush_pos_),
1100*6777b538SAndroid Build Coastguard Worker       mask, (size_t)(s->input_pos_ - s->last_flush_pos_));
1101*6777b538SAndroid Build Coastguard Worker   literal_context_lut = BROTLI_CONTEXT_LUT(literal_context_mode);
1102*6777b538SAndroid Build Coastguard Worker 
1103*6777b538SAndroid Build Coastguard Worker   if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;
1104*6777b538SAndroid Build Coastguard Worker 
1105*6777b538SAndroid Build Coastguard Worker   if (s->num_commands_ && s->last_insert_len_ == 0) {
1106*6777b538SAndroid Build Coastguard Worker     ExtendLastCommand(s, &bytes, &wrapped_last_processed_pos);
1107*6777b538SAndroid Build Coastguard Worker   }
1108*6777b538SAndroid Build Coastguard Worker 
1109*6777b538SAndroid Build Coastguard Worker   if (s->params.quality == ZOPFLIFICATION_QUALITY) {
1110*6777b538SAndroid Build Coastguard Worker     BROTLI_DCHECK(s->params.hasher.type == 10);
1111*6777b538SAndroid Build Coastguard Worker     BrotliCreateZopfliBackwardReferences(m, bytes, wrapped_last_processed_pos,
1112*6777b538SAndroid Build Coastguard Worker         data, mask, literal_context_lut, &s->params,
1113*6777b538SAndroid Build Coastguard Worker         &s->hasher_, s->dist_cache_,
1114*6777b538SAndroid Build Coastguard Worker         &s->last_insert_len_, &s->commands_[s->num_commands_],
1115*6777b538SAndroid Build Coastguard Worker         &s->num_commands_, &s->num_literals_);
1116*6777b538SAndroid Build Coastguard Worker     if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;
1117*6777b538SAndroid Build Coastguard Worker   } else if (s->params.quality == HQ_ZOPFLIFICATION_QUALITY) {
1118*6777b538SAndroid Build Coastguard Worker     BROTLI_DCHECK(s->params.hasher.type == 10);
1119*6777b538SAndroid Build Coastguard Worker     BrotliCreateHqZopfliBackwardReferences(m, bytes, wrapped_last_processed_pos,
1120*6777b538SAndroid Build Coastguard Worker         data, mask, literal_context_lut, &s->params,
1121*6777b538SAndroid Build Coastguard Worker         &s->hasher_, s->dist_cache_,
1122*6777b538SAndroid Build Coastguard Worker         &s->last_insert_len_, &s->commands_[s->num_commands_],
1123*6777b538SAndroid Build Coastguard Worker         &s->num_commands_, &s->num_literals_);
1124*6777b538SAndroid Build Coastguard Worker     if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;
1125*6777b538SAndroid Build Coastguard Worker   } else {
1126*6777b538SAndroid Build Coastguard Worker     BrotliCreateBackwardReferences(bytes, wrapped_last_processed_pos,
1127*6777b538SAndroid Build Coastguard Worker         data, mask, literal_context_lut, &s->params,
1128*6777b538SAndroid Build Coastguard Worker         &s->hasher_, s->dist_cache_,
1129*6777b538SAndroid Build Coastguard Worker         &s->last_insert_len_, &s->commands_[s->num_commands_],
1130*6777b538SAndroid Build Coastguard Worker         &s->num_commands_, &s->num_literals_);
1131*6777b538SAndroid Build Coastguard Worker   }
1132*6777b538SAndroid Build Coastguard Worker 
1133*6777b538SAndroid Build Coastguard Worker   {
1134*6777b538SAndroid Build Coastguard Worker     const size_t max_length = MaxMetablockSize(&s->params);
1135*6777b538SAndroid Build Coastguard Worker     const size_t max_literals = max_length / 8;
1136*6777b538SAndroid Build Coastguard Worker     const size_t max_commands = max_length / 8;
1137*6777b538SAndroid Build Coastguard Worker     const size_t processed_bytes = (size_t)(s->input_pos_ - s->last_flush_pos_);
1138*6777b538SAndroid Build Coastguard Worker     /* If maximal possible additional block doesn't fit metablock, flush now. */
1139*6777b538SAndroid Build Coastguard Worker     /* TODO(eustas): Postpone decision until next block arrives? */
1140*6777b538SAndroid Build Coastguard Worker     const BROTLI_BOOL next_input_fits_metablock = TO_BROTLI_BOOL(
1141*6777b538SAndroid Build Coastguard Worker         processed_bytes + InputBlockSize(s) <= max_length);
1142*6777b538SAndroid Build Coastguard Worker     /* If block splitting is not used, then flush as soon as there is some
1143*6777b538SAndroid Build Coastguard Worker        amount of commands / literals produced. */
1144*6777b538SAndroid Build Coastguard Worker     const BROTLI_BOOL should_flush = TO_BROTLI_BOOL(
1145*6777b538SAndroid Build Coastguard Worker         s->params.quality < MIN_QUALITY_FOR_BLOCK_SPLIT &&
1146*6777b538SAndroid Build Coastguard Worker         s->num_literals_ + s->num_commands_ >= MAX_NUM_DELAYED_SYMBOLS);
1147*6777b538SAndroid Build Coastguard Worker     if (!is_last && !force_flush && !should_flush &&
1148*6777b538SAndroid Build Coastguard Worker         next_input_fits_metablock &&
1149*6777b538SAndroid Build Coastguard Worker         s->num_literals_ < max_literals &&
1150*6777b538SAndroid Build Coastguard Worker         s->num_commands_ < max_commands) {
1151*6777b538SAndroid Build Coastguard Worker       /* Merge with next input block. Everything will happen later. */
1152*6777b538SAndroid Build Coastguard Worker       if (UpdateLastProcessedPos(s)) {
1153*6777b538SAndroid Build Coastguard Worker         HasherReset(&s->hasher_);
1154*6777b538SAndroid Build Coastguard Worker       }
1155*6777b538SAndroid Build Coastguard Worker       *out_size = 0;
1156*6777b538SAndroid Build Coastguard Worker       return BROTLI_TRUE;
1157*6777b538SAndroid Build Coastguard Worker     }
1158*6777b538SAndroid Build Coastguard Worker   }
1159*6777b538SAndroid Build Coastguard Worker 
1160*6777b538SAndroid Build Coastguard Worker   /* Create the last insert-only command. */
1161*6777b538SAndroid Build Coastguard Worker   if (s->last_insert_len_ > 0) {
1162*6777b538SAndroid Build Coastguard Worker     InitInsertCommand(&s->commands_[s->num_commands_++], s->last_insert_len_);
1163*6777b538SAndroid Build Coastguard Worker     s->num_literals_ += s->last_insert_len_;
1164*6777b538SAndroid Build Coastguard Worker     s->last_insert_len_ = 0;
1165*6777b538SAndroid Build Coastguard Worker   }
1166*6777b538SAndroid Build Coastguard Worker 
1167*6777b538SAndroid Build Coastguard Worker   if (!is_last && s->input_pos_ == s->last_flush_pos_) {
1168*6777b538SAndroid Build Coastguard Worker     /* We have no new input data and we don't have to finish the stream, so
1169*6777b538SAndroid Build Coastguard Worker        nothing to do. */
1170*6777b538SAndroid Build Coastguard Worker     *out_size = 0;
1171*6777b538SAndroid Build Coastguard Worker     return BROTLI_TRUE;
1172*6777b538SAndroid Build Coastguard Worker   }
1173*6777b538SAndroid Build Coastguard Worker   BROTLI_DCHECK(s->input_pos_ >= s->last_flush_pos_);
1174*6777b538SAndroid Build Coastguard Worker   BROTLI_DCHECK(s->input_pos_ > s->last_flush_pos_ || is_last);
1175*6777b538SAndroid Build Coastguard Worker   BROTLI_DCHECK(s->input_pos_ - s->last_flush_pos_ <= 1u << 24);
1176*6777b538SAndroid Build Coastguard Worker   {
1177*6777b538SAndroid Build Coastguard Worker     const uint32_t metablock_size =
1178*6777b538SAndroid Build Coastguard Worker         (uint32_t)(s->input_pos_ - s->last_flush_pos_);
1179*6777b538SAndroid Build Coastguard Worker     uint8_t* storage = GetBrotliStorage(s, 2 * metablock_size + 503);
1180*6777b538SAndroid Build Coastguard Worker     size_t storage_ix = s->last_bytes_bits_;
1181*6777b538SAndroid Build Coastguard Worker     if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;
1182*6777b538SAndroid Build Coastguard Worker     storage[0] = (uint8_t)s->last_bytes_;
1183*6777b538SAndroid Build Coastguard Worker     storage[1] = (uint8_t)(s->last_bytes_ >> 8);
1184*6777b538SAndroid Build Coastguard Worker     WriteMetaBlockInternal(
1185*6777b538SAndroid Build Coastguard Worker         m, data, mask, s->last_flush_pos_, metablock_size, is_last,
1186*6777b538SAndroid Build Coastguard Worker         literal_context_mode, &s->params, s->prev_byte_, s->prev_byte2_,
1187*6777b538SAndroid Build Coastguard Worker         s->num_literals_, s->num_commands_, s->commands_, s->saved_dist_cache_,
1188*6777b538SAndroid Build Coastguard Worker         s->dist_cache_, &storage_ix, storage);
1189*6777b538SAndroid Build Coastguard Worker     if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;
1190*6777b538SAndroid Build Coastguard Worker     s->last_bytes_ = (uint16_t)(storage[storage_ix >> 3]);
1191*6777b538SAndroid Build Coastguard Worker     s->last_bytes_bits_ = storage_ix & 7u;
1192*6777b538SAndroid Build Coastguard Worker     s->last_flush_pos_ = s->input_pos_;
1193*6777b538SAndroid Build Coastguard Worker     if (UpdateLastProcessedPos(s)) {
1194*6777b538SAndroid Build Coastguard Worker       HasherReset(&s->hasher_);
1195*6777b538SAndroid Build Coastguard Worker     }
1196*6777b538SAndroid Build Coastguard Worker     if (s->last_flush_pos_ > 0) {
1197*6777b538SAndroid Build Coastguard Worker       s->prev_byte_ = data[((uint32_t)s->last_flush_pos_ - 1) & mask];
1198*6777b538SAndroid Build Coastguard Worker     }
1199*6777b538SAndroid Build Coastguard Worker     if (s->last_flush_pos_ > 1) {
1200*6777b538SAndroid Build Coastguard Worker       s->prev_byte2_ = data[(uint32_t)(s->last_flush_pos_ - 2) & mask];
1201*6777b538SAndroid Build Coastguard Worker     }
1202*6777b538SAndroid Build Coastguard Worker     s->num_commands_ = 0;
1203*6777b538SAndroid Build Coastguard Worker     s->num_literals_ = 0;
1204*6777b538SAndroid Build Coastguard Worker     /* Save the state of the distance cache in case we need to restore it for
1205*6777b538SAndroid Build Coastguard Worker        emitting an uncompressed block. */
1206*6777b538SAndroid Build Coastguard Worker     memcpy(s->saved_dist_cache_, s->dist_cache_, sizeof(s->saved_dist_cache_));
1207*6777b538SAndroid Build Coastguard Worker     *output = &storage[0];
1208*6777b538SAndroid Build Coastguard Worker     *out_size = storage_ix >> 3;
1209*6777b538SAndroid Build Coastguard Worker     return BROTLI_TRUE;
1210*6777b538SAndroid Build Coastguard Worker   }
1211*6777b538SAndroid Build Coastguard Worker }
1212*6777b538SAndroid Build Coastguard Worker 
1213*6777b538SAndroid Build Coastguard Worker /* Dumps remaining output bits and metadata header to |header|.
1214*6777b538SAndroid Build Coastguard Worker    Returns number of produced bytes.
1215*6777b538SAndroid Build Coastguard Worker    REQUIRED: |header| should be 8-byte aligned and at least 16 bytes long.
1216*6777b538SAndroid Build Coastguard Worker    REQUIRED: |block_size| <= (1 << 24). */
WriteMetadataHeader(BrotliEncoderState * s,const size_t block_size,uint8_t * header)1217*6777b538SAndroid Build Coastguard Worker static size_t WriteMetadataHeader(
1218*6777b538SAndroid Build Coastguard Worker     BrotliEncoderState* s, const size_t block_size, uint8_t* header) {
1219*6777b538SAndroid Build Coastguard Worker   size_t storage_ix;
1220*6777b538SAndroid Build Coastguard Worker   storage_ix = s->last_bytes_bits_;
1221*6777b538SAndroid Build Coastguard Worker   header[0] = (uint8_t)s->last_bytes_;
1222*6777b538SAndroid Build Coastguard Worker   header[1] = (uint8_t)(s->last_bytes_ >> 8);
1223*6777b538SAndroid Build Coastguard Worker   s->last_bytes_ = 0;
1224*6777b538SAndroid Build Coastguard Worker   s->last_bytes_bits_ = 0;
1225*6777b538SAndroid Build Coastguard Worker 
1226*6777b538SAndroid Build Coastguard Worker   BrotliWriteBits(1, 0, &storage_ix, header);
1227*6777b538SAndroid Build Coastguard Worker   BrotliWriteBits(2, 3, &storage_ix, header);
1228*6777b538SAndroid Build Coastguard Worker   BrotliWriteBits(1, 0, &storage_ix, header);
1229*6777b538SAndroid Build Coastguard Worker   if (block_size == 0) {
1230*6777b538SAndroid Build Coastguard Worker     BrotliWriteBits(2, 0, &storage_ix, header);
1231*6777b538SAndroid Build Coastguard Worker   } else {
1232*6777b538SAndroid Build Coastguard Worker     uint32_t nbits = (block_size == 1) ? 0 :
1233*6777b538SAndroid Build Coastguard Worker         (Log2FloorNonZero((uint32_t)block_size - 1) + 1);
1234*6777b538SAndroid Build Coastguard Worker     uint32_t nbytes = (nbits + 7) / 8;
1235*6777b538SAndroid Build Coastguard Worker     BrotliWriteBits(2, nbytes, &storage_ix, header);
1236*6777b538SAndroid Build Coastguard Worker     BrotliWriteBits(8 * nbytes, block_size - 1, &storage_ix, header);
1237*6777b538SAndroid Build Coastguard Worker   }
1238*6777b538SAndroid Build Coastguard Worker   return (storage_ix + 7u) >> 3;
1239*6777b538SAndroid Build Coastguard Worker }
1240*6777b538SAndroid Build Coastguard Worker 
BrotliCompressBufferQuality10(int lgwin,size_t input_size,const uint8_t * input_buffer,size_t * encoded_size,uint8_t * encoded_buffer)1241*6777b538SAndroid Build Coastguard Worker static BROTLI_NOINLINE BROTLI_BOOL BrotliCompressBufferQuality10(
1242*6777b538SAndroid Build Coastguard Worker     int lgwin, size_t input_size, const uint8_t* input_buffer,
1243*6777b538SAndroid Build Coastguard Worker     size_t* encoded_size, uint8_t* encoded_buffer) {
1244*6777b538SAndroid Build Coastguard Worker   MemoryManager* m =
1245*6777b538SAndroid Build Coastguard Worker       (MemoryManager*)BrotliBootstrapAlloc(sizeof(MemoryManager), 0, 0, 0);
1246*6777b538SAndroid Build Coastguard Worker 
1247*6777b538SAndroid Build Coastguard Worker   const size_t mask = BROTLI_SIZE_MAX >> 1;
1248*6777b538SAndroid Build Coastguard Worker   int dist_cache[4] = { 4, 11, 15, 16 };
1249*6777b538SAndroid Build Coastguard Worker   int saved_dist_cache[4] = { 4, 11, 15, 16 };
1250*6777b538SAndroid Build Coastguard Worker   BROTLI_BOOL ok = BROTLI_TRUE;
1251*6777b538SAndroid Build Coastguard Worker   const size_t max_out_size = *encoded_size;
1252*6777b538SAndroid Build Coastguard Worker   size_t total_out_size = 0;
1253*6777b538SAndroid Build Coastguard Worker   uint16_t last_bytes;
1254*6777b538SAndroid Build Coastguard Worker   uint8_t last_bytes_bits;
1255*6777b538SAndroid Build Coastguard Worker 
1256*6777b538SAndroid Build Coastguard Worker   const size_t hasher_eff_size = BROTLI_MIN(size_t,
1257*6777b538SAndroid Build Coastguard Worker       input_size, BROTLI_MAX_BACKWARD_LIMIT(lgwin) + BROTLI_WINDOW_GAP);
1258*6777b538SAndroid Build Coastguard Worker 
1259*6777b538SAndroid Build Coastguard Worker   const int lgmetablock = BROTLI_MIN(int, 24, lgwin + 1);
1260*6777b538SAndroid Build Coastguard Worker   size_t max_block_size;
1261*6777b538SAndroid Build Coastguard Worker   const size_t max_metablock_size = (size_t)1 << lgmetablock;
1262*6777b538SAndroid Build Coastguard Worker   const size_t max_literals_per_metablock = max_metablock_size / 8;
1263*6777b538SAndroid Build Coastguard Worker   const size_t max_commands_per_metablock = max_metablock_size / 8;
1264*6777b538SAndroid Build Coastguard Worker   size_t metablock_start = 0;
1265*6777b538SAndroid Build Coastguard Worker   uint8_t prev_byte = 0;
1266*6777b538SAndroid Build Coastguard Worker   uint8_t prev_byte2 = 0;
1267*6777b538SAndroid Build Coastguard Worker 
1268*6777b538SAndroid Build Coastguard Worker   BrotliEncoderParams* params = NULL;
1269*6777b538SAndroid Build Coastguard Worker   Hasher* hasher = NULL;
1270*6777b538SAndroid Build Coastguard Worker 
1271*6777b538SAndroid Build Coastguard Worker   if (m == NULL) return BROTLI_FALSE;
1272*6777b538SAndroid Build Coastguard Worker   BrotliInitMemoryManager(m, 0, 0, 0);
1273*6777b538SAndroid Build Coastguard Worker   params = BROTLI_ALLOC(m, BrotliEncoderParams, 2);
1274*6777b538SAndroid Build Coastguard Worker   hasher = BROTLI_ALLOC(m, Hasher, 1);
1275*6777b538SAndroid Build Coastguard Worker   if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(params) || BROTLI_IS_NULL(hasher)) {
1276*6777b538SAndroid Build Coastguard Worker     goto oom;
1277*6777b538SAndroid Build Coastguard Worker   }
1278*6777b538SAndroid Build Coastguard Worker   BrotliEncoderInitParams(params);
1279*6777b538SAndroid Build Coastguard Worker   HasherInit(hasher);
1280*6777b538SAndroid Build Coastguard Worker 
1281*6777b538SAndroid Build Coastguard Worker   params->quality = 10;
1282*6777b538SAndroid Build Coastguard Worker   params->lgwin = lgwin;
1283*6777b538SAndroid Build Coastguard Worker   if (lgwin > BROTLI_MAX_WINDOW_BITS) {
1284*6777b538SAndroid Build Coastguard Worker     params->large_window = BROTLI_TRUE;
1285*6777b538SAndroid Build Coastguard Worker   }
1286*6777b538SAndroid Build Coastguard Worker   SanitizeParams(params);
1287*6777b538SAndroid Build Coastguard Worker   params->lgblock = ComputeLgBlock(params);
1288*6777b538SAndroid Build Coastguard Worker   ChooseDistanceParams(params);
1289*6777b538SAndroid Build Coastguard Worker   max_block_size = (size_t)1 << params->lgblock;
1290*6777b538SAndroid Build Coastguard Worker 
1291*6777b538SAndroid Build Coastguard Worker   /* Since default static dictionary is used we assume that
1292*6777b538SAndroid Build Coastguard Worker    * params->quality < params->dictionary.max_quality. */
1293*6777b538SAndroid Build Coastguard Worker 
1294*6777b538SAndroid Build Coastguard Worker   BROTLI_DCHECK(input_size <= mask + 1);
1295*6777b538SAndroid Build Coastguard Worker   EncodeWindowBits(lgwin, params->large_window, &last_bytes, &last_bytes_bits);
1296*6777b538SAndroid Build Coastguard Worker   InitOrStitchToPreviousBlock(m, hasher, input_buffer, mask, params,
1297*6777b538SAndroid Build Coastguard Worker       0, hasher_eff_size, BROTLI_TRUE);
1298*6777b538SAndroid Build Coastguard Worker   if (BROTLI_IS_OOM(m)) goto oom;
1299*6777b538SAndroid Build Coastguard Worker 
1300*6777b538SAndroid Build Coastguard Worker   while (ok && metablock_start < input_size) {
1301*6777b538SAndroid Build Coastguard Worker     const size_t metablock_end =
1302*6777b538SAndroid Build Coastguard Worker         BROTLI_MIN(size_t, input_size, metablock_start + max_metablock_size);
1303*6777b538SAndroid Build Coastguard Worker     const size_t expected_num_commands =
1304*6777b538SAndroid Build Coastguard Worker         (metablock_end - metablock_start) / 12 + 16;
1305*6777b538SAndroid Build Coastguard Worker     Command* commands = 0;
1306*6777b538SAndroid Build Coastguard Worker     size_t num_commands = 0;
1307*6777b538SAndroid Build Coastguard Worker     size_t last_insert_len = 0;
1308*6777b538SAndroid Build Coastguard Worker     size_t num_literals = 0;
1309*6777b538SAndroid Build Coastguard Worker     size_t metablock_size = 0;
1310*6777b538SAndroid Build Coastguard Worker     size_t cmd_alloc_size = 0;
1311*6777b538SAndroid Build Coastguard Worker     BROTLI_BOOL is_last;
1312*6777b538SAndroid Build Coastguard Worker     uint8_t* storage;
1313*6777b538SAndroid Build Coastguard Worker     size_t storage_ix;
1314*6777b538SAndroid Build Coastguard Worker 
1315*6777b538SAndroid Build Coastguard Worker     ContextType literal_context_mode = ChooseContextMode(params,
1316*6777b538SAndroid Build Coastguard Worker         input_buffer, metablock_start, mask, metablock_end - metablock_start);
1317*6777b538SAndroid Build Coastguard Worker     ContextLut literal_context_lut = BROTLI_CONTEXT_LUT(literal_context_mode);
1318*6777b538SAndroid Build Coastguard Worker 
1319*6777b538SAndroid Build Coastguard Worker     size_t block_start;
1320*6777b538SAndroid Build Coastguard Worker     for (block_start = metablock_start; block_start < metablock_end; ) {
1321*6777b538SAndroid Build Coastguard Worker       size_t block_size =
1322*6777b538SAndroid Build Coastguard Worker           BROTLI_MIN(size_t, metablock_end - block_start, max_block_size);
1323*6777b538SAndroid Build Coastguard Worker       ZopfliNode* nodes = BROTLI_ALLOC(m, ZopfliNode, block_size + 1);
1324*6777b538SAndroid Build Coastguard Worker       size_t path_size;
1325*6777b538SAndroid Build Coastguard Worker       size_t new_cmd_alloc_size;
1326*6777b538SAndroid Build Coastguard Worker       if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(nodes)) goto oom;
1327*6777b538SAndroid Build Coastguard Worker       BrotliInitZopfliNodes(nodes, block_size + 1);
1328*6777b538SAndroid Build Coastguard Worker       StitchToPreviousBlockH10(&hasher->privat._H10, block_size, block_start,
1329*6777b538SAndroid Build Coastguard Worker                                input_buffer, mask);
1330*6777b538SAndroid Build Coastguard Worker       path_size = BrotliZopfliComputeShortestPath(m, block_size, block_start,
1331*6777b538SAndroid Build Coastguard Worker           input_buffer, mask, literal_context_lut, params, dist_cache, hasher,
1332*6777b538SAndroid Build Coastguard Worker           nodes);
1333*6777b538SAndroid Build Coastguard Worker       if (BROTLI_IS_OOM(m)) goto oom;
1334*6777b538SAndroid Build Coastguard Worker       /* We allocate a command buffer in the first iteration of this loop that
1335*6777b538SAndroid Build Coastguard Worker          will be likely big enough for the whole metablock, so that for most
1336*6777b538SAndroid Build Coastguard Worker          inputs we will not have to reallocate in later iterations. We do the
1337*6777b538SAndroid Build Coastguard Worker          allocation here and not before the loop, because if the input is small,
1338*6777b538SAndroid Build Coastguard Worker          this will be allocated after the Zopfli cost model is freed, so this
1339*6777b538SAndroid Build Coastguard Worker          will not increase peak memory usage.
1340*6777b538SAndroid Build Coastguard Worker          TODO(eustas): If the first allocation is too small, increase command
1341*6777b538SAndroid Build Coastguard Worker          buffer size exponentially. */
1342*6777b538SAndroid Build Coastguard Worker       new_cmd_alloc_size = BROTLI_MAX(size_t, expected_num_commands,
1343*6777b538SAndroid Build Coastguard Worker                                       num_commands + path_size + 1);
1344*6777b538SAndroid Build Coastguard Worker       if (cmd_alloc_size != new_cmd_alloc_size) {
1345*6777b538SAndroid Build Coastguard Worker         Command* new_commands = BROTLI_ALLOC(m, Command, new_cmd_alloc_size);
1346*6777b538SAndroid Build Coastguard Worker         if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(new_commands)) goto oom;
1347*6777b538SAndroid Build Coastguard Worker         cmd_alloc_size = new_cmd_alloc_size;
1348*6777b538SAndroid Build Coastguard Worker         if (commands) {
1349*6777b538SAndroid Build Coastguard Worker           memcpy(new_commands, commands, sizeof(Command) * num_commands);
1350*6777b538SAndroid Build Coastguard Worker           BROTLI_FREE(m, commands);
1351*6777b538SAndroid Build Coastguard Worker         }
1352*6777b538SAndroid Build Coastguard Worker         commands = new_commands;
1353*6777b538SAndroid Build Coastguard Worker       }
1354*6777b538SAndroid Build Coastguard Worker       BrotliZopfliCreateCommands(block_size, block_start, &nodes[0], dist_cache,
1355*6777b538SAndroid Build Coastguard Worker           &last_insert_len, params, &commands[num_commands], &num_literals);
1356*6777b538SAndroid Build Coastguard Worker       num_commands += path_size;
1357*6777b538SAndroid Build Coastguard Worker       block_start += block_size;
1358*6777b538SAndroid Build Coastguard Worker       metablock_size += block_size;
1359*6777b538SAndroid Build Coastguard Worker       BROTLI_FREE(m, nodes);
1360*6777b538SAndroid Build Coastguard Worker       if (num_literals > max_literals_per_metablock ||
1361*6777b538SAndroid Build Coastguard Worker           num_commands > max_commands_per_metablock) {
1362*6777b538SAndroid Build Coastguard Worker         break;
1363*6777b538SAndroid Build Coastguard Worker       }
1364*6777b538SAndroid Build Coastguard Worker     }
1365*6777b538SAndroid Build Coastguard Worker 
1366*6777b538SAndroid Build Coastguard Worker     if (last_insert_len > 0) {
1367*6777b538SAndroid Build Coastguard Worker       InitInsertCommand(&commands[num_commands++], last_insert_len);
1368*6777b538SAndroid Build Coastguard Worker       num_literals += last_insert_len;
1369*6777b538SAndroid Build Coastguard Worker     }
1370*6777b538SAndroid Build Coastguard Worker 
1371*6777b538SAndroid Build Coastguard Worker     is_last = TO_BROTLI_BOOL(metablock_start + metablock_size == input_size);
1372*6777b538SAndroid Build Coastguard Worker     storage = NULL;
1373*6777b538SAndroid Build Coastguard Worker     storage_ix = last_bytes_bits;
1374*6777b538SAndroid Build Coastguard Worker 
1375*6777b538SAndroid Build Coastguard Worker     if (metablock_size == 0) {
1376*6777b538SAndroid Build Coastguard Worker       /* Write the ISLAST and ISEMPTY bits. */
1377*6777b538SAndroid Build Coastguard Worker       storage = BROTLI_ALLOC(m, uint8_t, 16);
1378*6777b538SAndroid Build Coastguard Worker       if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(storage)) goto oom;
1379*6777b538SAndroid Build Coastguard Worker       storage[0] = (uint8_t)last_bytes;
1380*6777b538SAndroid Build Coastguard Worker       storage[1] = (uint8_t)(last_bytes >> 8);
1381*6777b538SAndroid Build Coastguard Worker       BrotliWriteBits(2, 3, &storage_ix, storage);
1382*6777b538SAndroid Build Coastguard Worker       storage_ix = (storage_ix + 7u) & ~7u;
1383*6777b538SAndroid Build Coastguard Worker     } else if (!ShouldCompress(input_buffer, mask, metablock_start,
1384*6777b538SAndroid Build Coastguard Worker                                metablock_size, num_literals, num_commands)) {
1385*6777b538SAndroid Build Coastguard Worker       /* Restore the distance cache, as its last update by
1386*6777b538SAndroid Build Coastguard Worker          CreateBackwardReferences is now unused. */
1387*6777b538SAndroid Build Coastguard Worker       memcpy(dist_cache, saved_dist_cache, 4 * sizeof(dist_cache[0]));
1388*6777b538SAndroid Build Coastguard Worker       storage = BROTLI_ALLOC(m, uint8_t, metablock_size + 16);
1389*6777b538SAndroid Build Coastguard Worker       if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(storage)) goto oom;
1390*6777b538SAndroid Build Coastguard Worker       storage[0] = (uint8_t)last_bytes;
1391*6777b538SAndroid Build Coastguard Worker       storage[1] = (uint8_t)(last_bytes >> 8);
1392*6777b538SAndroid Build Coastguard Worker       BrotliStoreUncompressedMetaBlock(is_last, input_buffer,
1393*6777b538SAndroid Build Coastguard Worker                                        metablock_start, mask, metablock_size,
1394*6777b538SAndroid Build Coastguard Worker                                        &storage_ix, storage);
1395*6777b538SAndroid Build Coastguard Worker     } else {
1396*6777b538SAndroid Build Coastguard Worker       MetaBlockSplit mb;
1397*6777b538SAndroid Build Coastguard Worker       BrotliEncoderParams* block_params = params + 1;
1398*6777b538SAndroid Build Coastguard Worker       *block_params = *params;  /* shallow copy */
1399*6777b538SAndroid Build Coastguard Worker       InitMetaBlockSplit(&mb);
1400*6777b538SAndroid Build Coastguard Worker       BrotliBuildMetaBlock(m, input_buffer, metablock_start, mask,
1401*6777b538SAndroid Build Coastguard Worker                            block_params,
1402*6777b538SAndroid Build Coastguard Worker                            prev_byte, prev_byte2,
1403*6777b538SAndroid Build Coastguard Worker                            commands, num_commands,
1404*6777b538SAndroid Build Coastguard Worker                            literal_context_mode,
1405*6777b538SAndroid Build Coastguard Worker                            &mb);
1406*6777b538SAndroid Build Coastguard Worker       if (BROTLI_IS_OOM(m)) goto oom;
1407*6777b538SAndroid Build Coastguard Worker       {
1408*6777b538SAndroid Build Coastguard Worker         /* The number of distance symbols effectively used for distance
1409*6777b538SAndroid Build Coastguard Worker            histograms. It might be less than distance alphabet size
1410*6777b538SAndroid Build Coastguard Worker            for "Large Window Brotli" (32-bit). */
1411*6777b538SAndroid Build Coastguard Worker         BrotliOptimizeHistograms(block_params->dist.alphabet_size_limit, &mb);
1412*6777b538SAndroid Build Coastguard Worker       }
1413*6777b538SAndroid Build Coastguard Worker       storage = BROTLI_ALLOC(m, uint8_t, 2 * metablock_size + 503);
1414*6777b538SAndroid Build Coastguard Worker       if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(storage)) goto oom;
1415*6777b538SAndroid Build Coastguard Worker       storage[0] = (uint8_t)last_bytes;
1416*6777b538SAndroid Build Coastguard Worker       storage[1] = (uint8_t)(last_bytes >> 8);
1417*6777b538SAndroid Build Coastguard Worker       BrotliStoreMetaBlock(m, input_buffer, metablock_start, metablock_size,
1418*6777b538SAndroid Build Coastguard Worker                            mask, prev_byte, prev_byte2,
1419*6777b538SAndroid Build Coastguard Worker                            is_last,
1420*6777b538SAndroid Build Coastguard Worker                            block_params,
1421*6777b538SAndroid Build Coastguard Worker                            literal_context_mode,
1422*6777b538SAndroid Build Coastguard Worker                            commands, num_commands,
1423*6777b538SAndroid Build Coastguard Worker                            &mb,
1424*6777b538SAndroid Build Coastguard Worker                            &storage_ix, storage);
1425*6777b538SAndroid Build Coastguard Worker       if (BROTLI_IS_OOM(m)) goto oom;
1426*6777b538SAndroid Build Coastguard Worker       if (metablock_size + 4 < (storage_ix >> 3)) {
1427*6777b538SAndroid Build Coastguard Worker         /* Restore the distance cache and last byte. */
1428*6777b538SAndroid Build Coastguard Worker         memcpy(dist_cache, saved_dist_cache, 4 * sizeof(dist_cache[0]));
1429*6777b538SAndroid Build Coastguard Worker         storage[0] = (uint8_t)last_bytes;
1430*6777b538SAndroid Build Coastguard Worker         storage[1] = (uint8_t)(last_bytes >> 8);
1431*6777b538SAndroid Build Coastguard Worker         storage_ix = last_bytes_bits;
1432*6777b538SAndroid Build Coastguard Worker         BrotliStoreUncompressedMetaBlock(is_last, input_buffer,
1433*6777b538SAndroid Build Coastguard Worker                                          metablock_start, mask,
1434*6777b538SAndroid Build Coastguard Worker                                          metablock_size, &storage_ix, storage);
1435*6777b538SAndroid Build Coastguard Worker       }
1436*6777b538SAndroid Build Coastguard Worker       DestroyMetaBlockSplit(m, &mb);
1437*6777b538SAndroid Build Coastguard Worker     }
1438*6777b538SAndroid Build Coastguard Worker     last_bytes = (uint16_t)(storage[storage_ix >> 3]);
1439*6777b538SAndroid Build Coastguard Worker     last_bytes_bits = storage_ix & 7u;
1440*6777b538SAndroid Build Coastguard Worker     metablock_start += metablock_size;
1441*6777b538SAndroid Build Coastguard Worker     if (metablock_start < input_size) {
1442*6777b538SAndroid Build Coastguard Worker       prev_byte = input_buffer[metablock_start - 1];
1443*6777b538SAndroid Build Coastguard Worker       prev_byte2 = input_buffer[metablock_start - 2];
1444*6777b538SAndroid Build Coastguard Worker     }
1445*6777b538SAndroid Build Coastguard Worker     /* Save the state of the distance cache in case we need to restore it for
1446*6777b538SAndroid Build Coastguard Worker        emitting an uncompressed block. */
1447*6777b538SAndroid Build Coastguard Worker     memcpy(saved_dist_cache, dist_cache, 4 * sizeof(dist_cache[0]));
1448*6777b538SAndroid Build Coastguard Worker 
1449*6777b538SAndroid Build Coastguard Worker     {
1450*6777b538SAndroid Build Coastguard Worker       const size_t out_size = storage_ix >> 3;
1451*6777b538SAndroid Build Coastguard Worker       total_out_size += out_size;
1452*6777b538SAndroid Build Coastguard Worker       if (total_out_size <= max_out_size) {
1453*6777b538SAndroid Build Coastguard Worker         memcpy(encoded_buffer, storage, out_size);
1454*6777b538SAndroid Build Coastguard Worker         encoded_buffer += out_size;
1455*6777b538SAndroid Build Coastguard Worker       } else {
1456*6777b538SAndroid Build Coastguard Worker         ok = BROTLI_FALSE;
1457*6777b538SAndroid Build Coastguard Worker       }
1458*6777b538SAndroid Build Coastguard Worker     }
1459*6777b538SAndroid Build Coastguard Worker     BROTLI_FREE(m, storage);
1460*6777b538SAndroid Build Coastguard Worker     BROTLI_FREE(m, commands);
1461*6777b538SAndroid Build Coastguard Worker   }
1462*6777b538SAndroid Build Coastguard Worker 
1463*6777b538SAndroid Build Coastguard Worker   *encoded_size = total_out_size;
1464*6777b538SAndroid Build Coastguard Worker   DestroyHasher(m, hasher);
1465*6777b538SAndroid Build Coastguard Worker   BROTLI_FREE(m, hasher);
1466*6777b538SAndroid Build Coastguard Worker   BrotliEncoderCleanupParams(m, params);
1467*6777b538SAndroid Build Coastguard Worker   BROTLI_FREE(m, params);
1468*6777b538SAndroid Build Coastguard Worker   BrotliBootstrapFree(m, m);
1469*6777b538SAndroid Build Coastguard Worker   return ok;
1470*6777b538SAndroid Build Coastguard Worker 
1471*6777b538SAndroid Build Coastguard Worker oom:
1472*6777b538SAndroid Build Coastguard Worker   BrotliWipeOutMemoryManager(m);
1473*6777b538SAndroid Build Coastguard Worker   BrotliBootstrapFree(m, m);
1474*6777b538SAndroid Build Coastguard Worker   return BROTLI_FALSE;
1475*6777b538SAndroid Build Coastguard Worker }
1476*6777b538SAndroid Build Coastguard Worker 
BrotliEncoderMaxCompressedSize(size_t input_size)1477*6777b538SAndroid Build Coastguard Worker size_t BrotliEncoderMaxCompressedSize(size_t input_size) {
1478*6777b538SAndroid Build Coastguard Worker   /* [window bits / empty metadata] + N * [uncompressed] + [last empty] */
1479*6777b538SAndroid Build Coastguard Worker   size_t num_large_blocks = input_size >> 14;
1480*6777b538SAndroid Build Coastguard Worker   size_t overhead = 2 + (4 * num_large_blocks) + 3 + 1;
1481*6777b538SAndroid Build Coastguard Worker   size_t result = input_size + overhead;
1482*6777b538SAndroid Build Coastguard Worker   if (input_size == 0) return 2;
1483*6777b538SAndroid Build Coastguard Worker   return (result < input_size) ? 0 : result;
1484*6777b538SAndroid Build Coastguard Worker }
1485*6777b538SAndroid Build Coastguard Worker 
1486*6777b538SAndroid Build Coastguard Worker /* Wraps data to uncompressed brotli stream with minimal window size.
1487*6777b538SAndroid Build Coastguard Worker    |output| should point at region with at least BrotliEncoderMaxCompressedSize
1488*6777b538SAndroid Build Coastguard Worker    addressable bytes.
1489*6777b538SAndroid Build Coastguard Worker    Returns the length of stream. */
MakeUncompressedStream(const uint8_t * input,size_t input_size,uint8_t * output)1490*6777b538SAndroid Build Coastguard Worker static size_t MakeUncompressedStream(
1491*6777b538SAndroid Build Coastguard Worker     const uint8_t* input, size_t input_size, uint8_t* output) {
1492*6777b538SAndroid Build Coastguard Worker   size_t size = input_size;
1493*6777b538SAndroid Build Coastguard Worker   size_t result = 0;
1494*6777b538SAndroid Build Coastguard Worker   size_t offset = 0;
1495*6777b538SAndroid Build Coastguard Worker   if (input_size == 0) {
1496*6777b538SAndroid Build Coastguard Worker     output[0] = 6;
1497*6777b538SAndroid Build Coastguard Worker     return 1;
1498*6777b538SAndroid Build Coastguard Worker   }
1499*6777b538SAndroid Build Coastguard Worker   output[result++] = 0x21;  /* window bits = 10, is_last = false */
1500*6777b538SAndroid Build Coastguard Worker   output[result++] = 0x03;  /* empty metadata, padding */
1501*6777b538SAndroid Build Coastguard Worker   while (size > 0) {
1502*6777b538SAndroid Build Coastguard Worker     uint32_t nibbles = 0;
1503*6777b538SAndroid Build Coastguard Worker     uint32_t chunk_size;
1504*6777b538SAndroid Build Coastguard Worker     uint32_t bits;
1505*6777b538SAndroid Build Coastguard Worker     chunk_size = (size > (1u << 24)) ? (1u << 24) : (uint32_t)size;
1506*6777b538SAndroid Build Coastguard Worker     if (chunk_size > (1u << 16)) nibbles = (chunk_size > (1u << 20)) ? 2 : 1;
1507*6777b538SAndroid Build Coastguard Worker     bits =
1508*6777b538SAndroid Build Coastguard Worker         (nibbles << 1) | ((chunk_size - 1) << 3) | (1u << (19 + 4 * nibbles));
1509*6777b538SAndroid Build Coastguard Worker     output[result++] = (uint8_t)bits;
1510*6777b538SAndroid Build Coastguard Worker     output[result++] = (uint8_t)(bits >> 8);
1511*6777b538SAndroid Build Coastguard Worker     output[result++] = (uint8_t)(bits >> 16);
1512*6777b538SAndroid Build Coastguard Worker     if (nibbles == 2) output[result++] = (uint8_t)(bits >> 24);
1513*6777b538SAndroid Build Coastguard Worker     memcpy(&output[result], &input[offset], chunk_size);
1514*6777b538SAndroid Build Coastguard Worker     result += chunk_size;
1515*6777b538SAndroid Build Coastguard Worker     offset += chunk_size;
1516*6777b538SAndroid Build Coastguard Worker     size -= chunk_size;
1517*6777b538SAndroid Build Coastguard Worker   }
1518*6777b538SAndroid Build Coastguard Worker   output[result++] = 3;
1519*6777b538SAndroid Build Coastguard Worker   return result;
1520*6777b538SAndroid Build Coastguard Worker }
1521*6777b538SAndroid Build Coastguard Worker 
BrotliEncoderCompress(int quality,int lgwin,BrotliEncoderMode mode,size_t input_size,const uint8_t input_buffer[BROTLI_ARRAY_PARAM (input_size)],size_t * encoded_size,uint8_t encoded_buffer[BROTLI_ARRAY_PARAM (* encoded_size)])1522*6777b538SAndroid Build Coastguard Worker BROTLI_BOOL BrotliEncoderCompress(
1523*6777b538SAndroid Build Coastguard Worker     int quality, int lgwin, BrotliEncoderMode mode, size_t input_size,
1524*6777b538SAndroid Build Coastguard Worker     const uint8_t input_buffer[BROTLI_ARRAY_PARAM(input_size)],
1525*6777b538SAndroid Build Coastguard Worker     size_t* encoded_size,
1526*6777b538SAndroid Build Coastguard Worker     uint8_t encoded_buffer[BROTLI_ARRAY_PARAM(*encoded_size)]) {
1527*6777b538SAndroid Build Coastguard Worker   BrotliEncoderState* s;
1528*6777b538SAndroid Build Coastguard Worker   size_t out_size = *encoded_size;
1529*6777b538SAndroid Build Coastguard Worker   const uint8_t* input_start = input_buffer;
1530*6777b538SAndroid Build Coastguard Worker   uint8_t* output_start = encoded_buffer;
1531*6777b538SAndroid Build Coastguard Worker   size_t max_out_size = BrotliEncoderMaxCompressedSize(input_size);
1532*6777b538SAndroid Build Coastguard Worker   if (out_size == 0) {
1533*6777b538SAndroid Build Coastguard Worker     /* Output buffer needs at least one byte. */
1534*6777b538SAndroid Build Coastguard Worker     return BROTLI_FALSE;
1535*6777b538SAndroid Build Coastguard Worker   }
1536*6777b538SAndroid Build Coastguard Worker   if (input_size == 0) {
1537*6777b538SAndroid Build Coastguard Worker     /* Handle the special case of empty input. */
1538*6777b538SAndroid Build Coastguard Worker     *encoded_size = 1;
1539*6777b538SAndroid Build Coastguard Worker     *encoded_buffer = 6;
1540*6777b538SAndroid Build Coastguard Worker     return BROTLI_TRUE;
1541*6777b538SAndroid Build Coastguard Worker   }
1542*6777b538SAndroid Build Coastguard Worker   if (quality == 10) {
1543*6777b538SAndroid Build Coastguard Worker     /* TODO(eustas): Implement this direct path for all quality levels. */
1544*6777b538SAndroid Build Coastguard Worker     const int lg_win = BROTLI_MIN(int, BROTLI_LARGE_MAX_WINDOW_BITS,
1545*6777b538SAndroid Build Coastguard Worker                                        BROTLI_MAX(int, 16, lgwin));
1546*6777b538SAndroid Build Coastguard Worker     int ok = BrotliCompressBufferQuality10(lg_win, input_size, input_buffer,
1547*6777b538SAndroid Build Coastguard Worker                                            encoded_size, encoded_buffer);
1548*6777b538SAndroid Build Coastguard Worker     if (!ok || (max_out_size && *encoded_size > max_out_size)) {
1549*6777b538SAndroid Build Coastguard Worker       goto fallback;
1550*6777b538SAndroid Build Coastguard Worker     }
1551*6777b538SAndroid Build Coastguard Worker     return BROTLI_TRUE;
1552*6777b538SAndroid Build Coastguard Worker   }
1553*6777b538SAndroid Build Coastguard Worker 
1554*6777b538SAndroid Build Coastguard Worker   s = BrotliEncoderCreateInstance(0, 0, 0);
1555*6777b538SAndroid Build Coastguard Worker   if (!s) {
1556*6777b538SAndroid Build Coastguard Worker     return BROTLI_FALSE;
1557*6777b538SAndroid Build Coastguard Worker   } else {
1558*6777b538SAndroid Build Coastguard Worker     size_t available_in = input_size;
1559*6777b538SAndroid Build Coastguard Worker     const uint8_t* next_in = input_buffer;
1560*6777b538SAndroid Build Coastguard Worker     size_t available_out = *encoded_size;
1561*6777b538SAndroid Build Coastguard Worker     uint8_t* next_out = encoded_buffer;
1562*6777b538SAndroid Build Coastguard Worker     size_t total_out = 0;
1563*6777b538SAndroid Build Coastguard Worker     BROTLI_BOOL result = BROTLI_FALSE;
1564*6777b538SAndroid Build Coastguard Worker     BrotliEncoderSetParameter(s, BROTLI_PARAM_QUALITY, (uint32_t)quality);
1565*6777b538SAndroid Build Coastguard Worker     BrotliEncoderSetParameter(s, BROTLI_PARAM_LGWIN, (uint32_t)lgwin);
1566*6777b538SAndroid Build Coastguard Worker     BrotliEncoderSetParameter(s, BROTLI_PARAM_MODE, (uint32_t)mode);
1567*6777b538SAndroid Build Coastguard Worker     BrotliEncoderSetParameter(s, BROTLI_PARAM_SIZE_HINT, (uint32_t)input_size);
1568*6777b538SAndroid Build Coastguard Worker     if (lgwin > BROTLI_MAX_WINDOW_BITS) {
1569*6777b538SAndroid Build Coastguard Worker       BrotliEncoderSetParameter(s, BROTLI_PARAM_LARGE_WINDOW, BROTLI_TRUE);
1570*6777b538SAndroid Build Coastguard Worker     }
1571*6777b538SAndroid Build Coastguard Worker     result = BrotliEncoderCompressStream(s, BROTLI_OPERATION_FINISH,
1572*6777b538SAndroid Build Coastguard Worker         &available_in, &next_in, &available_out, &next_out, &total_out);
1573*6777b538SAndroid Build Coastguard Worker     if (!BrotliEncoderIsFinished(s)) result = 0;
1574*6777b538SAndroid Build Coastguard Worker     *encoded_size = total_out;
1575*6777b538SAndroid Build Coastguard Worker     BrotliEncoderDestroyInstance(s);
1576*6777b538SAndroid Build Coastguard Worker     if (!result || (max_out_size && *encoded_size > max_out_size)) {
1577*6777b538SAndroid Build Coastguard Worker       goto fallback;
1578*6777b538SAndroid Build Coastguard Worker     }
1579*6777b538SAndroid Build Coastguard Worker     return BROTLI_TRUE;
1580*6777b538SAndroid Build Coastguard Worker   }
1581*6777b538SAndroid Build Coastguard Worker fallback:
1582*6777b538SAndroid Build Coastguard Worker   *encoded_size = 0;
1583*6777b538SAndroid Build Coastguard Worker   if (!max_out_size) return BROTLI_FALSE;
1584*6777b538SAndroid Build Coastguard Worker   if (out_size >= max_out_size) {
1585*6777b538SAndroid Build Coastguard Worker     *encoded_size =
1586*6777b538SAndroid Build Coastguard Worker         MakeUncompressedStream(input_start, input_size, output_start);
1587*6777b538SAndroid Build Coastguard Worker     return BROTLI_TRUE;
1588*6777b538SAndroid Build Coastguard Worker   }
1589*6777b538SAndroid Build Coastguard Worker   return BROTLI_FALSE;
1590*6777b538SAndroid Build Coastguard Worker }
1591*6777b538SAndroid Build Coastguard Worker 
InjectBytePaddingBlock(BrotliEncoderState * s)1592*6777b538SAndroid Build Coastguard Worker static void InjectBytePaddingBlock(BrotliEncoderState* s) {
1593*6777b538SAndroid Build Coastguard Worker   uint32_t seal = s->last_bytes_;
1594*6777b538SAndroid Build Coastguard Worker   size_t seal_bits = s->last_bytes_bits_;
1595*6777b538SAndroid Build Coastguard Worker   uint8_t* destination;
1596*6777b538SAndroid Build Coastguard Worker   s->last_bytes_ = 0;
1597*6777b538SAndroid Build Coastguard Worker   s->last_bytes_bits_ = 0;
1598*6777b538SAndroid Build Coastguard Worker   /* is_last = 0, data_nibbles = 11, reserved = 0, meta_nibbles = 00 */
1599*6777b538SAndroid Build Coastguard Worker   seal |= 0x6u << seal_bits;
1600*6777b538SAndroid Build Coastguard Worker   seal_bits += 6;
1601*6777b538SAndroid Build Coastguard Worker   /* If we have already created storage, then append to it.
1602*6777b538SAndroid Build Coastguard Worker      Storage is valid until next block is being compressed. */
1603*6777b538SAndroid Build Coastguard Worker   if (s->next_out_) {
1604*6777b538SAndroid Build Coastguard Worker     destination = s->next_out_ + s->available_out_;
1605*6777b538SAndroid Build Coastguard Worker   } else {
1606*6777b538SAndroid Build Coastguard Worker     destination = s->tiny_buf_.u8;
1607*6777b538SAndroid Build Coastguard Worker     s->next_out_ = destination;
1608*6777b538SAndroid Build Coastguard Worker   }
1609*6777b538SAndroid Build Coastguard Worker   destination[0] = (uint8_t)seal;
1610*6777b538SAndroid Build Coastguard Worker   if (seal_bits > 8) destination[1] = (uint8_t)(seal >> 8);
1611*6777b538SAndroid Build Coastguard Worker   if (seal_bits > 16) destination[2] = (uint8_t)(seal >> 16);
1612*6777b538SAndroid Build Coastguard Worker   s->available_out_ += (seal_bits + 7) >> 3;
1613*6777b538SAndroid Build Coastguard Worker }
1614*6777b538SAndroid Build Coastguard Worker 
1615*6777b538SAndroid Build Coastguard Worker /* Injects padding bits or pushes compressed data to output.
1616*6777b538SAndroid Build Coastguard Worker    Returns false if nothing is done. */
InjectFlushOrPushOutput(BrotliEncoderState * s,size_t * available_out,uint8_t ** next_out,size_t * total_out)1617*6777b538SAndroid Build Coastguard Worker static BROTLI_BOOL InjectFlushOrPushOutput(BrotliEncoderState* s,
1618*6777b538SAndroid Build Coastguard Worker     size_t* available_out, uint8_t** next_out, size_t* total_out) {
1619*6777b538SAndroid Build Coastguard Worker   if (s->stream_state_ == BROTLI_STREAM_FLUSH_REQUESTED &&
1620*6777b538SAndroid Build Coastguard Worker       s->last_bytes_bits_ != 0) {
1621*6777b538SAndroid Build Coastguard Worker     InjectBytePaddingBlock(s);
1622*6777b538SAndroid Build Coastguard Worker     return BROTLI_TRUE;
1623*6777b538SAndroid Build Coastguard Worker   }
1624*6777b538SAndroid Build Coastguard Worker 
1625*6777b538SAndroid Build Coastguard Worker   if (s->available_out_ != 0 && *available_out != 0) {
1626*6777b538SAndroid Build Coastguard Worker     size_t copy_output_size =
1627*6777b538SAndroid Build Coastguard Worker         BROTLI_MIN(size_t, s->available_out_, *available_out);
1628*6777b538SAndroid Build Coastguard Worker     memcpy(*next_out, s->next_out_, copy_output_size);
1629*6777b538SAndroid Build Coastguard Worker     *next_out += copy_output_size;
1630*6777b538SAndroid Build Coastguard Worker     *available_out -= copy_output_size;
1631*6777b538SAndroid Build Coastguard Worker     s->next_out_ += copy_output_size;
1632*6777b538SAndroid Build Coastguard Worker     s->available_out_ -= copy_output_size;
1633*6777b538SAndroid Build Coastguard Worker     s->total_out_ += copy_output_size;
1634*6777b538SAndroid Build Coastguard Worker     if (total_out) *total_out = s->total_out_;
1635*6777b538SAndroid Build Coastguard Worker     return BROTLI_TRUE;
1636*6777b538SAndroid Build Coastguard Worker   }
1637*6777b538SAndroid Build Coastguard Worker 
1638*6777b538SAndroid Build Coastguard Worker   return BROTLI_FALSE;
1639*6777b538SAndroid Build Coastguard Worker }
1640*6777b538SAndroid Build Coastguard Worker 
CheckFlushComplete(BrotliEncoderState * s)1641*6777b538SAndroid Build Coastguard Worker static void CheckFlushComplete(BrotliEncoderState* s) {
1642*6777b538SAndroid Build Coastguard Worker   if (s->stream_state_ == BROTLI_STREAM_FLUSH_REQUESTED &&
1643*6777b538SAndroid Build Coastguard Worker       s->available_out_ == 0) {
1644*6777b538SAndroid Build Coastguard Worker     s->stream_state_ = BROTLI_STREAM_PROCESSING;
1645*6777b538SAndroid Build Coastguard Worker     s->next_out_ = 0;
1646*6777b538SAndroid Build Coastguard Worker   }
1647*6777b538SAndroid Build Coastguard Worker }
1648*6777b538SAndroid Build Coastguard Worker 
BrotliEncoderCompressStreamFast(BrotliEncoderState * s,BrotliEncoderOperation op,size_t * available_in,const uint8_t ** next_in,size_t * available_out,uint8_t ** next_out,size_t * total_out)1649*6777b538SAndroid Build Coastguard Worker static BROTLI_BOOL BrotliEncoderCompressStreamFast(
1650*6777b538SAndroid Build Coastguard Worker     BrotliEncoderState* s, BrotliEncoderOperation op, size_t* available_in,
1651*6777b538SAndroid Build Coastguard Worker     const uint8_t** next_in, size_t* available_out, uint8_t** next_out,
1652*6777b538SAndroid Build Coastguard Worker     size_t* total_out) {
1653*6777b538SAndroid Build Coastguard Worker   const size_t block_size_limit = (size_t)1 << s->params.lgwin;
1654*6777b538SAndroid Build Coastguard Worker   const size_t buf_size = BROTLI_MIN(size_t, kCompressFragmentTwoPassBlockSize,
1655*6777b538SAndroid Build Coastguard Worker       BROTLI_MIN(size_t, *available_in, block_size_limit));
1656*6777b538SAndroid Build Coastguard Worker   uint32_t* tmp_command_buf = NULL;
1657*6777b538SAndroid Build Coastguard Worker   uint32_t* command_buf = NULL;
1658*6777b538SAndroid Build Coastguard Worker   uint8_t* tmp_literal_buf = NULL;
1659*6777b538SAndroid Build Coastguard Worker   uint8_t* literal_buf = NULL;
1660*6777b538SAndroid Build Coastguard Worker   MemoryManager* m = &s->memory_manager_;
1661*6777b538SAndroid Build Coastguard Worker   if (s->params.quality != FAST_ONE_PASS_COMPRESSION_QUALITY &&
1662*6777b538SAndroid Build Coastguard Worker       s->params.quality != FAST_TWO_PASS_COMPRESSION_QUALITY) {
1663*6777b538SAndroid Build Coastguard Worker     return BROTLI_FALSE;
1664*6777b538SAndroid Build Coastguard Worker   }
1665*6777b538SAndroid Build Coastguard Worker   if (s->params.quality == FAST_TWO_PASS_COMPRESSION_QUALITY) {
1666*6777b538SAndroid Build Coastguard Worker     if (!s->command_buf_ && buf_size == kCompressFragmentTwoPassBlockSize) {
1667*6777b538SAndroid Build Coastguard Worker       s->command_buf_ =
1668*6777b538SAndroid Build Coastguard Worker           BROTLI_ALLOC(m, uint32_t, kCompressFragmentTwoPassBlockSize);
1669*6777b538SAndroid Build Coastguard Worker       s->literal_buf_ =
1670*6777b538SAndroid Build Coastguard Worker           BROTLI_ALLOC(m, uint8_t, kCompressFragmentTwoPassBlockSize);
1671*6777b538SAndroid Build Coastguard Worker       if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(s->command_buf_) ||
1672*6777b538SAndroid Build Coastguard Worker           BROTLI_IS_NULL(s->literal_buf_)) {
1673*6777b538SAndroid Build Coastguard Worker         return BROTLI_FALSE;
1674*6777b538SAndroid Build Coastguard Worker       }
1675*6777b538SAndroid Build Coastguard Worker     }
1676*6777b538SAndroid Build Coastguard Worker     if (s->command_buf_) {
1677*6777b538SAndroid Build Coastguard Worker       command_buf = s->command_buf_;
1678*6777b538SAndroid Build Coastguard Worker       literal_buf = s->literal_buf_;
1679*6777b538SAndroid Build Coastguard Worker     } else {
1680*6777b538SAndroid Build Coastguard Worker       tmp_command_buf = BROTLI_ALLOC(m, uint32_t, buf_size);
1681*6777b538SAndroid Build Coastguard Worker       tmp_literal_buf = BROTLI_ALLOC(m, uint8_t, buf_size);
1682*6777b538SAndroid Build Coastguard Worker       if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(tmp_command_buf) ||
1683*6777b538SAndroid Build Coastguard Worker           BROTLI_IS_NULL(tmp_literal_buf)) {
1684*6777b538SAndroid Build Coastguard Worker         return BROTLI_FALSE;
1685*6777b538SAndroid Build Coastguard Worker       }
1686*6777b538SAndroid Build Coastguard Worker       command_buf = tmp_command_buf;
1687*6777b538SAndroid Build Coastguard Worker       literal_buf = tmp_literal_buf;
1688*6777b538SAndroid Build Coastguard Worker     }
1689*6777b538SAndroid Build Coastguard Worker   }
1690*6777b538SAndroid Build Coastguard Worker 
1691*6777b538SAndroid Build Coastguard Worker   while (BROTLI_TRUE) {
1692*6777b538SAndroid Build Coastguard Worker     if (InjectFlushOrPushOutput(s, available_out, next_out, total_out)) {
1693*6777b538SAndroid Build Coastguard Worker       continue;
1694*6777b538SAndroid Build Coastguard Worker     }
1695*6777b538SAndroid Build Coastguard Worker 
1696*6777b538SAndroid Build Coastguard Worker     /* Compress block only when internal output buffer is empty, stream is not
1697*6777b538SAndroid Build Coastguard Worker        finished, there is no pending flush request, and there is either
1698*6777b538SAndroid Build Coastguard Worker        additional input or pending operation. */
1699*6777b538SAndroid Build Coastguard Worker     if (s->available_out_ == 0 &&
1700*6777b538SAndroid Build Coastguard Worker         s->stream_state_ == BROTLI_STREAM_PROCESSING &&
1701*6777b538SAndroid Build Coastguard Worker         (*available_in != 0 || op != BROTLI_OPERATION_PROCESS)) {
1702*6777b538SAndroid Build Coastguard Worker       size_t block_size = BROTLI_MIN(size_t, block_size_limit, *available_in);
1703*6777b538SAndroid Build Coastguard Worker       BROTLI_BOOL is_last =
1704*6777b538SAndroid Build Coastguard Worker           (*available_in == block_size) && (op == BROTLI_OPERATION_FINISH);
1705*6777b538SAndroid Build Coastguard Worker       BROTLI_BOOL force_flush =
1706*6777b538SAndroid Build Coastguard Worker           (*available_in == block_size) && (op == BROTLI_OPERATION_FLUSH);
1707*6777b538SAndroid Build Coastguard Worker       size_t max_out_size = 2 * block_size + 503;
1708*6777b538SAndroid Build Coastguard Worker       BROTLI_BOOL inplace = BROTLI_TRUE;
1709*6777b538SAndroid Build Coastguard Worker       uint8_t* storage = NULL;
1710*6777b538SAndroid Build Coastguard Worker       size_t storage_ix = s->last_bytes_bits_;
1711*6777b538SAndroid Build Coastguard Worker       size_t table_size;
1712*6777b538SAndroid Build Coastguard Worker       int* table;
1713*6777b538SAndroid Build Coastguard Worker 
1714*6777b538SAndroid Build Coastguard Worker       if (force_flush && block_size == 0) {
1715*6777b538SAndroid Build Coastguard Worker         s->stream_state_ = BROTLI_STREAM_FLUSH_REQUESTED;
1716*6777b538SAndroid Build Coastguard Worker         continue;
1717*6777b538SAndroid Build Coastguard Worker       }
1718*6777b538SAndroid Build Coastguard Worker       if (max_out_size <= *available_out) {
1719*6777b538SAndroid Build Coastguard Worker         storage = *next_out;
1720*6777b538SAndroid Build Coastguard Worker       } else {
1721*6777b538SAndroid Build Coastguard Worker         inplace = BROTLI_FALSE;
1722*6777b538SAndroid Build Coastguard Worker         storage = GetBrotliStorage(s, max_out_size);
1723*6777b538SAndroid Build Coastguard Worker         if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;
1724*6777b538SAndroid Build Coastguard Worker       }
1725*6777b538SAndroid Build Coastguard Worker       storage[0] = (uint8_t)s->last_bytes_;
1726*6777b538SAndroid Build Coastguard Worker       storage[1] = (uint8_t)(s->last_bytes_ >> 8);
1727*6777b538SAndroid Build Coastguard Worker       table = GetHashTable(s, s->params.quality, block_size, &table_size);
1728*6777b538SAndroid Build Coastguard Worker       if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;
1729*6777b538SAndroid Build Coastguard Worker 
1730*6777b538SAndroid Build Coastguard Worker       if (s->params.quality == FAST_ONE_PASS_COMPRESSION_QUALITY) {
1731*6777b538SAndroid Build Coastguard Worker         BrotliCompressFragmentFast(s->one_pass_arena_, *next_in, block_size,
1732*6777b538SAndroid Build Coastguard Worker             is_last, table, table_size, &storage_ix, storage);
1733*6777b538SAndroid Build Coastguard Worker         if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;
1734*6777b538SAndroid Build Coastguard Worker       } else {
1735*6777b538SAndroid Build Coastguard Worker         BrotliCompressFragmentTwoPass(s->two_pass_arena_, *next_in, block_size,
1736*6777b538SAndroid Build Coastguard Worker             is_last, command_buf, literal_buf, table, table_size,
1737*6777b538SAndroid Build Coastguard Worker             &storage_ix, storage);
1738*6777b538SAndroid Build Coastguard Worker         if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;
1739*6777b538SAndroid Build Coastguard Worker       }
1740*6777b538SAndroid Build Coastguard Worker       if (block_size != 0) {
1741*6777b538SAndroid Build Coastguard Worker         *next_in += block_size;
1742*6777b538SAndroid Build Coastguard Worker         *available_in -= block_size;
1743*6777b538SAndroid Build Coastguard Worker       }
1744*6777b538SAndroid Build Coastguard Worker       if (inplace) {
1745*6777b538SAndroid Build Coastguard Worker         size_t out_bytes = storage_ix >> 3;
1746*6777b538SAndroid Build Coastguard Worker         BROTLI_DCHECK(out_bytes <= *available_out);
1747*6777b538SAndroid Build Coastguard Worker         BROTLI_DCHECK((storage_ix & 7) == 0 || out_bytes < *available_out);
1748*6777b538SAndroid Build Coastguard Worker         *next_out += out_bytes;
1749*6777b538SAndroid Build Coastguard Worker         *available_out -= out_bytes;
1750*6777b538SAndroid Build Coastguard Worker         s->total_out_ += out_bytes;
1751*6777b538SAndroid Build Coastguard Worker         if (total_out) *total_out = s->total_out_;
1752*6777b538SAndroid Build Coastguard Worker       } else {
1753*6777b538SAndroid Build Coastguard Worker         size_t out_bytes = storage_ix >> 3;
1754*6777b538SAndroid Build Coastguard Worker         s->next_out_ = storage;
1755*6777b538SAndroid Build Coastguard Worker         s->available_out_ = out_bytes;
1756*6777b538SAndroid Build Coastguard Worker       }
1757*6777b538SAndroid Build Coastguard Worker       s->last_bytes_ = (uint16_t)(storage[storage_ix >> 3]);
1758*6777b538SAndroid Build Coastguard Worker       s->last_bytes_bits_ = storage_ix & 7u;
1759*6777b538SAndroid Build Coastguard Worker 
1760*6777b538SAndroid Build Coastguard Worker       if (force_flush) s->stream_state_ = BROTLI_STREAM_FLUSH_REQUESTED;
1761*6777b538SAndroid Build Coastguard Worker       if (is_last) s->stream_state_ = BROTLI_STREAM_FINISHED;
1762*6777b538SAndroid Build Coastguard Worker       continue;
1763*6777b538SAndroid Build Coastguard Worker     }
1764*6777b538SAndroid Build Coastguard Worker     break;
1765*6777b538SAndroid Build Coastguard Worker   }
1766*6777b538SAndroid Build Coastguard Worker   BROTLI_FREE(m, tmp_command_buf);
1767*6777b538SAndroid Build Coastguard Worker   BROTLI_FREE(m, tmp_literal_buf);
1768*6777b538SAndroid Build Coastguard Worker   CheckFlushComplete(s);
1769*6777b538SAndroid Build Coastguard Worker   return BROTLI_TRUE;
1770*6777b538SAndroid Build Coastguard Worker }
1771*6777b538SAndroid Build Coastguard Worker 
ProcessMetadata(BrotliEncoderState * s,size_t * available_in,const uint8_t ** next_in,size_t * available_out,uint8_t ** next_out,size_t * total_out)1772*6777b538SAndroid Build Coastguard Worker static BROTLI_BOOL ProcessMetadata(
1773*6777b538SAndroid Build Coastguard Worker     BrotliEncoderState* s, size_t* available_in, const uint8_t** next_in,
1774*6777b538SAndroid Build Coastguard Worker     size_t* available_out, uint8_t** next_out, size_t* total_out) {
1775*6777b538SAndroid Build Coastguard Worker   if (*available_in > (1u << 24)) return BROTLI_FALSE;
1776*6777b538SAndroid Build Coastguard Worker   /* Switch to metadata block workflow, if required. */
1777*6777b538SAndroid Build Coastguard Worker   if (s->stream_state_ == BROTLI_STREAM_PROCESSING) {
1778*6777b538SAndroid Build Coastguard Worker     s->remaining_metadata_bytes_ = (uint32_t)*available_in;
1779*6777b538SAndroid Build Coastguard Worker     s->stream_state_ = BROTLI_STREAM_METADATA_HEAD;
1780*6777b538SAndroid Build Coastguard Worker   }
1781*6777b538SAndroid Build Coastguard Worker   if (s->stream_state_ != BROTLI_STREAM_METADATA_HEAD &&
1782*6777b538SAndroid Build Coastguard Worker       s->stream_state_ != BROTLI_STREAM_METADATA_BODY) {
1783*6777b538SAndroid Build Coastguard Worker     return BROTLI_FALSE;
1784*6777b538SAndroid Build Coastguard Worker   }
1785*6777b538SAndroid Build Coastguard Worker 
1786*6777b538SAndroid Build Coastguard Worker   while (BROTLI_TRUE) {
1787*6777b538SAndroid Build Coastguard Worker     if (InjectFlushOrPushOutput(s, available_out, next_out, total_out)) {
1788*6777b538SAndroid Build Coastguard Worker       continue;
1789*6777b538SAndroid Build Coastguard Worker     }
1790*6777b538SAndroid Build Coastguard Worker     if (s->available_out_ != 0) break;
1791*6777b538SAndroid Build Coastguard Worker 
1792*6777b538SAndroid Build Coastguard Worker     if (s->input_pos_ != s->last_flush_pos_) {
1793*6777b538SAndroid Build Coastguard Worker       BROTLI_BOOL result = EncodeData(s, BROTLI_FALSE, BROTLI_TRUE,
1794*6777b538SAndroid Build Coastguard Worker           &s->available_out_, &s->next_out_);
1795*6777b538SAndroid Build Coastguard Worker       if (!result) return BROTLI_FALSE;
1796*6777b538SAndroid Build Coastguard Worker       continue;
1797*6777b538SAndroid Build Coastguard Worker     }
1798*6777b538SAndroid Build Coastguard Worker 
1799*6777b538SAndroid Build Coastguard Worker     if (s->stream_state_ == BROTLI_STREAM_METADATA_HEAD) {
1800*6777b538SAndroid Build Coastguard Worker       s->next_out_ = s->tiny_buf_.u8;
1801*6777b538SAndroid Build Coastguard Worker       s->available_out_ =
1802*6777b538SAndroid Build Coastguard Worker           WriteMetadataHeader(s, s->remaining_metadata_bytes_, s->next_out_);
1803*6777b538SAndroid Build Coastguard Worker       s->stream_state_ = BROTLI_STREAM_METADATA_BODY;
1804*6777b538SAndroid Build Coastguard Worker       continue;
1805*6777b538SAndroid Build Coastguard Worker     } else {
1806*6777b538SAndroid Build Coastguard Worker       /* Exit workflow only when there is no more input and no more output.
1807*6777b538SAndroid Build Coastguard Worker          Otherwise client may continue producing empty metadata blocks. */
1808*6777b538SAndroid Build Coastguard Worker       if (s->remaining_metadata_bytes_ == 0) {
1809*6777b538SAndroid Build Coastguard Worker         s->remaining_metadata_bytes_ = BROTLI_UINT32_MAX;
1810*6777b538SAndroid Build Coastguard Worker         s->stream_state_ = BROTLI_STREAM_PROCESSING;
1811*6777b538SAndroid Build Coastguard Worker         break;
1812*6777b538SAndroid Build Coastguard Worker       }
1813*6777b538SAndroid Build Coastguard Worker       if (*available_out) {
1814*6777b538SAndroid Build Coastguard Worker         /* Directly copy input to output. */
1815*6777b538SAndroid Build Coastguard Worker         uint32_t copy = (uint32_t)BROTLI_MIN(
1816*6777b538SAndroid Build Coastguard Worker             size_t, s->remaining_metadata_bytes_, *available_out);
1817*6777b538SAndroid Build Coastguard Worker         memcpy(*next_out, *next_in, copy);
1818*6777b538SAndroid Build Coastguard Worker         *next_in += copy;
1819*6777b538SAndroid Build Coastguard Worker         *available_in -= copy;
1820*6777b538SAndroid Build Coastguard Worker         s->remaining_metadata_bytes_ -= copy;
1821*6777b538SAndroid Build Coastguard Worker         *next_out += copy;
1822*6777b538SAndroid Build Coastguard Worker         *available_out -= copy;
1823*6777b538SAndroid Build Coastguard Worker       } else {
1824*6777b538SAndroid Build Coastguard Worker         /* This guarantees progress in "TakeOutput" workflow. */
1825*6777b538SAndroid Build Coastguard Worker         uint32_t copy = BROTLI_MIN(uint32_t, s->remaining_metadata_bytes_, 16);
1826*6777b538SAndroid Build Coastguard Worker         s->next_out_ = s->tiny_buf_.u8;
1827*6777b538SAndroid Build Coastguard Worker         memcpy(s->next_out_, *next_in, copy);
1828*6777b538SAndroid Build Coastguard Worker         *next_in += copy;
1829*6777b538SAndroid Build Coastguard Worker         *available_in -= copy;
1830*6777b538SAndroid Build Coastguard Worker         s->remaining_metadata_bytes_ -= copy;
1831*6777b538SAndroid Build Coastguard Worker         s->available_out_ = copy;
1832*6777b538SAndroid Build Coastguard Worker       }
1833*6777b538SAndroid Build Coastguard Worker       continue;
1834*6777b538SAndroid Build Coastguard Worker     }
1835*6777b538SAndroid Build Coastguard Worker   }
1836*6777b538SAndroid Build Coastguard Worker 
1837*6777b538SAndroid Build Coastguard Worker   return BROTLI_TRUE;
1838*6777b538SAndroid Build Coastguard Worker }
1839*6777b538SAndroid Build Coastguard Worker 
UpdateSizeHint(BrotliEncoderState * s,size_t available_in)1840*6777b538SAndroid Build Coastguard Worker static void UpdateSizeHint(BrotliEncoderState* s, size_t available_in) {
1841*6777b538SAndroid Build Coastguard Worker   if (s->params.size_hint == 0) {
1842*6777b538SAndroid Build Coastguard Worker     uint64_t delta = UnprocessedInputSize(s);
1843*6777b538SAndroid Build Coastguard Worker     uint64_t tail = available_in;
1844*6777b538SAndroid Build Coastguard Worker     uint32_t limit = 1u << 30;
1845*6777b538SAndroid Build Coastguard Worker     uint32_t total;
1846*6777b538SAndroid Build Coastguard Worker     if ((delta >= limit) || (tail >= limit) || ((delta + tail) >= limit)) {
1847*6777b538SAndroid Build Coastguard Worker       total = limit;
1848*6777b538SAndroid Build Coastguard Worker     } else {
1849*6777b538SAndroid Build Coastguard Worker       total = (uint32_t)(delta + tail);
1850*6777b538SAndroid Build Coastguard Worker     }
1851*6777b538SAndroid Build Coastguard Worker     s->params.size_hint = total;
1852*6777b538SAndroid Build Coastguard Worker   }
1853*6777b538SAndroid Build Coastguard Worker }
1854*6777b538SAndroid Build Coastguard Worker 
BrotliEncoderCompressStream(BrotliEncoderState * s,BrotliEncoderOperation op,size_t * available_in,const uint8_t ** next_in,size_t * available_out,uint8_t ** next_out,size_t * total_out)1855*6777b538SAndroid Build Coastguard Worker BROTLI_BOOL BrotliEncoderCompressStream(
1856*6777b538SAndroid Build Coastguard Worker     BrotliEncoderState* s, BrotliEncoderOperation op, size_t* available_in,
1857*6777b538SAndroid Build Coastguard Worker     const uint8_t** next_in, size_t* available_out,uint8_t** next_out,
1858*6777b538SAndroid Build Coastguard Worker     size_t* total_out) {
1859*6777b538SAndroid Build Coastguard Worker   if (!EnsureInitialized(s)) return BROTLI_FALSE;
1860*6777b538SAndroid Build Coastguard Worker 
1861*6777b538SAndroid Build Coastguard Worker   /* Unfinished metadata block; check requirements. */
1862*6777b538SAndroid Build Coastguard Worker   if (s->remaining_metadata_bytes_ != BROTLI_UINT32_MAX) {
1863*6777b538SAndroid Build Coastguard Worker     if (*available_in != s->remaining_metadata_bytes_) return BROTLI_FALSE;
1864*6777b538SAndroid Build Coastguard Worker     if (op != BROTLI_OPERATION_EMIT_METADATA) return BROTLI_FALSE;
1865*6777b538SAndroid Build Coastguard Worker   }
1866*6777b538SAndroid Build Coastguard Worker 
1867*6777b538SAndroid Build Coastguard Worker   if (op == BROTLI_OPERATION_EMIT_METADATA) {
1868*6777b538SAndroid Build Coastguard Worker     UpdateSizeHint(s, 0);  /* First data metablock might be emitted here. */
1869*6777b538SAndroid Build Coastguard Worker     return ProcessMetadata(
1870*6777b538SAndroid Build Coastguard Worker         s, available_in, next_in, available_out, next_out, total_out);
1871*6777b538SAndroid Build Coastguard Worker   }
1872*6777b538SAndroid Build Coastguard Worker 
1873*6777b538SAndroid Build Coastguard Worker   if (s->stream_state_ == BROTLI_STREAM_METADATA_HEAD ||
1874*6777b538SAndroid Build Coastguard Worker       s->stream_state_ == BROTLI_STREAM_METADATA_BODY) {
1875*6777b538SAndroid Build Coastguard Worker     return BROTLI_FALSE;
1876*6777b538SAndroid Build Coastguard Worker   }
1877*6777b538SAndroid Build Coastguard Worker 
1878*6777b538SAndroid Build Coastguard Worker   if (s->stream_state_ != BROTLI_STREAM_PROCESSING && *available_in != 0) {
1879*6777b538SAndroid Build Coastguard Worker     return BROTLI_FALSE;
1880*6777b538SAndroid Build Coastguard Worker   }
1881*6777b538SAndroid Build Coastguard Worker   if (s->params.quality == FAST_ONE_PASS_COMPRESSION_QUALITY ||
1882*6777b538SAndroid Build Coastguard Worker       s->params.quality == FAST_TWO_PASS_COMPRESSION_QUALITY) {
1883*6777b538SAndroid Build Coastguard Worker     return BrotliEncoderCompressStreamFast(s, op, available_in, next_in,
1884*6777b538SAndroid Build Coastguard Worker         available_out, next_out, total_out);
1885*6777b538SAndroid Build Coastguard Worker   }
1886*6777b538SAndroid Build Coastguard Worker   while (BROTLI_TRUE) {
1887*6777b538SAndroid Build Coastguard Worker     size_t remaining_block_size = RemainingInputBlockSize(s);
1888*6777b538SAndroid Build Coastguard Worker     /* Shorten input to flint size. */
1889*6777b538SAndroid Build Coastguard Worker     if (s->flint_ >= 0 && remaining_block_size > (size_t)s->flint_) {
1890*6777b538SAndroid Build Coastguard Worker       remaining_block_size = (size_t)s->flint_;
1891*6777b538SAndroid Build Coastguard Worker     }
1892*6777b538SAndroid Build Coastguard Worker 
1893*6777b538SAndroid Build Coastguard Worker     if (remaining_block_size != 0 && *available_in != 0) {
1894*6777b538SAndroid Build Coastguard Worker       size_t copy_input_size =
1895*6777b538SAndroid Build Coastguard Worker           BROTLI_MIN(size_t, remaining_block_size, *available_in);
1896*6777b538SAndroid Build Coastguard Worker       CopyInputToRingBuffer(s, copy_input_size, *next_in);
1897*6777b538SAndroid Build Coastguard Worker       *next_in += copy_input_size;
1898*6777b538SAndroid Build Coastguard Worker       *available_in -= copy_input_size;
1899*6777b538SAndroid Build Coastguard Worker       if (s->flint_ > 0) s->flint_ = (int8_t)(s->flint_ - (int)copy_input_size);
1900*6777b538SAndroid Build Coastguard Worker       continue;
1901*6777b538SAndroid Build Coastguard Worker     }
1902*6777b538SAndroid Build Coastguard Worker 
1903*6777b538SAndroid Build Coastguard Worker     if (InjectFlushOrPushOutput(s, available_out, next_out, total_out)) {
1904*6777b538SAndroid Build Coastguard Worker       /* Exit the "emit flint" workflow. */
1905*6777b538SAndroid Build Coastguard Worker       if (s->flint_ == BROTLI_FLINT_WAITING_FOR_FLUSHING) {
1906*6777b538SAndroid Build Coastguard Worker         CheckFlushComplete(s);
1907*6777b538SAndroid Build Coastguard Worker         if (s->stream_state_ == BROTLI_STREAM_PROCESSING) {
1908*6777b538SAndroid Build Coastguard Worker           s->flint_ = BROTLI_FLINT_DONE;
1909*6777b538SAndroid Build Coastguard Worker         }
1910*6777b538SAndroid Build Coastguard Worker       }
1911*6777b538SAndroid Build Coastguard Worker       continue;
1912*6777b538SAndroid Build Coastguard Worker     }
1913*6777b538SAndroid Build Coastguard Worker 
1914*6777b538SAndroid Build Coastguard Worker     /* Compress data only when internal output buffer is empty, stream is not
1915*6777b538SAndroid Build Coastguard Worker        finished and there is no pending flush request. */
1916*6777b538SAndroid Build Coastguard Worker     if (s->available_out_ == 0 &&
1917*6777b538SAndroid Build Coastguard Worker         s->stream_state_ == BROTLI_STREAM_PROCESSING) {
1918*6777b538SAndroid Build Coastguard Worker       if (remaining_block_size == 0 || op != BROTLI_OPERATION_PROCESS) {
1919*6777b538SAndroid Build Coastguard Worker         BROTLI_BOOL is_last = TO_BROTLI_BOOL(
1920*6777b538SAndroid Build Coastguard Worker             (*available_in == 0) && op == BROTLI_OPERATION_FINISH);
1921*6777b538SAndroid Build Coastguard Worker         BROTLI_BOOL force_flush = TO_BROTLI_BOOL(
1922*6777b538SAndroid Build Coastguard Worker             (*available_in == 0) && op == BROTLI_OPERATION_FLUSH);
1923*6777b538SAndroid Build Coastguard Worker         BROTLI_BOOL result;
1924*6777b538SAndroid Build Coastguard Worker         /* Force emitting (uncompressed) piece containing flint. */
1925*6777b538SAndroid Build Coastguard Worker         if (!is_last && s->flint_ == 0) {
1926*6777b538SAndroid Build Coastguard Worker           s->flint_ = BROTLI_FLINT_WAITING_FOR_FLUSHING;
1927*6777b538SAndroid Build Coastguard Worker           force_flush = BROTLI_TRUE;
1928*6777b538SAndroid Build Coastguard Worker         }
1929*6777b538SAndroid Build Coastguard Worker         UpdateSizeHint(s, *available_in);
1930*6777b538SAndroid Build Coastguard Worker         result = EncodeData(s, is_last, force_flush,
1931*6777b538SAndroid Build Coastguard Worker             &s->available_out_, &s->next_out_);
1932*6777b538SAndroid Build Coastguard Worker         if (!result) return BROTLI_FALSE;
1933*6777b538SAndroid Build Coastguard Worker         if (force_flush) s->stream_state_ = BROTLI_STREAM_FLUSH_REQUESTED;
1934*6777b538SAndroid Build Coastguard Worker         if (is_last) s->stream_state_ = BROTLI_STREAM_FINISHED;
1935*6777b538SAndroid Build Coastguard Worker         continue;
1936*6777b538SAndroid Build Coastguard Worker       }
1937*6777b538SAndroid Build Coastguard Worker     }
1938*6777b538SAndroid Build Coastguard Worker     break;
1939*6777b538SAndroid Build Coastguard Worker   }
1940*6777b538SAndroid Build Coastguard Worker   CheckFlushComplete(s);
1941*6777b538SAndroid Build Coastguard Worker   return BROTLI_TRUE;
1942*6777b538SAndroid Build Coastguard Worker }
1943*6777b538SAndroid Build Coastguard Worker 
BrotliEncoderIsFinished(BrotliEncoderState * s)1944*6777b538SAndroid Build Coastguard Worker BROTLI_BOOL BrotliEncoderIsFinished(BrotliEncoderState* s) {
1945*6777b538SAndroid Build Coastguard Worker   return TO_BROTLI_BOOL(s->stream_state_ == BROTLI_STREAM_FINISHED &&
1946*6777b538SAndroid Build Coastguard Worker       !BrotliEncoderHasMoreOutput(s));
1947*6777b538SAndroid Build Coastguard Worker }
1948*6777b538SAndroid Build Coastguard Worker 
BrotliEncoderHasMoreOutput(BrotliEncoderState * s)1949*6777b538SAndroid Build Coastguard Worker BROTLI_BOOL BrotliEncoderHasMoreOutput(BrotliEncoderState* s) {
1950*6777b538SAndroid Build Coastguard Worker   return TO_BROTLI_BOOL(s->available_out_ != 0);
1951*6777b538SAndroid Build Coastguard Worker }
1952*6777b538SAndroid Build Coastguard Worker 
BrotliEncoderTakeOutput(BrotliEncoderState * s,size_t * size)1953*6777b538SAndroid Build Coastguard Worker const uint8_t* BrotliEncoderTakeOutput(BrotliEncoderState* s, size_t* size) {
1954*6777b538SAndroid Build Coastguard Worker   size_t consumed_size = s->available_out_;
1955*6777b538SAndroid Build Coastguard Worker   uint8_t* result = s->next_out_;
1956*6777b538SAndroid Build Coastguard Worker   if (*size) {
1957*6777b538SAndroid Build Coastguard Worker     consumed_size = BROTLI_MIN(size_t, *size, s->available_out_);
1958*6777b538SAndroid Build Coastguard Worker   }
1959*6777b538SAndroid Build Coastguard Worker   if (consumed_size) {
1960*6777b538SAndroid Build Coastguard Worker     s->next_out_ += consumed_size;
1961*6777b538SAndroid Build Coastguard Worker     s->available_out_ -= consumed_size;
1962*6777b538SAndroid Build Coastguard Worker     s->total_out_ += consumed_size;
1963*6777b538SAndroid Build Coastguard Worker     CheckFlushComplete(s);
1964*6777b538SAndroid Build Coastguard Worker     *size = consumed_size;
1965*6777b538SAndroid Build Coastguard Worker   } else {
1966*6777b538SAndroid Build Coastguard Worker     *size = 0;
1967*6777b538SAndroid Build Coastguard Worker     result = 0;
1968*6777b538SAndroid Build Coastguard Worker   }
1969*6777b538SAndroid Build Coastguard Worker   return result;
1970*6777b538SAndroid Build Coastguard Worker }
1971*6777b538SAndroid Build Coastguard Worker 
BrotliEncoderVersion(void)1972*6777b538SAndroid Build Coastguard Worker uint32_t BrotliEncoderVersion(void) {
1973*6777b538SAndroid Build Coastguard Worker   return BROTLI_VERSION;
1974*6777b538SAndroid Build Coastguard Worker }
1975*6777b538SAndroid Build Coastguard Worker 
BrotliEncoderPrepareDictionary(BrotliSharedDictionaryType type,size_t size,const uint8_t data[BROTLI_ARRAY_PARAM (size)],int quality,brotli_alloc_func alloc_func,brotli_free_func free_func,void * opaque)1976*6777b538SAndroid Build Coastguard Worker BrotliEncoderPreparedDictionary* BrotliEncoderPrepareDictionary(
1977*6777b538SAndroid Build Coastguard Worker     BrotliSharedDictionaryType type, size_t size,
1978*6777b538SAndroid Build Coastguard Worker     const uint8_t data[BROTLI_ARRAY_PARAM(size)], int quality,
1979*6777b538SAndroid Build Coastguard Worker     brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque) {
1980*6777b538SAndroid Build Coastguard Worker   ManagedDictionary* managed_dictionary = NULL;
1981*6777b538SAndroid Build Coastguard Worker   if (type != BROTLI_SHARED_DICTIONARY_RAW &&
1982*6777b538SAndroid Build Coastguard Worker       type != BROTLI_SHARED_DICTIONARY_SERIALIZED) {
1983*6777b538SAndroid Build Coastguard Worker     return NULL;
1984*6777b538SAndroid Build Coastguard Worker   }
1985*6777b538SAndroid Build Coastguard Worker   managed_dictionary =
1986*6777b538SAndroid Build Coastguard Worker       BrotliCreateManagedDictionary(alloc_func, free_func, opaque);
1987*6777b538SAndroid Build Coastguard Worker   if (managed_dictionary == NULL) {
1988*6777b538SAndroid Build Coastguard Worker     return NULL;
1989*6777b538SAndroid Build Coastguard Worker   }
1990*6777b538SAndroid Build Coastguard Worker   if (type == BROTLI_SHARED_DICTIONARY_RAW) {
1991*6777b538SAndroid Build Coastguard Worker     managed_dictionary->dictionary = (uint32_t*)CreatePreparedDictionary(
1992*6777b538SAndroid Build Coastguard Worker         &managed_dictionary->memory_manager_, data, size);
1993*6777b538SAndroid Build Coastguard Worker   } else {
1994*6777b538SAndroid Build Coastguard Worker     SharedEncoderDictionary* dict = (SharedEncoderDictionary*)BrotliAllocate(
1995*6777b538SAndroid Build Coastguard Worker         &managed_dictionary->memory_manager_, sizeof(SharedEncoderDictionary));
1996*6777b538SAndroid Build Coastguard Worker     managed_dictionary->dictionary = (uint32_t*)dict;
1997*6777b538SAndroid Build Coastguard Worker     if (dict != NULL) {
1998*6777b538SAndroid Build Coastguard Worker       BROTLI_BOOL ok = BrotliInitCustomSharedEncoderDictionary(
1999*6777b538SAndroid Build Coastguard Worker           &managed_dictionary->memory_manager_, data, size, quality, dict);
2000*6777b538SAndroid Build Coastguard Worker       if (!ok) {
2001*6777b538SAndroid Build Coastguard Worker         BrotliFree(&managed_dictionary->memory_manager_, dict);
2002*6777b538SAndroid Build Coastguard Worker         managed_dictionary->dictionary = NULL;
2003*6777b538SAndroid Build Coastguard Worker       }
2004*6777b538SAndroid Build Coastguard Worker     }
2005*6777b538SAndroid Build Coastguard Worker   }
2006*6777b538SAndroid Build Coastguard Worker   if (managed_dictionary->dictionary == NULL) {
2007*6777b538SAndroid Build Coastguard Worker     BrotliDestroyManagedDictionary(managed_dictionary);
2008*6777b538SAndroid Build Coastguard Worker     return NULL;
2009*6777b538SAndroid Build Coastguard Worker   }
2010*6777b538SAndroid Build Coastguard Worker   return (BrotliEncoderPreparedDictionary*)managed_dictionary;
2011*6777b538SAndroid Build Coastguard Worker }
2012*6777b538SAndroid Build Coastguard Worker 
BrotliEncoderDestroyPreparedDictionary(BrotliEncoderPreparedDictionary * dictionary)2013*6777b538SAndroid Build Coastguard Worker void BrotliEncoderDestroyPreparedDictionary(
2014*6777b538SAndroid Build Coastguard Worker     BrotliEncoderPreparedDictionary* dictionary) {
2015*6777b538SAndroid Build Coastguard Worker   ManagedDictionary* dict = (ManagedDictionary*)dictionary;
2016*6777b538SAndroid Build Coastguard Worker   if (!dictionary) return;
2017*6777b538SAndroid Build Coastguard Worker   /* First field of dictionary structs. */
2018*6777b538SAndroid Build Coastguard Worker   /* Only managed dictionaries are eligible for destruction by this method. */
2019*6777b538SAndroid Build Coastguard Worker   if (dict->magic != kManagedDictionaryMagic) {
2020*6777b538SAndroid Build Coastguard Worker     return;
2021*6777b538SAndroid Build Coastguard Worker   }
2022*6777b538SAndroid Build Coastguard Worker   if (dict->dictionary == NULL) {
2023*6777b538SAndroid Build Coastguard Worker     /* This should never ever happen. */
2024*6777b538SAndroid Build Coastguard Worker   } else if (*dict->dictionary == kPreparedDictionaryMagic) {
2025*6777b538SAndroid Build Coastguard Worker     DestroyPreparedDictionary(
2026*6777b538SAndroid Build Coastguard Worker         &dict->memory_manager_, (PreparedDictionary*)dict->dictionary);
2027*6777b538SAndroid Build Coastguard Worker   } else if (*dict->dictionary == kSharedDictionaryMagic) {
2028*6777b538SAndroid Build Coastguard Worker     BrotliCleanupSharedEncoderDictionary(&dict->memory_manager_,
2029*6777b538SAndroid Build Coastguard Worker         (SharedEncoderDictionary*)dict->dictionary);
2030*6777b538SAndroid Build Coastguard Worker     BrotliFree(&dict->memory_manager_, dict->dictionary);
2031*6777b538SAndroid Build Coastguard Worker   } else {
2032*6777b538SAndroid Build Coastguard Worker     /* This should never ever happen. */
2033*6777b538SAndroid Build Coastguard Worker   }
2034*6777b538SAndroid Build Coastguard Worker   dict->dictionary = NULL;
2035*6777b538SAndroid Build Coastguard Worker   BrotliDestroyManagedDictionary(dict);
2036*6777b538SAndroid Build Coastguard Worker }
2037*6777b538SAndroid Build Coastguard Worker 
BrotliEncoderAttachPreparedDictionary(BrotliEncoderState * state,const BrotliEncoderPreparedDictionary * dictionary)2038*6777b538SAndroid Build Coastguard Worker BROTLI_BOOL BrotliEncoderAttachPreparedDictionary(BrotliEncoderState* state,
2039*6777b538SAndroid Build Coastguard Worker     const BrotliEncoderPreparedDictionary* dictionary) {
2040*6777b538SAndroid Build Coastguard Worker   /* First field of dictionary structs */
2041*6777b538SAndroid Build Coastguard Worker   const BrotliEncoderPreparedDictionary* dict = dictionary;
2042*6777b538SAndroid Build Coastguard Worker   uint32_t magic = *((const uint32_t*)dict);
2043*6777b538SAndroid Build Coastguard Worker   SharedEncoderDictionary* current = NULL;
2044*6777b538SAndroid Build Coastguard Worker   if (magic == kManagedDictionaryMagic) {
2045*6777b538SAndroid Build Coastguard Worker     /* Unwrap managed dictionary. */
2046*6777b538SAndroid Build Coastguard Worker     ManagedDictionary* managed_dictionary = (ManagedDictionary*)dict;
2047*6777b538SAndroid Build Coastguard Worker     magic = *managed_dictionary->dictionary;
2048*6777b538SAndroid Build Coastguard Worker     dict = (BrotliEncoderPreparedDictionary*)managed_dictionary->dictionary;
2049*6777b538SAndroid Build Coastguard Worker   }
2050*6777b538SAndroid Build Coastguard Worker   current = &state->params.dictionary;
2051*6777b538SAndroid Build Coastguard Worker   if (magic == kPreparedDictionaryMagic) {
2052*6777b538SAndroid Build Coastguard Worker     const PreparedDictionary* prepared = (const PreparedDictionary*)dict;
2053*6777b538SAndroid Build Coastguard Worker     if (!AttachPreparedDictionary(&current->compound, prepared)) {
2054*6777b538SAndroid Build Coastguard Worker       return BROTLI_FALSE;
2055*6777b538SAndroid Build Coastguard Worker     }
2056*6777b538SAndroid Build Coastguard Worker   } else if (magic == kSharedDictionaryMagic) {
2057*6777b538SAndroid Build Coastguard Worker     const SharedEncoderDictionary* attached =
2058*6777b538SAndroid Build Coastguard Worker         (const SharedEncoderDictionary*)dict;
2059*6777b538SAndroid Build Coastguard Worker     BROTLI_BOOL was_default = !current->contextual.context_based &&
2060*6777b538SAndroid Build Coastguard Worker         current->contextual.num_dictionaries == 1 &&
2061*6777b538SAndroid Build Coastguard Worker         current->contextual.dict[0]->hash_table_words ==
2062*6777b538SAndroid Build Coastguard Worker         kStaticDictionaryHashWords &&
2063*6777b538SAndroid Build Coastguard Worker         current->contextual.dict[0]->hash_table_lengths ==
2064*6777b538SAndroid Build Coastguard Worker         kStaticDictionaryHashLengths;
2065*6777b538SAndroid Build Coastguard Worker     BROTLI_BOOL new_default = !attached->contextual.context_based &&
2066*6777b538SAndroid Build Coastguard Worker         attached->contextual.num_dictionaries == 1 &&
2067*6777b538SAndroid Build Coastguard Worker         attached->contextual.dict[0]->hash_table_words ==
2068*6777b538SAndroid Build Coastguard Worker         kStaticDictionaryHashWords &&
2069*6777b538SAndroid Build Coastguard Worker         attached->contextual.dict[0]->hash_table_lengths ==
2070*6777b538SAndroid Build Coastguard Worker         kStaticDictionaryHashLengths;
2071*6777b538SAndroid Build Coastguard Worker     size_t i;
2072*6777b538SAndroid Build Coastguard Worker     if (state->is_initialized_) return BROTLI_FALSE;
2073*6777b538SAndroid Build Coastguard Worker     current->max_quality =
2074*6777b538SAndroid Build Coastguard Worker         BROTLI_MIN(int, current->max_quality, attached->max_quality);
2075*6777b538SAndroid Build Coastguard Worker     for (i = 0; i < attached->compound.num_chunks; i++) {
2076*6777b538SAndroid Build Coastguard Worker       if (!AttachPreparedDictionary(&current->compound,
2077*6777b538SAndroid Build Coastguard Worker           attached->compound.chunks[i])) {
2078*6777b538SAndroid Build Coastguard Worker         return BROTLI_FALSE;
2079*6777b538SAndroid Build Coastguard Worker       }
2080*6777b538SAndroid Build Coastguard Worker     }
2081*6777b538SAndroid Build Coastguard Worker     if (!new_default) {
2082*6777b538SAndroid Build Coastguard Worker       if (!was_default) return BROTLI_FALSE;
2083*6777b538SAndroid Build Coastguard Worker       /* Copy by value, but then set num_instances_ to 0 because their memory
2084*6777b538SAndroid Build Coastguard Worker       is managed by attached, not by current */
2085*6777b538SAndroid Build Coastguard Worker       current->contextual = attached->contextual;
2086*6777b538SAndroid Build Coastguard Worker       current->contextual.num_instances_ = 0;
2087*6777b538SAndroid Build Coastguard Worker     }
2088*6777b538SAndroid Build Coastguard Worker   } else {
2089*6777b538SAndroid Build Coastguard Worker     return BROTLI_FALSE;
2090*6777b538SAndroid Build Coastguard Worker   }
2091*6777b538SAndroid Build Coastguard Worker   return BROTLI_TRUE;
2092*6777b538SAndroid Build Coastguard Worker }
2093*6777b538SAndroid Build Coastguard Worker 
BrotliEncoderEstimatePeakMemoryUsage(int quality,int lgwin,size_t input_size)2094*6777b538SAndroid Build Coastguard Worker size_t BrotliEncoderEstimatePeakMemoryUsage(int quality, int lgwin,
2095*6777b538SAndroid Build Coastguard Worker                                             size_t input_size) {
2096*6777b538SAndroid Build Coastguard Worker   BrotliEncoderParams params;
2097*6777b538SAndroid Build Coastguard Worker   BrotliEncoderInitParams(&params);
2098*6777b538SAndroid Build Coastguard Worker   params.quality = quality;
2099*6777b538SAndroid Build Coastguard Worker   params.lgwin = lgwin;
2100*6777b538SAndroid Build Coastguard Worker   params.size_hint = input_size;
2101*6777b538SAndroid Build Coastguard Worker   SanitizeParams(&params);
2102*6777b538SAndroid Build Coastguard Worker   params.lgblock = ComputeLgBlock(&params);
2103*6777b538SAndroid Build Coastguard Worker   ChooseHasher(&params, &params.hasher);
2104*6777b538SAndroid Build Coastguard Worker   if (params.quality == FAST_ONE_PASS_COMPRESSION_QUALITY ||
2105*6777b538SAndroid Build Coastguard Worker       params.quality == FAST_TWO_PASS_COMPRESSION_QUALITY) {
2106*6777b538SAndroid Build Coastguard Worker     size_t state_size = sizeof(BrotliEncoderState);
2107*6777b538SAndroid Build Coastguard Worker     size_t block_size = BROTLI_MIN(size_t, input_size, (1ul << params.lgwin));
2108*6777b538SAndroid Build Coastguard Worker     size_t hash_table_size =
2109*6777b538SAndroid Build Coastguard Worker         HashTableSize(MaxHashTableSize(params.quality), block_size);
2110*6777b538SAndroid Build Coastguard Worker     size_t hash_size =
2111*6777b538SAndroid Build Coastguard Worker         (hash_table_size < (1u << 10)) ? 0 : sizeof(int) * hash_table_size;
2112*6777b538SAndroid Build Coastguard Worker     size_t cmdbuf_size = params.quality == FAST_TWO_PASS_COMPRESSION_QUALITY ?
2113*6777b538SAndroid Build Coastguard Worker         5 * BROTLI_MIN(size_t, block_size, 1ul << 17) : 0;
2114*6777b538SAndroid Build Coastguard Worker     if (params.quality == FAST_ONE_PASS_COMPRESSION_QUALITY) {
2115*6777b538SAndroid Build Coastguard Worker       state_size += sizeof(BrotliOnePassArena);
2116*6777b538SAndroid Build Coastguard Worker     } else {
2117*6777b538SAndroid Build Coastguard Worker       state_size += sizeof(BrotliTwoPassArena);
2118*6777b538SAndroid Build Coastguard Worker     }
2119*6777b538SAndroid Build Coastguard Worker     return hash_size + cmdbuf_size + state_size;
2120*6777b538SAndroid Build Coastguard Worker   } else {
2121*6777b538SAndroid Build Coastguard Worker     size_t short_ringbuffer_size = (size_t)1 << params.lgblock;
2122*6777b538SAndroid Build Coastguard Worker     int ringbuffer_bits = ComputeRbBits(&params);
2123*6777b538SAndroid Build Coastguard Worker     size_t ringbuffer_size = input_size < short_ringbuffer_size ?
2124*6777b538SAndroid Build Coastguard Worker         input_size : (1u << ringbuffer_bits) + short_ringbuffer_size;
2125*6777b538SAndroid Build Coastguard Worker     size_t hash_size[4] = {0};
2126*6777b538SAndroid Build Coastguard Worker     size_t metablock_size =
2127*6777b538SAndroid Build Coastguard Worker         BROTLI_MIN(size_t, input_size, MaxMetablockSize(&params));
2128*6777b538SAndroid Build Coastguard Worker     size_t inputblock_size =
2129*6777b538SAndroid Build Coastguard Worker         BROTLI_MIN(size_t, input_size, (size_t)1 << params.lgblock);
2130*6777b538SAndroid Build Coastguard Worker     size_t cmdbuf_size = metablock_size * 2 + inputblock_size * 6;
2131*6777b538SAndroid Build Coastguard Worker     size_t outbuf_size = metablock_size * 2 + 503;
2132*6777b538SAndroid Build Coastguard Worker     size_t histogram_size = 0;
2133*6777b538SAndroid Build Coastguard Worker     HasherSize(&params, BROTLI_TRUE, input_size, hash_size);
2134*6777b538SAndroid Build Coastguard Worker     if (params.quality < MIN_QUALITY_FOR_BLOCK_SPLIT) {
2135*6777b538SAndroid Build Coastguard Worker       cmdbuf_size = BROTLI_MIN(size_t, cmdbuf_size,
2136*6777b538SAndroid Build Coastguard Worker           MAX_NUM_DELAYED_SYMBOLS * sizeof(Command) + inputblock_size * 12);
2137*6777b538SAndroid Build Coastguard Worker     }
2138*6777b538SAndroid Build Coastguard Worker     if (params.quality >= MIN_QUALITY_FOR_HQ_BLOCK_SPLITTING) {
2139*6777b538SAndroid Build Coastguard Worker       /* Only a very rough estimation, based on enwik8. */
2140*6777b538SAndroid Build Coastguard Worker       histogram_size = 200 << 20;
2141*6777b538SAndroid Build Coastguard Worker     } else if (params.quality >= MIN_QUALITY_FOR_BLOCK_SPLIT) {
2142*6777b538SAndroid Build Coastguard Worker       size_t literal_histograms =
2143*6777b538SAndroid Build Coastguard Worker           BROTLI_MIN(size_t, metablock_size / 6144, 256);
2144*6777b538SAndroid Build Coastguard Worker       size_t command_histograms =
2145*6777b538SAndroid Build Coastguard Worker           BROTLI_MIN(size_t, metablock_size / 6144, 256);
2146*6777b538SAndroid Build Coastguard Worker       size_t distance_histograms =
2147*6777b538SAndroid Build Coastguard Worker           BROTLI_MIN(size_t, metablock_size / 6144, 256);
2148*6777b538SAndroid Build Coastguard Worker       histogram_size = literal_histograms * sizeof(HistogramLiteral) +
2149*6777b538SAndroid Build Coastguard Worker                        command_histograms * sizeof(HistogramCommand) +
2150*6777b538SAndroid Build Coastguard Worker                        distance_histograms * sizeof(HistogramDistance);
2151*6777b538SAndroid Build Coastguard Worker     }
2152*6777b538SAndroid Build Coastguard Worker     return (ringbuffer_size +
2153*6777b538SAndroid Build Coastguard Worker             hash_size[0] + hash_size[1] + hash_size[2] + hash_size[3] +
2154*6777b538SAndroid Build Coastguard Worker             cmdbuf_size +
2155*6777b538SAndroid Build Coastguard Worker             outbuf_size +
2156*6777b538SAndroid Build Coastguard Worker             histogram_size);
2157*6777b538SAndroid Build Coastguard Worker   }
2158*6777b538SAndroid Build Coastguard Worker }
BrotliEncoderGetPreparedDictionarySize(const BrotliEncoderPreparedDictionary * prepared_dictionary)2159*6777b538SAndroid Build Coastguard Worker size_t BrotliEncoderGetPreparedDictionarySize(
2160*6777b538SAndroid Build Coastguard Worker     const BrotliEncoderPreparedDictionary* prepared_dictionary) {
2161*6777b538SAndroid Build Coastguard Worker   /* First field of dictionary structs */
2162*6777b538SAndroid Build Coastguard Worker   const BrotliEncoderPreparedDictionary* prepared = prepared_dictionary;
2163*6777b538SAndroid Build Coastguard Worker   uint32_t magic = *((const uint32_t*)prepared);
2164*6777b538SAndroid Build Coastguard Worker   size_t overhead = 0;
2165*6777b538SAndroid Build Coastguard Worker   if (magic == kManagedDictionaryMagic) {
2166*6777b538SAndroid Build Coastguard Worker     const ManagedDictionary* managed = (const ManagedDictionary*)prepared;
2167*6777b538SAndroid Build Coastguard Worker     overhead = sizeof(ManagedDictionary);
2168*6777b538SAndroid Build Coastguard Worker     magic = *managed->dictionary;
2169*6777b538SAndroid Build Coastguard Worker     prepared = (const BrotliEncoderPreparedDictionary*)managed->dictionary;
2170*6777b538SAndroid Build Coastguard Worker   }
2171*6777b538SAndroid Build Coastguard Worker 
2172*6777b538SAndroid Build Coastguard Worker   if (magic == kPreparedDictionaryMagic) {
2173*6777b538SAndroid Build Coastguard Worker     const PreparedDictionary* dictionary =
2174*6777b538SAndroid Build Coastguard Worker         (const PreparedDictionary*)prepared;
2175*6777b538SAndroid Build Coastguard Worker     /* Keep in sync with step 3 of CreatePreparedDictionary */
2176*6777b538SAndroid Build Coastguard Worker     return sizeof(PreparedDictionary) + dictionary->source_size +
2177*6777b538SAndroid Build Coastguard Worker         (sizeof(uint32_t) << dictionary->slot_bits) +
2178*6777b538SAndroid Build Coastguard Worker         (sizeof(uint16_t) << dictionary->bucket_bits) +
2179*6777b538SAndroid Build Coastguard Worker         (sizeof(uint32_t) * dictionary->source_offset) + overhead;
2180*6777b538SAndroid Build Coastguard Worker   } else if (magic == kSharedDictionaryMagic) {
2181*6777b538SAndroid Build Coastguard Worker     const SharedEncoderDictionary* dictionary =
2182*6777b538SAndroid Build Coastguard Worker         (const SharedEncoderDictionary*)prepared;
2183*6777b538SAndroid Build Coastguard Worker     const CompoundDictionary* compound = &dictionary->compound;
2184*6777b538SAndroid Build Coastguard Worker     const ContextualEncoderDictionary* contextual = &dictionary->contextual;
2185*6777b538SAndroid Build Coastguard Worker     size_t result = sizeof(*dictionary);
2186*6777b538SAndroid Build Coastguard Worker     size_t i;
2187*6777b538SAndroid Build Coastguard Worker     size_t num_instances;
2188*6777b538SAndroid Build Coastguard Worker     const BrotliEncoderDictionary* instances;
2189*6777b538SAndroid Build Coastguard Worker     for (i = 0; i < compound->num_prepared_instances_; i++) {
2190*6777b538SAndroid Build Coastguard Worker       size_t size = BrotliEncoderGetPreparedDictionarySize(
2191*6777b538SAndroid Build Coastguard Worker           (const BrotliEncoderPreparedDictionary*)
2192*6777b538SAndroid Build Coastguard Worker           compound->prepared_instances_[i]);
2193*6777b538SAndroid Build Coastguard Worker       if (!size) return 0;  /* error */
2194*6777b538SAndroid Build Coastguard Worker       result += size;
2195*6777b538SAndroid Build Coastguard Worker     }
2196*6777b538SAndroid Build Coastguard Worker     if (contextual->context_based) {
2197*6777b538SAndroid Build Coastguard Worker       num_instances = contextual->num_instances_;
2198*6777b538SAndroid Build Coastguard Worker       instances = contextual->instances_;
2199*6777b538SAndroid Build Coastguard Worker       result += sizeof(*instances) * num_instances;
2200*6777b538SAndroid Build Coastguard Worker     } else {
2201*6777b538SAndroid Build Coastguard Worker       num_instances = 1;
2202*6777b538SAndroid Build Coastguard Worker       instances = &contextual->instance_;
2203*6777b538SAndroid Build Coastguard Worker     }
2204*6777b538SAndroid Build Coastguard Worker     for (i = 0; i < num_instances; i++) {
2205*6777b538SAndroid Build Coastguard Worker       const BrotliEncoderDictionary* dict = &instances[i];
2206*6777b538SAndroid Build Coastguard Worker       result += dict->trie.pool_capacity * sizeof(BrotliTrieNode);
2207*6777b538SAndroid Build Coastguard Worker       if (dict->hash_table_data_words_) {
2208*6777b538SAndroid Build Coastguard Worker         result += sizeof(kStaticDictionaryHashWords);
2209*6777b538SAndroid Build Coastguard Worker       }
2210*6777b538SAndroid Build Coastguard Worker       if (dict->hash_table_data_lengths_) {
2211*6777b538SAndroid Build Coastguard Worker         result += sizeof(kStaticDictionaryHashLengths);
2212*6777b538SAndroid Build Coastguard Worker       }
2213*6777b538SAndroid Build Coastguard Worker       if (dict->buckets_data_) {
2214*6777b538SAndroid Build Coastguard Worker         result += sizeof(*dict->buckets_data_) * dict->buckets_alloc_size_;
2215*6777b538SAndroid Build Coastguard Worker       }
2216*6777b538SAndroid Build Coastguard Worker       if (dict->dict_words_data_) {
2217*6777b538SAndroid Build Coastguard Worker         result += sizeof(*dict->dict_words) * dict->dict_words_alloc_size_;
2218*6777b538SAndroid Build Coastguard Worker       }
2219*6777b538SAndroid Build Coastguard Worker       if (dict->words_instance_) {
2220*6777b538SAndroid Build Coastguard Worker         result += sizeof(*dict->words_instance_);
2221*6777b538SAndroid Build Coastguard Worker         /* data_size not added here: it is never allocated by the
2222*6777b538SAndroid Build Coastguard Worker            SharedEncoderDictionary, instead it always points to the file
2223*6777b538SAndroid Build Coastguard Worker            already loaded in memory. So if the caller wants to include
2224*6777b538SAndroid Build Coastguard Worker            this memory as well, add the size of the loaded dictionary
2225*6777b538SAndroid Build Coastguard Worker            file to this. */
2226*6777b538SAndroid Build Coastguard Worker       }
2227*6777b538SAndroid Build Coastguard Worker     }
2228*6777b538SAndroid Build Coastguard Worker     return result + overhead;
2229*6777b538SAndroid Build Coastguard Worker   }
2230*6777b538SAndroid Build Coastguard Worker   return 0;  /* error */
2231*6777b538SAndroid Build Coastguard Worker }
2232*6777b538SAndroid Build Coastguard Worker 
2233*6777b538SAndroid Build Coastguard Worker #if defined(BROTLI_TEST)
2234*6777b538SAndroid Build Coastguard Worker size_t MakeUncompressedStreamForTest(const uint8_t*, size_t, uint8_t*);
MakeUncompressedStreamForTest(const uint8_t * input,size_t input_size,uint8_t * output)2235*6777b538SAndroid Build Coastguard Worker size_t MakeUncompressedStreamForTest(
2236*6777b538SAndroid Build Coastguard Worker     const uint8_t* input, size_t input_size, uint8_t* output) {
2237*6777b538SAndroid Build Coastguard Worker   return MakeUncompressedStream(input, input_size, output);
2238*6777b538SAndroid Build Coastguard Worker }
2239*6777b538SAndroid Build Coastguard Worker #endif
2240*6777b538SAndroid Build Coastguard Worker 
2241*6777b538SAndroid Build Coastguard Worker #if defined(__cplusplus) || defined(c_plusplus)
2242*6777b538SAndroid Build Coastguard Worker }  /* extern "C" */
2243*6777b538SAndroid Build Coastguard Worker #endif
2244