source: code/trunk/vendor/github.com/andybalholm/brotli/backward_references.go@ 145

Last change on this file since 145 was 145, checked in by Izuru Yakumo, 22 months ago

Updated the Makefile and vendored depedencies

Signed-off-by: Izuru Yakumo <yakumo.izuru@…>

File size: 6.4 KB
Line 
1package brotli
2
3import (
4 "sync"
5)
6
7/* Copyright 2013 Google Inc. All Rights Reserved.
8
9 Distributed under MIT license.
10 See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
11*/
12
13/* Function to find backward reference copies. */
14
15func computeDistanceCode(distance uint, max_distance uint, dist_cache []int) uint {
16 if distance <= max_distance {
17 var distance_plus_3 uint = distance + 3
18 var offset0 uint = distance_plus_3 - uint(dist_cache[0])
19 var offset1 uint = distance_plus_3 - uint(dist_cache[1])
20 if distance == uint(dist_cache[0]) {
21 return 0
22 } else if distance == uint(dist_cache[1]) {
23 return 1
24 } else if offset0 < 7 {
25 return (0x9750468 >> (4 * offset0)) & 0xF
26 } else if offset1 < 7 {
27 return (0xFDB1ACE >> (4 * offset1)) & 0xF
28 } else if distance == uint(dist_cache[2]) {
29 return 2
30 } else if distance == uint(dist_cache[3]) {
31 return 3
32 }
33 }
34
35 return distance + numDistanceShortCodes - 1
36}
37
38var hasherSearchResultPool sync.Pool
39
40func createBackwardReferences(num_bytes uint, position uint, ringbuffer []byte, ringbuffer_mask uint, params *encoderParams, hasher hasherHandle, dist_cache []int, last_insert_len *uint, commands *[]command, num_literals *uint) {
41 var max_backward_limit uint = maxBackwardLimit(params.lgwin)
42 var insert_length uint = *last_insert_len
43 var pos_end uint = position + num_bytes
44 var store_end uint
45 if num_bytes >= hasher.StoreLookahead() {
46 store_end = position + num_bytes - hasher.StoreLookahead() + 1
47 } else {
48 store_end = position
49 }
50 var random_heuristics_window_size uint = literalSpreeLengthForSparseSearch(params)
51 var apply_random_heuristics uint = position + random_heuristics_window_size
52 var gap uint = 0
53 /* Set maximum distance, see section 9.1. of the spec. */
54
55 const kMinScore uint = scoreBase + 100
56
57 /* For speed up heuristics for random data. */
58
59 /* Minimum score to accept a backward reference. */
60 hasher.PrepareDistanceCache(dist_cache)
61 sr2, _ := hasherSearchResultPool.Get().(*hasherSearchResult)
62 if sr2 == nil {
63 sr2 = &hasherSearchResult{}
64 }
65 sr, _ := hasherSearchResultPool.Get().(*hasherSearchResult)
66 if sr == nil {
67 sr = &hasherSearchResult{}
68 }
69
70 for position+hasher.HashTypeLength() < pos_end {
71 var max_length uint = pos_end - position
72 var max_distance uint = brotli_min_size_t(position, max_backward_limit)
73 sr.len = 0
74 sr.len_code_delta = 0
75 sr.distance = 0
76 sr.score = kMinScore
77 hasher.FindLongestMatch(&params.dictionary, ringbuffer, ringbuffer_mask, dist_cache, position, max_length, max_distance, gap, params.dist.max_distance, sr)
78 if sr.score > kMinScore {
79 /* Found a match. Let's look for something even better ahead. */
80 var delayed_backward_references_in_row int = 0
81 max_length--
82 for ; ; max_length-- {
83 var cost_diff_lazy uint = 175
84 if params.quality < minQualityForExtensiveReferenceSearch {
85 sr2.len = brotli_min_size_t(sr.len-1, max_length)
86 } else {
87 sr2.len = 0
88 }
89 sr2.len_code_delta = 0
90 sr2.distance = 0
91 sr2.score = kMinScore
92 max_distance = brotli_min_size_t(position+1, max_backward_limit)
93 hasher.FindLongestMatch(&params.dictionary, ringbuffer, ringbuffer_mask, dist_cache, position+1, max_length, max_distance, gap, params.dist.max_distance, sr2)
94 if sr2.score >= sr.score+cost_diff_lazy {
95 /* Ok, let's just write one byte for now and start a match from the
96 next byte. */
97 position++
98
99 insert_length++
100 *sr = *sr2
101 delayed_backward_references_in_row++
102 if delayed_backward_references_in_row < 4 && position+hasher.HashTypeLength() < pos_end {
103 continue
104 }
105 }
106
107 break
108 }
109
110 apply_random_heuristics = position + 2*sr.len + random_heuristics_window_size
111 max_distance = brotli_min_size_t(position, max_backward_limit)
112 {
113 /* The first 16 codes are special short-codes,
114 and the minimum offset is 1. */
115 var distance_code uint = computeDistanceCode(sr.distance, max_distance+gap, dist_cache)
116 if (sr.distance <= (max_distance + gap)) && distance_code > 0 {
117 dist_cache[3] = dist_cache[2]
118 dist_cache[2] = dist_cache[1]
119 dist_cache[1] = dist_cache[0]
120 dist_cache[0] = int(sr.distance)
121 hasher.PrepareDistanceCache(dist_cache)
122 }
123
124 *commands = append(*commands, makeCommand(&params.dist, insert_length, sr.len, sr.len_code_delta, distance_code))
125 }
126
127 *num_literals += insert_length
128 insert_length = 0
129 /* Put the hash keys into the table, if there are enough bytes left.
130 Depending on the hasher implementation, it can push all positions
131 in the given range or only a subset of them.
132 Avoid hash poisoning with RLE data. */
133 {
134 var range_start uint = position + 2
135 var range_end uint = brotli_min_size_t(position+sr.len, store_end)
136 if sr.distance < sr.len>>2 {
137 range_start = brotli_min_size_t(range_end, brotli_max_size_t(range_start, position+sr.len-(sr.distance<<2)))
138 }
139
140 hasher.StoreRange(ringbuffer, ringbuffer_mask, range_start, range_end)
141 }
142
143 position += sr.len
144 } else {
145 insert_length++
146 position++
147
148 /* If we have not seen matches for a long time, we can skip some
149 match lookups. Unsuccessful match lookups are very very expensive
150 and this kind of a heuristic speeds up compression quite
151 a lot. */
152 if position > apply_random_heuristics {
153 /* Going through uncompressible data, jump. */
154 if position > apply_random_heuristics+4*random_heuristics_window_size {
155 var kMargin uint = brotli_max_size_t(hasher.StoreLookahead()-1, 4)
156 /* It is quite a long time since we saw a copy, so we assume
157 that this data is not compressible, and store hashes less
158 often. Hashes of non compressible data are less likely to
159 turn out to be useful in the future, too, so we store less of
160 them to not to flood out the hash table of good compressible
161 data. */
162
163 var pos_jump uint = brotli_min_size_t(position+16, pos_end-kMargin)
164 for ; position < pos_jump; position += 4 {
165 hasher.Store(ringbuffer, ringbuffer_mask, position)
166 insert_length += 4
167 }
168 } else {
169 var kMargin uint = brotli_max_size_t(hasher.StoreLookahead()-1, 2)
170 var pos_jump uint = brotli_min_size_t(position+8, pos_end-kMargin)
171 for ; position < pos_jump; position += 2 {
172 hasher.Store(ringbuffer, ringbuffer_mask, position)
173 insert_length += 2
174 }
175 }
176 }
177 }
178 }
179
180 insert_length += pos_end - position
181 *last_insert_len = insert_length
182
183 hasherSearchResultPool.Put(sr)
184 hasherSearchResultPool.Put(sr2)
185}
Note: See TracBrowser for help on using the repository browser.