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