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