brotli 0.2.1 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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