brotli 0.2.1 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 654b30a28d785e3484c1305d26f50115c8310f1098826444c54b697fa059882f
4
- data.tar.gz: 66db5adaf23432e61b3b8ca73d1f9c9fea8a0402e96ed550b3ba74b2b3a9e2f7
3
+ metadata.gz: 81b3e01265c409832de742771d83abbfa21c0445a0ad3fa44d8ae646998786d5
4
+ data.tar.gz: 79d4545e4c507a0ef774412c005fe8ac999a31457347fbea31e21533c194b0ba
5
5
  SHA512:
6
- metadata.gz: eb94be99c4623a954eee6d8d32e59870980b412a8691fee3a2f86ba9de655e28d88df7957a89af4a4d20504eb586e6ba1f1a05b9d9f617f94dfe00344324d4e8
7
- data.tar.gz: d056d603ce93f6580fe7fcf7b111a30ffce2e45d215a1f0bc189599665dd0361dbdc7d3d44dd0642bc2e61174672e11bd65666f2f2083d612223c0aa19128220
6
+ metadata.gz: 9380345b150e5d8e2de3d9c58e4a1b5e6e4ac293f247c9a86caf5b9d1e9026b9b3a89d91254d91edf12212e553fe979894c1a01d6e0d1bfbf5cb1fd37571a7af
7
+ data.tar.gz: 64bb2538e6d712929a8fdfb2511f612b638c0f33d47eb38b973c9a26876e8ed44642ab1198dcc9f92614716e2b2d5b519705287897dca3ecd66e102d21a41b4e
@@ -9,7 +9,7 @@ rvm:
9
9
  - 2.2.8
10
10
  - 2.3.5
11
11
  - 2.4.2
12
- - 2.5.0-preview1
12
+ - 2.5.3
13
13
  env:
14
14
  global:
15
15
  - RANTLY_COUNT=10000
@@ -25,6 +25,3 @@ deploy:
25
25
  tags: true
26
26
  repo: miyucy/brotli
27
27
  script: bundle exec rake && ./smoke.sh
28
- matrix:
29
- allow_failures:
30
- - rvm: 2.5.0-preview1
@@ -1,3 +1,3 @@
1
1
  module Brotli
2
- VERSION = '0.2.1'
2
+ VERSION = '0.2.2'
3
3
  end
@@ -71,7 +71,7 @@ OR:
71
71
  */
72
72
  #if BROTLI_GNUC_HAS_BUILTIN(__builtin_expect, 3, 0, 0) || \
73
73
  BROTLI_INTEL_VERSION_CHECK(16, 0, 0) || \
74
- BROTLI_SUNPRO_VERSION_CHECK(5, 12, 0) || \
74
+ BROTLI_SUNPRO_VERSION_CHECK(5, 15, 0) || \
75
75
  BROTLI_ARM_VERSION_CHECK(4, 1, 0) || \
76
76
  BROTLI_IBM_VERSION_CHECK(10, 1, 0) || \
77
77
  BROTLI_TI_VERSION_CHECK(7, 3, 0) || \
@@ -180,6 +180,12 @@ OR:
180
180
  #define BROTLI_UNUSED_FUNCTION static BROTLI_INLINE
181
181
  #endif
182
182
 
183
+ #if BROTLI_GNUC_HAS_ATTRIBUTE(aligned, 2, 7, 0)
184
+ #define BROTLI_ALIGNED(N) __attribute__((aligned(N)))
185
+ #else
186
+ #define BROTLI_ALIGNED(N)
187
+ #endif
188
+
183
189
  #if (defined(__ARM_ARCH) && (__ARM_ARCH == 7)) || \
184
190
  (defined(M_ARM) && (M_ARM == 7))
185
191
  #define BROTLI_TARGET_ARMV7
@@ -187,9 +193,20 @@ OR:
187
193
 
188
194
  #if (defined(__ARM_ARCH) && (__ARM_ARCH == 8)) || \
189
195
  defined(__aarch64__) || defined(__ARM64_ARCH_8__)
190
- #define BROTLI_TARGET_ARMV8
196
+ #define BROTLI_TARGET_ARMV8_ANY
197
+
198
+ #if defined(__ARM_32BIT_STATE)
199
+ #define BROTLI_TARGET_ARMV8_32
200
+ #elif defined(__ARM_64BIT_STATE)
201
+ #define BROTLI_TARGET_ARMV8_64
202
+ #endif
203
+
191
204
  #endif /* ARMv8 */
192
205
 
206
+ #if defined(__ARM_NEON__) || defined(__ARM_NEON)
207
+ #define BROTLI_TARGET_NEON
208
+ #endif
209
+
193
210
  #if defined(__i386) || defined(_M_IX86)
194
211
  #define BROTLI_TARGET_X86
195
212
  #endif
@@ -210,7 +227,7 @@ OR:
210
227
  #define BROTLI_64_BITS 1
211
228
  #elif defined(BROTLI_BUILD_32_BIT)
212
229
  #define BROTLI_64_BITS 0
213
- #elif defined(BROTLI_TARGET_X64) || defined(BROTLI_TARGET_ARMV8) || \
230
+ #elif defined(BROTLI_TARGET_X64) || defined(BROTLI_TARGET_ARMV8_64) || \
214
231
  defined(BROTLI_TARGET_POWERPC64) || defined(BROTLI_TARGET_RISCV64)
215
232
  #define BROTLI_64_BITS 1
216
233
  #else
@@ -261,7 +278,7 @@ OR:
261
278
  #if defined(BROTLI_BUILD_PORTABLE)
262
279
  #define BROTLI_ALIGNED_READ (!!1)
263
280
  #elif defined(BROTLI_TARGET_X86) || defined(BROTLI_TARGET_X64) || \
264
- defined(BROTLI_TARGET_ARMV7) || defined(BROTLI_TARGET_ARMV8) || \
281
+ defined(BROTLI_TARGET_ARMV7) || defined(BROTLI_TARGET_ARMV8_ANY) || \
265
282
  defined(BROTLI_TARGET_RISCV64)
266
283
  /* Allow unaligned read only for white-listed CPUs. */
267
284
  #define BROTLI_ALIGNED_READ (!!0)
@@ -291,6 +308,33 @@ static BROTLI_INLINE void BrotliUnalignedWrite64(void* p, uint64_t v) {
291
308
  }
292
309
  #else /* BROTLI_ALIGNED_READ */
293
310
  /* Unaligned memory access is allowed: just cast pointer to requested type. */
311
+ #if defined(ADDRESS_SANITIZER) || defined(THREAD_SANITIZER) || \
312
+ defined(MEMORY_SANITIZER)
313
+ /* Consider we have an unaligned load/store of 4 bytes from address 0x...05.
314
+ AddressSanitizer will treat it as a 3-byte access to the range 05:07 and
315
+ will miss a bug if 08 is the first unaddressable byte.
316
+ ThreadSanitizer will also treat this as a 3-byte access to 05:07 and will
317
+ miss a race between this access and some other accesses to 08.
318
+ MemorySanitizer will correctly propagate the shadow on unaligned stores
319
+ and correctly report bugs on unaligned loads, but it may not properly
320
+ update and report the origin of the uninitialized memory.
321
+ For all three tools, replacing an unaligned access with a tool-specific
322
+ callback solves the problem. */
323
+ #if defined(__cplusplus)
324
+ extern "C" {
325
+ #endif /* __cplusplus */
326
+ uint16_t __sanitizer_unaligned_load16(const void* p);
327
+ uint32_t __sanitizer_unaligned_load32(const void* p);
328
+ uint64_t __sanitizer_unaligned_load64(const void* p);
329
+ void __sanitizer_unaligned_store64(void* p, uint64_t v);
330
+ #if defined(__cplusplus)
331
+ } /* extern "C" */
332
+ #endif /* __cplusplus */
333
+ #define BrotliUnalignedRead16 __sanitizer_unaligned_load16
334
+ #define BrotliUnalignedRead32 __sanitizer_unaligned_load32
335
+ #define BrotliUnalignedRead64 __sanitizer_unaligned_load64
336
+ #define BrotliUnalignedWrite64 __sanitizer_unaligned_store64
337
+ #else
294
338
  static BROTLI_INLINE uint16_t BrotliUnalignedRead16(const void* p) {
295
339
  return *(const uint16_t*)p;
296
340
  }
@@ -306,16 +350,31 @@ static BROTLI_INLINE void BrotliUnalignedWrite64(void* p, uint64_t v) {
306
350
  }
307
351
  #else /* BROTLI_64_BITS */
308
352
  /* Avoid emitting LDRD / STRD, which require properly aligned address. */
353
+ /* If __attribute__(aligned) is available, use that. Otherwise, memcpy. */
354
+
355
+ #if BROTLI_GNUC_HAS_ATTRIBUTE(aligned, 2, 7, 0)
356
+ typedef BROTLI_ALIGNED(1) uint64_t brotli_unaligned_uint64_t;
357
+
358
+ static BROTLI_INLINE uint64_t BrotliUnalignedRead64(const void* p) {
359
+ return (uint64_t) ((brotli_unaligned_uint64_t*) p)[0];
360
+ }
361
+ static BROTLI_INLINE void BrotliUnalignedWrite64(void* p, uint64_t v) {
362
+ brotli_unaligned_uint64_t* dwords = (brotli_unaligned_uint64_t*) p;
363
+ dwords[0] = (brotli_unaligned_uint64_t) v;
364
+ }
365
+ #else /* BROTLI_GNUC_HAS_ATTRIBUTE(aligned, 2, 7, 0) */
309
366
  static BROTLI_INLINE uint64_t BrotliUnalignedRead64(const void* p) {
310
- const uint32_t* dwords = (const uint32_t*)p;
311
- return dwords[0] | ((uint64_t)dwords[1] << 32);
367
+ uint64_t v;
368
+ memcpy(&v, p, sizeof(uint64_t));
369
+ return v;
312
370
  }
371
+
313
372
  static BROTLI_INLINE void BrotliUnalignedWrite64(void* p, uint64_t v) {
314
- uint32_t* dwords = (uint32_t *)p;
315
- dwords[0] = (uint32_t)v;
316
- dwords[1] = (uint32_t)(v >> 32);
373
+ memcpy(p, &v, sizeof(uint64_t));
317
374
  }
375
+ #endif /* BROTLI_GNUC_HAS_ATTRIBUTE(aligned, 2, 7, 0) */
318
376
  #endif /* BROTLI_64_BITS */
377
+ #endif /* ASAN / TSAN / MSAN */
319
378
  #endif /* BROTLI_ALIGNED_READ */
320
379
 
321
380
  #if BROTLI_LITTLE_ENDIAN
@@ -400,7 +459,7 @@ static BROTLI_INLINE void BROTLI_UNALIGNED_STORE64LE(void* p, uint64_t v) {
400
459
  #define BROTLI_IS_CONSTANT(x) (!!0)
401
460
  #endif
402
461
 
403
- #if defined(BROTLI_TARGET_ARMV7) || defined(BROTLI_TARGET_ARMV8)
462
+ #if defined(BROTLI_TARGET_ARMV7) || defined(BROTLI_TARGET_ARMV8_ANY)
404
463
  #define BROTLI_HAS_UBFX (!!1)
405
464
  #else
406
465
  #define BROTLI_HAS_UBFX (!!0)
@@ -427,7 +486,7 @@ static BROTLI_INLINE void BrotliDump(const char* f, int l, const char* fn) {
427
486
  /* TODO: add appropriate icc/sunpro/arm/ibm/ti checks. */
428
487
  #if (BROTLI_GNUC_VERSION_CHECK(3, 0, 0) || defined(__llvm__)) && \
429
488
  !defined(BROTLI_BUILD_NO_RBIT)
430
- #if defined(BROTLI_TARGET_ARMV7) || defined(BROTLI_TARGET_ARMV8)
489
+ #if defined(BROTLI_TARGET_ARMV7) || defined(BROTLI_TARGET_ARMV8_ANY)
431
490
  /* TODO: detect ARMv6T2 and enable this code for it. */
432
491
  static BROTLI_INLINE brotli_reg_t BrotliRBit(brotli_reg_t input) {
433
492
  brotli_reg_t output;
@@ -191,11 +191,11 @@ static int ToUpperCase(uint8_t* p) {
191
191
  }
192
192
 
193
193
  int BrotliTransformDictionaryWord(uint8_t* dst, const uint8_t* word, int len,
194
- const BrotliTransforms* transforms, int transfom_idx) {
194
+ const BrotliTransforms* transforms, int transform_idx) {
195
195
  int idx = 0;
196
- const uint8_t* prefix = BROTLI_TRANSFORM_PREFIX(transforms, transfom_idx);
197
- uint8_t type = BROTLI_TRANSFORM_TYPE(transforms, transfom_idx);
198
- const uint8_t* suffix = BROTLI_TRANSFORM_SUFFIX(transforms, transfom_idx);
196
+ const uint8_t* prefix = BROTLI_TRANSFORM_PREFIX(transforms, transform_idx);
197
+ uint8_t type = BROTLI_TRANSFORM_TYPE(transforms, transform_idx);
198
+ const uint8_t* suffix = BROTLI_TRANSFORM_SUFFIX(transforms, transform_idx);
199
199
  {
200
200
  int prefix_len = *prefix++;
201
201
  while (prefix_len--) { dst[idx++] = *prefix++; }
@@ -14,13 +14,13 @@
14
14
  BrotliEncoderVersion methods. */
15
15
 
16
16
  /* Semantic version, calculated as (MAJOR << 24) | (MINOR << 12) | PATCH */
17
- #define BROTLI_VERSION 0x1000005
17
+ #define BROTLI_VERSION 0x1000007
18
18
 
19
19
  /* This macro is used by build system to produce Libtool-friendly soname. See
20
20
  https://www.gnu.org/software/libtool/manual/html_node/Libtool-versioning.html
21
21
  */
22
22
 
23
23
  /* ABI version, calculated as (CURRENT << 24) | (REVISION << 12) | AGE */
24
- #define BROTLI_ABI_VERSION 0x1005000
24
+ #define BROTLI_ABI_VERSION 0x1007000
25
25
 
26
26
  #endif /* BROTLI_COMMON_VERSION_H_ */
@@ -6,10 +6,6 @@
6
6
 
7
7
  #include <brotli/decode.h>
8
8
 
9
- #if defined(__ARM_NEON__)
10
- #include <arm_neon.h>
11
- #endif
12
-
13
9
  #include <stdlib.h> /* free, malloc */
14
10
  #include <string.h> /* memcpy, memset */
15
11
 
@@ -24,6 +20,10 @@
24
20
  #include "./prefix.h"
25
21
  #include "./state.h"
26
22
 
23
+ #if defined(BROTLI_TARGET_NEON)
24
+ #include <arm_neon.h>
25
+ #endif
26
+
27
27
  #if defined(__cplusplus) || defined(c_plusplus)
28
28
  extern "C" {
29
29
  #endif
@@ -167,7 +167,7 @@ static BrotliDecoderErrorCode DecodeWindowBits(BrotliDecoderState* s,
167
167
  }
168
168
 
169
169
  static BROTLI_INLINE void memmove16(uint8_t* dst, uint8_t* src) {
170
- #if defined(__ARM_NEON__)
170
+ #if defined(BROTLI_TARGET_NEON)
171
171
  vst1q_u8(dst, vld1q_u8(src));
172
172
  #else
173
173
  uint32_t buffer[4];
@@ -347,15 +347,17 @@ static BrotliDecoderErrorCode BROTLI_NOINLINE DecodeMetaBlockLength(
347
347
  static BROTLI_INLINE uint32_t DecodeSymbol(uint32_t bits,
348
348
  const HuffmanCode* table,
349
349
  BrotliBitReader* br) {
350
- table += bits & HUFFMAN_TABLE_MASK;
351
- if (table->bits > HUFFMAN_TABLE_BITS) {
352
- uint32_t nbits = table->bits - HUFFMAN_TABLE_BITS;
350
+ BROTLI_HC_MARK_TABLE_FOR_FAST_LOAD(table);
351
+ BROTLI_HC_ADJUST_TABLE_INDEX(table, bits & HUFFMAN_TABLE_MASK);
352
+ if (BROTLI_HC_FAST_LOAD_BITS(table) > HUFFMAN_TABLE_BITS) {
353
+ uint32_t nbits = BROTLI_HC_FAST_LOAD_BITS(table) - HUFFMAN_TABLE_BITS;
353
354
  BrotliDropBits(br, HUFFMAN_TABLE_BITS);
354
- table += table->value;
355
- table += (bits >> HUFFMAN_TABLE_BITS) & BitMask(nbits);
355
+ BROTLI_HC_ADJUST_TABLE_INDEX(table,
356
+ BROTLI_HC_FAST_LOAD_VALUE(table) +
357
+ ((bits >> HUFFMAN_TABLE_BITS) & BitMask(nbits)));
356
358
  }
357
- BrotliDropBits(br, table->bits);
358
- return table->value;
359
+ BrotliDropBits(br, BROTLI_HC_FAST_LOAD_BITS(table));
360
+ return BROTLI_HC_FAST_LOAD_VALUE(table);
359
361
  }
360
362
 
361
363
  /* Reads and decodes the next Huffman code from bit-stream.
@@ -371,19 +373,20 @@ static BROTLI_NOINLINE BROTLI_BOOL SafeDecodeSymbol(
371
373
  const HuffmanCode* table, BrotliBitReader* br, uint32_t* result) {
372
374
  uint32_t val;
373
375
  uint32_t available_bits = BrotliGetAvailableBits(br);
376
+ BROTLI_HC_MARK_TABLE_FOR_FAST_LOAD(table);
374
377
  if (available_bits == 0) {
375
- if (table->bits == 0) {
376
- *result = table->value;
378
+ if (BROTLI_HC_FAST_LOAD_BITS(table) == 0) {
379
+ *result = BROTLI_HC_FAST_LOAD_VALUE(table);
377
380
  return BROTLI_TRUE;
378
381
  }
379
382
  return BROTLI_FALSE; /* No valid bits at all. */
380
383
  }
381
384
  val = (uint32_t)BrotliGetBitsUnmasked(br);
382
- table += val & HUFFMAN_TABLE_MASK;
383
- if (table->bits <= HUFFMAN_TABLE_BITS) {
384
- if (table->bits <= available_bits) {
385
- BrotliDropBits(br, table->bits);
386
- *result = table->value;
385
+ BROTLI_HC_ADJUST_TABLE_INDEX(table, val & HUFFMAN_TABLE_MASK);
386
+ if (BROTLI_HC_FAST_LOAD_BITS(table) <= HUFFMAN_TABLE_BITS) {
387
+ if (BROTLI_HC_FAST_LOAD_BITS(table) <= available_bits) {
388
+ BrotliDropBits(br, BROTLI_HC_FAST_LOAD_BITS(table));
389
+ *result = BROTLI_HC_FAST_LOAD_VALUE(table);
387
390
  return BROTLI_TRUE;
388
391
  } else {
389
392
  return BROTLI_FALSE; /* Not enough bits for the first level. */
@@ -394,15 +397,15 @@ static BROTLI_NOINLINE BROTLI_BOOL SafeDecodeSymbol(
394
397
  }
395
398
 
396
399
  /* Speculatively drop HUFFMAN_TABLE_BITS. */
397
- val = (val & BitMask(table->bits)) >> HUFFMAN_TABLE_BITS;
400
+ val = (val & BitMask(BROTLI_HC_FAST_LOAD_BITS(table))) >> HUFFMAN_TABLE_BITS;
398
401
  available_bits -= HUFFMAN_TABLE_BITS;
399
- table += table->value + val;
400
- if (available_bits < table->bits) {
402
+ BROTLI_HC_ADJUST_TABLE_INDEX(table, BROTLI_HC_FAST_LOAD_VALUE(table) + val);
403
+ if (available_bits < BROTLI_HC_FAST_LOAD_BITS(table)) {
401
404
  return BROTLI_FALSE; /* Not enough bits for the second level. */
402
405
  }
403
406
 
404
- BrotliDropBits(br, HUFFMAN_TABLE_BITS + table->bits);
405
- *result = table->value;
407
+ BrotliDropBits(br, HUFFMAN_TABLE_BITS + BROTLI_HC_FAST_LOAD_BITS(table));
408
+ *result = BROTLI_HC_FAST_LOAD_VALUE(table);
406
409
  return BROTLI_TRUE;
407
410
  }
408
411
 
@@ -425,9 +428,10 @@ static BROTLI_INLINE void PreloadSymbol(int safe,
425
428
  if (safe) {
426
429
  return;
427
430
  }
428
- table += BrotliGetBits(br, HUFFMAN_TABLE_BITS);
429
- *bits = table->bits;
430
- *value = table->value;
431
+ BROTLI_HC_MARK_TABLE_FOR_FAST_LOAD(table);
432
+ BROTLI_HC_ADJUST_TABLE_INDEX(table, BrotliGetBits(br, HUFFMAN_TABLE_BITS));
433
+ *bits = BROTLI_HC_FAST_LOAD_BITS(table);
434
+ *value = BROTLI_HC_FAST_LOAD_VALUE(table);
431
435
  }
432
436
 
433
437
  /* Decodes the next Huffman code using data prepared by PreloadSymbol.
@@ -441,10 +445,11 @@ static BROTLI_INLINE uint32_t ReadPreloadedSymbol(const HuffmanCode* table,
441
445
  uint32_t val = BrotliGet16BitsUnmasked(br);
442
446
  const HuffmanCode* ext = table + (val & HUFFMAN_TABLE_MASK) + *value;
443
447
  uint32_t mask = BitMask((*bits - HUFFMAN_TABLE_BITS));
448
+ BROTLI_HC_MARK_TABLE_FOR_FAST_LOAD(ext);
444
449
  BrotliDropBits(br, HUFFMAN_TABLE_BITS);
445
- ext += (val >> HUFFMAN_TABLE_BITS) & mask;
446
- BrotliDropBits(br, ext->bits);
447
- result = ext->value;
450
+ BROTLI_HC_ADJUST_TABLE_INDEX(ext, (val >> HUFFMAN_TABLE_BITS) & mask);
451
+ BrotliDropBits(br, BROTLI_HC_FAST_LOAD_BITS(ext));
452
+ result = BROTLI_HC_FAST_LOAD_VALUE(ext);
448
453
  } else {
449
454
  BrotliDropBits(br, *bits);
450
455
  }
@@ -597,6 +602,7 @@ static BrotliDecoderErrorCode ReadSymbolCodeLengths(
597
602
  while (symbol < alphabet_size && space > 0) {
598
603
  const HuffmanCode* p = s->table;
599
604
  uint32_t code_len;
605
+ BROTLI_HC_MARK_TABLE_FOR_FAST_LOAD(p);
600
606
  if (!BrotliCheckInputAmount(br, BROTLI_SHORT_FILL_BIT_WINDOW_READ)) {
601
607
  s->symbol = symbol;
602
608
  s->repeat = repeat;
@@ -606,10 +612,10 @@ static BrotliDecoderErrorCode ReadSymbolCodeLengths(
606
612
  return BROTLI_DECODER_NEEDS_MORE_INPUT;
607
613
  }
608
614
  BrotliFillBitWindow16(br);
609
- p += BrotliGetBitsUnmasked(br) &
610
- BitMask(BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH);
611
- BrotliDropBits(br, p->bits); /* Use 1..5 bits. */
612
- code_len = p->value; /* code_len == 0..17 */
615
+ BROTLI_HC_ADJUST_TABLE_INDEX(p, BrotliGetBitsUnmasked(br) &
616
+ BitMask(BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH));
617
+ BrotliDropBits(br, BROTLI_HC_FAST_LOAD_BITS(p)); /* Use 1..5 bits. */
618
+ code_len = BROTLI_HC_FAST_LOAD_VALUE(p); /* code_len == 0..17 */
613
619
  if (code_len < BROTLI_REPEAT_PREVIOUS_CODE_LENGTH) {
614
620
  ProcessSingleCodeLength(code_len, &symbol, &repeat, &space,
615
621
  &prev_code_len, symbol_lists, code_length_histo, next_symbol);
@@ -637,31 +643,34 @@ static BrotliDecoderErrorCode SafeReadSymbolCodeLengths(
637
643
  uint32_t code_len;
638
644
  uint32_t available_bits;
639
645
  uint32_t bits = 0;
646
+ BROTLI_HC_MARK_TABLE_FOR_FAST_LOAD(p);
640
647
  if (get_byte && !BrotliPullByte(br)) return BROTLI_DECODER_NEEDS_MORE_INPUT;
641
648
  get_byte = BROTLI_FALSE;
642
649
  available_bits = BrotliGetAvailableBits(br);
643
650
  if (available_bits != 0) {
644
651
  bits = (uint32_t)BrotliGetBitsUnmasked(br);
645
652
  }
646
- p += bits & BitMask(BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH);
647
- if (p->bits > available_bits) {
653
+ BROTLI_HC_ADJUST_TABLE_INDEX(p,
654
+ bits & BitMask(BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH));
655
+ if (BROTLI_HC_FAST_LOAD_BITS(p) > available_bits) {
648
656
  get_byte = BROTLI_TRUE;
649
657
  continue;
650
658
  }
651
- code_len = p->value; /* code_len == 0..17 */
659
+ code_len = BROTLI_HC_FAST_LOAD_VALUE(p); /* code_len == 0..17 */
652
660
  if (code_len < BROTLI_REPEAT_PREVIOUS_CODE_LENGTH) {
653
- BrotliDropBits(br, p->bits);
661
+ BrotliDropBits(br, BROTLI_HC_FAST_LOAD_BITS(p));
654
662
  ProcessSingleCodeLength(code_len, &s->symbol, &s->repeat, &s->space,
655
663
  &s->prev_code_len, s->symbol_lists, s->code_length_histo,
656
664
  s->next_symbol);
657
665
  } else { /* code_len == 16..17, extra_bits == 2..3 */
658
666
  uint32_t extra_bits = code_len - 14U;
659
- uint32_t repeat_delta = (bits >> p->bits) & BitMask(extra_bits);
660
- if (available_bits < p->bits + extra_bits) {
667
+ uint32_t repeat_delta = (bits >> BROTLI_HC_FAST_LOAD_BITS(p)) &
668
+ BitMask(extra_bits);
669
+ if (available_bits < BROTLI_HC_FAST_LOAD_BITS(p) + extra_bits) {
661
670
  get_byte = BROTLI_TRUE;
662
671
  continue;
663
672
  }
664
- BrotliDropBits(br, p->bits + extra_bits);
673
+ BrotliDropBits(br, BROTLI_HC_FAST_LOAD_BITS(p) + extra_bits);
665
674
  ProcessRepeatedCodeLength(code_len, repeat_delta, alphabet_size,
666
675
  &s->symbol, &s->repeat, &s->space, &s->prev_code_len,
667
676
  &s->repeat_code_len, s->symbol_lists, s->code_length_histo,
@@ -142,8 +142,7 @@ void BrotliBuildCodeLengthsHuffmanTable(HuffmanCode* table,
142
142
 
143
143
  /* Special case: all symbols but one have 0 code length. */
144
144
  if (offset[0] == 0) {
145
- code.bits = 0;
146
- code.value = (uint16_t)sorted[0];
145
+ code = ConstructHuffmanCode(0, (uint16_t)sorted[0]);
147
146
  for (key = 0; key < (brotli_reg_t)table_size; ++key) {
148
147
  table[key] = code;
149
148
  }
@@ -157,9 +156,8 @@ void BrotliBuildCodeLengthsHuffmanTable(HuffmanCode* table,
157
156
  bits = 1;
158
157
  step = 2;
159
158
  do {
160
- code.bits = (uint8_t)bits;
161
159
  for (bits_count = count[bits]; bits_count != 0; --bits_count) {
162
- code.value = (uint16_t)sorted[symbol++];
160
+ code = ConstructHuffmanCode((uint8_t)bits, (uint16_t)sorted[symbol++]);
163
161
  ReplicateValue(&table[BrotliReverseBits(key)], step, table_size, code);
164
162
  key += key_step;
165
163
  }
@@ -211,11 +209,10 @@ uint32_t BrotliBuildHuffmanTable(HuffmanCode* root_table,
211
209
  bits = 1;
212
210
  step = 2;
213
211
  do {
214
- code.bits = (uint8_t)bits;
215
212
  symbol = bits - (BROTLI_HUFFMAN_MAX_CODE_LENGTH + 1);
216
213
  for (bits_count = count[bits]; bits_count != 0; --bits_count) {
217
214
  symbol = symbol_lists[symbol];
218
- code.value = (uint16_t)symbol;
215
+ code = ConstructHuffmanCode((uint8_t)bits, (uint16_t)symbol);
219
216
  ReplicateValue(&table[BrotliReverseBits(key)], step, table_size, code);
220
217
  key += key_step;
221
218
  }
@@ -244,14 +241,13 @@ uint32_t BrotliBuildHuffmanTable(HuffmanCode* root_table,
244
241
  total_size += table_size;
245
242
  sub_key = BrotliReverseBits(key);
246
243
  key += key_step;
247
- root_table[sub_key].bits = (uint8_t)(table_bits + root_bits);
248
- root_table[sub_key].value =
249
- (uint16_t)(((size_t)(table - root_table)) - sub_key);
244
+ root_table[sub_key] = ConstructHuffmanCode(
245
+ (uint8_t)(table_bits + root_bits),
246
+ (uint16_t)(((size_t)(table - root_table)) - sub_key));
250
247
  sub_key = 0;
251
248
  }
252
- code.bits = (uint8_t)(len - root_bits);
253
249
  symbol = symbol_lists[symbol];
254
- code.value = (uint16_t)symbol;
250
+ code = ConstructHuffmanCode((uint8_t)(len - root_bits), (uint16_t)symbol);
255
251
  ReplicateValue(
256
252
  &table[BrotliReverseBits(sub_key)], step, table_size, code);
257
253
  sub_key += sub_key_step;
@@ -270,35 +266,28 @@ uint32_t BrotliBuildSimpleHuffmanTable(HuffmanCode* table,
270
266
  const uint32_t goal_size = 1U << root_bits;
271
267
  switch (num_symbols) {
272
268
  case 0:
273
- table[0].bits = 0;
274
- table[0].value = val[0];
269
+ table[0] = ConstructHuffmanCode(0, val[0]);
275
270
  break;
276
271
  case 1:
277
- table[0].bits = 1;
278
- table[1].bits = 1;
279
272
  if (val[1] > val[0]) {
280
- table[0].value = val[0];
281
- table[1].value = val[1];
273
+ table[0] = ConstructHuffmanCode(1, val[0]);
274
+ table[1] = ConstructHuffmanCode(1, val[1]);
282
275
  } else {
283
- table[0].value = val[1];
284
- table[1].value = val[0];
276
+ table[0] = ConstructHuffmanCode(1, val[1]);
277
+ table[1] = ConstructHuffmanCode(1, val[0]);
285
278
  }
286
279
  table_size = 2;
287
280
  break;
288
281
  case 2:
289
- table[0].bits = 1;
290
- table[0].value = val[0];
291
- table[2].bits = 1;
292
- table[2].value = val[0];
282
+ table[0] = ConstructHuffmanCode(1, val[0]);
283
+ table[2] = ConstructHuffmanCode(1, val[0]);
293
284
  if (val[2] > val[1]) {
294
- table[1].value = val[1];
295
- table[3].value = val[2];
285
+ table[1] = ConstructHuffmanCode(2, val[1]);
286
+ table[3] = ConstructHuffmanCode(2, val[2]);
296
287
  } else {
297
- table[1].value = val[2];
298
- table[3].value = val[1];
288
+ table[1] = ConstructHuffmanCode(2, val[2]);
289
+ table[3] = ConstructHuffmanCode(2, val[1]);
299
290
  }
300
- table[1].bits = 2;
301
- table[3].bits = 2;
302
291
  table_size = 4;
303
292
  break;
304
293
  case 3: {
@@ -312,33 +301,27 @@ uint32_t BrotliBuildSimpleHuffmanTable(HuffmanCode* table,
312
301
  }
313
302
  }
314
303
  }
315
- for (i = 0; i < 4; ++i) {
316
- table[i].bits = 2;
317
- }
318
- table[0].value = val[0];
319
- table[2].value = val[1];
320
- table[1].value = val[2];
321
- table[3].value = val[3];
304
+ table[0] = ConstructHuffmanCode(2, val[0]);
305
+ table[2] = ConstructHuffmanCode(2, val[1]);
306
+ table[1] = ConstructHuffmanCode(2, val[2]);
307
+ table[3] = ConstructHuffmanCode(2, val[3]);
322
308
  table_size = 4;
323
309
  break;
324
310
  }
325
311
  case 4: {
326
- int i;
327
312
  if (val[3] < val[2]) {
328
313
  uint16_t t = val[3];
329
314
  val[3] = val[2];
330
315
  val[2] = t;
331
316
  }
332
- for (i = 0; i < 7; ++i) {
333
- table[i].value = val[0];
334
- table[i].bits = (uint8_t)(1 + (i & 1));
335
- }
336
- table[1].value = val[1];
337
- table[3].value = val[2];
338
- table[5].value = val[1];
339
- table[7].value = val[3];
340
- table[3].bits = 3;
341
- table[7].bits = 3;
317
+ table[0] = ConstructHuffmanCode(1, val[0]);
318
+ table[1] = ConstructHuffmanCode(2, val[1]);
319
+ table[2] = ConstructHuffmanCode(1, val[0]);
320
+ table[3] = ConstructHuffmanCode(3, val[2]);
321
+ table[4] = ConstructHuffmanCode(1, val[0]);
322
+ table[5] = ConstructHuffmanCode(2, val[1]);
323
+ table[6] = ConstructHuffmanCode(1, val[0]);
324
+ table[7] = ConstructHuffmanCode(3, val[3]);
342
325
  table_size = 8;
343
326
  break;
344
327
  }
@@ -33,11 +33,66 @@ static const uint16_t kMaxHuffmanTableSize[] = {
33
33
 
34
34
  #define BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH 5
35
35
 
36
+ #if ((defined(BROTLI_TARGET_ARMV7) || defined(BROTLI_TARGET_ARMV8_32)) && \
37
+ BROTLI_GNUC_HAS_ATTRIBUTE(aligned, 2, 7, 0))
38
+ #define BROTLI_HUFFMAN_CODE_FAST_LOAD
39
+ #endif
40
+
41
+ #if !defined(BROTLI_HUFFMAN_CODE_FAST_LOAD)
42
+ /* Do not create this struct directly - use the ConstructHuffmanCode
43
+ * constructor below! */
36
44
  typedef struct {
37
45
  uint8_t bits; /* number of bits used for this symbol */
38
46
  uint16_t value; /* symbol value or table offset */
39
47
  } HuffmanCode;
40
48
 
49
+ static BROTLI_INLINE HuffmanCode ConstructHuffmanCode(const uint8_t bits,
50
+ const uint16_t value) {
51
+ HuffmanCode h;
52
+ h.bits = bits;
53
+ h.value = value;
54
+ return h;
55
+ }
56
+
57
+ /* Please use the following macros to optimize HuffmanCode accesses in hot
58
+ * paths.
59
+ *
60
+ * For example, assuming |table| contains a HuffmanCode pointer:
61
+ *
62
+ * BROTLI_HC_MARK_TABLE_FOR_FAST_LOAD(table);
63
+ * BROTLI_HC_ADJUST_TABLE_INDEX(table, index_into_table);
64
+ * *bits = BROTLI_HC_GET_BITS(table);
65
+ * *value = BROTLI_HC_GET_VALUE(table);
66
+ * BROTLI_HC_ADJUST_TABLE_INDEX(table, offset);
67
+ * *bits2 = BROTLI_HC_GET_BITS(table);
68
+ * *value2 = BROTLI_HC_GET_VALUE(table);
69
+ *
70
+ */
71
+
72
+ #define BROTLI_HC_MARK_TABLE_FOR_FAST_LOAD(H)
73
+ #define BROTLI_HC_ADJUST_TABLE_INDEX(H, V) H += (V)
74
+
75
+ /* These must be given a HuffmanCode pointer! */
76
+ #define BROTLI_HC_FAST_LOAD_BITS(H) (H->bits)
77
+ #define BROTLI_HC_FAST_LOAD_VALUE(H) (H->value)
78
+
79
+ #else /* BROTLI_HUFFMAN_CODE_FAST_LOAD */
80
+
81
+ typedef BROTLI_ALIGNED(4) uint32_t HuffmanCode;
82
+
83
+ static BROTLI_INLINE HuffmanCode ConstructHuffmanCode(const uint8_t bits,
84
+ const uint16_t value) {
85
+ return ((value & 0xFFFF) << 16) | (bits & 0xFF);
86
+ }
87
+
88
+ #define BROTLI_HC_MARK_TABLE_FOR_FAST_LOAD(H) uint32_t __fastload_##H = (*H)
89
+ #define BROTLI_HC_ADJUST_TABLE_INDEX(H, V) H += (V); __fastload_##H = (*H)
90
+
91
+ /* These must be given a HuffmanCode pointer! */
92
+ #define BROTLI_HC_FAST_LOAD_BITS(H) ((__fastload_##H) & 0xFF)
93
+ #define BROTLI_HC_FAST_LOAD_VALUE(H) ((__fastload_##H) >> 16)
94
+ #endif /* BROTLI_HUFFMAN_CODE_FAST_LOAD */
95
+
41
96
  /* Builds Huffman lookup table assuming code lengths are in symbol order. */
42
97
  BROTLI_INTERNAL void BrotliBuildCodeLengthsHuffmanTable(HuffmanCode* root_table,
43
98
  const uint8_t* const code_lengths, uint16_t* count);
@@ -330,7 +330,7 @@ static size_t ComputeMinimumCopyLength(const float start_cost,
330
330
  REQUIRES: nodes[0..pos] satisfies that "ZopfliNode array invariant". */
331
331
  static uint32_t ComputeDistanceShortcut(const size_t block_start,
332
332
  const size_t pos,
333
- const size_t max_backward,
333
+ const size_t max_backward_limit,
334
334
  const size_t gap,
335
335
  const ZopfliNode* nodes) {
336
336
  const size_t clen = ZopfliNodeCopyLength(&nodes[pos]);
@@ -338,13 +338,13 @@ static uint32_t ComputeDistanceShortcut(const size_t block_start,
338
338
  const size_t dist = ZopfliNodeCopyDistance(&nodes[pos]);
339
339
  /* Since |block_start + pos| is the end position of the command, the copy part
340
340
  starts from |block_start + pos - clen|. Distances that are greater than
341
- this or greater than |max_backward| are static dictionary references, and
342
- do not update the last distances. Also distance code 0 (last distance)
343
- does not update the last distances. */
341
+ this or greater than |max_backward_limit| + |gap| are static dictionary
342
+ references, and do not update the last distances.
343
+ Also distance code 0 (last distance) does not update the last distances. */
344
344
  if (pos == 0) {
345
345
  return 0;
346
346
  } else if (dist + clen <= block_start + pos + gap &&
347
- dist <= max_backward + gap &&
347
+ dist <= max_backward_limit + gap &&
348
348
  ZopfliNodeDistanceCode(&nodes[pos]) > 0) {
349
349
  return (uint32_t)pos;
350
350
  } else {
@@ -454,9 +454,11 @@ static size_t UpdateNodes(
454
454
  break;
455
455
  }
456
456
  if (BROTLI_PREDICT_FALSE(backward > max_distance + gap)) {
457
+ /* Word dictionary -> ignore. */
457
458
  continue;
458
459
  }
459
460
  if (backward <= max_distance) {
461
+ /* Regular backward reference. */
460
462
  if (prev_ix >= cur_ix) {
461
463
  continue;
462
464
  }
@@ -564,14 +566,10 @@ static size_t ComputeShortestPathFromNodes(size_t num_bytes,
564
566
 
565
567
  /* REQUIRES: nodes != NULL and len(nodes) >= num_bytes + 1 */
566
568
  void BrotliZopfliCreateCommands(const size_t num_bytes,
567
- const size_t block_start,
568
- const size_t max_backward_limit,
569
- const ZopfliNode* nodes,
570
- int* dist_cache,
571
- size_t* last_insert_len,
572
- const BrotliEncoderParams* params,
573
- Command* commands,
574
- size_t* num_literals) {
569
+ const size_t block_start, const ZopfliNode* nodes, int* dist_cache,
570
+ size_t* last_insert_len, const BrotliEncoderParams* params,
571
+ Command* commands, size_t* num_literals) {
572
+ const size_t max_backward_limit = BROTLI_MAX_BACKWARD_LIMIT(params->lgwin);
575
573
  size_t pos = 0;
576
574
  uint32_t offset = nodes[0].u.next;
577
575
  size_t i;
@@ -610,18 +608,12 @@ void BrotliZopfliCreateCommands(const size_t num_bytes,
610
608
  *last_insert_len += num_bytes - pos;
611
609
  }
612
610
 
613
- static size_t ZopfliIterate(size_t num_bytes,
614
- size_t position,
615
- const uint8_t* ringbuffer,
616
- size_t ringbuffer_mask,
617
- const BrotliEncoderParams* params,
618
- const size_t max_backward_limit,
619
- const size_t gap,
620
- const int* dist_cache,
621
- const ZopfliCostModel* model,
622
- const uint32_t* num_matches,
623
- const BackwardMatch* matches,
624
- ZopfliNode* nodes) {
611
+ static size_t ZopfliIterate(size_t num_bytes, size_t position,
612
+ const uint8_t* ringbuffer, size_t ringbuffer_mask,
613
+ const BrotliEncoderParams* params, const size_t gap, const int* dist_cache,
614
+ const ZopfliCostModel* model, const uint32_t* num_matches,
615
+ const BackwardMatch* matches, ZopfliNode* nodes) {
616
+ const size_t max_backward_limit = BROTLI_MAX_BACKWARD_LIMIT(params->lgwin);
625
617
  const size_t max_zopfli_len = MaxZopfliLen(params);
626
618
  StartPosQueue queue;
627
619
  size_t cur_match_pos = 0;
@@ -645,8 +637,8 @@ static size_t ZopfliIterate(size_t num_bytes,
645
637
  while (skip) {
646
638
  i++;
647
639
  if (i + 3 >= num_bytes) break;
648
- EvaluateNode(position, i, max_backward_limit, gap, dist_cache, model,
649
- &queue, nodes);
640
+ EvaluateNode(position, i, max_backward_limit, gap,
641
+ dist_cache, model, &queue, nodes);
650
642
  cur_match_pos += num_matches[i];
651
643
  skip--;
652
644
  }
@@ -656,11 +648,11 @@ static size_t ZopfliIterate(size_t num_bytes,
656
648
  }
657
649
 
658
650
  /* REQUIRES: nodes != NULL and len(nodes) >= num_bytes + 1 */
659
- size_t BrotliZopfliComputeShortestPath(MemoryManager* m,
660
- size_t num_bytes, size_t position, const uint8_t* ringbuffer,
661
- size_t ringbuffer_mask, const BrotliEncoderParams* params,
662
- const size_t max_backward_limit, const int* dist_cache, HasherHandle hasher,
663
- ZopfliNode* nodes) {
651
+ size_t BrotliZopfliComputeShortestPath(MemoryManager* m, size_t num_bytes,
652
+ size_t position, const uint8_t* ringbuffer, size_t ringbuffer_mask,
653
+ const BrotliEncoderParams* params,
654
+ const int* dist_cache, HasherHandle hasher, ZopfliNode* nodes) {
655
+ const size_t max_backward_limit = BROTLI_MAX_BACKWARD_LIMIT(params->lgwin);
664
656
  const size_t max_zopfli_len = MaxZopfliLen(params);
665
657
  ZopfliCostModel model;
666
658
  StartPosQueue queue;
@@ -681,9 +673,11 @@ size_t BrotliZopfliComputeShortestPath(MemoryManager* m,
681
673
  const size_t pos = position + i;
682
674
  const size_t max_distance = BROTLI_MIN(size_t, pos, max_backward_limit);
683
675
  size_t skip;
684
- size_t num_matches = FindAllMatchesH10(hasher, &params->dictionary,
685
- ringbuffer, ringbuffer_mask, pos, num_bytes - i, max_distance, gap,
686
- params, &matches[lz_matches_offset]);
676
+ size_t num_matches;
677
+ num_matches = FindAllMatchesH10(hasher,
678
+ &params->dictionary,
679
+ ringbuffer, ringbuffer_mask, pos, num_bytes - i, max_distance,
680
+ gap, params, &matches[lz_matches_offset]);
687
681
  if (num_matches > 0 &&
688
682
  BackwardMatchLength(&matches[num_matches - 1]) > max_zopfli_len) {
689
683
  matches[0] = matches[num_matches - 1];
@@ -704,8 +698,8 @@ size_t BrotliZopfliComputeShortestPath(MemoryManager* m,
704
698
  while (skip) {
705
699
  i++;
706
700
  if (i + HashTypeLengthH10() - 1 >= num_bytes) break;
707
- EvaluateNode(position, i, max_backward_limit, gap, dist_cache, &model,
708
- &queue, nodes);
701
+ EvaluateNode(position, i, max_backward_limit, gap,
702
+ dist_cache, &model, &queue, nodes);
709
703
  skip--;
710
704
  }
711
705
  }
@@ -714,28 +708,27 @@ size_t BrotliZopfliComputeShortestPath(MemoryManager* m,
714
708
  return ComputeShortestPathFromNodes(num_bytes, nodes);
715
709
  }
716
710
 
717
- void BrotliCreateZopfliBackwardReferences(MemoryManager* m,
718
- size_t num_bytes, size_t position, const uint8_t* ringbuffer,
719
- size_t ringbuffer_mask, const BrotliEncoderParams* params,
711
+ void BrotliCreateZopfliBackwardReferences(MemoryManager* m, size_t num_bytes,
712
+ size_t position, const uint8_t* ringbuffer, size_t ringbuffer_mask,
713
+ const BrotliEncoderParams* params,
720
714
  HasherHandle hasher, int* dist_cache, size_t* last_insert_len,
721
715
  Command* commands, size_t* num_commands, size_t* num_literals) {
722
- const size_t max_backward_limit = BROTLI_MAX_BACKWARD_LIMIT(params->lgwin);
723
716
  ZopfliNode* nodes;
724
717
  nodes = BROTLI_ALLOC(m, ZopfliNode, num_bytes + 1);
725
718
  if (BROTLI_IS_OOM(m)) return;
726
719
  BrotliInitZopfliNodes(nodes, num_bytes + 1);
727
- *num_commands += BrotliZopfliComputeShortestPath(m,
728
- num_bytes, position, ringbuffer, ringbuffer_mask,
729
- params, max_backward_limit, dist_cache, hasher, nodes);
720
+ *num_commands += BrotliZopfliComputeShortestPath(m, num_bytes,
721
+ position, ringbuffer, ringbuffer_mask, params,
722
+ dist_cache, hasher, nodes);
730
723
  if (BROTLI_IS_OOM(m)) return;
731
- BrotliZopfliCreateCommands(num_bytes, position, max_backward_limit, nodes,
732
- dist_cache, last_insert_len, params, commands, num_literals);
724
+ BrotliZopfliCreateCommands(num_bytes, position, nodes, dist_cache,
725
+ last_insert_len, params, commands, num_literals);
733
726
  BROTLI_FREE(m, nodes);
734
727
  }
735
728
 
736
- void BrotliCreateHqZopfliBackwardReferences(MemoryManager* m,
737
- size_t num_bytes, size_t position, const uint8_t* ringbuffer,
738
- size_t ringbuffer_mask, const BrotliEncoderParams* params,
729
+ void BrotliCreateHqZopfliBackwardReferences(MemoryManager* m, size_t num_bytes,
730
+ size_t position, const uint8_t* ringbuffer, size_t ringbuffer_mask,
731
+ const BrotliEncoderParams* params,
739
732
  HasherHandle hasher, int* dist_cache, size_t* last_insert_len,
740
733
  Command* commands, size_t* num_commands, size_t* num_literals) {
741
734
  const size_t max_backward_limit = BROTLI_MAX_BACKWARD_LIMIT(params->lgwin);
@@ -767,8 +760,10 @@ void BrotliCreateHqZopfliBackwardReferences(MemoryManager* m,
767
760
  cur_match_pos + MAX_NUM_MATCHES_H10 + shadow_matches);
768
761
  if (BROTLI_IS_OOM(m)) return;
769
762
  num_found_matches = FindAllMatchesH10(hasher,
770
- &params->dictionary, ringbuffer, ringbuffer_mask, pos, max_length,
771
- max_distance, gap, params, &matches[cur_match_pos + shadow_matches]);
763
+ &params->dictionary,
764
+ ringbuffer, ringbuffer_mask, pos, max_length,
765
+ max_distance, gap, params,
766
+ &matches[cur_match_pos + shadow_matches]);
772
767
  cur_match_end = cur_match_pos + num_found_matches;
773
768
  for (j = cur_match_pos; j + 1 < cur_match_end; ++j) {
774
769
  BROTLI_DCHECK(BackwardMatchLength(&matches[j]) <=
@@ -814,10 +809,10 @@ void BrotliCreateHqZopfliBackwardReferences(MemoryManager* m,
814
809
  *last_insert_len = orig_last_insert_len;
815
810
  memcpy(dist_cache, orig_dist_cache, 4 * sizeof(dist_cache[0]));
816
811
  *num_commands += ZopfliIterate(num_bytes, position, ringbuffer,
817
- ringbuffer_mask, params, max_backward_limit, gap, dist_cache,
818
- &model, num_matches, matches, nodes);
819
- BrotliZopfliCreateCommands(num_bytes, position, max_backward_limit,
820
- nodes, dist_cache, last_insert_len, params, commands, num_literals);
812
+ ringbuffer_mask, params, gap, dist_cache, &model, num_matches, matches,
813
+ nodes);
814
+ BrotliZopfliCreateCommands(num_bytes, position, nodes, dist_cache,
815
+ last_insert_len, params, commands, num_literals);
821
816
  }
822
817
  CleanupZopfliCostModel(m, &model);
823
818
  BROTLI_FREE(m, nodes);
@@ -74,15 +74,14 @@ BROTLI_INTERNAL void BrotliInitZopfliNodes(ZopfliNode* array, size_t length);
74
74
  (1) nodes[i].copy_length() >= 2
75
75
  (2) nodes[i].command_length() <= i and
76
76
  (3) nodes[i - nodes[i].command_length()].cost < kInfinity */
77
- BROTLI_INTERNAL size_t BrotliZopfliComputeShortestPath(MemoryManager* m,
78
- size_t num_bytes, size_t position, const uint8_t* ringbuffer,
79
- size_t ringbuffer_mask, const BrotliEncoderParams* params,
80
- const size_t max_backward_limit, const int* dist_cache, HasherHandle hasher,
81
- ZopfliNode* nodes);
77
+ BROTLI_INTERNAL size_t BrotliZopfliComputeShortestPath(
78
+ MemoryManager* m, size_t num_bytes,
79
+ size_t position, const uint8_t* ringbuffer, size_t ringbuffer_mask,
80
+ const BrotliEncoderParams* params,
81
+ const int* dist_cache, HasherHandle hasher, ZopfliNode* nodes);
82
82
 
83
83
  BROTLI_INTERNAL void BrotliZopfliCreateCommands(
84
- const size_t num_bytes, const size_t block_start,
85
- const size_t max_backward_limit, const ZopfliNode* nodes,
84
+ const size_t num_bytes, const size_t block_start, const ZopfliNode* nodes,
86
85
  int* dist_cache, size_t* last_insert_len, const BrotliEncoderParams* params,
87
86
  Command* commands, size_t* num_literals);
88
87
 
@@ -10,9 +10,9 @@
10
10
  static BROTLI_NOINLINE void EXPORT_FN(CreateBackwardReferences)(
11
11
  size_t num_bytes, size_t position,
12
12
  const uint8_t* ringbuffer, size_t ringbuffer_mask,
13
- const BrotliEncoderParams* params, HasherHandle hasher, int* dist_cache,
14
- size_t* last_insert_len, Command* commands, size_t* num_commands,
15
- size_t* num_literals) {
13
+ const BrotliEncoderParams* params,
14
+ HasherHandle hasher, int* dist_cache, size_t* last_insert_len,
15
+ Command* commands, size_t* num_commands, size_t* num_literals) {
16
16
  /* Set maximum distance, see section 9.1. of the spec. */
17
17
  const size_t max_backward_limit = BROTLI_MAX_BACKWARD_LIMIT(params->lgwin);
18
18
 
@@ -42,9 +42,8 @@ static BROTLI_NOINLINE void EXPORT_FN(CreateBackwardReferences)(
42
42
  sr.distance = 0;
43
43
  sr.score = kMinScore;
44
44
  FN(FindLongestMatch)(hasher, &params->dictionary,
45
- ringbuffer, ringbuffer_mask, dist_cache, position,
46
- max_length, max_distance, gap,
47
- params->dist.max_distance, &sr);
45
+ ringbuffer, ringbuffer_mask, dist_cache, position, max_length,
46
+ max_distance, gap, params->dist.max_distance, &sr);
48
47
  if (sr.score > kMinScore) {
49
48
  /* Found a match. Let's look for something even better ahead. */
50
49
  int delayed_backward_references_in_row = 0;
@@ -58,7 +57,8 @@ static BROTLI_NOINLINE void EXPORT_FN(CreateBackwardReferences)(
58
57
  sr2.distance = 0;
59
58
  sr2.score = kMinScore;
60
59
  max_distance = BROTLI_MIN(size_t, position + 1, max_backward_limit);
61
- FN(FindLongestMatch)(hasher, &params->dictionary,
60
+ FN(FindLongestMatch)(hasher,
61
+ &params->dictionary,
62
62
  ringbuffer, ringbuffer_mask, dist_cache, position + 1, max_length,
63
63
  max_distance, gap, params->dist.max_distance, &sr2);
64
64
  if (sr2.score >= sr.score + cost_diff_lazy) {
@@ -80,8 +80,8 @@ static BROTLI_NOINLINE void EXPORT_FN(CreateBackwardReferences)(
80
80
  {
81
81
  /* The first 16 codes are special short-codes,
82
82
  and the minimum offset is 1. */
83
- size_t distance_code =
84
- ComputeDistanceCode(sr.distance, max_distance + gap, dist_cache);
83
+ size_t distance_code = ComputeDistanceCode(
84
+ sr.distance, max_distance + gap, dist_cache);
85
85
  if ((sr.distance <= (max_distance + gap)) && distance_code > 0) {
86
86
  dist_cache[3] = dist_cache[2];
87
87
  dist_cache[2] = dist_cache[1];
@@ -496,6 +496,8 @@ static void DecideOverLiteralContextModeling(const uint8_t* input,
496
496
  static BROTLI_BOOL ShouldCompress(
497
497
  const uint8_t* data, const size_t mask, const uint64_t last_flush_pos,
498
498
  const size_t bytes, const size_t num_literals, const size_t num_commands) {
499
+ /* TODO: find more precise minimal block overhead. */
500
+ if (bytes <= 2) return BROTLI_FALSE;
499
501
  if (num_commands < (bytes >> 8) + 2) {
500
502
  if (num_literals > 0.99 * (double)bytes) {
501
503
  uint32_t literal_histo[256] = { 0 };
@@ -674,12 +676,14 @@ static BROTLI_BOOL EnsureInitialized(BrotliEncoderState* s) {
674
676
  if (BROTLI_IS_OOM(&s->memory_manager_)) return BROTLI_FALSE;
675
677
  if (s->is_initialized_) return BROTLI_TRUE;
676
678
 
679
+ s->last_bytes_bits_ = 0;
680
+ s->last_bytes_ = 0;
681
+ s->remaining_metadata_bytes_ = BROTLI_UINT32_MAX;
682
+
677
683
  SanitizeParams(&s->params);
678
684
  s->params.lgblock = ComputeLgBlock(&s->params);
679
685
  ChooseDistanceParams(&s->params);
680
686
 
681
- s->remaining_metadata_bytes_ = BROTLI_UINT32_MAX;
682
-
683
687
  RingBufferSetup(&s->params, &s->ringbuffer_);
684
688
 
685
689
  /* Initialize last byte with stream header. */
@@ -1029,23 +1033,20 @@ static BROTLI_BOOL EncodeData(
1029
1033
 
1030
1034
  if (s->params.quality == ZOPFLIFICATION_QUALITY) {
1031
1035
  BROTLI_DCHECK(s->params.hasher.type == 10);
1032
- BrotliCreateZopfliBackwardReferences(m,
1033
- bytes, wrapped_last_processed_pos,
1036
+ BrotliCreateZopfliBackwardReferences(m, bytes, wrapped_last_processed_pos,
1034
1037
  data, mask, &s->params, s->hasher_, s->dist_cache_,
1035
1038
  &s->last_insert_len_, &s->commands_[s->num_commands_],
1036
1039
  &s->num_commands_, &s->num_literals_);
1037
1040
  if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;
1038
1041
  } else if (s->params.quality == HQ_ZOPFLIFICATION_QUALITY) {
1039
1042
  BROTLI_DCHECK(s->params.hasher.type == 10);
1040
- BrotliCreateHqZopfliBackwardReferences(m,
1041
- bytes, wrapped_last_processed_pos,
1043
+ BrotliCreateHqZopfliBackwardReferences(m, bytes, wrapped_last_processed_pos,
1042
1044
  data, mask, &s->params, s->hasher_, s->dist_cache_,
1043
1045
  &s->last_insert_len_, &s->commands_[s->num_commands_],
1044
1046
  &s->num_commands_, &s->num_literals_);
1045
1047
  if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;
1046
1048
  } else {
1047
- BrotliCreateBackwardReferences(
1048
- bytes, wrapped_last_processed_pos,
1049
+ BrotliCreateBackwardReferences(bytes, wrapped_last_processed_pos,
1049
1050
  data, mask, &s->params, s->hasher_, s->dist_cache_,
1050
1051
  &s->last_insert_len_, &s->commands_[s->num_commands_],
1051
1052
  &s->num_commands_, &s->num_literals_);
@@ -1166,7 +1167,6 @@ static BROTLI_BOOL BrotliCompressBufferQuality10(
1166
1167
  MemoryManager* m = &memory_manager;
1167
1168
 
1168
1169
  const size_t mask = BROTLI_SIZE_MAX >> 1;
1169
- const size_t max_backward_limit = BROTLI_MAX_BACKWARD_LIMIT(lgwin);
1170
1170
  int dist_cache[4] = { 4, 11, 15, 16 };
1171
1171
  int saved_dist_cache[4] = { 4, 11, 15, 16 };
1172
1172
  BROTLI_BOOL ok = BROTLI_TRUE;
@@ -1176,8 +1176,8 @@ static BROTLI_BOOL BrotliCompressBufferQuality10(
1176
1176
  uint8_t last_bytes_bits;
1177
1177
  HasherHandle hasher = NULL;
1178
1178
 
1179
- const size_t hasher_eff_size =
1180
- BROTLI_MIN(size_t, input_size, max_backward_limit + BROTLI_WINDOW_GAP);
1179
+ const size_t hasher_eff_size = BROTLI_MIN(size_t,
1180
+ input_size, BROTLI_MAX_BACKWARD_LIMIT(lgwin) + BROTLI_WINDOW_GAP);
1181
1181
 
1182
1182
  BrotliEncoderParams params;
1183
1183
 
@@ -1238,9 +1238,9 @@ static BROTLI_BOOL BrotliCompressBufferQuality10(
1238
1238
  BrotliInitZopfliNodes(nodes, block_size + 1);
1239
1239
  StitchToPreviousBlockH10(hasher, block_size, block_start,
1240
1240
  input_buffer, mask);
1241
- path_size = BrotliZopfliComputeShortestPath(m,
1242
- block_size, block_start, input_buffer, mask, &params,
1243
- max_backward_limit, dist_cache, hasher, nodes);
1241
+ path_size = BrotliZopfliComputeShortestPath(m, block_size, block_start,
1242
+ input_buffer, mask, &params, dist_cache, hasher,
1243
+ nodes);
1244
1244
  if (BROTLI_IS_OOM(m)) goto oom;
1245
1245
  /* We allocate a command buffer in the first iteration of this loop that
1246
1246
  will be likely big enough for the whole metablock, so that for most
@@ -1262,10 +1262,8 @@ static BROTLI_BOOL BrotliCompressBufferQuality10(
1262
1262
  }
1263
1263
  commands = new_commands;
1264
1264
  }
1265
- BrotliZopfliCreateCommands(block_size, block_start, max_backward_limit,
1266
- &nodes[0], dist_cache, &last_insert_len,
1267
- &params, &commands[num_commands],
1268
- &num_literals);
1265
+ BrotliZopfliCreateCommands(block_size, block_start, &nodes[0], dist_cache,
1266
+ &last_insert_len, &params, &commands[num_commands], &num_literals);
1269
1267
  num_commands += path_size;
1270
1268
  block_start += block_size;
1271
1269
  metablock_size += block_size;
@@ -149,9 +149,9 @@ static BROTLI_INLINE score_t BackwardReferencePenaltyUsingLastDistance(
149
149
  }
150
150
 
151
151
  static BROTLI_INLINE BROTLI_BOOL TestStaticDictionaryItem(
152
- const BrotliEncoderDictionary* dictionary, size_t item, const uint8_t* data,
153
- size_t max_length, size_t max_backward, size_t max_distance,
154
- HasherSearchResult* out) {
152
+ const BrotliEncoderDictionary* dictionary, size_t item,
153
+ const uint8_t* data, size_t max_length, size_t max_backward,
154
+ size_t max_distance, HasherSearchResult* out) {
155
155
  size_t len;
156
156
  size_t word_idx;
157
157
  size_t offset;
@@ -208,7 +208,8 @@ static BROTLI_INLINE void SearchInStaticDictionary(
208
208
  self->dict_num_lookups++;
209
209
  if (item != 0) {
210
210
  BROTLI_BOOL item_matches = TestStaticDictionaryItem(
211
- dictionary, item, data, max_length, max_backward, max_distance, out);
211
+ dictionary, item, data,
212
+ max_length, max_backward, max_distance, out);
212
213
  if (item_matches) {
213
214
  self->dict_num_matches++;
214
215
  }
@@ -121,13 +121,16 @@ static BROTLI_INLINE void FN(FindLongestMatch)(HasherHandle handle,
121
121
  const BrotliEncoderDictionary* dictionary,
122
122
  const uint8_t* BROTLI_RESTRICT data, const size_t ring_buffer_mask,
123
123
  const int* BROTLI_RESTRICT distance_cache, const size_t cur_ix,
124
- const size_t max_length, const size_t max_backward, const size_t gap,
125
- const size_t max_distance, HasherSearchResult* BROTLI_RESTRICT out) {
124
+ const size_t max_length, const size_t max_backward,
125
+ const size_t gap, const size_t max_distance,
126
+ HasherSearchResult* BROTLI_RESTRICT out) {
126
127
  HashComposite* self = FN(Self)(handle);
127
128
  FN_A(FindLongestMatch)(self->ha, dictionary, data, ring_buffer_mask,
128
- distance_cache, cur_ix, max_length, max_backward, gap, max_distance, out);
129
+ distance_cache, cur_ix, max_length, max_backward, gap,
130
+ max_distance, out);
129
131
  FN_B(FindLongestMatch)(self->hb, dictionary, data, ring_buffer_mask,
130
- distance_cache, cur_ix, max_length, max_backward, gap, max_distance, out);
132
+ distance_cache, cur_ix, max_length, max_backward, gap,
133
+ max_distance, out);
131
134
  }
132
135
 
133
136
  #undef HashComposite
@@ -161,8 +161,9 @@ static BROTLI_INLINE void FN(FindLongestMatch)(HasherHandle handle,
161
161
  const BrotliEncoderDictionary* dictionary,
162
162
  const uint8_t* BROTLI_RESTRICT data, const size_t ring_buffer_mask,
163
163
  const int* BROTLI_RESTRICT distance_cache, const size_t cur_ix,
164
- const size_t max_length, const size_t max_backward, const size_t gap,
165
- const size_t max_distance, HasherSearchResult* BROTLI_RESTRICT out) {
164
+ const size_t max_length, const size_t max_backward,
165
+ const size_t gap, const size_t max_distance,
166
+ HasherSearchResult* BROTLI_RESTRICT out) {
166
167
  HasherCommon* common = GetHasherCommon(handle);
167
168
  HashLongestMatch* self = FN(Self)(handle);
168
169
  uint16_t* num = FN(Num)(self);
@@ -154,8 +154,9 @@ static BROTLI_INLINE void FN(FindLongestMatch)(HasherHandle handle,
154
154
  const BrotliEncoderDictionary* dictionary,
155
155
  const uint8_t* BROTLI_RESTRICT data, const size_t ring_buffer_mask,
156
156
  const int* BROTLI_RESTRICT distance_cache, const size_t cur_ix,
157
- const size_t max_length, const size_t max_backward, const size_t gap,
158
- const size_t max_distance, HasherSearchResult* BROTLI_RESTRICT out) {
157
+ const size_t max_length, const size_t max_backward,
158
+ const size_t gap, const size_t max_distance,
159
+ HasherSearchResult* BROTLI_RESTRICT out) {
159
160
  HasherCommon* common = GetHasherCommon(handle);
160
161
  HashLongestMatch* self = FN(Self)(handle);
161
162
  uint16_t* num = FN(Num)(self);
@@ -155,8 +155,9 @@ static BROTLI_INLINE void FN(FindLongestMatch)(HasherHandle handle,
155
155
  const BrotliEncoderDictionary* dictionary,
156
156
  const uint8_t* BROTLI_RESTRICT data, const size_t ring_buffer_mask,
157
157
  const int* BROTLI_RESTRICT distance_cache, const size_t cur_ix,
158
- const size_t max_length, const size_t max_backward, const size_t gap,
159
- const size_t max_distance, HasherSearchResult* BROTLI_RESTRICT out) {
158
+ const size_t max_length, const size_t max_backward,
159
+ const size_t gap, const size_t max_distance,
160
+ HasherSearchResult* BROTLI_RESTRICT out) {
160
161
  HashRolling* self = FN(Self)(handle);
161
162
  const size_t cur_ix_masked = cur_ix & ring_buffer_mask;
162
163
  size_t pos = self->next_ix;
@@ -202,8 +202,9 @@ static BROTLI_INLINE BackwardMatch* FN(StoreAndFindMatches)(
202
202
  static BROTLI_INLINE size_t FN(FindAllMatches)(HasherHandle handle,
203
203
  const BrotliEncoderDictionary* dictionary, const uint8_t* data,
204
204
  const size_t ring_buffer_mask, const size_t cur_ix,
205
- const size_t max_length, const size_t max_backward, const size_t gap,
206
- const BrotliEncoderParams* params, BackwardMatch* matches) {
205
+ const size_t max_length, const size_t max_backward,
206
+ const size_t gap, const BrotliEncoderParams* params,
207
+ BackwardMatch* matches) {
207
208
  BackwardMatch* const orig_matches = matches;
208
209
  const size_t cur_ix_masked = cur_ix & ring_buffer_mask;
209
210
  size_t best_len = 1;
@@ -181,7 +181,8 @@ void BrotliBuildMetaBlock(MemoryManager* m,
181
181
  ComputeDistanceCost(cmds, num_commands,
182
182
  &orig_params.dist, &orig_params.dist, &dist_cost);
183
183
  if (dist_cost < best_dist_cost) {
184
- best_dist_cost = dist_cost;
184
+ /* NB: currently unused; uncomment when more param tuning is added. */
185
+ /* best_dist_cost = dist_cost; */
185
186
  params->dist = orig_params.dist;
186
187
  }
187
188
  }
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: brotli
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - miyucy
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-08-17 00:00:00.000000000 Z
11
+ date: 2018-11-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -229,7 +229,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
229
229
  version: '0'
230
230
  requirements: []
231
231
  rubyforge_project:
232
- rubygems_version: 2.7.6
232
+ rubygems_version: 2.7.7
233
233
  signing_key:
234
234
  specification_version: 4
235
235
  summary: Brotli compressor/decompressor