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.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +7 -3
- data/brotli.gemspec +1 -1
- data/ext/brotli/brotli.c +4 -4
- data/ext/brotli/brotli.h +2 -2
- data/ext/brotli/extconf.rb +9 -16
- data/lib/brotli/version.rb +1 -1
- data/vendor/brotli/{common → c/common}/constants.h +11 -1
- data/vendor/brotli/c/common/dictionary.bin +432 -0
- data/vendor/brotli/c/common/dictionary.c +5905 -0
- data/vendor/brotli/c/common/dictionary.h +64 -0
- data/vendor/brotli/c/common/version.h +19 -0
- data/vendor/brotli/{dec → c/dec}/bit_reader.c +2 -2
- data/vendor/brotli/{dec → c/dec}/bit_reader.h +11 -34
- data/vendor/brotli/{dec → c/dec}/context.h +1 -1
- data/vendor/brotli/{dec → c/dec}/decode.c +389 -356
- data/vendor/brotli/{dec → c/dec}/huffman.c +24 -23
- data/vendor/brotli/{dec → c/dec}/huffman.h +1 -1
- data/vendor/brotli/{dec → c/dec}/port.h +19 -10
- data/vendor/brotli/{dec → c/dec}/prefix.h +1 -1
- data/vendor/brotli/{dec → c/dec}/state.c +23 -19
- data/vendor/brotli/{dec → c/dec}/state.h +18 -17
- data/vendor/brotli/{dec → c/dec}/transform.h +2 -2
- data/vendor/brotli/c/enc/backward_references.c +134 -0
- data/vendor/brotli/c/enc/backward_references.h +39 -0
- data/vendor/brotli/{enc/backward_references.c → c/enc/backward_references_hq.c} +144 -232
- data/vendor/brotli/{enc/backward_references.h → c/enc/backward_references_hq.h} +28 -31
- data/vendor/brotli/{enc → c/enc}/backward_references_inc.h +37 -31
- data/vendor/brotli/{enc → c/enc}/bit_cost.c +1 -1
- data/vendor/brotli/{enc → c/enc}/bit_cost.h +1 -1
- data/vendor/brotli/{enc → c/enc}/bit_cost_inc.h +0 -0
- data/vendor/brotli/{enc → c/enc}/block_encoder_inc.h +0 -0
- data/vendor/brotli/{enc → c/enc}/block_splitter.c +2 -4
- data/vendor/brotli/{enc → c/enc}/block_splitter.h +1 -1
- data/vendor/brotli/{enc → c/enc}/block_splitter_inc.h +6 -7
- data/vendor/brotli/{enc → c/enc}/brotli_bit_stream.c +22 -26
- data/vendor/brotli/{enc → c/enc}/brotli_bit_stream.h +1 -5
- data/vendor/brotli/{enc → c/enc}/cluster.c +1 -1
- data/vendor/brotli/{enc → c/enc}/cluster.h +1 -1
- data/vendor/brotli/{enc → c/enc}/cluster_inc.h +2 -0
- data/vendor/brotli/{enc → c/enc}/command.h +34 -17
- data/vendor/brotli/{enc → c/enc}/compress_fragment.c +97 -53
- data/vendor/brotli/{enc → c/enc}/compress_fragment.h +5 -2
- data/vendor/brotli/{enc → c/enc}/compress_fragment_two_pass.c +106 -51
- data/vendor/brotli/{enc → c/enc}/compress_fragment_two_pass.h +5 -2
- data/vendor/brotli/{enc → c/enc}/context.h +3 -3
- data/vendor/brotli/c/enc/dictionary_hash.c +1120 -0
- data/vendor/brotli/c/enc/dictionary_hash.h +24 -0
- data/vendor/brotli/{enc → c/enc}/encode.c +442 -240
- data/vendor/brotli/{enc → c/enc}/entropy_encode.c +9 -9
- data/vendor/brotli/{enc → c/enc}/entropy_encode.h +4 -4
- data/vendor/brotli/{enc → c/enc}/entropy_encode_static.h +4 -4
- data/vendor/brotli/{enc → c/enc}/fast_log.h +3 -3
- data/vendor/brotli/{enc → c/enc}/find_match_length.h +8 -8
- data/vendor/brotli/c/enc/hash.h +446 -0
- data/vendor/brotli/{enc → c/enc}/hash_forgetful_chain_inc.h +72 -68
- data/vendor/brotli/c/enc/hash_longest_match64_inc.h +266 -0
- data/vendor/brotli/c/enc/hash_longest_match_inc.h +258 -0
- data/vendor/brotli/{enc → c/enc}/hash_longest_match_quickly_inc.h +81 -77
- data/vendor/brotli/c/enc/hash_to_binary_tree_inc.h +326 -0
- data/vendor/brotli/{enc → c/enc}/histogram.c +4 -2
- data/vendor/brotli/{enc → c/enc}/histogram.h +1 -1
- data/vendor/brotli/{enc → c/enc}/histogram_inc.h +0 -0
- data/vendor/brotli/{enc → c/enc}/literal_cost.c +4 -7
- data/vendor/brotli/{enc → c/enc}/literal_cost.h +2 -2
- data/vendor/brotli/{enc → c/enc}/memory.c +1 -1
- data/vendor/brotli/{enc → c/enc}/memory.h +3 -2
- data/vendor/brotli/{enc → c/enc}/metablock.c +136 -123
- data/vendor/brotli/{enc → c/enc}/metablock.h +2 -12
- data/vendor/brotli/{enc → c/enc}/metablock_inc.h +0 -0
- data/vendor/brotli/{enc → c/enc}/port.h +49 -33
- data/vendor/brotli/{enc → c/enc}/prefix.h +4 -2
- data/vendor/brotli/{enc → c/enc}/quality.h +47 -17
- data/vendor/brotli/{enc → c/enc}/ringbuffer.h +6 -6
- data/vendor/brotli/{enc → c/enc}/static_dict.c +26 -22
- data/vendor/brotli/{enc → c/enc}/static_dict.h +3 -1
- data/vendor/brotli/c/enc/static_dict_lut.h +5864 -0
- data/vendor/brotli/{enc → c/enc}/utf8_util.c +1 -1
- data/vendor/brotli/{enc → c/enc}/utf8_util.h +2 -2
- data/vendor/brotli/{enc → c/enc}/write_bits.h +3 -3
- data/vendor/brotli/c/include/brotli/decode.h +339 -0
- data/vendor/brotli/c/include/brotli/encode.h +402 -0
- data/vendor/brotli/c/include/brotli/port.h +146 -0
- data/vendor/brotli/c/include/brotli/types.h +90 -0
- metadata +80 -79
- data/vendor/brotli/common/dictionary.c +0 -9474
- data/vendor/brotli/common/dictionary.h +0 -29
- data/vendor/brotli/common/port.h +0 -107
- data/vendor/brotli/common/types.h +0 -58
- data/vendor/brotli/dec/decode.h +0 -188
- data/vendor/brotli/enc/compressor.cc +0 -139
- data/vendor/brotli/enc/compressor.h +0 -161
- data/vendor/brotli/enc/dictionary_hash.h +0 -4121
- data/vendor/brotli/enc/encode.h +0 -221
- data/vendor/brotli/enc/encode_parallel.cc +0 -289
- data/vendor/brotli/enc/encode_parallel.h +0 -27
- data/vendor/brotli/enc/hash.h +0 -717
- data/vendor/brotli/enc/hash_longest_match_inc.h +0 -241
- data/vendor/brotli/enc/static_dict_lut.h +0 -11241
- data/vendor/brotli/enc/streams.cc +0 -114
- 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 "./
|
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
|
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
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
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 ?
|
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
|
-
|
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
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
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
|
-
|
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
|
-
|
435
|
-
|
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 (
|
425
|
+
if (BROTLI_PREDICT_FALSE(backward > max_distance + gap)) {
|
438
426
|
continue;
|
439
427
|
}
|
440
|
-
|
428
|
+
if (backward <= max_distance) {
|
429
|
+
if (prev_ix >= cur_ix) {
|
430
|
+
continue;
|
431
|
+
}
|
441
432
|
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
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 =
|
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 +
|
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
|
-
|
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,
|
601
|
-
|
602
|
-
|
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
|
-
|
609
|
-
|
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
|
-
|
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,
|
644
|
-
pos, num_bytes - i, max_distance, params,
|
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
|
-
|
652
|
-
|
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 +
|
657
|
-
|
658
|
-
|
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
|
-
|
666
|
-
|
667
|
-
|
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 =
|
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,
|
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
|
-
|
753
|
-
MemoryManager* m,
|
754
|
-
const uint8_t* ringbuffer, size_t ringbuffer_mask,
|
755
|
-
const BrotliEncoderParams* params,
|
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 =
|
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,
|
789
|
-
pos, max_length, max_distance, params,
|
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
|