zopfli-bin 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +7 -0
  2. data/.document +5 -0
  3. data/.gitmodules +3 -0
  4. data/.testguardrc +1 -0
  5. data/Gemfile +17 -0
  6. data/Gemfile.lock +111 -0
  7. data/LICENSE.txt +20 -0
  8. data/README.rdoc +19 -0
  9. data/Rakefile +39 -0
  10. data/VERSION +1 -0
  11. data/ext/Makefile +8 -0
  12. data/ext/extconf.rb +4 -0
  13. data/lib/zopfli-bin.rb +5 -0
  14. data/lib/zopfli/bin.rb +34 -0
  15. data/test/helper.rb +19 -0
  16. data/test/test_zopfli-bin.rb +33 -0
  17. data/vendor/zopfli/CONTRIBUTORS +7 -0
  18. data/vendor/zopfli/COPYING +201 -0
  19. data/vendor/zopfli/Makefile +37 -0
  20. data/vendor/zopfli/README +32 -0
  21. data/vendor/zopfli/README.zopflipng +35 -0
  22. data/vendor/zopfli/src/zopfli/blocksplitter.c +342 -0
  23. data/vendor/zopfli/src/zopfli/blocksplitter.h +77 -0
  24. data/vendor/zopfli/src/zopfli/cache.c +119 -0
  25. data/vendor/zopfli/src/zopfli/cache.h +66 -0
  26. data/vendor/zopfli/src/zopfli/deflate.c +866 -0
  27. data/vendor/zopfli/src/zopfli/deflate.h +86 -0
  28. data/vendor/zopfli/src/zopfli/gzip_container.c +117 -0
  29. data/vendor/zopfli/src/zopfli/gzip_container.h +50 -0
  30. data/vendor/zopfli/src/zopfli/hash.c +135 -0
  31. data/vendor/zopfli/src/zopfli/hash.h +70 -0
  32. data/vendor/zopfli/src/zopfli/katajainen.c +251 -0
  33. data/vendor/zopfli/src/zopfli/katajainen.h +42 -0
  34. data/vendor/zopfli/src/zopfli/lz77.c +482 -0
  35. data/vendor/zopfli/src/zopfli/lz77.h +129 -0
  36. data/vendor/zopfli/src/zopfli/squeeze.c +546 -0
  37. data/vendor/zopfli/src/zopfli/squeeze.h +60 -0
  38. data/vendor/zopfli/src/zopfli/tree.c +101 -0
  39. data/vendor/zopfli/src/zopfli/tree.h +51 -0
  40. data/vendor/zopfli/src/zopfli/util.c +213 -0
  41. data/vendor/zopfli/src/zopfli/util.h +175 -0
  42. data/vendor/zopfli/src/zopfli/zlib_container.c +79 -0
  43. data/vendor/zopfli/src/zopfli/zlib_container.h +50 -0
  44. data/vendor/zopfli/src/zopfli/zopfli.h +97 -0
  45. data/vendor/zopfli/src/zopfli/zopfli_bin.c +203 -0
  46. data/vendor/zopfli/src/zopfli/zopfli_lib.c +42 -0
  47. data/vendor/zopfli/src/zopflipng/lodepng/lodepng.cpp +6260 -0
  48. data/vendor/zopfli/src/zopflipng/lodepng/lodepng.h +1716 -0
  49. data/vendor/zopfli/src/zopflipng/lodepng/lodepng_util.cpp +656 -0
  50. data/vendor/zopfli/src/zopflipng/lodepng/lodepng_util.h +151 -0
  51. data/vendor/zopfli/src/zopflipng/zopflipng_bin.cc +407 -0
  52. data/vendor/zopfli/src/zopflipng/zopflipng_lib.cc +425 -0
  53. data/vendor/zopfli/src/zopflipng/zopflipng_lib.h +79 -0
  54. data/zopfli-bin.gemspec +119 -0
  55. metadata +225 -0
@@ -0,0 +1,251 @@
1
+ /*
2
+ Copyright 2011 Google Inc. All Rights Reserved.
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
15
+
16
+ Author: lode.vandevenne@gmail.com (Lode Vandevenne)
17
+ Author: jyrki.alakuijala@gmail.com (Jyrki Alakuijala)
18
+ */
19
+
20
+ /*
21
+ Bounded package merge algorithm, based on the paper
22
+ "A Fast and Space-Economical Algorithm for Length-Limited Coding
23
+ Jyrki Katajainen, Alistair Moffat, Andrew Turpin".
24
+ */
25
+
26
+ #include "katajainen.h"
27
+ #include <assert.h>
28
+ #include <stdlib.h>
29
+
30
+ typedef struct Node Node;
31
+
32
+ /*
33
+ Nodes forming chains. Also used to represent leaves.
34
+ */
35
+ struct Node {
36
+ size_t weight; /* Total weight (symbol count) of this chain. */
37
+ Node* tail; /* Previous node(s) of this chain, or 0 if none. */
38
+ int count; /* Leaf symbol index, or number of leaves before this chain. */
39
+ char inuse; /* Tracking for garbage collection. */
40
+ };
41
+
42
+ /*
43
+ Memory pool for nodes.
44
+ */
45
+ typedef struct NodePool {
46
+ Node* nodes; /* The pool. */
47
+ Node* next; /* Pointer to a possibly free node in the pool. */
48
+ int size; /* Size of the memory pool. */
49
+ } NodePool;
50
+
51
+ /*
52
+ Initializes a chain node with the given values and marks it as in use.
53
+ */
54
+ static void InitNode(size_t weight, int count, Node* tail, Node* node) {
55
+ node->weight = weight;
56
+ node->count = count;
57
+ node->tail = tail;
58
+ node->inuse = 1;
59
+ }
60
+
61
+ /*
62
+ Finds a free location in the memory pool. Performs garbage collection if needed.
63
+ lists: If given, used to mark in-use nodes during garbage collection.
64
+ maxbits: Size of lists.
65
+ pool: Memory pool to get free node from.
66
+ */
67
+ static Node* GetFreeNode(Node* (*lists)[2], int maxbits, NodePool* pool) {
68
+ for (;;) {
69
+ if (pool->next >= &pool->nodes[pool->size]) {
70
+ /* Garbage collection. */
71
+ int i;
72
+ for (i = 0; i < pool->size; i++) {
73
+ pool->nodes[i].inuse = 0;
74
+ }
75
+ if (lists) {
76
+ for (i = 0; i < maxbits * 2; i++) {
77
+ Node* node;
78
+ for (node = lists[i / 2][i % 2]; node; node = node->tail) {
79
+ node->inuse = 1;
80
+ }
81
+ }
82
+ }
83
+ pool->next = &pool->nodes[0];
84
+ }
85
+ if (!pool->next->inuse) break; /* Found one. */
86
+ pool->next++;
87
+ }
88
+ return pool->next++;
89
+ }
90
+
91
+
92
+ /*
93
+ Performs a Boundary Package-Merge step. Puts a new chain in the given list. The
94
+ new chain is, depending on the weights, a leaf or a combination of two chains
95
+ from the previous list.
96
+ lists: The lists of chains.
97
+ maxbits: Number of lists.
98
+ leaves: The leaves, one per symbol.
99
+ numsymbols: Number of leaves.
100
+ pool: the node memory pool.
101
+ index: The index of the list in which a new chain or leaf is required.
102
+ final: Whether this is the last time this function is called. If it is then it
103
+ is no more needed to recursively call self.
104
+ */
105
+ static void BoundaryPM(Node* (*lists)[2], int maxbits,
106
+ Node* leaves, int numsymbols, NodePool* pool, int index, char final) {
107
+ Node* newchain;
108
+ Node* oldchain;
109
+ int lastcount = lists[index][1]->count; /* Count of last chain of list. */
110
+
111
+ if (index == 0 && lastcount >= numsymbols) return;
112
+
113
+ newchain = GetFreeNode(lists, maxbits, pool);
114
+ oldchain = lists[index][1];
115
+
116
+ /* These are set up before the recursive calls below, so that there is a list
117
+ pointing to the new node, to let the garbage collection know it's in use. */
118
+ lists[index][0] = oldchain;
119
+ lists[index][1] = newchain;
120
+
121
+ if (index == 0) {
122
+ /* New leaf node in list 0. */
123
+ InitNode(leaves[lastcount].weight, lastcount + 1, 0, newchain);
124
+ } else {
125
+ size_t sum = lists[index - 1][0]->weight + lists[index - 1][1]->weight;
126
+ if (lastcount < numsymbols && sum > leaves[lastcount].weight) {
127
+ /* New leaf inserted in list, so count is incremented. */
128
+ InitNode(leaves[lastcount].weight, lastcount + 1, oldchain->tail,
129
+ newchain);
130
+ } else {
131
+ InitNode(sum, lastcount, lists[index - 1][1], newchain);
132
+ if (!final) {
133
+ /* Two lookahead chains of previous list used up, create new ones. */
134
+ BoundaryPM(lists, maxbits, leaves, numsymbols, pool, index - 1, 0);
135
+ BoundaryPM(lists, maxbits, leaves, numsymbols, pool, index - 1, 0);
136
+ }
137
+ }
138
+ }
139
+ }
140
+
141
+ /*
142
+ Initializes each list with as lookahead chains the two leaves with lowest
143
+ weights.
144
+ */
145
+ static void InitLists(
146
+ NodePool* pool, const Node* leaves, int maxbits, Node* (*lists)[2]) {
147
+ int i;
148
+ Node* node0 = GetFreeNode(0, maxbits, pool);
149
+ Node* node1 = GetFreeNode(0, maxbits, pool);
150
+ InitNode(leaves[0].weight, 1, 0, node0);
151
+ InitNode(leaves[1].weight, 2, 0, node1);
152
+ for (i = 0; i < maxbits; i++) {
153
+ lists[i][0] = node0;
154
+ lists[i][1] = node1;
155
+ }
156
+ }
157
+
158
+ /*
159
+ Converts result of boundary package-merge to the bitlengths. The result in the
160
+ last chain of the last list contains the amount of active leaves in each list.
161
+ chain: Chain to extract the bit length from (last chain from last list).
162
+ */
163
+ static void ExtractBitLengths(Node* chain, Node* leaves, unsigned* bitlengths) {
164
+ Node* node;
165
+ for (node = chain; node; node = node->tail) {
166
+ int i;
167
+ for (i = 0; i < node->count; i++) {
168
+ bitlengths[leaves[i].count]++;
169
+ }
170
+ }
171
+ }
172
+
173
+ /*
174
+ Comparator for sorting the leaves. Has the function signature for qsort.
175
+ */
176
+ static int LeafComparator(const void* a, const void* b) {
177
+ return ((const Node*)a)->weight - ((const Node*)b)->weight;
178
+ }
179
+
180
+ int ZopfliLengthLimitedCodeLengths(
181
+ const size_t* frequencies, int n, int maxbits, unsigned* bitlengths) {
182
+ NodePool pool;
183
+ int i;
184
+ int numsymbols = 0; /* Amount of symbols with frequency > 0. */
185
+ int numBoundaryPMRuns;
186
+
187
+ /* Array of lists of chains. Each list requires only two lookahead chains at
188
+ a time, so each list is a array of two Node*'s. */
189
+ Node* (*lists)[2];
190
+
191
+ /* One leaf per symbol. Only numsymbols leaves will be used. */
192
+ Node* leaves = (Node*)malloc(n * sizeof(*leaves));
193
+
194
+ /* Initialize all bitlengths at 0. */
195
+ for (i = 0; i < n; i++) {
196
+ bitlengths[i] = 0;
197
+ }
198
+
199
+ /* Count used symbols and place them in the leaves. */
200
+ for (i = 0; i < n; i++) {
201
+ if (frequencies[i]) {
202
+ leaves[numsymbols].weight = frequencies[i];
203
+ leaves[numsymbols].count = i; /* Index of symbol this leaf represents. */
204
+ numsymbols++;
205
+ }
206
+ }
207
+
208
+ /* Check special cases and error conditions. */
209
+ if ((1 << maxbits) < numsymbols) {
210
+ free(leaves);
211
+ return 1; /* Error, too few maxbits to represent symbols. */
212
+ }
213
+ if (numsymbols == 0) {
214
+ free(leaves);
215
+ return 0; /* No symbols at all. OK. */
216
+ }
217
+ if (numsymbols == 1) {
218
+ bitlengths[leaves[0].count] = 1;
219
+ free(leaves);
220
+ return 0; /* Only one symbol, give it bitlength 1, not 0. OK. */
221
+ }
222
+
223
+ /* Sort the leaves from lightest to heaviest. */
224
+ qsort(leaves, numsymbols, sizeof(Node), LeafComparator);
225
+
226
+ /* Initialize node memory pool. */
227
+ pool.size = 2 * maxbits * (maxbits + 1);
228
+ pool.nodes = (Node*)malloc(pool.size * sizeof(*pool.nodes));
229
+ pool.next = pool.nodes;
230
+ for (i = 0; i < pool.size; i++) {
231
+ pool.nodes[i].inuse = 0;
232
+ }
233
+
234
+ lists = (Node* (*)[2])malloc(maxbits * sizeof(*lists));
235
+ InitLists(&pool, leaves, maxbits, lists);
236
+
237
+ /* In the last list, 2 * numsymbols - 2 active chains need to be created. Two
238
+ are already created in the initialization. Each BoundaryPM run creates one. */
239
+ numBoundaryPMRuns = 2 * numsymbols - 4;
240
+ for (i = 0; i < numBoundaryPMRuns; i++) {
241
+ char final = i == numBoundaryPMRuns - 1;
242
+ BoundaryPM(lists, maxbits, leaves, numsymbols, &pool, maxbits - 1, final);
243
+ }
244
+
245
+ ExtractBitLengths(lists[maxbits - 1][1], leaves, bitlengths);
246
+
247
+ free(lists);
248
+ free(leaves);
249
+ free(pool.nodes);
250
+ return 0; /* OK. */
251
+ }
@@ -0,0 +1,42 @@
1
+ /*
2
+ Copyright 2011 Google Inc. All Rights Reserved.
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
15
+
16
+ Author: lode.vandevenne@gmail.com (Lode Vandevenne)
17
+ Author: jyrki.alakuijala@gmail.com (Jyrki Alakuijala)
18
+ */
19
+
20
+ #ifndef ZOPFLI_KATAJAINEN_H_
21
+ #define ZOPFLI_KATAJAINEN_H_
22
+
23
+ #include <string.h>
24
+
25
+ /*
26
+ Outputs minimum-redundancy length-limited code bitlengths for symbols with the
27
+ given counts. The bitlengths are limited by maxbits.
28
+
29
+ The output is tailored for DEFLATE: symbols that never occur, get a bit length
30
+ of 0, and if only a single symbol occurs at least once, its bitlength will be 1,
31
+ and not 0 as would theoretically be needed for a single symbol.
32
+
33
+ frequencies: The amount of occurances of each symbol.
34
+ n: The amount of symbols.
35
+ maxbits: Maximum bit length, inclusive.
36
+ bitlengths: Output, the bitlengths for the symbol prefix codes.
37
+ return: 0 for OK, non-0 for error.
38
+ */
39
+ int ZopfliLengthLimitedCodeLengths(
40
+ const size_t* frequencies, int n, int maxbits, unsigned* bitlengths);
41
+
42
+ #endif /* ZOPFLI_KATAJAINEN_H_ */
@@ -0,0 +1,482 @@
1
+ /*
2
+ Copyright 2011 Google Inc. All Rights Reserved.
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
15
+
16
+ Author: lode.vandevenne@gmail.com (Lode Vandevenne)
17
+ Author: jyrki.alakuijala@gmail.com (Jyrki Alakuijala)
18
+ */
19
+
20
+ #include "lz77.h"
21
+ #include "util.h"
22
+
23
+ #include <assert.h>
24
+ #include <stdio.h>
25
+ #include <stdlib.h>
26
+
27
+ void ZopfliInitLZ77Store(ZopfliLZ77Store* store) {
28
+ store->size = 0;
29
+ store->litlens = 0;
30
+ store->dists = 0;
31
+ }
32
+
33
+ void ZopfliCleanLZ77Store(ZopfliLZ77Store* store) {
34
+ free(store->litlens);
35
+ free(store->dists);
36
+ }
37
+
38
+ void ZopfliCopyLZ77Store(
39
+ const ZopfliLZ77Store* source, ZopfliLZ77Store* dest) {
40
+ size_t i;
41
+ ZopfliCleanLZ77Store(dest);
42
+ dest->litlens =
43
+ (unsigned short*)malloc(sizeof(*dest->litlens) * source->size);
44
+ dest->dists = (unsigned short*)malloc(sizeof(*dest->dists) * source->size);
45
+
46
+ if (!dest->litlens || !dest->dists) exit(-1); /* Allocation failed. */
47
+
48
+ dest->size = source->size;
49
+ for (i = 0; i < source->size; i++) {
50
+ dest->litlens[i] = source->litlens[i];
51
+ dest->dists[i] = source->dists[i];
52
+ }
53
+ }
54
+
55
+ /*
56
+ Appends the length and distance to the LZ77 arrays of the ZopfliLZ77Store.
57
+ context must be a ZopfliLZ77Store*.
58
+ */
59
+ void ZopfliStoreLitLenDist(unsigned short length, unsigned short dist,
60
+ ZopfliLZ77Store* store) {
61
+ size_t size2 = store->size; /* Needed for using ZOPFLI_APPEND_DATA twice. */
62
+ ZOPFLI_APPEND_DATA(length, &store->litlens, &store->size);
63
+ ZOPFLI_APPEND_DATA(dist, &store->dists, &size2);
64
+ }
65
+
66
+ /*
67
+ Gets a score of the length given the distance. Typically, the score of the
68
+ length is the length itself, but if the distance is very long, decrease the
69
+ score of the length a bit to make up for the fact that long distances use large
70
+ amounts of extra bits.
71
+
72
+ This is not an accurate score, it is a heuristic only for the greedy LZ77
73
+ implementation. More accurate cost models are employed later. Making this
74
+ heuristic more accurate may hurt rather than improve compression.
75
+
76
+ The two direct uses of this heuristic are:
77
+ -avoid using a length of 3 in combination with a long distance. This only has
78
+ an effect if length == 3.
79
+ -make a slightly better choice between the two options of the lazy matching.
80
+
81
+ Indirectly, this affects:
82
+ -the block split points if the default of block splitting first is used, in a
83
+ rather unpredictable way
84
+ -the first zopfli run, so it affects the chance of the first run being closer
85
+ to the optimal output
86
+ */
87
+ static int GetLengthScore(int length, int distance) {
88
+ /*
89
+ At 1024, the distance uses 9+ extra bits and this seems to be the sweet spot
90
+ on tested files.
91
+ */
92
+ return distance > 1024 ? length - 1 : length;
93
+ }
94
+
95
+ void ZopfliVerifyLenDist(const unsigned char* data, size_t datasize, size_t pos,
96
+ unsigned short dist, unsigned short length) {
97
+
98
+ /* TODO(lode): make this only run in a debug compile, it's for assert only. */
99
+ size_t i;
100
+
101
+ assert(pos + length <= datasize);
102
+ for (i = 0; i < length; i++) {
103
+ if (data[pos - dist + i] != data[pos + i]) {
104
+ assert(data[pos - dist + i] == data[pos + i]);
105
+ break;
106
+ }
107
+ }
108
+ }
109
+
110
+ /*
111
+ Finds how long the match of scan and match is. Can be used to find how many
112
+ bytes starting from scan, and from match, are equal. Returns the last byte
113
+ after scan, which is still equal to the correspondinb byte after match.
114
+ scan is the position to compare
115
+ match is the earlier position to compare.
116
+ end is the last possible byte, beyond which to stop looking.
117
+ safe_end is a few (8) bytes before end, for comparing multiple bytes at once.
118
+ */
119
+ static const unsigned char* GetMatch(const unsigned char* scan,
120
+ const unsigned char* match,
121
+ const unsigned char* end,
122
+ const unsigned char* safe_end) {
123
+
124
+ if (sizeof(size_t) == 8) {
125
+ /* 8 checks at once per array bounds check (size_t is 64-bit). */
126
+ while (scan < safe_end && *((size_t*)scan) == *((size_t*)match)) {
127
+ scan += 8;
128
+ match += 8;
129
+ }
130
+ } else if (sizeof(unsigned int) == 4) {
131
+ /* 4 checks at once per array bounds check (unsigned int is 32-bit). */
132
+ while (scan < safe_end
133
+ && *((unsigned int*)scan) == *((unsigned int*)match)) {
134
+ scan += 4;
135
+ match += 4;
136
+ }
137
+ } else {
138
+ /* do 8 checks at once per array bounds check. */
139
+ while (scan < safe_end && *scan == *match && *++scan == *++match
140
+ && *++scan == *++match && *++scan == *++match
141
+ && *++scan == *++match && *++scan == *++match
142
+ && *++scan == *++match && *++scan == *++match) {
143
+ scan++; match++;
144
+ }
145
+ }
146
+
147
+ /* The remaining few bytes. */
148
+ while (scan != end && *scan == *match) {
149
+ scan++; match++;
150
+ }
151
+
152
+ return scan;
153
+ }
154
+
155
+ #ifdef ZOPFLI_LONGEST_MATCH_CACHE
156
+ /*
157
+ Gets distance, length and sublen values from the cache if possible.
158
+ Returns 1 if it got the values from the cache, 0 if not.
159
+ Updates the limit value to a smaller one if possible with more limited
160
+ information from the cache.
161
+ */
162
+ static int TryGetFromLongestMatchCache(ZopfliBlockState* s,
163
+ size_t pos, size_t* limit,
164
+ unsigned short* sublen, unsigned short* distance, unsigned short* length) {
165
+ /* The LMC cache starts at the beginning of the block rather than the
166
+ beginning of the whole array. */
167
+ size_t lmcpos = pos - s->blockstart;
168
+
169
+ /* Length > 0 and dist 0 is invalid combination, which indicates on purpose
170
+ that this cache value is not filled in yet. */
171
+ unsigned char cache_available = s->lmc && (s->lmc->length[lmcpos] == 0 ||
172
+ s->lmc->dist[lmcpos] != 0);
173
+ unsigned char limit_ok_for_cache = cache_available &&
174
+ (*limit == ZOPFLI_MAX_MATCH || s->lmc->length[lmcpos] <= *limit ||
175
+ (sublen && ZopfliMaxCachedSublen(s->lmc,
176
+ lmcpos, s->lmc->length[lmcpos]) >= *limit));
177
+
178
+ if (s->lmc && limit_ok_for_cache && cache_available) {
179
+ if (!sublen || s->lmc->length[lmcpos]
180
+ <= ZopfliMaxCachedSublen(s->lmc, lmcpos, s->lmc->length[lmcpos])) {
181
+ *length = s->lmc->length[lmcpos];
182
+ if (*length > *limit) *length = *limit;
183
+ if (sublen) {
184
+ ZopfliCacheToSublen(s->lmc, lmcpos, *length, sublen);
185
+ *distance = sublen[*length];
186
+ if (*limit == ZOPFLI_MAX_MATCH && *length >= ZOPFLI_MIN_MATCH) {
187
+ assert(sublen[*length] == s->lmc->dist[lmcpos]);
188
+ }
189
+ } else {
190
+ *distance = s->lmc->dist[lmcpos];
191
+ }
192
+ return 1;
193
+ }
194
+ /* Can't use much of the cache, since the "sublens" need to be calculated,
195
+ but at least we already know when to stop. */
196
+ *limit = s->lmc->length[lmcpos];
197
+ }
198
+
199
+ return 0;
200
+ }
201
+
202
+ /*
203
+ Stores the found sublen, distance and length in the longest match cache, if
204
+ possible.
205
+ */
206
+ static void StoreInLongestMatchCache(ZopfliBlockState* s,
207
+ size_t pos, size_t limit,
208
+ const unsigned short* sublen,
209
+ unsigned short distance, unsigned short length) {
210
+ /* The LMC cache starts at the beginning of the block rather than the
211
+ beginning of the whole array. */
212
+ size_t lmcpos = pos - s->blockstart;
213
+
214
+ /* Length > 0 and dist 0 is invalid combination, which indicates on purpose
215
+ that this cache value is not filled in yet. */
216
+ unsigned char cache_available = s->lmc && (s->lmc->length[lmcpos] == 0 ||
217
+ s->lmc->dist[lmcpos] != 0);
218
+
219
+ if (s->lmc && limit == ZOPFLI_MAX_MATCH && sublen && !cache_available) {
220
+ assert(s->lmc->length[lmcpos] == 1 && s->lmc->dist[lmcpos] == 0);
221
+ s->lmc->dist[lmcpos] = length < ZOPFLI_MIN_MATCH ? 0 : distance;
222
+ s->lmc->length[lmcpos] = length < ZOPFLI_MIN_MATCH ? 0 : length;
223
+ assert(!(s->lmc->length[lmcpos] == 1 && s->lmc->dist[lmcpos] == 0));
224
+ ZopfliSublenToCache(sublen, lmcpos, length, s->lmc);
225
+ }
226
+ }
227
+ #endif
228
+
229
+ void ZopfliFindLongestMatch(ZopfliBlockState* s, const ZopfliHash* h,
230
+ const unsigned char* array,
231
+ size_t pos, size_t size, size_t limit,
232
+ unsigned short* sublen, unsigned short* distance, unsigned short* length) {
233
+ unsigned short hpos = pos & ZOPFLI_WINDOW_MASK, p, pp;
234
+ unsigned short bestdist = 0;
235
+ unsigned short bestlength = 1;
236
+ const unsigned char* scan;
237
+ const unsigned char* match;
238
+ const unsigned char* arrayend;
239
+ const unsigned char* arrayend_safe;
240
+ #if ZOPFLI_MAX_CHAIN_HITS < ZOPFLI_WINDOW_SIZE
241
+ int chain_counter = ZOPFLI_MAX_CHAIN_HITS; /* For quitting early. */
242
+ #endif
243
+
244
+ unsigned dist = 0; /* Not unsigned short on purpose. */
245
+
246
+ int* hhead = h->head;
247
+ unsigned short* hprev = h->prev;
248
+ int* hhashval = h->hashval;
249
+ int hval = h->val;
250
+
251
+ #ifdef ZOPFLI_LONGEST_MATCH_CACHE
252
+ if (TryGetFromLongestMatchCache(s, pos, &limit, sublen, distance, length)) {
253
+ assert(pos + *length <= size);
254
+ return;
255
+ }
256
+ #endif
257
+
258
+ assert(limit <= ZOPFLI_MAX_MATCH);
259
+ assert(limit >= ZOPFLI_MIN_MATCH);
260
+ assert(pos < size);
261
+
262
+ if (size - pos < ZOPFLI_MIN_MATCH) {
263
+ /* The rest of the code assumes there are at least ZOPFLI_MIN_MATCH bytes to
264
+ try. */
265
+ *length = 0;
266
+ *distance = 0;
267
+ return;
268
+ }
269
+
270
+ if (pos + limit > size) {
271
+ limit = size - pos;
272
+ }
273
+ arrayend = &array[pos] + limit;
274
+ arrayend_safe = arrayend - 8;
275
+
276
+ assert(hval < 65536);
277
+
278
+ pp = hhead[hval]; /* During the whole loop, p == hprev[pp]. */
279
+ p = hprev[pp];
280
+
281
+ assert(pp == hpos);
282
+
283
+ dist = p < pp ? pp - p : ((ZOPFLI_WINDOW_SIZE - p) + pp);
284
+
285
+ /* Go through all distances. */
286
+ while (dist < ZOPFLI_WINDOW_SIZE) {
287
+ unsigned short currentlength = 0;
288
+
289
+ assert(p < ZOPFLI_WINDOW_SIZE);
290
+ assert(p == hprev[pp]);
291
+ assert(hhashval[p] == hval);
292
+
293
+ if (dist > 0) {
294
+ assert(pos < size);
295
+ assert(dist <= pos);
296
+ scan = &array[pos];
297
+ match = &array[pos - dist];
298
+
299
+ /* Testing the byte at position bestlength first, goes slightly faster. */
300
+ if (pos + bestlength >= size
301
+ || *(scan + bestlength) == *(match + bestlength)) {
302
+
303
+ #ifdef ZOPFLI_HASH_SAME
304
+ unsigned short same0 = h->same[pos & ZOPFLI_WINDOW_MASK];
305
+ if (same0 > 2 && *scan == *match) {
306
+ unsigned short same1 = h->same[(pos - dist) & ZOPFLI_WINDOW_MASK];
307
+ unsigned short same = same0 < same1 ? same0 : same1;
308
+ if (same > limit) same = limit;
309
+ scan += same;
310
+ match += same;
311
+ }
312
+ #endif
313
+ scan = GetMatch(scan, match, arrayend, arrayend_safe);
314
+ currentlength = scan - &array[pos]; /* The found length. */
315
+ }
316
+
317
+ if (currentlength > bestlength) {
318
+ if (sublen) {
319
+ unsigned short j;
320
+ for (j = bestlength + 1; j <= currentlength; j++) {
321
+ sublen[j] = dist;
322
+ }
323
+ }
324
+ bestdist = dist;
325
+ bestlength = currentlength;
326
+ if (currentlength >= limit) break;
327
+ }
328
+ }
329
+
330
+
331
+ #ifdef ZOPFLI_HASH_SAME_HASH
332
+ /* Switch to the other hash once this will be more efficient. */
333
+ if (hhead != h->head2 && bestlength >= h->same[hpos] &&
334
+ h->val2 == h->hashval2[p]) {
335
+ /* Now use the hash that encodes the length and first byte. */
336
+ hhead = h->head2;
337
+ hprev = h->prev2;
338
+ hhashval = h->hashval2;
339
+ hval = h->val2;
340
+ }
341
+ #endif
342
+
343
+ pp = p;
344
+ p = hprev[p];
345
+ if (p == pp) break; /* Uninited prev value. */
346
+
347
+ dist += p < pp ? pp - p : ((ZOPFLI_WINDOW_SIZE - p) + pp);
348
+
349
+ #if ZOPFLI_MAX_CHAIN_HITS < ZOPFLI_WINDOW_SIZE
350
+ chain_counter--;
351
+ if (chain_counter <= 0) break;
352
+ #endif
353
+ }
354
+
355
+ #ifdef ZOPFLI_LONGEST_MATCH_CACHE
356
+ StoreInLongestMatchCache(s, pos, limit, sublen, bestdist, bestlength);
357
+ #endif
358
+
359
+ assert(bestlength <= limit);
360
+
361
+ *distance = bestdist;
362
+ *length = bestlength;
363
+ assert(pos + *length <= size);
364
+ }
365
+
366
+ void ZopfliLZ77Greedy(ZopfliBlockState* s, const unsigned char* in,
367
+ size_t instart, size_t inend,
368
+ ZopfliLZ77Store* store) {
369
+ size_t i = 0, j;
370
+ unsigned short leng;
371
+ unsigned short dist;
372
+ int lengthscore;
373
+ size_t windowstart = instart > ZOPFLI_WINDOW_SIZE
374
+ ? instart - ZOPFLI_WINDOW_SIZE : 0;
375
+ unsigned short dummysublen[259];
376
+
377
+ ZopfliHash hash;
378
+ ZopfliHash* h = &hash;
379
+
380
+ #ifdef ZOPFLI_LAZY_MATCHING
381
+ /* Lazy matching. */
382
+ unsigned prev_length = 0;
383
+ unsigned prev_match = 0;
384
+ int prevlengthscore;
385
+ int match_available = 0;
386
+ #endif
387
+
388
+ if (instart == inend) return;
389
+
390
+ ZopfliInitHash(ZOPFLI_WINDOW_SIZE, h);
391
+ ZopfliWarmupHash(in, windowstart, inend, h);
392
+ for (i = windowstart; i < instart; i++) {
393
+ ZopfliUpdateHash(in, i, inend, h);
394
+ }
395
+
396
+ for (i = instart; i < inend; i++) {
397
+ ZopfliUpdateHash(in, i, inend, h);
398
+
399
+ ZopfliFindLongestMatch(s, h, in, i, inend, ZOPFLI_MAX_MATCH, dummysublen,
400
+ &dist, &leng);
401
+ lengthscore = GetLengthScore(leng, dist);
402
+
403
+ #ifdef ZOPFLI_LAZY_MATCHING
404
+ /* Lazy matching. */
405
+ prevlengthscore = GetLengthScore(prev_length, prev_match);
406
+ if (match_available) {
407
+ match_available = 0;
408
+ if (lengthscore > prevlengthscore + 1) {
409
+ ZopfliStoreLitLenDist(in[i - 1], 0, store);
410
+ if (lengthscore >= ZOPFLI_MIN_MATCH && leng < ZOPFLI_MAX_MATCH) {
411
+ match_available = 1;
412
+ prev_length = leng;
413
+ prev_match = dist;
414
+ continue;
415
+ }
416
+ } else {
417
+ /* Add previous to output. */
418
+ leng = prev_length;
419
+ dist = prev_match;
420
+ lengthscore = prevlengthscore;
421
+ /* Add to output. */
422
+ ZopfliVerifyLenDist(in, inend, i - 1, dist, leng);
423
+ ZopfliStoreLitLenDist(leng, dist, store);
424
+ for (j = 2; j < leng; j++) {
425
+ assert(i < inend);
426
+ i++;
427
+ ZopfliUpdateHash(in, i, inend, h);
428
+ }
429
+ continue;
430
+ }
431
+ }
432
+ else if (lengthscore >= ZOPFLI_MIN_MATCH && leng < ZOPFLI_MAX_MATCH) {
433
+ match_available = 1;
434
+ prev_length = leng;
435
+ prev_match = dist;
436
+ continue;
437
+ }
438
+ /* End of lazy matching. */
439
+ #endif
440
+
441
+ /* Add to output. */
442
+ if (lengthscore >= ZOPFLI_MIN_MATCH) {
443
+ ZopfliVerifyLenDist(in, inend, i, dist, leng);
444
+ ZopfliStoreLitLenDist(leng, dist, store);
445
+ } else {
446
+ leng = 1;
447
+ ZopfliStoreLitLenDist(in[i], 0, store);
448
+ }
449
+ for (j = 1; j < leng; j++) {
450
+ assert(i < inend);
451
+ i++;
452
+ ZopfliUpdateHash(in, i, inend, h);
453
+ }
454
+ }
455
+
456
+ ZopfliCleanHash(h);
457
+ }
458
+
459
+ void ZopfliLZ77Counts(const unsigned short* litlens,
460
+ const unsigned short* dists,
461
+ size_t start, size_t end,
462
+ size_t* ll_count, size_t* d_count) {
463
+ size_t i;
464
+
465
+ for (i = 0; i < 288; i++) {
466
+ ll_count[i] = 0;
467
+ }
468
+ for (i = 0; i < 32; i++) {
469
+ d_count[i] = 0;
470
+ }
471
+
472
+ for (i = start; i < end; i++) {
473
+ if (dists[i] == 0) {
474
+ ll_count[litlens[i]]++;
475
+ } else {
476
+ ll_count[ZopfliGetLengthSymbol(litlens[i])]++;
477
+ d_count[ZopfliGetDistSymbol(dists[i])]++;
478
+ }
479
+ }
480
+
481
+ ll_count[256] = 1; /* End symbol. */
482
+ }