brotli 0.1.8 → 0.2.0

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.
Files changed (102) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.travis.yml +7 -3
  4. data/brotli.gemspec +1 -1
  5. data/ext/brotli/brotli.c +4 -4
  6. data/ext/brotli/brotli.h +2 -2
  7. data/ext/brotli/extconf.rb +9 -16
  8. data/lib/brotli/version.rb +1 -1
  9. data/vendor/brotli/{common → c/common}/constants.h +11 -1
  10. data/vendor/brotli/c/common/dictionary.bin +432 -0
  11. data/vendor/brotli/c/common/dictionary.c +5905 -0
  12. data/vendor/brotli/c/common/dictionary.h +64 -0
  13. data/vendor/brotli/c/common/version.h +19 -0
  14. data/vendor/brotli/{dec → c/dec}/bit_reader.c +2 -2
  15. data/vendor/brotli/{dec → c/dec}/bit_reader.h +11 -34
  16. data/vendor/brotli/{dec → c/dec}/context.h +1 -1
  17. data/vendor/brotli/{dec → c/dec}/decode.c +389 -356
  18. data/vendor/brotli/{dec → c/dec}/huffman.c +24 -23
  19. data/vendor/brotli/{dec → c/dec}/huffman.h +1 -1
  20. data/vendor/brotli/{dec → c/dec}/port.h +19 -10
  21. data/vendor/brotli/{dec → c/dec}/prefix.h +1 -1
  22. data/vendor/brotli/{dec → c/dec}/state.c +23 -19
  23. data/vendor/brotli/{dec → c/dec}/state.h +18 -17
  24. data/vendor/brotli/{dec → c/dec}/transform.h +2 -2
  25. data/vendor/brotli/c/enc/backward_references.c +134 -0
  26. data/vendor/brotli/c/enc/backward_references.h +39 -0
  27. data/vendor/brotli/{enc/backward_references.c → c/enc/backward_references_hq.c} +144 -232
  28. data/vendor/brotli/{enc/backward_references.h → c/enc/backward_references_hq.h} +28 -31
  29. data/vendor/brotli/{enc → c/enc}/backward_references_inc.h +37 -31
  30. data/vendor/brotli/{enc → c/enc}/bit_cost.c +1 -1
  31. data/vendor/brotli/{enc → c/enc}/bit_cost.h +1 -1
  32. data/vendor/brotli/{enc → c/enc}/bit_cost_inc.h +0 -0
  33. data/vendor/brotli/{enc → c/enc}/block_encoder_inc.h +0 -0
  34. data/vendor/brotli/{enc → c/enc}/block_splitter.c +2 -4
  35. data/vendor/brotli/{enc → c/enc}/block_splitter.h +1 -1
  36. data/vendor/brotli/{enc → c/enc}/block_splitter_inc.h +6 -7
  37. data/vendor/brotli/{enc → c/enc}/brotli_bit_stream.c +22 -26
  38. data/vendor/brotli/{enc → c/enc}/brotli_bit_stream.h +1 -5
  39. data/vendor/brotli/{enc → c/enc}/cluster.c +1 -1
  40. data/vendor/brotli/{enc → c/enc}/cluster.h +1 -1
  41. data/vendor/brotli/{enc → c/enc}/cluster_inc.h +2 -0
  42. data/vendor/brotli/{enc → c/enc}/command.h +34 -17
  43. data/vendor/brotli/{enc → c/enc}/compress_fragment.c +97 -53
  44. data/vendor/brotli/{enc → c/enc}/compress_fragment.h +5 -2
  45. data/vendor/brotli/{enc → c/enc}/compress_fragment_two_pass.c +106 -51
  46. data/vendor/brotli/{enc → c/enc}/compress_fragment_two_pass.h +5 -2
  47. data/vendor/brotli/{enc → c/enc}/context.h +3 -3
  48. data/vendor/brotli/c/enc/dictionary_hash.c +1120 -0
  49. data/vendor/brotli/c/enc/dictionary_hash.h +24 -0
  50. data/vendor/brotli/{enc → c/enc}/encode.c +442 -240
  51. data/vendor/brotli/{enc → c/enc}/entropy_encode.c +9 -9
  52. data/vendor/brotli/{enc → c/enc}/entropy_encode.h +4 -4
  53. data/vendor/brotli/{enc → c/enc}/entropy_encode_static.h +4 -4
  54. data/vendor/brotli/{enc → c/enc}/fast_log.h +3 -3
  55. data/vendor/brotli/{enc → c/enc}/find_match_length.h +8 -8
  56. data/vendor/brotli/c/enc/hash.h +446 -0
  57. data/vendor/brotli/{enc → c/enc}/hash_forgetful_chain_inc.h +72 -68
  58. data/vendor/brotli/c/enc/hash_longest_match64_inc.h +266 -0
  59. data/vendor/brotli/c/enc/hash_longest_match_inc.h +258 -0
  60. data/vendor/brotli/{enc → c/enc}/hash_longest_match_quickly_inc.h +81 -77
  61. data/vendor/brotli/c/enc/hash_to_binary_tree_inc.h +326 -0
  62. data/vendor/brotli/{enc → c/enc}/histogram.c +4 -2
  63. data/vendor/brotli/{enc → c/enc}/histogram.h +1 -1
  64. data/vendor/brotli/{enc → c/enc}/histogram_inc.h +0 -0
  65. data/vendor/brotli/{enc → c/enc}/literal_cost.c +4 -7
  66. data/vendor/brotli/{enc → c/enc}/literal_cost.h +2 -2
  67. data/vendor/brotli/{enc → c/enc}/memory.c +1 -1
  68. data/vendor/brotli/{enc → c/enc}/memory.h +3 -2
  69. data/vendor/brotli/{enc → c/enc}/metablock.c +136 -123
  70. data/vendor/brotli/{enc → c/enc}/metablock.h +2 -12
  71. data/vendor/brotli/{enc → c/enc}/metablock_inc.h +0 -0
  72. data/vendor/brotli/{enc → c/enc}/port.h +49 -33
  73. data/vendor/brotli/{enc → c/enc}/prefix.h +4 -2
  74. data/vendor/brotli/{enc → c/enc}/quality.h +47 -17
  75. data/vendor/brotli/{enc → c/enc}/ringbuffer.h +6 -6
  76. data/vendor/brotli/{enc → c/enc}/static_dict.c +26 -22
  77. data/vendor/brotli/{enc → c/enc}/static_dict.h +3 -1
  78. data/vendor/brotli/c/enc/static_dict_lut.h +5864 -0
  79. data/vendor/brotli/{enc → c/enc}/utf8_util.c +1 -1
  80. data/vendor/brotli/{enc → c/enc}/utf8_util.h +2 -2
  81. data/vendor/brotli/{enc → c/enc}/write_bits.h +3 -3
  82. data/vendor/brotli/c/include/brotli/decode.h +339 -0
  83. data/vendor/brotli/c/include/brotli/encode.h +402 -0
  84. data/vendor/brotli/c/include/brotli/port.h +146 -0
  85. data/vendor/brotli/c/include/brotli/types.h +90 -0
  86. metadata +80 -79
  87. data/vendor/brotli/common/dictionary.c +0 -9474
  88. data/vendor/brotli/common/dictionary.h +0 -29
  89. data/vendor/brotli/common/port.h +0 -107
  90. data/vendor/brotli/common/types.h +0 -58
  91. data/vendor/brotli/dec/decode.h +0 -188
  92. data/vendor/brotli/enc/compressor.cc +0 -139
  93. data/vendor/brotli/enc/compressor.h +0 -161
  94. data/vendor/brotli/enc/dictionary_hash.h +0 -4121
  95. data/vendor/brotli/enc/encode.h +0 -221
  96. data/vendor/brotli/enc/encode_parallel.cc +0 -289
  97. data/vendor/brotli/enc/encode_parallel.h +0 -27
  98. data/vendor/brotli/enc/hash.h +0 -717
  99. data/vendor/brotli/enc/hash_longest_match_inc.h +0 -241
  100. data/vendor/brotli/enc/static_dict_lut.h +0 -11241
  101. data/vendor/brotli/enc/streams.cc +0 -114
  102. data/vendor/brotli/enc/streams.h +0 -121
@@ -0,0 +1,39 @@
1
+ /* Copyright 2013 Google Inc. All Rights Reserved.
2
+
3
+ Distributed under MIT license.
4
+ See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
5
+ */
6
+
7
+ /* Function to find backward reference copies. */
8
+
9
+ #ifndef BROTLI_ENC_BACKWARD_REFERENCES_H_
10
+ #define BROTLI_ENC_BACKWARD_REFERENCES_H_
11
+
12
+ #include "../common/constants.h"
13
+ #include "../common/dictionary.h"
14
+ #include <brotli/types.h>
15
+ #include "./command.h"
16
+ #include "./hash.h"
17
+ #include "./port.h"
18
+ #include "./quality.h"
19
+
20
+ #if defined(__cplusplus) || defined(c_plusplus)
21
+ extern "C" {
22
+ #endif
23
+
24
+ /* "commands" points to the next output command to write to, "*num_commands" is
25
+ initially the total amount of commands output by previous
26
+ CreateBackwardReferences calls, and must be incremented by the amount written
27
+ by this call. */
28
+ BROTLI_INTERNAL void BrotliCreateBackwardReferences(
29
+ const BrotliDictionary* dictionary, size_t num_bytes, size_t position,
30
+ const uint8_t* ringbuffer, size_t ringbuffer_mask,
31
+ const BrotliEncoderParams* params, HasherHandle hasher, int* dist_cache,
32
+ size_t* last_insert_len, Command* commands, size_t* num_commands,
33
+ size_t* num_literals);
34
+
35
+ #if defined(__cplusplus) || defined(c_plusplus)
36
+ } /* extern "C" */
37
+ #endif
38
+
39
+ #endif /* BROTLI_ENC_BACKWARD_REFERENCES_H_ */
@@ -6,13 +6,12 @@
6
6
 
7
7
  /* Function to find backward reference copies. */
8
8
 
9
- #include "./backward_references.h"
9
+ #include "./backward_references_hq.h"
10
10
 
11
- #include <math.h> /* INFINITY */
12
11
  #include <string.h> /* memcpy, memset */
13
12
 
14
13
  #include "../common/constants.h"
15
- #include "../common/types.h"
14
+ #include <brotli/types.h>
16
15
  #include "./command.h"
17
16
  #include "./fast_log.h"
18
17
  #include "./find_match_length.h"
@@ -26,11 +25,14 @@
26
25
  extern "C" {
27
26
  #endif
28
27
 
29
- #ifdef INFINITY
30
- static const float kInfinity = INFINITY;
31
- #else
32
- static const float kInfinity = 3.4028e38f;
33
- #endif
28
+ static const float kInfinity = 1.7e38f; /* ~= 2 ^ 127 */
29
+
30
+ static const uint32_t kDistanceCacheIndex[] = {
31
+ 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1,
32
+ };
33
+ static const int kDistanceCacheOffset[] = {
34
+ 0, 0, 0, 0, -1, 1, -2, 2, -3, 3, -1, 1, -2, 2, -3, 3
35
+ };
34
36
 
35
37
  void BrotliInitZopfliNodes(ZopfliNode* array, size_t length) {
36
38
  ZopfliNode stub;
@@ -57,7 +59,9 @@ static BROTLI_INLINE uint32_t ZopfliNodeCopyDistance(const ZopfliNode* self) {
57
59
 
58
60
  static BROTLI_INLINE uint32_t ZopfliNodeDistanceCode(const ZopfliNode* self) {
59
61
  const uint32_t short_code = self->distance >> 25;
60
- return short_code == 0 ? ZopfliNodeCopyDistance(self) + 15 : short_code - 1;
62
+ return short_code == 0 ?
63
+ ZopfliNodeCopyDistance(self) + BROTLI_NUM_DISTANCE_SHORT_CODES - 1 :
64
+ short_code - 1;
61
65
  }
62
66
 
63
67
  static BROTLI_INLINE uint32_t ZopfliNodeCommandLength(const ZopfliNode* self) {
@@ -210,30 +214,6 @@ static BROTLI_INLINE float ZopfliCostModelGetMinCostCmd(
210
214
  return self->min_cost_cmd_;
211
215
  }
212
216
 
213
- static BROTLI_INLINE size_t ComputeDistanceCode(size_t distance,
214
- size_t max_distance,
215
- const int* dist_cache) {
216
- if (distance <= max_distance) {
217
- size_t distance_plus_3 = distance + 3;
218
- size_t offset0 = distance_plus_3 - (size_t)dist_cache[0];
219
- size_t offset1 = distance_plus_3 - (size_t)dist_cache[1];
220
- if (distance == (size_t)dist_cache[0]) {
221
- return 0;
222
- } else if (distance == (size_t)dist_cache[1]) {
223
- return 1;
224
- } else if (offset0 < 7) {
225
- return (0x9750468 >> (4 * offset0)) & 0xF;
226
- } else if (offset1 < 7) {
227
- return (0xFDB1ACE >> (4 * offset1)) & 0xF;
228
- } else if (distance == (size_t)dist_cache[2]) {
229
- return 2;
230
- } else if (distance == (size_t)dist_cache[3]) {
231
- return 3;
232
- }
233
- }
234
- return distance + 15;
235
- }
236
-
237
217
  /* REQUIRES: len >= 2, start_pos <= pos */
238
218
  /* REQUIRES: cost < kInfinity, nodes[start_pos].cost < kInfinity */
239
219
  /* Maintains the "ZopfliNode array invariant". */
@@ -320,6 +300,7 @@ static size_t ComputeMinimumCopyLength(const float start_cost,
320
300
  static uint32_t ComputeDistanceShortcut(const size_t block_start,
321
301
  const size_t pos,
322
302
  const size_t max_backward,
303
+ const size_t gap,
323
304
  const ZopfliNode* nodes) {
324
305
  const size_t clen = ZopfliNodeCopyLength(&nodes[pos]);
325
306
  const size_t ilen = nodes[pos].insert_length;
@@ -331,8 +312,8 @@ static uint32_t ComputeDistanceShortcut(const size_t block_start,
331
312
  does not update the last distances. */
332
313
  if (pos == 0) {
333
314
  return 0;
334
- } else if (dist + clen <= block_start + pos &&
335
- dist <= max_backward &&
315
+ } else if (dist + clen <= block_start + pos + gap &&
316
+ dist <= max_backward + gap &&
336
317
  ZopfliNodeDistanceCode(&nodes[pos]) > 0) {
337
318
  return (uint32_t)pos;
338
319
  } else {
@@ -344,7 +325,7 @@ static uint32_t ComputeDistanceShortcut(const size_t block_start,
344
325
  Section 4. of the Spec) that would be used at (block_start + pos) if we
345
326
  used the shortest path of commands from block_start, computed from
346
327
  nodes[0..pos]. The last four distances at block_start are in
347
- starting_dist_cach[0..3].
328
+ starting_dist_cache[0..3].
348
329
  REQUIRES: nodes[pos].cost < kInfinity
349
330
  REQUIRES: nodes[0..pos] satisfies that "ZopfliNode array invariant". */
350
331
  static void ComputeDistanceCache(const size_t pos,
@@ -366,19 +347,36 @@ static void ComputeDistanceCache(const size_t pos,
366
347
  }
367
348
  }
368
349
 
369
- static void UpdateNodes(const size_t num_bytes,
370
- const size_t block_start,
371
- const size_t pos,
372
- const uint8_t* ringbuffer,
373
- const size_t ringbuffer_mask,
374
- const BrotliEncoderParams* params,
375
- const size_t max_backward_limit,
376
- const int* starting_dist_cache,
377
- const size_t num_matches,
378
- const BackwardMatch* matches,
379
- const ZopfliCostModel* model,
380
- StartPosQueue* queue,
381
- ZopfliNode* nodes) {
350
+ /* Maintains "ZopfliNode array invariant" and pushes node to the queue, if it
351
+ is eligible. */
352
+ static void EvaluateNode(
353
+ const size_t block_start, const size_t pos, const size_t max_backward_limit,
354
+ const size_t gap, const int* starting_dist_cache,
355
+ const ZopfliCostModel* model, StartPosQueue* queue, ZopfliNode* nodes) {
356
+ /* Save cost, because ComputeDistanceCache invalidates it. */
357
+ float node_cost = nodes[pos].u.cost;
358
+ nodes[pos].u.shortcut = ComputeDistanceShortcut(
359
+ block_start, pos, max_backward_limit, gap, nodes);
360
+ if (node_cost <= ZopfliCostModelGetLiteralCosts(model, 0, pos)) {
361
+ PosData posdata;
362
+ posdata.pos = pos;
363
+ posdata.cost = node_cost;
364
+ posdata.costdiff = node_cost -
365
+ ZopfliCostModelGetLiteralCosts(model, 0, pos);
366
+ ComputeDistanceCache(
367
+ pos, starting_dist_cache, nodes, posdata.distance_cache);
368
+ StartPosQueuePush(queue, &posdata);
369
+ }
370
+ }
371
+
372
+ /* Returns longest copy length. */
373
+ static size_t UpdateNodes(
374
+ const size_t num_bytes, const size_t block_start, const size_t pos,
375
+ const uint8_t* ringbuffer, const size_t ringbuffer_mask,
376
+ const BrotliEncoderParams* params, const size_t max_backward_limit,
377
+ const int* starting_dist_cache, const size_t num_matches,
378
+ const BackwardMatch* matches, const ZopfliCostModel* model,
379
+ StartPosQueue* queue, ZopfliNode* nodes) {
382
380
  const size_t cur_ix = block_start + pos;
383
381
  const size_t cur_ix_masked = cur_ix & ringbuffer_mask;
384
382
  const size_t max_distance = BROTLI_MIN(size_t, cur_ix, max_backward_limit);
@@ -386,24 +384,12 @@ static void UpdateNodes(const size_t num_bytes,
386
384
  const size_t max_zopfli_len = MaxZopfliLen(params);
387
385
  const size_t max_iters = MaxZopfliCandidates(params);
388
386
  size_t min_len;
387
+ size_t result = 0;
389
388
  size_t k;
389
+ size_t gap = 0;
390
390
 
391
- {
392
- /* Save cost, because ComputeDistanceCache invalidates it. */
393
- float node_cost = nodes[pos].u.cost;
394
- nodes[pos].u.shortcut = ComputeDistanceShortcut(
395
- block_start, pos, max_backward_limit, nodes);
396
- if (node_cost <= ZopfliCostModelGetLiteralCosts(model, 0, pos)) {
397
- PosData posdata;
398
- posdata.pos = pos;
399
- posdata.cost = node_cost;
400
- posdata.costdiff = node_cost -
401
- ZopfliCostModelGetLiteralCosts(model, 0, pos);
402
- ComputeDistanceCache(
403
- pos, starting_dist_cache, nodes, posdata.distance_cache);
404
- StartPosQueuePush(queue, &posdata);
405
- }
406
- }
391
+ EvaluateNode(block_start, pos, max_backward_limit, gap, starting_dist_cache,
392
+ model, queue, nodes);
407
393
 
408
394
  {
409
395
  const PosData* posdata = StartPosQueueAt(queue, 0);
@@ -431,25 +417,31 @@ static void UpdateNodes(const size_t num_bytes,
431
417
  const size_t backward =
432
418
  (size_t)(posdata->distance_cache[idx] + kDistanceCacheOffset[j]);
433
419
  size_t prev_ix = cur_ix - backward;
434
- if (prev_ix >= cur_ix) {
435
- continue;
420
+ size_t len = 0;
421
+ uint8_t continuation = ringbuffer[cur_ix_masked + best_len];
422
+ if (cur_ix_masked + best_len > ringbuffer_mask) {
423
+ break;
436
424
  }
437
- if (PREDICT_FALSE(backward > max_distance)) {
425
+ if (BROTLI_PREDICT_FALSE(backward > max_distance + gap)) {
438
426
  continue;
439
427
  }
440
- prev_ix &= ringbuffer_mask;
428
+ if (backward <= max_distance) {
429
+ if (prev_ix >= cur_ix) {
430
+ continue;
431
+ }
441
432
 
442
- if (cur_ix_masked + best_len > ringbuffer_mask ||
443
- prev_ix + best_len > ringbuffer_mask ||
444
- ringbuffer[cur_ix_masked + best_len] !=
445
- ringbuffer[prev_ix + best_len]) {
433
+ prev_ix &= ringbuffer_mask;
434
+ if (prev_ix + best_len > ringbuffer_mask ||
435
+ continuation != ringbuffer[prev_ix + best_len]) {
436
+ continue;
437
+ }
438
+ len = FindMatchLengthWithLimit(&ringbuffer[prev_ix],
439
+ &ringbuffer[cur_ix_masked],
440
+ max_len);
441
+ } else {
446
442
  continue;
447
443
  }
448
444
  {
449
- const size_t len =
450
- FindMatchLengthWithLimit(&ringbuffer[prev_ix],
451
- &ringbuffer[cur_ix_masked],
452
- max_len);
453
445
  const float dist_cost = base_cost +
454
446
  ZopfliCostModelGetDistanceCost(model, j);
455
447
  size_t l;
@@ -462,6 +454,7 @@ static void UpdateNodes(const size_t num_bytes,
462
454
  ZopfliCostModelGetCommandCost(model, cmdcode);
463
455
  if (cost < nodes[pos + l].u.cost) {
464
456
  UpdateZopfliNode(nodes, pos, start, l, l, backward, j + 1, cost);
457
+ result = BROTLI_MAX(size_t, result, l);
465
458
  }
466
459
  best_len = l;
467
460
  }
@@ -479,10 +472,11 @@ static void UpdateNodes(const size_t num_bytes,
479
472
  for (j = 0; j < num_matches; ++j) {
480
473
  BackwardMatch match = matches[j];
481
474
  size_t dist = match.distance;
482
- BROTLI_BOOL is_dictionary_match = TO_BROTLI_BOOL(dist > max_distance);
475
+ BROTLI_BOOL is_dictionary_match =
476
+ TO_BROTLI_BOOL(dist > max_distance + gap);
483
477
  /* We already tried all possible last distance matches, so we can use
484
478
  normal distance code here. */
485
- size_t dist_code = dist + 15;
479
+ size_t dist_code = dist + BROTLI_NUM_DISTANCE_SHORT_CODES - 1;
486
480
  uint16_t dist_symbol;
487
481
  uint32_t distextra;
488
482
  uint32_t distnumextra;
@@ -510,11 +504,13 @@ static void UpdateNodes(const size_t num_bytes,
510
504
  ZopfliCostModelGetCommandCost(model, cmdcode);
511
505
  if (cost < nodes[pos + len].u.cost) {
512
506
  UpdateZopfliNode(nodes, pos, start, len, len_code, dist, 0, cost);
507
+ result = BROTLI_MAX(size_t, result, len);
513
508
  }
514
509
  }
515
510
  }
516
511
  }
517
512
  }
513
+ return result;
518
514
  }
519
515
 
520
516
  static size_t ComputeShortestPathFromNodes(size_t num_bytes,
@@ -532,17 +528,21 @@ static size_t ComputeShortestPathFromNodes(size_t num_bytes,
532
528
  return num_commands;
533
529
  }
534
530
 
531
+ /* REQUIRES: nodes != NULL and len(nodes) >= num_bytes + 1 */
535
532
  void BrotliZopfliCreateCommands(const size_t num_bytes,
536
533
  const size_t block_start,
537
534
  const size_t max_backward_limit,
538
535
  const ZopfliNode* nodes,
539
536
  int* dist_cache,
540
537
  size_t* last_insert_len,
538
+ const BrotliEncoderParams* params,
541
539
  Command* commands,
542
540
  size_t* num_literals) {
543
541
  size_t pos = 0;
544
542
  uint32_t offset = nodes[0].u.next;
545
543
  size_t i;
544
+ size_t gap = 0;
545
+ BROTLI_UNUSED(params);
546
546
  for (i = 0; offset != BROTLI_UINT32_MAX; i++) {
547
547
  const ZopfliNode* next = &nodes[pos + offset];
548
548
  size_t copy_length = ZopfliNodeCopyLength(next);
@@ -558,11 +558,11 @@ void BrotliZopfliCreateCommands(const size_t num_bytes,
558
558
  size_t len_code = ZopfliNodeLengthCode(next);
559
559
  size_t max_distance =
560
560
  BROTLI_MIN(size_t, block_start + pos, max_backward_limit);
561
- BROTLI_BOOL is_dictionary = TO_BROTLI_BOOL(distance > max_distance);
561
+ BROTLI_BOOL is_dictionary = TO_BROTLI_BOOL(distance > max_distance + gap);
562
562
  size_t dist_code = ZopfliNodeDistanceCode(next);
563
563
 
564
- InitCommand(
565
- &commands[i], insert_length, copy_length, len_code, dist_code);
564
+ InitCommand(&commands[i], insert_length,
565
+ copy_length, (int)len_code - (int)copy_length, dist_code);
566
566
 
567
567
  if (!is_dictionary && dist_code > 0) {
568
568
  dist_cache[3] = dist_cache[2];
@@ -584,6 +584,7 @@ static size_t ZopfliIterate(size_t num_bytes,
584
584
  size_t ringbuffer_mask,
585
585
  const BrotliEncoderParams* params,
586
586
  const size_t max_backward_limit,
587
+ const size_t gap,
587
588
  const int* dist_cache,
588
589
  const ZopfliCostModel* model,
589
590
  const uint32_t* num_matches,
@@ -597,23 +598,34 @@ static size_t ZopfliIterate(size_t num_bytes,
597
598
  nodes[0].u.cost = 0;
598
599
  InitStartPosQueue(&queue);
599
600
  for (i = 0; i + 3 < num_bytes; i++) {
600
- UpdateNodes(num_bytes, position, i, ringbuffer, ringbuffer_mask,
601
- params, max_backward_limit, dist_cache, num_matches[i],
602
- &matches[cur_match_pos], model, &queue, nodes);
601
+ size_t skip = UpdateNodes(num_bytes, position, i, ringbuffer,
602
+ ringbuffer_mask, params, max_backward_limit, dist_cache,
603
+ num_matches[i], &matches[cur_match_pos], model, &queue, nodes);
604
+ if (skip < BROTLI_LONG_COPY_QUICK_STEP) skip = 0;
603
605
  cur_match_pos += num_matches[i];
604
- /* The zopflification can be too slow in case of very long lengths, so in
605
- such case skip it all, it does not cost a lot of compression ratio. */
606
606
  if (num_matches[i] == 1 &&
607
607
  BackwardMatchLength(&matches[cur_match_pos - 1]) > max_zopfli_len) {
608
- i += BackwardMatchLength(&matches[cur_match_pos - 1]) - 1;
609
- InitStartPosQueue(&queue);
608
+ skip = BROTLI_MAX(size_t,
609
+ BackwardMatchLength(&matches[cur_match_pos - 1]), skip);
610
+ }
611
+ if (skip > 1) {
612
+ skip--;
613
+ while (skip) {
614
+ i++;
615
+ if (i + 3 >= num_bytes) break;
616
+ EvaluateNode(position, i, max_backward_limit, gap, dist_cache, model,
617
+ &queue, nodes);
618
+ cur_match_pos += num_matches[i];
619
+ skip--;
620
+ }
610
621
  }
611
622
  }
612
623
  return ComputeShortestPathFromNodes(num_bytes, nodes);
613
624
  }
614
625
 
615
-
626
+ /* REQUIRES: nodes != NULL and len(nodes) >= num_bytes + 1 */
616
627
  size_t BrotliZopfliComputeShortestPath(MemoryManager* m,
628
+ const BrotliDictionary* dictionary,
617
629
  size_t num_bytes,
618
630
  size_t position,
619
631
  const uint8_t* ringbuffer,
@@ -621,7 +633,7 @@ size_t BrotliZopfliComputeShortestPath(MemoryManager* m,
621
633
  const BrotliEncoderParams* params,
622
634
  const size_t max_backward_limit,
623
635
  const int* dist_cache,
624
- H10* hasher,
636
+ HasherHandle hasher,
625
637
  ZopfliNode* nodes) {
626
638
  const size_t max_zopfli_len = MaxZopfliLen(params);
627
639
  ZopfliCostModel model;
@@ -630,6 +642,7 @@ size_t BrotliZopfliComputeShortestPath(MemoryManager* m,
630
642
  const size_t store_end = num_bytes >= StoreLookaheadH10() ?
631
643
  position + num_bytes - StoreLookaheadH10() + 1 : position;
632
644
  size_t i;
645
+ size_t gap = 0;
633
646
  nodes[0].length = 0;
634
647
  nodes[0].u.cost = 0;
635
648
  InitZopfliCostModel(m, &model, num_bytes);
@@ -640,122 +653,67 @@ size_t BrotliZopfliComputeShortestPath(MemoryManager* m,
640
653
  for (i = 0; i + HashTypeLengthH10() - 1 < num_bytes; i++) {
641
654
  const size_t pos = position + i;
642
655
  const size_t max_distance = BROTLI_MIN(size_t, pos, max_backward_limit);
643
- size_t num_matches = FindAllMatchesH10(hasher, ringbuffer, ringbuffer_mask,
644
- pos, num_bytes - i, max_distance, params, matches);
656
+ size_t num_matches = FindAllMatchesH10(hasher, dictionary, ringbuffer,
657
+ ringbuffer_mask, pos, num_bytes - i, max_distance, gap, params,
658
+ matches);
659
+ size_t skip;
645
660
  if (num_matches > 0 &&
646
661
  BackwardMatchLength(&matches[num_matches - 1]) > max_zopfli_len) {
647
662
  matches[0] = matches[num_matches - 1];
648
663
  num_matches = 1;
649
664
  }
650
- UpdateNodes(num_bytes, position, i, ringbuffer, ringbuffer_mask,
651
- params, max_backward_limit, dist_cache, num_matches, matches,
652
- &model, &queue, nodes);
665
+ skip = UpdateNodes(num_bytes, position, i, ringbuffer, ringbuffer_mask,
666
+ params, max_backward_limit, dist_cache, num_matches, matches, &model,
667
+ &queue, nodes);
668
+ if (skip < BROTLI_LONG_COPY_QUICK_STEP) skip = 0;
653
669
  if (num_matches == 1 && BackwardMatchLength(&matches[0]) > max_zopfli_len) {
670
+ skip = BROTLI_MAX(size_t, BackwardMatchLength(&matches[0]), skip);
671
+ }
672
+ if (skip > 1) {
654
673
  /* Add the tail of the copy to the hasher. */
655
674
  StoreRangeH10(hasher, ringbuffer, ringbuffer_mask, pos + 1, BROTLI_MIN(
656
- size_t, pos + BackwardMatchLength(&matches[0]), store_end));
657
- i += BackwardMatchLength(&matches[0]) - 1;
658
- InitStartPosQueue(&queue);
675
+ size_t, pos + skip, store_end));
676
+ skip--;
677
+ while (skip) {
678
+ i++;
679
+ if (i + HashTypeLengthH10() - 1 >= num_bytes) break;
680
+ EvaluateNode(position, i, max_backward_limit, gap, dist_cache, &model,
681
+ &queue, nodes);
682
+ skip--;
683
+ }
659
684
  }
660
685
  }
661
686
  CleanupZopfliCostModel(m, &model);
662
687
  return ComputeShortestPathFromNodes(num_bytes, nodes);
663
688
  }
664
689
 
665
- #define EXPAND_CAT(a, b) CAT(a, b)
666
- #define CAT(a, b) a ## b
667
- #define FN(X) EXPAND_CAT(X, HASHER())
668
-
669
- #define HASHER() H2
670
- /* NOLINTNEXTLINE(build/include) */
671
- #include "./backward_references_inc.h"
672
- #undef HASHER
673
-
674
- #define HASHER() H3
675
- /* NOLINTNEXTLINE(build/include) */
676
- #include "./backward_references_inc.h"
677
- #undef HASHER
678
-
679
- #define HASHER() H4
680
- /* NOLINTNEXTLINE(build/include) */
681
- #include "./backward_references_inc.h"
682
- #undef HASHER
683
-
684
- #define HASHER() H5
685
- /* NOLINTNEXTLINE(build/include) */
686
- #include "./backward_references_inc.h"
687
- #undef HASHER
688
-
689
- #define HASHER() H6
690
- /* NOLINTNEXTLINE(build/include) */
691
- #include "./backward_references_inc.h"
692
- #undef HASHER
693
-
694
- #define HASHER() H7
695
- /* NOLINTNEXTLINE(build/include) */
696
- #include "./backward_references_inc.h"
697
- #undef HASHER
698
-
699
- #define HASHER() H8
700
- /* NOLINTNEXTLINE(build/include) */
701
- #include "./backward_references_inc.h"
702
- #undef HASHER
703
-
704
- #define HASHER() H9
705
- /* NOLINTNEXTLINE(build/include) */
706
- #include "./backward_references_inc.h"
707
- #undef HASHER
708
-
709
- #define HASHER() H40
710
- /* NOLINTNEXTLINE(build/include) */
711
- #include "./backward_references_inc.h"
712
- #undef HASHER
713
-
714
- #define HASHER() H41
715
- /* NOLINTNEXTLINE(build/include) */
716
- #include "./backward_references_inc.h"
717
- #undef HASHER
718
-
719
- #define HASHER() H42
720
- /* NOLINTNEXTLINE(build/include) */
721
- #include "./backward_references_inc.h"
722
- #undef HASHER
723
-
724
- #undef FN
725
- #undef CAT
726
- #undef EXPAND_CAT
727
-
728
- static BROTLI_NOINLINE void CreateZopfliBackwardReferences(
729
- MemoryManager* m, size_t num_bytes, size_t position, BROTLI_BOOL is_last,
730
- const uint8_t* ringbuffer, size_t ringbuffer_mask,
731
- const BrotliEncoderParams* params, H10* hasher, int* dist_cache,
690
+ void BrotliCreateZopfliBackwardReferences(
691
+ MemoryManager* m, const BrotliDictionary* dictionary, size_t num_bytes,
692
+ size_t position, const uint8_t* ringbuffer, size_t ringbuffer_mask,
693
+ const BrotliEncoderParams* params, HasherHandle hasher, int* dist_cache,
732
694
  size_t* last_insert_len, Command* commands, size_t* num_commands,
733
695
  size_t* num_literals) {
734
- const size_t max_backward_limit = MaxBackwardLimit(params->lgwin);
696
+ const size_t max_backward_limit = BROTLI_MAX_BACKWARD_LIMIT(params->lgwin);
735
697
  ZopfliNode* nodes;
736
- InitH10(m, hasher, ringbuffer, params, position, num_bytes, is_last);
737
- if (BROTLI_IS_OOM(m)) return;
738
- StitchToPreviousBlockH10(hasher, num_bytes, position,
739
- ringbuffer, ringbuffer_mask);
740
698
  nodes = BROTLI_ALLOC(m, ZopfliNode, num_bytes + 1);
741
699
  if (BROTLI_IS_OOM(m)) return;
742
700
  BrotliInitZopfliNodes(nodes, num_bytes + 1);
743
- *num_commands += BrotliZopfliComputeShortestPath(m, num_bytes, position,
744
- ringbuffer, ringbuffer_mask, params, max_backward_limit,
701
+ *num_commands += BrotliZopfliComputeShortestPath(m, dictionary, num_bytes,
702
+ position, ringbuffer, ringbuffer_mask, params, max_backward_limit,
745
703
  dist_cache, hasher, nodes);
746
704
  if (BROTLI_IS_OOM(m)) return;
747
705
  BrotliZopfliCreateCommands(num_bytes, position, max_backward_limit, nodes,
748
- dist_cache, last_insert_len, commands, num_literals);
706
+ dist_cache, last_insert_len, params, commands, num_literals);
749
707
  BROTLI_FREE(m, nodes);
750
708
  }
751
709
 
752
- static BROTLI_NOINLINE void CreateHqZopfliBackwardReferences(
753
- MemoryManager* m, size_t num_bytes, size_t position, BROTLI_BOOL is_last,
754
- const uint8_t* ringbuffer, size_t ringbuffer_mask,
755
- const BrotliEncoderParams* params, H10* hasher, int* dist_cache,
710
+ void BrotliCreateHqZopfliBackwardReferences(
711
+ MemoryManager* m, const BrotliDictionary* dictionary, size_t num_bytes,
712
+ size_t position, const uint8_t* ringbuffer, size_t ringbuffer_mask,
713
+ const BrotliEncoderParams* params, HasherHandle hasher, int* dist_cache,
756
714
  size_t* last_insert_len, Command* commands, size_t* num_commands,
757
715
  size_t* num_literals) {
758
- const size_t max_backward_limit = MaxBackwardLimit(params->lgwin);
716
+ const size_t max_backward_limit = BROTLI_MAX_BACKWARD_LIMIT(params->lgwin);
759
717
  uint32_t* num_matches = BROTLI_ALLOC(m, uint32_t, num_bytes);
760
718
  size_t matches_size = 4 * num_bytes;
761
719
  const size_t store_end = num_bytes >= StoreLookaheadH10() ?
@@ -769,11 +727,8 @@ static BROTLI_NOINLINE void CreateHqZopfliBackwardReferences(
769
727
  ZopfliCostModel model;
770
728
  ZopfliNode* nodes;
771
729
  BackwardMatch* matches = BROTLI_ALLOC(m, BackwardMatch, matches_size);
730
+ size_t gap = 0;
772
731
  if (BROTLI_IS_OOM(m)) return;
773
- InitH10(m, hasher, ringbuffer, params, position, num_bytes, is_last);
774
- if (BROTLI_IS_OOM(m)) return;
775
- StitchToPreviousBlockH10(hasher, num_bytes, position,
776
- ringbuffer, ringbuffer_mask);
777
732
  for (i = 0; i + HashTypeLengthH10() - 1 < num_bytes; ++i) {
778
733
  const size_t pos = position + i;
779
734
  size_t max_distance = BROTLI_MIN(size_t, pos, max_backward_limit);
@@ -785,14 +740,13 @@ static BROTLI_NOINLINE void CreateHqZopfliBackwardReferences(
785
740
  BROTLI_ENSURE_CAPACITY(m, BackwardMatch, matches, matches_size,
786
741
  cur_match_pos + MAX_NUM_MATCHES_H10);
787
742
  if (BROTLI_IS_OOM(m)) return;
788
- num_found_matches = FindAllMatchesH10(hasher, ringbuffer, ringbuffer_mask,
789
- pos, max_length, max_distance, params, &matches[cur_match_pos]);
743
+ num_found_matches = FindAllMatchesH10(hasher, dictionary, ringbuffer,
744
+ ringbuffer_mask, pos, max_length, max_distance, gap, params,
745
+ &matches[cur_match_pos]);
790
746
  cur_match_end = cur_match_pos + num_found_matches;
791
747
  for (j = cur_match_pos; j + 1 < cur_match_end; ++j) {
792
- assert(BackwardMatchLength(&matches[j]) <
748
+ assert(BackwardMatchLength(&matches[j]) <=
793
749
  BackwardMatchLength(&matches[j + 1]));
794
- assert(matches[j].distance > max_distance ||
795
- matches[j].distance <= matches[j + 1].distance);
796
750
  }
797
751
  num_matches[i] = (uint32_t)num_found_matches;
798
752
  if (num_found_matches > 0) {
@@ -834,10 +788,10 @@ static BROTLI_NOINLINE void CreateHqZopfliBackwardReferences(
834
788
  *last_insert_len = orig_last_insert_len;
835
789
  memcpy(dist_cache, orig_dist_cache, 4 * sizeof(dist_cache[0]));
836
790
  *num_commands += ZopfliIterate(num_bytes, position, ringbuffer,
837
- ringbuffer_mask, params, max_backward_limit, dist_cache,
791
+ ringbuffer_mask, params, max_backward_limit, gap, dist_cache,
838
792
  &model, num_matches, matches, nodes);
839
793
  BrotliZopfliCreateCommands(num_bytes, position, max_backward_limit,
840
- nodes, dist_cache, last_insert_len, commands, num_literals);
794
+ nodes, dist_cache, last_insert_len, params, commands, num_literals);
841
795
  }
842
796
  CleanupZopfliCostModel(m, &model);
843
797
  BROTLI_FREE(m, nodes);
@@ -845,48 +799,6 @@ static BROTLI_NOINLINE void CreateHqZopfliBackwardReferences(
845
799
  BROTLI_FREE(m, num_matches);
846
800
  }
847
801
 
848
- void BrotliCreateBackwardReferences(MemoryManager* m,
849
- size_t num_bytes,
850
- size_t position,
851
- BROTLI_BOOL is_last,
852
- const uint8_t* ringbuffer,
853
- size_t ringbuffer_mask,
854
- const BrotliEncoderParams* params,
855
- Hashers* hashers,
856
- int* dist_cache,
857
- size_t* last_insert_len,
858
- Command* commands,
859
- size_t* num_commands,
860
- size_t* num_literals) {
861
- if (params->quality == ZOPFLIFICATION_QUALITY) {
862
- CreateZopfliBackwardReferences(
863
- m, num_bytes, position, is_last, ringbuffer, ringbuffer_mask,
864
- params, hashers->h10, dist_cache,
865
- last_insert_len, commands, num_commands, num_literals);
866
- return;
867
- } else if (params->quality == HQ_ZOPFLIFICATION_QUALITY) {
868
- CreateHqZopfliBackwardReferences(
869
- m, num_bytes, position, is_last, ringbuffer, ringbuffer_mask,
870
- params, hashers->h10, dist_cache,
871
- last_insert_len, commands, num_commands, num_literals);
872
- return;
873
- }
874
-
875
- switch (ChooseHasher(params)) {
876
- #define _CASE(N) \
877
- case N: \
878
- CreateBackwardReferencesH ## N(m, num_bytes, position, is_last, \
879
- ringbuffer, ringbuffer_mask, params, hashers->h ## N, dist_cache, \
880
- last_insert_len, commands, num_commands, num_literals); \
881
- break;
882
- FOR_GENERIC_HASHERS(_CASE)
883
- #undef _CASE
884
- default:
885
- break;
886
- }
887
- if (BROTLI_IS_OOM(m)) return;
888
- }
889
-
890
802
  #if defined(__cplusplus) || defined(c_plusplus)
891
803
  } /* extern "C" */
892
804
  #endif