Coverage Report

Created: 2026-04-09 07:06

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