lz77.c revision 1.1.1.1.8.2 1 1.1.1.1.8.2 snj /*
2 1.1.1.1.8.2 snj Copyright 2011 Google Inc. All Rights Reserved.
3 1.1.1.1.8.2 snj
4 1.1.1.1.8.2 snj Licensed under the Apache License, Version 2.0 (the "License");
5 1.1.1.1.8.2 snj you may not use this file except in compliance with the License.
6 1.1.1.1.8.2 snj You may obtain a copy of the License at
7 1.1.1.1.8.2 snj
8 1.1.1.1.8.2 snj http://www.apache.org/licenses/LICENSE-2.0
9 1.1.1.1.8.2 snj
10 1.1.1.1.8.2 snj Unless required by applicable law or agreed to in writing, software
11 1.1.1.1.8.2 snj distributed under the License is distributed on an "AS IS" BASIS,
12 1.1.1.1.8.2 snj WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 1.1.1.1.8.2 snj See the License for the specific language governing permissions and
14 1.1.1.1.8.2 snj limitations under the License.
15 1.1.1.1.8.2 snj
16 1.1.1.1.8.2 snj Author: lode.vandevenne (at) gmail.com (Lode Vandevenne)
17 1.1.1.1.8.2 snj Author: jyrki.alakuijala (at) gmail.com (Jyrki Alakuijala)
18 1.1.1.1.8.2 snj */
19 1.1.1.1.8.2 snj
20 1.1.1.1.8.2 snj #include "lz77.h"
21 1.1.1.1.8.2 snj #include "util.h"
22 1.1.1.1.8.2 snj
23 1.1.1.1.8.2 snj #include <assert.h>
24 1.1.1.1.8.2 snj #include <stdio.h>
25 1.1.1.1.8.2 snj #include <stdlib.h>
26 1.1.1.1.8.2 snj
27 1.1.1.1.8.2 snj void ZopfliInitLZ77Store(ZopfliLZ77Store* store) {
28 1.1.1.1.8.2 snj store->size = 0;
29 1.1.1.1.8.2 snj store->litlens = 0;
30 1.1.1.1.8.2 snj store->dists = 0;
31 1.1.1.1.8.2 snj }
32 1.1.1.1.8.2 snj
33 1.1.1.1.8.2 snj void ZopfliCleanLZ77Store(ZopfliLZ77Store* store) {
34 1.1.1.1.8.2 snj free(store->litlens);
35 1.1.1.1.8.2 snj free(store->dists);
36 1.1.1.1.8.2 snj }
37 1.1.1.1.8.2 snj
38 1.1.1.1.8.2 snj void ZopfliCopyLZ77Store(
39 1.1.1.1.8.2 snj const ZopfliLZ77Store* source, ZopfliLZ77Store* dest) {
40 1.1.1.1.8.2 snj size_t i;
41 1.1.1.1.8.2 snj ZopfliCleanLZ77Store(dest);
42 1.1.1.1.8.2 snj dest->litlens =
43 1.1.1.1.8.2 snj (unsigned short*)malloc(sizeof(*dest->litlens) * source->size);
44 1.1.1.1.8.2 snj dest->dists = (unsigned short*)malloc(sizeof(*dest->dists) * source->size);
45 1.1.1.1.8.2 snj
46 1.1.1.1.8.2 snj if (!dest->litlens || !dest->dists) exit(-1); /* Allocation failed. */
47 1.1.1.1.8.2 snj
48 1.1.1.1.8.2 snj dest->size = source->size;
49 1.1.1.1.8.2 snj for (i = 0; i < source->size; i++) {
50 1.1.1.1.8.2 snj dest->litlens[i] = source->litlens[i];
51 1.1.1.1.8.2 snj dest->dists[i] = source->dists[i];
52 1.1.1.1.8.2 snj }
53 1.1.1.1.8.2 snj }
54 1.1.1.1.8.2 snj
55 1.1.1.1.8.2 snj /*
56 1.1.1.1.8.2 snj Appends the length and distance to the LZ77 arrays of the ZopfliLZ77Store.
57 1.1.1.1.8.2 snj context must be a ZopfliLZ77Store*.
58 1.1.1.1.8.2 snj */
59 1.1.1.1.8.2 snj void ZopfliStoreLitLenDist(unsigned short length, unsigned short dist,
60 1.1.1.1.8.2 snj ZopfliLZ77Store* store) {
61 1.1.1.1.8.2 snj size_t size2 = store->size; /* Needed for using ZOPFLI_APPEND_DATA twice. */
62 1.1.1.1.8.2 snj ZOPFLI_APPEND_DATA(length, &store->litlens, &store->size);
63 1.1.1.1.8.2 snj ZOPFLI_APPEND_DATA(dist, &store->dists, &size2);
64 1.1.1.1.8.2 snj }
65 1.1.1.1.8.2 snj
66 1.1.1.1.8.2 snj /*
67 1.1.1.1.8.2 snj Gets the value of the length given the distance. Typically, the value of the
68 1.1.1.1.8.2 snj length is the length, but if the distance is very long, decrease the value of
69 1.1.1.1.8.2 snj the length a bit to make up for the fact that long distances use large amounts
70 1.1.1.1.8.2 snj of extra bits.
71 1.1.1.1.8.2 snj */
72 1.1.1.1.8.2 snj static int GetLengthValue(int length, int distance) {
73 1.1.1.1.8.2 snj /*
74 1.1.1.1.8.2 snj At distance > 1024, using length 3 is no longer good, due to the large amount
75 1.1.1.1.8.2 snj of extra bits for the distance code. distance > 1024 uses 9+ extra bits, and
76 1.1.1.1.8.2 snj this seems to be the sweet spot.
77 1.1.1.1.8.2 snj */
78 1.1.1.1.8.2 snj return distance > 1024 ? length - 1 : length;
79 1.1.1.1.8.2 snj }
80 1.1.1.1.8.2 snj
81 1.1.1.1.8.2 snj void ZopfliVerifyLenDist(const unsigned char* data, size_t datasize, size_t pos,
82 1.1.1.1.8.2 snj unsigned short dist, unsigned short length) {
83 1.1.1.1.8.2 snj
84 1.1.1.1.8.2 snj /* TODO(lode): make this only run in a debug compile, it's for assert only. */
85 1.1.1.1.8.2 snj size_t i;
86 1.1.1.1.8.2 snj
87 1.1.1.1.8.2 snj assert(pos + length <= datasize);
88 1.1.1.1.8.2 snj for (i = 0; i < length; i++) {
89 1.1.1.1.8.2 snj if (data[pos - dist + i] != data[pos + i]) {
90 1.1.1.1.8.2 snj assert(data[pos - dist + i] == data[pos + i]);
91 1.1.1.1.8.2 snj break;
92 1.1.1.1.8.2 snj }
93 1.1.1.1.8.2 snj }
94 1.1.1.1.8.2 snj }
95 1.1.1.1.8.2 snj
96 1.1.1.1.8.2 snj /*
97 1.1.1.1.8.2 snj Finds how long the match of scan and match is. Can be used to find how many
98 1.1.1.1.8.2 snj bytes starting from scan, and from match, are equal. Returns the last byte
99 1.1.1.1.8.2 snj after scan, which is still equal to the correspondinb byte after match.
100 1.1.1.1.8.2 snj scan is the position to compare
101 1.1.1.1.8.2 snj match is the earlier position to compare.
102 1.1.1.1.8.2 snj end is the last possible byte, beyond which to stop looking.
103 1.1.1.1.8.2 snj safe_end is a few (8) bytes before end, for comparing multiple bytes at once.
104 1.1.1.1.8.2 snj */
105 1.1.1.1.8.2 snj static const unsigned char* GetMatch(const unsigned char* scan,
106 1.1.1.1.8.2 snj const unsigned char* match,
107 1.1.1.1.8.2 snj const unsigned char* end,
108 1.1.1.1.8.2 snj const unsigned char* safe_end) {
109 1.1.1.1.8.2 snj
110 1.1.1.1.8.2 snj if (sizeof(size_t) == 8) {
111 1.1.1.1.8.2 snj /* 8 checks at once per array bounds check (size_t is 64-bit). */
112 1.1.1.1.8.2 snj while (scan < safe_end && *((size_t*)scan) == *((size_t*)match)) {
113 1.1.1.1.8.2 snj scan += 8;
114 1.1.1.1.8.2 snj match += 8;
115 1.1.1.1.8.2 snj }
116 1.1.1.1.8.2 snj } else if (sizeof(unsigned int) == 4) {
117 1.1.1.1.8.2 snj /* 4 checks at once per array bounds check (unsigned int is 32-bit). */
118 1.1.1.1.8.2 snj while (scan < safe_end
119 1.1.1.1.8.2 snj && *((unsigned int*)scan) == *((unsigned int*)match)) {
120 1.1.1.1.8.2 snj scan += 4;
121 1.1.1.1.8.2 snj match += 4;
122 1.1.1.1.8.2 snj }
123 1.1.1.1.8.2 snj } else {
124 1.1.1.1.8.2 snj /* do 8 checks at once per array bounds check. */
125 1.1.1.1.8.2 snj while (scan < safe_end && *scan == *match && *++scan == *++match
126 1.1.1.1.8.2 snj && *++scan == *++match && *++scan == *++match
127 1.1.1.1.8.2 snj && *++scan == *++match && *++scan == *++match
128 1.1.1.1.8.2 snj && *++scan == *++match && *++scan == *++match) {
129 1.1.1.1.8.2 snj scan++; match++;
130 1.1.1.1.8.2 snj }
131 1.1.1.1.8.2 snj }
132 1.1.1.1.8.2 snj
133 1.1.1.1.8.2 snj /* The remaining few bytes. */
134 1.1.1.1.8.2 snj while (scan != end && *scan == *match) {
135 1.1.1.1.8.2 snj scan++; match++;
136 1.1.1.1.8.2 snj }
137 1.1.1.1.8.2 snj
138 1.1.1.1.8.2 snj return scan;
139 1.1.1.1.8.2 snj }
140 1.1.1.1.8.2 snj
141 1.1.1.1.8.2 snj #ifdef ZOPFLI_LONGEST_MATCH_CACHE
142 1.1.1.1.8.2 snj /*
143 1.1.1.1.8.2 snj Gets distance, length and sublen values from the cache if possible.
144 1.1.1.1.8.2 snj Returns 1 if it got the values from the cache, 0 if not.
145 1.1.1.1.8.2 snj Updates the limit value to a smaller one if possible with more limited
146 1.1.1.1.8.2 snj information from the cache.
147 1.1.1.1.8.2 snj */
148 1.1.1.1.8.2 snj static int TryGetFromLongestMatchCache(ZopfliBlockState* s,
149 1.1.1.1.8.2 snj size_t pos, size_t* limit,
150 1.1.1.1.8.2 snj unsigned short* sublen, unsigned short* distance, unsigned short* length) {
151 1.1.1.1.8.2 snj /* The LMC cache starts at the beginning of the block rather than the
152 1.1.1.1.8.2 snj beginning of the whole array. */
153 1.1.1.1.8.2 snj size_t lmcpos = pos - s->blockstart;
154 1.1.1.1.8.2 snj
155 1.1.1.1.8.2 snj /* Length > 0 and dist 0 is invalid combination, which indicates on purpose
156 1.1.1.1.8.2 snj that this cache value is not filled in yet. */
157 1.1.1.1.8.2 snj unsigned char cache_available = s->lmc && (s->lmc->length[lmcpos] == 0 ||
158 1.1.1.1.8.2 snj s->lmc->dist[lmcpos] != 0);
159 1.1.1.1.8.2 snj unsigned char limit_ok_for_cache = cache_available &&
160 1.1.1.1.8.2 snj (*limit == ZOPFLI_MAX_MATCH || s->lmc->length[lmcpos] <= *limit ||
161 1.1.1.1.8.2 snj (sublen && ZopfliMaxCachedSublen(s->lmc,
162 1.1.1.1.8.2 snj lmcpos, s->lmc->length[lmcpos]) >= *limit));
163 1.1.1.1.8.2 snj
164 1.1.1.1.8.2 snj if (s->lmc && limit_ok_for_cache && cache_available) {
165 1.1.1.1.8.2 snj if (!sublen || s->lmc->length[lmcpos]
166 1.1.1.1.8.2 snj <= ZopfliMaxCachedSublen(s->lmc, lmcpos, s->lmc->length[lmcpos])) {
167 1.1.1.1.8.2 snj *length = s->lmc->length[lmcpos];
168 1.1.1.1.8.2 snj if (*length > *limit) *length = *limit;
169 1.1.1.1.8.2 snj if (sublen) {
170 1.1.1.1.8.2 snj ZopfliCacheToSublen(s->lmc, lmcpos, *length, sublen);
171 1.1.1.1.8.2 snj *distance = sublen[*length];
172 1.1.1.1.8.2 snj if (*limit == ZOPFLI_MAX_MATCH && *length >= ZOPFLI_MIN_MATCH) {
173 1.1.1.1.8.2 snj assert(sublen[*length] == s->lmc->dist[lmcpos]);
174 1.1.1.1.8.2 snj }
175 1.1.1.1.8.2 snj } else {
176 1.1.1.1.8.2 snj *distance = s->lmc->dist[lmcpos];
177 1.1.1.1.8.2 snj }
178 1.1.1.1.8.2 snj return 1;
179 1.1.1.1.8.2 snj }
180 1.1.1.1.8.2 snj /* Can't use much of the cache, since the "sublens" need to be calculated,
181 1.1.1.1.8.2 snj but at least we already know when to stop. */
182 1.1.1.1.8.2 snj *limit = s->lmc->length[lmcpos];
183 1.1.1.1.8.2 snj }
184 1.1.1.1.8.2 snj
185 1.1.1.1.8.2 snj return 0;
186 1.1.1.1.8.2 snj }
187 1.1.1.1.8.2 snj
188 1.1.1.1.8.2 snj /*
189 1.1.1.1.8.2 snj Stores the found sublen, distance and length in the longest match cache, if
190 1.1.1.1.8.2 snj possible.
191 1.1.1.1.8.2 snj */
192 1.1.1.1.8.2 snj static void StoreInLongestMatchCache(ZopfliBlockState* s,
193 1.1.1.1.8.2 snj size_t pos, size_t limit,
194 1.1.1.1.8.2 snj const unsigned short* sublen,
195 1.1.1.1.8.2 snj unsigned short distance, unsigned short length) {
196 1.1.1.1.8.2 snj /* The LMC cache starts at the beginning of the block rather than the
197 1.1.1.1.8.2 snj beginning of the whole array. */
198 1.1.1.1.8.2 snj size_t lmcpos = pos - s->blockstart;
199 1.1.1.1.8.2 snj
200 1.1.1.1.8.2 snj /* Length > 0 and dist 0 is invalid combination, which indicates on purpose
201 1.1.1.1.8.2 snj that this cache value is not filled in yet. */
202 1.1.1.1.8.2 snj unsigned char cache_available = s->lmc && (s->lmc->length[lmcpos] == 0 ||
203 1.1.1.1.8.2 snj s->lmc->dist[lmcpos] != 0);
204 1.1.1.1.8.2 snj
205 1.1.1.1.8.2 snj if (s->lmc && limit == ZOPFLI_MAX_MATCH && sublen && !cache_available) {
206 1.1.1.1.8.2 snj assert(s->lmc->length[lmcpos] == 1 && s->lmc->dist[lmcpos] == 0);
207 1.1.1.1.8.2 snj s->lmc->dist[lmcpos] = length < ZOPFLI_MIN_MATCH ? 0 : distance;
208 1.1.1.1.8.2 snj s->lmc->length[lmcpos] = length < ZOPFLI_MIN_MATCH ? 0 : length;
209 1.1.1.1.8.2 snj assert(!(s->lmc->length[lmcpos] == 1 && s->lmc->dist[lmcpos] == 0));
210 1.1.1.1.8.2 snj ZopfliSublenToCache(sublen, lmcpos, length, s->lmc);
211 1.1.1.1.8.2 snj }
212 1.1.1.1.8.2 snj }
213 1.1.1.1.8.2 snj #endif
214 1.1.1.1.8.2 snj
215 1.1.1.1.8.2 snj void ZopfliFindLongestMatch(ZopfliBlockState* s, const ZopfliHash* h,
216 1.1.1.1.8.2 snj const unsigned char* array,
217 1.1.1.1.8.2 snj size_t pos, size_t size, size_t limit,
218 1.1.1.1.8.2 snj unsigned short* sublen, unsigned short* distance, unsigned short* length) {
219 1.1.1.1.8.2 snj unsigned short hpos = pos & ZOPFLI_WINDOW_MASK, p, pp;
220 1.1.1.1.8.2 snj unsigned short bestdist = 0;
221 1.1.1.1.8.2 snj unsigned short bestlength = 1;
222 1.1.1.1.8.2 snj const unsigned char* scan;
223 1.1.1.1.8.2 snj const unsigned char* match;
224 1.1.1.1.8.2 snj const unsigned char* arrayend;
225 1.1.1.1.8.2 snj const unsigned char* arrayend_safe;
226 1.1.1.1.8.2 snj #if ZOPFLI_MAX_CHAIN_HITS < ZOPFLI_WINDOW_SIZE
227 1.1.1.1.8.2 snj int chain_counter = ZOPFLI_MAX_CHAIN_HITS; /* For quitting early. */
228 1.1.1.1.8.2 snj #endif
229 1.1.1.1.8.2 snj
230 1.1.1.1.8.2 snj unsigned dist = 0; /* Not unsigned short on purpose. */
231 1.1.1.1.8.2 snj
232 1.1.1.1.8.2 snj int* hhead = h->head;
233 1.1.1.1.8.2 snj unsigned short* hprev = h->prev;
234 1.1.1.1.8.2 snj int* hhashval = h->hashval;
235 1.1.1.1.8.2 snj int hval = h->val;
236 1.1.1.1.8.2 snj
237 1.1.1.1.8.2 snj #ifdef ZOPFLI_LONGEST_MATCH_CACHE
238 1.1.1.1.8.2 snj if (TryGetFromLongestMatchCache(s, pos, &limit, sublen, distance, length)) {
239 1.1.1.1.8.2 snj assert(pos + *length <= size);
240 1.1.1.1.8.2 snj return;
241 1.1.1.1.8.2 snj }
242 1.1.1.1.8.2 snj #endif
243 1.1.1.1.8.2 snj
244 1.1.1.1.8.2 snj assert(limit <= ZOPFLI_MAX_MATCH);
245 1.1.1.1.8.2 snj assert(limit >= ZOPFLI_MIN_MATCH);
246 1.1.1.1.8.2 snj assert(pos < size);
247 1.1.1.1.8.2 snj
248 1.1.1.1.8.2 snj if (size - pos < ZOPFLI_MIN_MATCH) {
249 1.1.1.1.8.2 snj /* The rest of the code assumes there are at least ZOPFLI_MIN_MATCH bytes to
250 1.1.1.1.8.2 snj try. */
251 1.1.1.1.8.2 snj *length = 0;
252 1.1.1.1.8.2 snj *distance = 0;
253 1.1.1.1.8.2 snj return;
254 1.1.1.1.8.2 snj }
255 1.1.1.1.8.2 snj
256 1.1.1.1.8.2 snj if (pos + limit > size) {
257 1.1.1.1.8.2 snj limit = size - pos;
258 1.1.1.1.8.2 snj }
259 1.1.1.1.8.2 snj arrayend = &array[pos] + limit;
260 1.1.1.1.8.2 snj arrayend_safe = arrayend - 8;
261 1.1.1.1.8.2 snj
262 1.1.1.1.8.2 snj assert(hval < 65536);
263 1.1.1.1.8.2 snj
264 1.1.1.1.8.2 snj pp = hhead[hval]; /* During the whole loop, p == hprev[pp]. */
265 1.1.1.1.8.2 snj p = hprev[pp];
266 1.1.1.1.8.2 snj
267 1.1.1.1.8.2 snj assert(pp == hpos);
268 1.1.1.1.8.2 snj
269 1.1.1.1.8.2 snj dist = p < pp ? pp - p : ((ZOPFLI_WINDOW_SIZE - p) + pp);
270 1.1.1.1.8.2 snj
271 1.1.1.1.8.2 snj /* Go through all distances. */
272 1.1.1.1.8.2 snj while (dist < ZOPFLI_WINDOW_SIZE) {
273 1.1.1.1.8.2 snj unsigned short currentlength = 0;
274 1.1.1.1.8.2 snj
275 1.1.1.1.8.2 snj assert(p < ZOPFLI_WINDOW_SIZE);
276 1.1.1.1.8.2 snj assert(p == hprev[pp]);
277 1.1.1.1.8.2 snj assert(hhashval[p] == hval);
278 1.1.1.1.8.2 snj
279 1.1.1.1.8.2 snj if (dist > 0) {
280 1.1.1.1.8.2 snj assert(pos < size);
281 1.1.1.1.8.2 snj assert(dist <= pos);
282 1.1.1.1.8.2 snj scan = &array[pos];
283 1.1.1.1.8.2 snj match = &array[pos - dist];
284 1.1.1.1.8.2 snj
285 1.1.1.1.8.2 snj /* Testing the byte at position bestlength first, goes slightly faster. */
286 1.1.1.1.8.2 snj if (pos + bestlength >= size
287 1.1.1.1.8.2 snj || *(scan + bestlength) == *(match + bestlength)) {
288 1.1.1.1.8.2 snj
289 1.1.1.1.8.2 snj #ifdef ZOPFLI_HASH_SAME
290 1.1.1.1.8.2 snj unsigned short same0 = h->same[pos & ZOPFLI_WINDOW_MASK];
291 1.1.1.1.8.2 snj if (same0 > 2 && *scan == *match) {
292 1.1.1.1.8.2 snj unsigned short same1 = h->same[(pos - dist) & ZOPFLI_WINDOW_MASK];
293 1.1.1.1.8.2 snj unsigned short same = same0 < same1 ? same0 : same1;
294 1.1.1.1.8.2 snj if (same > limit) same = limit;
295 1.1.1.1.8.2 snj scan += same;
296 1.1.1.1.8.2 snj match += same;
297 1.1.1.1.8.2 snj }
298 1.1.1.1.8.2 snj #endif
299 1.1.1.1.8.2 snj scan = GetMatch(scan, match, arrayend, arrayend_safe);
300 1.1.1.1.8.2 snj currentlength = scan - &array[pos]; /* The found length. */
301 1.1.1.1.8.2 snj }
302 1.1.1.1.8.2 snj
303 1.1.1.1.8.2 snj if (currentlength > bestlength) {
304 1.1.1.1.8.2 snj if (sublen) {
305 1.1.1.1.8.2 snj unsigned short j;
306 1.1.1.1.8.2 snj for (j = bestlength + 1; j <= currentlength; j++) {
307 1.1.1.1.8.2 snj sublen[j] = dist;
308 1.1.1.1.8.2 snj }
309 1.1.1.1.8.2 snj }
310 1.1.1.1.8.2 snj bestdist = dist;
311 1.1.1.1.8.2 snj bestlength = currentlength;
312 1.1.1.1.8.2 snj if (currentlength >= limit) break;
313 1.1.1.1.8.2 snj }
314 1.1.1.1.8.2 snj }
315 1.1.1.1.8.2 snj
316 1.1.1.1.8.2 snj
317 1.1.1.1.8.2 snj #ifdef ZOPFLI_HASH_SAME_HASH
318 1.1.1.1.8.2 snj /* Switch to the other hash once this will be more efficient. */
319 1.1.1.1.8.2 snj if (hhead != h->head2 && bestlength >= h->same[hpos] &&
320 1.1.1.1.8.2 snj h->val2 == h->hashval2[p]) {
321 1.1.1.1.8.2 snj /* Now use the hash that encodes the length and first byte. */
322 1.1.1.1.8.2 snj hhead = h->head2;
323 1.1.1.1.8.2 snj hprev = h->prev2;
324 1.1.1.1.8.2 snj hhashval = h->hashval2;
325 1.1.1.1.8.2 snj hval = h->val2;
326 1.1.1.1.8.2 snj }
327 1.1.1.1.8.2 snj #endif
328 1.1.1.1.8.2 snj
329 1.1.1.1.8.2 snj pp = p;
330 1.1.1.1.8.2 snj p = hprev[p];
331 1.1.1.1.8.2 snj if (p == pp) break; /* Uninited prev value. */
332 1.1.1.1.8.2 snj
333 1.1.1.1.8.2 snj dist += p < pp ? pp - p : ((ZOPFLI_WINDOW_SIZE - p) + pp);
334 1.1.1.1.8.2 snj
335 1.1.1.1.8.2 snj #if ZOPFLI_MAX_CHAIN_HITS < ZOPFLI_WINDOW_SIZE
336 1.1.1.1.8.2 snj chain_counter--;
337 1.1.1.1.8.2 snj if (chain_counter <= 0) break;
338 1.1.1.1.8.2 snj #endif
339 1.1.1.1.8.2 snj }
340 1.1.1.1.8.2 snj
341 1.1.1.1.8.2 snj #ifdef ZOPFLI_LONGEST_MATCH_CACHE
342 1.1.1.1.8.2 snj StoreInLongestMatchCache(s, pos, limit, sublen, bestdist, bestlength);
343 1.1.1.1.8.2 snj #endif
344 1.1.1.1.8.2 snj
345 1.1.1.1.8.2 snj assert(bestlength <= limit);
346 1.1.1.1.8.2 snj
347 1.1.1.1.8.2 snj *distance = bestdist;
348 1.1.1.1.8.2 snj *length = bestlength;
349 1.1.1.1.8.2 snj assert(pos + *length <= size);
350 1.1.1.1.8.2 snj }
351 1.1.1.1.8.2 snj
352 1.1.1.1.8.2 snj void ZopfliLZ77Greedy(ZopfliBlockState* s, const unsigned char* in,
353 1.1.1.1.8.2 snj size_t instart, size_t inend,
354 1.1.1.1.8.2 snj ZopfliLZ77Store* store) {
355 1.1.1.1.8.2 snj size_t i = 0, j;
356 1.1.1.1.8.2 snj unsigned short leng;
357 1.1.1.1.8.2 snj unsigned short dist;
358 1.1.1.1.8.2 snj int lengvalue;
359 1.1.1.1.8.2 snj size_t windowstart = instart > ZOPFLI_WINDOW_SIZE
360 1.1.1.1.8.2 snj ? instart - ZOPFLI_WINDOW_SIZE : 0;
361 1.1.1.1.8.2 snj unsigned short dummysublen[259];
362 1.1.1.1.8.2 snj
363 1.1.1.1.8.2 snj ZopfliHash hash;
364 1.1.1.1.8.2 snj ZopfliHash* h = &hash;
365 1.1.1.1.8.2 snj
366 1.1.1.1.8.2 snj #ifdef ZOPFLI_LAZY_MATCHING
367 1.1.1.1.8.2 snj /* Lazy matching. */
368 1.1.1.1.8.2 snj unsigned prev_length = 0;
369 1.1.1.1.8.2 snj unsigned prev_match = 0;
370 1.1.1.1.8.2 snj int prevlengvalue;
371 1.1.1.1.8.2 snj int match_available = 0;
372 1.1.1.1.8.2 snj #endif
373 1.1.1.1.8.2 snj
374 1.1.1.1.8.2 snj if (instart == inend) return;
375 1.1.1.1.8.2 snj
376 1.1.1.1.8.2 snj ZopfliInitHash(ZOPFLI_WINDOW_SIZE, h);
377 1.1.1.1.8.2 snj ZopfliWarmupHash(in, windowstart, inend, h);
378 1.1.1.1.8.2 snj for (i = windowstart; i < instart; i++) {
379 1.1.1.1.8.2 snj ZopfliUpdateHash(in, i, inend, h);
380 1.1.1.1.8.2 snj }
381 1.1.1.1.8.2 snj
382 1.1.1.1.8.2 snj for (i = instart; i < inend; i++) {
383 1.1.1.1.8.2 snj ZopfliUpdateHash(in, i, inend, h);
384 1.1.1.1.8.2 snj
385 1.1.1.1.8.2 snj ZopfliFindLongestMatch(s, h, in, i, inend, ZOPFLI_MAX_MATCH, dummysublen,
386 1.1.1.1.8.2 snj &dist, &leng);
387 1.1.1.1.8.2 snj lengvalue = GetLengthValue(leng, dist);
388 1.1.1.1.8.2 snj
389 1.1.1.1.8.2 snj #ifdef ZOPFLI_LAZY_MATCHING
390 1.1.1.1.8.2 snj /* Lazy matching. */
391 1.1.1.1.8.2 snj prevlengvalue = GetLengthValue(prev_length, prev_match);
392 1.1.1.1.8.2 snj if (match_available) {
393 1.1.1.1.8.2 snj match_available = 0;
394 1.1.1.1.8.2 snj if (lengvalue > prevlengvalue + 1) {
395 1.1.1.1.8.2 snj ZopfliStoreLitLenDist(in[i - 1], 0, store);
396 1.1.1.1.8.2 snj if (lengvalue >= ZOPFLI_MIN_MATCH && lengvalue < ZOPFLI_MAX_MATCH) {
397 1.1.1.1.8.2 snj match_available = 1;
398 1.1.1.1.8.2 snj prev_length = leng;
399 1.1.1.1.8.2 snj prev_match = dist;
400 1.1.1.1.8.2 snj continue;
401 1.1.1.1.8.2 snj }
402 1.1.1.1.8.2 snj } else {
403 1.1.1.1.8.2 snj /* Add previous to output. */
404 1.1.1.1.8.2 snj leng = prev_length;
405 1.1.1.1.8.2 snj dist = prev_match;
406 1.1.1.1.8.2 snj lengvalue = prevlengvalue;
407 1.1.1.1.8.2 snj /* Add to output. */
408 1.1.1.1.8.2 snj ZopfliVerifyLenDist(in, inend, i - 1, dist, leng);
409 1.1.1.1.8.2 snj ZopfliStoreLitLenDist(leng, dist, store);
410 1.1.1.1.8.2 snj for (j = 2; j < leng; j++) {
411 1.1.1.1.8.2 snj assert(i < inend);
412 1.1.1.1.8.2 snj i++;
413 1.1.1.1.8.2 snj ZopfliUpdateHash(in, i, inend, h);
414 1.1.1.1.8.2 snj }
415 1.1.1.1.8.2 snj continue;
416 1.1.1.1.8.2 snj }
417 1.1.1.1.8.2 snj }
418 1.1.1.1.8.2 snj else if (lengvalue >= ZOPFLI_MIN_MATCH && leng < ZOPFLI_MAX_MATCH) {
419 1.1.1.1.8.2 snj match_available = 1;
420 1.1.1.1.8.2 snj prev_length = leng;
421 1.1.1.1.8.2 snj prev_match = dist;
422 1.1.1.1.8.2 snj continue;
423 1.1.1.1.8.2 snj }
424 1.1.1.1.8.2 snj /* End of lazy matching. */
425 1.1.1.1.8.2 snj #endif
426 1.1.1.1.8.2 snj
427 1.1.1.1.8.2 snj /* Add to output. */
428 1.1.1.1.8.2 snj if (lengvalue >= ZOPFLI_MIN_MATCH) {
429 1.1.1.1.8.2 snj ZopfliVerifyLenDist(in, inend, i, dist, leng);
430 1.1.1.1.8.2 snj ZopfliStoreLitLenDist(leng, dist, store);
431 1.1.1.1.8.2 snj } else {
432 1.1.1.1.8.2 snj leng = 1;
433 1.1.1.1.8.2 snj ZopfliStoreLitLenDist(in[i], 0, store);
434 1.1.1.1.8.2 snj }
435 1.1.1.1.8.2 snj for (j = 1; j < leng; j++) {
436 1.1.1.1.8.2 snj assert(i < inend);
437 1.1.1.1.8.2 snj i++;
438 1.1.1.1.8.2 snj ZopfliUpdateHash(in, i, inend, h);
439 1.1.1.1.8.2 snj }
440 1.1.1.1.8.2 snj }
441 1.1.1.1.8.2 snj
442 1.1.1.1.8.2 snj ZopfliCleanHash(h);
443 1.1.1.1.8.2 snj }
444 1.1.1.1.8.2 snj
445 1.1.1.1.8.2 snj void ZopfliLZ77Counts(const unsigned short* litlens,
446 1.1.1.1.8.2 snj const unsigned short* dists,
447 1.1.1.1.8.2 snj size_t start, size_t end,
448 1.1.1.1.8.2 snj size_t* ll_count, size_t* d_count) {
449 1.1.1.1.8.2 snj size_t i;
450 1.1.1.1.8.2 snj
451 1.1.1.1.8.2 snj for (i = 0; i < 288; i++) {
452 1.1.1.1.8.2 snj ll_count[i] = 0;
453 1.1.1.1.8.2 snj }
454 1.1.1.1.8.2 snj for (i = 0; i < 32; i++) {
455 1.1.1.1.8.2 snj d_count[i] = 0;
456 1.1.1.1.8.2 snj }
457 1.1.1.1.8.2 snj
458 1.1.1.1.8.2 snj for (i = start; i < end; i++) {
459 1.1.1.1.8.2 snj if (dists[i] == 0) {
460 1.1.1.1.8.2 snj ll_count[litlens[i]]++;
461 1.1.1.1.8.2 snj } else {
462 1.1.1.1.8.2 snj ll_count[ZopfliGetLengthSymbol(litlens[i])]++;
463 1.1.1.1.8.2 snj d_count[ZopfliGetDistSymbol(dists[i])]++;
464 1.1.1.1.8.2 snj }
465 1.1.1.1.8.2 snj }
466 1.1.1.1.8.2 snj
467 1.1.1.1.8.2 snj ll_count[256] = 1; /* End symbol. */
468 1.1.1.1.8.2 snj }
469