brotli 0.1.8 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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