Coverage Report

Created: 2025-11-14 07:32

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