aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatarLarge Libravatar Bram Stein <steinadobecom>2014-11-06 16:22:16 +0100
committerLibravatarLarge Libravatar Bram Stein <steinadobecom>2014-11-06 16:22:16 +0100
commite67716a2725037220a1d1226e12ff6212f1e5031 (patch)
tree97f71a6b06acade510d43491caf6389e5fafbc22
parent64833aa89615b59b25f887443dfd344f24bbe3dc (diff)
downloadsfnt2woff-zopfli-e67716a2725037220a1d1226e12ff6212f1e5031.tar.gz
sfnt2woff-zopfli-e67716a2725037220a1d1226e12ff6212f1e5031.tar.bz2
sfnt2woff-zopfli-e67716a2725037220a1d1226e12ff6212f1e5031.tar.lz
sfnt2woff-zopfli-e67716a2725037220a1d1226e12ff6212f1e5031.zip

Add Zopfli files.

-rw-r--r--.gitignore4
-rw-r--r--Makefile16
-rw-r--r--blocksplitter.c342
-rw-r--r--blocksplitter.h77
-rw-r--r--cache.c119
-rw-r--r--cache.h66
-rw-r--r--deflate.c866
-rw-r--r--deflate.h86
-rw-r--r--gzip_container.c117
-rw-r--r--gzip_container.h50
-rw-r--r--hash.c135
-rw-r--r--hash.h70
-rw-r--r--katajainen.c251
-rw-r--r--katajainen.h42
-rw-r--r--lz77.c482
-rw-r--r--lz77.h129
-rw-r--r--squeeze.c546
-rw-r--r--squeeze.h60
-rw-r--r--tree.c101
-rw-r--r--tree.h51
-rw-r--r--util.c213
-rw-r--r--util.h175
-rw-r--r--woff.c32
-rw-r--r--zlib_container.c79
-rw-r--r--zlib_container.h50
-rw-r--r--zopfli.h97
-rw-r--r--zopfli_bin.c203
-rw-r--r--zopfli_lib.c42
28 files changed, 4481 insertions, 20 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..7563329
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+*.gch
+*.out
+woff2sfnt
+sfnt2woff
diff --git a/Makefile b/Makefile
index f9942eb..7ab1256 100644
--- a/Makefile
+++ b/Makefile
@@ -1,16 +1,12 @@
-all: sfnt2woff woff2sfnt
-
-sfnt2woff: sfnt2woff.o woff.o woff.h Makefile
- $(CC) $(LDFLAGS) -o $@ $< woff.o -lz
+FILES=blocksplitter.c cache.c deflate.c gzip_container.c hash.c katajainen.c lz77.c squeeze.c tree.c util.c zlib_container.c zopfli_lib.c woff.c
-woff2sfnt: woff2sfnt.o woff.o woff.h Makefile
- $(CC) $(LDFLAGS) -o $@ $< woff.o -lz
-
-sfnt2woff.o: sfnt2woff.c woff.h Makefile
+all: sfnt2woff woff2sfnt
-woff2sfnt.o: woff2sfnt.c woff.h Makefile
+sfnt2woff: sfnt2woff.c $(FILES) Makefile
+ $(CC) $(LDFLAGS) $(FILES) $< -o $@ -lz
-woff.o: woff.c woff.h woff-private.h Makefile
+woff2sfnt: woff2sfnt.c $(FILES) Makefile
+ $(CC) $(LDFLAGS) $(FILES) $< -o $@ -lz
clean:
$(RM) -r *.o *.dSYM
diff --git a/blocksplitter.c b/blocksplitter.c
new file mode 100644
index 0000000..68f5ff3
--- /dev/null
+++ b/blocksplitter.c
@@ -0,0 +1,342 @@
+/*
+Copyright 2011 Google Inc. All Rights Reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+Author: lode.vandevenne@gmail.com (Lode Vandevenne)
+Author: jyrki.alakuijala@gmail.com (Jyrki Alakuijala)
+*/
+
+#include "blocksplitter.h"
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "deflate.h"
+#include "lz77.h"
+#include "squeeze.h"
+#include "tree.h"
+#include "util.h"
+
+/*
+The "f" for the FindMinimum function below.
+i: the current parameter of f(i)
+context: for your implementation
+*/
+typedef double FindMinimumFun(size_t i, void* context);
+
+/*
+Finds minimum of function f(i) where is is of type size_t, f(i) is of type
+double, i is in range start-end (excluding end).
+*/
+static size_t FindMinimum(FindMinimumFun f, void* context,
+ size_t start, size_t end) {
+ if (end - start < 1024) {
+ double best = ZOPFLI_LARGE_FLOAT;
+ size_t result = start;
+ size_t i;
+ for (i = start; i < end; i++) {
+ double v = f(i, context);
+ if (v < best) {
+ best = v;
+ result = i;
+ }
+ }
+ return result;
+ } else {
+ /* Try to find minimum faster by recursively checking multiple points. */
+#define NUM 9 /* Good value: 9. */
+ size_t i;
+ size_t p[NUM];
+ double vp[NUM];
+ size_t besti;
+ double best;
+ double lastbest = ZOPFLI_LARGE_FLOAT;
+ size_t pos = start;
+
+ for (;;) {
+ if (end - start <= NUM) break;
+
+ for (i = 0; i < NUM; i++) {
+ p[i] = start + (i + 1) * ((end - start) / (NUM + 1));
+ vp[i] = f(p[i], context);
+ }
+ besti = 0;
+ best = vp[0];
+ for (i = 1; i < NUM; i++) {
+ if (vp[i] < best) {
+ best = vp[i];
+ besti = i;
+ }
+ }
+ if (best > lastbest) break;
+
+ start = besti == 0 ? start : p[besti - 1];
+ end = besti == NUM - 1 ? end : p[besti + 1];
+
+ pos = p[besti];
+ lastbest = best;
+ }
+ return pos;
+#undef NUM
+ }
+}
+
+/*
+Returns estimated cost of a block in bits. It includes the size to encode the
+tree and the size to encode all literal, length and distance symbols and their
+extra bits.
+
+litlens: lz77 lit/lengths
+dists: ll77 distances
+lstart: start of block
+lend: end of block (not inclusive)
+*/
+static double EstimateCost(const unsigned short* litlens,
+ const unsigned short* dists,
+ size_t lstart, size_t lend) {
+ return ZopfliCalculateBlockSize(litlens, dists, lstart, lend, 2);
+}
+
+typedef struct SplitCostContext {
+ const unsigned short* litlens;
+ const unsigned short* dists;
+ size_t llsize;
+ size_t start;
+ size_t end;
+} SplitCostContext;
+
+
+/*
+Gets the cost which is the sum of the cost of the left and the right section
+of the data.
+type: FindMinimumFun
+*/
+static double SplitCost(size_t i, void* context) {
+ SplitCostContext* c = (SplitCostContext*)context;
+ return EstimateCost(c->litlens, c->dists, c->start, i) +
+ EstimateCost(c->litlens, c->dists, i, c->end);
+}
+
+static void AddSorted(size_t value, size_t** out, size_t* outsize) {
+ size_t i;
+ ZOPFLI_APPEND_DATA(value, out, outsize);
+ for (i = 0; i + 1 < *outsize; i++) {
+ if ((*out)[i] > value) {
+ size_t j;
+ for (j = *outsize - 1; j > i; j--) {
+ (*out)[j] = (*out)[j - 1];
+ }
+ (*out)[i] = value;
+ break;
+ }
+ }
+}
+
+/*
+Prints the block split points as decimal and hex values in the terminal.
+*/
+static void PrintBlockSplitPoints(const unsigned short* litlens,
+ const unsigned short* dists,
+ size_t llsize, const size_t* lz77splitpoints,
+ size_t nlz77points) {
+ size_t* splitpoints = 0;
+ size_t npoints = 0;
+ size_t i;
+ /* The input is given as lz77 indices, but we want to see the uncompressed
+ index values. */
+ size_t pos = 0;
+ if (nlz77points > 0) {
+ for (i = 0; i < llsize; i++) {
+ size_t length = dists[i] == 0 ? 1 : litlens[i];
+ if (lz77splitpoints[npoints] == i) {
+ ZOPFLI_APPEND_DATA(pos, &splitpoints, &npoints);
+ if (npoints == nlz77points) break;
+ }
+ pos += length;
+ }
+ }
+ assert(npoints == nlz77points);
+
+ fprintf(stderr, "block split points: ");
+ for (i = 0; i < npoints; i++) {
+ fprintf(stderr, "%d ", (int)splitpoints[i]);
+ }
+ fprintf(stderr, "(hex:");
+ for (i = 0; i < npoints; i++) {
+ fprintf(stderr, " %x", (int)splitpoints[i]);
+ }
+ fprintf(stderr, ")\n");
+
+ free(splitpoints);
+}
+
+/*
+Finds next block to try to split, the largest of the available ones.
+The largest is chosen to make sure that if only a limited amount of blocks is
+requested, their sizes are spread evenly.
+llsize: the size of the LL77 data, which is the size of the done array here.
+done: array indicating which blocks starting at that position are no longer
+ splittable (splitting them increases rather than decreases cost).
+splitpoints: the splitpoints found so far.
+npoints: the amount of splitpoints found so far.
+lstart: output variable, giving start of block.
+lend: output variable, giving end of block.
+returns 1 if a block was found, 0 if no block found (all are done).
+*/
+static int FindLargestSplittableBlock(
+ size_t llsize, const unsigned char* done,
+ const size_t* splitpoints, size_t npoints,
+ size_t* lstart, size_t* lend) {
+ size_t longest = 0;
+ int found = 0;
+ size_t i;
+ for (i = 0; i <= npoints; i++) {
+ size_t start = i == 0 ? 0 : splitpoints[i - 1];
+ size_t end = i == npoints ? llsize - 1 : splitpoints[i];
+ if (!done[start] && end - start > longest) {
+ *lstart = start;
+ *lend = end;
+ found = 1;
+ longest = end - start;
+ }
+ }
+ return found;
+}
+
+void ZopfliBlockSplitLZ77(const ZopfliOptions* options,
+ const unsigned short* litlens,
+ const unsigned short* dists,
+ size_t llsize, size_t maxblocks,
+ size_t** splitpoints, size_t* npoints) {
+ size_t lstart, lend;
+ size_t i;
+ size_t llpos = 0;
+ size_t numblocks = 1;
+ unsigned char* done;
+ double splitcost, origcost;
+
+ if (llsize < 10) return; /* This code fails on tiny files. */
+
+ done = (unsigned char*)malloc(llsize);
+ if (!done) exit(-1); /* Allocation failed. */
+ for (i = 0; i < llsize; i++) done[i] = 0;
+
+ lstart = 0;
+ lend = llsize;
+ for (;;) {
+ SplitCostContext c;
+
+ if (maxblocks > 0 && numblocks >= maxblocks) {
+ break;
+ }
+
+ c.litlens = litlens;
+ c.dists = dists;
+ c.llsize = llsize;
+ c.start = lstart;
+ c.end = lend;
+ assert(lstart < lend);
+ llpos = FindMinimum(SplitCost, &c, lstart + 1, lend);
+
+ assert(llpos > lstart);
+ assert(llpos < lend);
+
+ splitcost = EstimateCost(litlens, dists, lstart, llpos) +
+ EstimateCost(litlens, dists, llpos, lend);
+ origcost = EstimateCost(litlens, dists, lstart, lend);
+
+ if (splitcost > origcost || llpos == lstart + 1 || llpos == lend) {
+ done[lstart] = 1;
+ } else {
+ AddSorted(llpos, splitpoints, npoints);
+ numblocks++;
+ }
+
+ if (!FindLargestSplittableBlock(
+ llsize, done, *splitpoints, *npoints, &lstart, &lend)) {
+ break; /* No further split will probably reduce compression. */
+ }
+
+ if (lend - lstart < 10) {
+ break;
+ }
+ }
+
+ if (options->verbose) {
+ PrintBlockSplitPoints(litlens, dists, llsize, *splitpoints, *npoints);
+ }
+
+ free(done);
+}
+
+void ZopfliBlockSplit(const ZopfliOptions* options,
+ const unsigned char* in, size_t instart, size_t inend,
+ size_t maxblocks, size_t** splitpoints, size_t* npoints) {
+ size_t pos = 0;
+ size_t i;
+ ZopfliBlockState s;
+ size_t* lz77splitpoints = 0;
+ size_t nlz77points = 0;
+ ZopfliLZ77Store store;
+
+ ZopfliInitLZ77Store(&store);
+
+ s.options = options;
+ s.blockstart = instart;
+ s.blockend = inend;
+#ifdef ZOPFLI_LONGEST_MATCH_CACHE
+ s.lmc = 0;
+#endif
+
+ *npoints = 0;
+ *splitpoints = 0;
+
+ /* Unintuitively, Using a simple LZ77 method here instead of ZopfliLZ77Optimal
+ results in better blocks. */
+ ZopfliLZ77Greedy(&s, in, instart, inend, &store);
+
+ ZopfliBlockSplitLZ77(options,
+ store.litlens, store.dists, store.size, maxblocks,
+ &lz77splitpoints, &nlz77points);
+
+ /* Convert LZ77 positions to positions in the uncompressed input. */
+ pos = instart;
+ if (nlz77points > 0) {
+ for (i = 0; i < store.size; i++) {
+ size_t length = store.dists[i] == 0 ? 1 : store.litlens[i];
+ if (lz77splitpoints[*npoints] == i) {
+ ZOPFLI_APPEND_DATA(pos, splitpoints, npoints);
+ if (*npoints == nlz77points) break;
+ }
+ pos += length;
+ }
+ }
+ assert(*npoints == nlz77points);
+
+ free(lz77splitpoints);
+ ZopfliCleanLZ77Store(&store);
+}
+
+void ZopfliBlockSplitSimple(const unsigned char* in,
+ size_t instart, size_t inend,
+ size_t blocksize,
+ size_t** splitpoints, size_t* npoints) {
+ size_t i = instart;
+ while (i < inend) {
+ ZOPFLI_APPEND_DATA(i, splitpoints, npoints);
+ i += blocksize;
+ }
+ (void)in;
+}
diff --git a/blocksplitter.h b/blocksplitter.h
new file mode 100644
index 0000000..6791702
--- /dev/null
+++ b/blocksplitter.h
@@ -0,0 +1,77 @@
+/*
+Copyright 2011 Google Inc. All Rights Reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+Author: lode.vandevenne@gmail.com (Lode Vandevenne)
+Author: jyrki.alakuijala@gmail.com (Jyrki Alakuijala)
+*/
+
+/*
+Functions to choose good boundaries for block splitting. Deflate allows encoding
+the data in multiple blocks, with a separate Huffman tree for each block. The
+Huffman tree itself requires some bytes to encode, so by choosing certain
+blocks, you can either hurt, or enhance compression. These functions choose good
+ones that enhance it.
+*/
+
+#ifndef ZOPFLI_BLOCKSPLITTER_H_
+#define ZOPFLI_BLOCKSPLITTER_H_
+
+#include <stdlib.h>
+
+#include "zopfli.h"
+
+
+/*
+Does blocksplitting on LZ77 data.
+The output splitpoints are indices in the LZ77 data.
+litlens: lz77 lit/lengths
+dists: lz77 distances
+llsize: size of litlens and dists
+maxblocks: set a limit to the amount of blocks. Set to 0 to mean no limit.
+*/
+void ZopfliBlockSplitLZ77(const ZopfliOptions* options,
+ const unsigned short* litlens,
+ const unsigned short* dists,
+ size_t llsize, size_t maxblocks,
+ size_t** splitpoints, size_t* npoints);
+
+/*
+Does blocksplitting on uncompressed data.
+The output splitpoints are indices in the uncompressed bytes.
+
+options: general program options.
+in: uncompressed input data
+instart: where to start splitting
+inend: where to end splitting (not inclusive)
+maxblocks: maximum amount of blocks to split into, or 0 for no limit
+splitpoints: dynamic array to put the resulting split point coordinates into.
+ The coordinates are indices in the input array.
+npoints: pointer to amount of splitpoints, for the dynamic array. The amount of
+ blocks is the amount of splitpoitns + 1.
+*/
+void ZopfliBlockSplit(const ZopfliOptions* options,
+ const unsigned char* in, size_t instart, size_t inend,
+ size_t maxblocks, size_t** splitpoints, size_t* npoints);
+
+/*
+Divides the input into equal blocks, does not even take LZ77 lengths into
+account.
+*/
+void ZopfliBlockSplitSimple(const unsigned char* in,
+ size_t instart, size_t inend,
+ size_t blocksize,
+ size_t** splitpoints, size_t* npoints);
+
+#endif /* ZOPFLI_BLOCKSPLITTER_H_ */
diff --git a/cache.c b/cache.c
new file mode 100644
index 0000000..88a49ac
--- /dev/null
+++ b/cache.c
@@ -0,0 +1,119 @@
+/*
+Copyright 2011 Google Inc. All Rights Reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+Author: lode.vandevenne@gmail.com (Lode Vandevenne)
+Author: jyrki.alakuijala@gmail.com (Jyrki Alakuijala)
+*/
+
+#include "cache.h"
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifdef ZOPFLI_LONGEST_MATCH_CACHE
+
+void ZopfliInitCache(size_t blocksize, ZopfliLongestMatchCache* lmc) {
+ size_t i;
+ lmc->length = (unsigned short*)malloc(sizeof(unsigned short) * blocksize);
+ lmc->dist = (unsigned short*)malloc(sizeof(unsigned short) * blocksize);
+ /* Rather large amount of memory. */
+ lmc->sublen = (unsigned char*)malloc(ZOPFLI_CACHE_LENGTH * 3 * blocksize);
+
+ /* length > 0 and dist 0 is invalid combination, which indicates on purpose
+ that this cache value is not filled in yet. */
+ for (i = 0; i < blocksize; i++) lmc->length[i] = 1;
+ for (i = 0; i < blocksize; i++) lmc->dist[i] = 0;
+ for (i = 0; i < ZOPFLI_CACHE_LENGTH * blocksize * 3; i++) lmc->sublen[i] = 0;
+}
+
+void ZopfliCleanCache(ZopfliLongestMatchCache* lmc) {
+ free(lmc->length);
+ free(lmc->dist);
+ free(lmc->sublen);
+}
+
+void ZopfliSublenToCache(const unsigned short* sublen,
+ size_t pos, size_t length,
+ ZopfliLongestMatchCache* lmc) {
+ size_t i;
+ size_t j = 0;
+ unsigned bestlength = 0;
+ unsigned char* cache;
+
+#if ZOPFLI_CACHE_LENGTH == 0
+ return;
+#endif
+
+ cache = &lmc->sublen[ZOPFLI_CACHE_LENGTH * pos * 3];
+ if (length < 3) return;
+ for (i = 3; i <= length; i++) {
+ if (i == length || sublen[i] != sublen[i + 1]) {
+ cache[j * 3] = i - 3;
+ cache[j * 3 + 1] = sublen[i] % 256;
+ cache[j * 3 + 2] = (sublen[i] >> 8) % 256;
+ bestlength = i;
+ j++;
+ if (j >= ZOPFLI_CACHE_LENGTH) break;
+ }
+ }
+ if (j < ZOPFLI_CACHE_LENGTH) {
+ assert(bestlength == length);
+ cache[(ZOPFLI_CACHE_LENGTH - 1) * 3] = bestlength - 3;
+ } else {
+ assert(bestlength <= length);
+ }
+ assert(bestlength == ZopfliMaxCachedSublen(lmc, pos, length));
+}
+
+void ZopfliCacheToSublen(const ZopfliLongestMatchCache* lmc,
+ size_t pos, size_t length,
+ unsigned short* sublen) {
+ size_t i, j;
+ unsigned maxlength = ZopfliMaxCachedSublen(lmc, pos, length);
+ unsigned prevlength = 0;
+ unsigned char* cache;
+#if ZOPFLI_CACHE_LENGTH == 0
+ return;
+#endif
+ if (length < 3) return;
+ cache = &lmc->sublen[ZOPFLI_CACHE_LENGTH * pos * 3];
+ for (j = 0; j < ZOPFLI_CACHE_LENGTH; j++) {
+ unsigned length = cache[j * 3] + 3;
+ unsigned dist = cache[j * 3 + 1] + 256 * cache[j * 3 + 2];
+ for (i = prevlength; i <= length; i++) {
+ sublen[i] = dist;
+ }
+ if (length == maxlength) break;
+ prevlength = length + 1;
+ }
+}
+
+/*
+Returns the length up to which could be stored in the cache.
+*/
+unsigned ZopfliMaxCachedSublen(const ZopfliLongestMatchCache* lmc,
+ size_t pos, size_t length) {
+ unsigned char* cache;
+#if ZOPFLI_CACHE_LENGTH == 0
+ return 0;
+#endif
+ cache = &lmc->sublen[ZOPFLI_CACHE_LENGTH * pos * 3];
+ (void)length;
+ if (cache[1] == 0 && cache[2] == 0) return 0; /* No sublen cached. */
+ return cache[(ZOPFLI_CACHE_LENGTH - 1) * 3] + 3;
+}
+
+#endif /* ZOPFLI_LONGEST_MATCH_CACHE */
diff --git a/cache.h b/cache.h
new file mode 100644
index 0000000..5ca0c50
--- /dev/null
+++ b/cache.h
@@ -0,0 +1,66 @@
+/*
+Copyright 2011 Google Inc. All Rights Reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+Author: lode.vandevenne@gmail.com (Lode Vandevenne)
+Author: jyrki.alakuijala@gmail.com (Jyrki Alakuijala)
+*/
+
+/*
+The cache that speeds up ZopfliFindLongestMatch of lz77.c.
+*/
+
+#ifndef ZOPFLI_CACHE_H_
+#define ZOPFLI_CACHE_H_
+
+#include "util.h"
+
+#ifdef ZOPFLI_LONGEST_MATCH_CACHE
+
+/*
+Cache used by ZopfliFindLongestMatch to remember previously found length/dist
+values.
+This is needed because the squeeze runs will ask these values multiple times for
+the same position.
+Uses large amounts of memory, since it has to remember the distance belonging
+to every possible shorter-than-the-best length (the so called "sublen" array).
+*/
+typedef struct ZopfliLongestMatchCache {
+ unsigned short* length;
+ unsigned short* dist;
+ unsigned char* sublen;
+} ZopfliLongestMatchCache;
+
+/* Initializes the ZopfliLongestMatchCache. */
+void ZopfliInitCache(size_t blocksize, ZopfliLongestMatchCache* lmc);
+
+/* Frees up the memory of the ZopfliLongestMatchCache. */
+void ZopfliCleanCache(ZopfliLongestMatchCache* lmc);
+
+/* Stores sublen array in the cache. */
+void ZopfliSublenToCache(const unsigned short* sublen,
+ size_t pos, size_t length,
+ ZopfliLongestMatchCache* lmc);
+
+/* Extracts sublen array from the cache. */
+void ZopfliCacheToSublen(const ZopfliLongestMatchCache* lmc,
+ size_t pos, size_t length,
+ unsigned short* sublen);
+/* Returns the length up to which could be stored in the cache. */
+unsigned ZopfliMaxCachedSublen(const ZopfliLongestMatchCache* lmc,
+ size_t pos, size_t length);
+
+#endif /* ZOPFLI_LONGEST_MATCH_CACHE */
+
+#endif /* ZOPFLI_CACHE_H_ */
diff --git a/deflate.c b/deflate.c
new file mode 100644
index 0000000..4b0724b
--- /dev/null
+++ b/deflate.c
@@ -0,0 +1,866 @@
+/*
+Copyright 2011 Google Inc. All Rights Reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+Author: lode.vandevenne@gmail.com (Lode Vandevenne)
+Author: jyrki.alakuijala@gmail.com (Jyrki Alakuijala)
+*/
+
+#include "deflate.h"
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "blocksplitter.h"
+#include "lz77.h"
+#include "squeeze.h"
+#include "tree.h"
+
+/*
+bp = bitpointer, always in range [0, 7].
+The outsize is number of necessary bytes to encode the bits.
+Given the value of bp and the amount of bytes, the amount of bits represented
+is not simply bytesize * 8 + bp because even representing one bit requires a
+whole byte. It is: (bp == 0) ? (bytesize * 8) : ((bytesize - 1) * 8 + bp)
+*/
+static void AddBit(int bit,
+ unsigned char* bp, unsigned char** out, size_t* outsize) {
+ if (*bp == 0) ZOPFLI_APPEND_DATA(0, out, outsize);
+ (*out)[*outsize - 1] |= bit << *bp;
+ *bp = (*bp + 1) & 7;
+}
+
+static void AddBits(unsigned symbol, unsigned length,
+ unsigned char* bp, unsigned char** out, size_t* outsize) {
+ /* TODO(lode): make more efficient (add more bits at once). */
+ unsigned i;
+ for (i = 0; i < length; i++) {
+ unsigned bit = (symbol >> i) & 1;
+ if (*bp == 0) ZOPFLI_APPEND_DATA(0, out, outsize);
+ (*out)[*outsize - 1] |= bit << *bp;
+ *bp = (*bp + 1) & 7;
+ }
+}
+
+/*
+Adds bits, like AddBits, but the order is inverted. The deflate specification
+uses both orders in one standard.
+*/
+static void AddHuffmanBits(unsigned symbol, unsigned length,
+ unsigned char* bp, unsigned char** out,
+ size_t* outsize) {
+ /* TODO(lode): make more efficient (add more bits at once). */
+ unsigned i;
+ for (i = 0; i < length; i++) {
+ unsigned bit = (symbol >> (length - i - 1)) & 1;
+ if (*bp == 0) ZOPFLI_APPEND_DATA(0, out, outsize);
+ (*out)[*outsize - 1] |= bit << *bp;
+ *bp = (*bp + 1) & 7;
+ }
+}
+
+/*
+Ensures there are at least 2 distance codes to support buggy decoders.
+Zlib 1.2.1 and below have a bug where it fails if there isn't at least 1
+distance code (with length > 0), even though it's valid according to the
+deflate spec to have 0 distance codes. On top of that, some mobile phones
+require at least two distance codes. To support these decoders too (but
+potentially at the cost of a few bytes), add dummy code lengths of 1.
+References to this bug can be found in the changelog of
+Zlib 1.2.2 and here: http://www.jonof.id.au/forum/index.php?topic=515.0.
+
+d_lengths: the 32 lengths of the distance codes.
+*/
+static void PatchDistanceCodesForBuggyDecoders(unsigned* d_lengths) {
+ int num_dist_codes = 0; /* Amount of non-zero distance codes */
+ int i;
+ for (i = 0; i < 30 /* Ignore the two unused codes from the spec */; i++) {
+ if (d_lengths[i]) num_dist_codes++;
+ if (num_dist_codes >= 2) return; /* Two or more codes is fine. */
+ }
+
+ if (num_dist_codes == 0) {
+ d_lengths[0] = d_lengths[1] = 1;
+ } else if (num_dist_codes == 1) {
+ d_lengths[d_lengths[0] ? 1 : 0] = 1;
+ }
+}
+
+/*
+Encodes the Huffman tree and returns how many bits its encoding takes. If out
+is a null pointer, only returns the size and runs faster.
+*/
+static size_t EncodeTree(const unsigned* ll_lengths,
+ const unsigned* d_lengths,
+ int use_16, int use_17, int use_18,
+ unsigned char* bp,
+ unsigned char** out, size_t* outsize) {
+ unsigned lld_total; /* Total amount of literal, length, distance codes. */
+ /* Runlength encoded version of lengths of litlen and dist trees. */
+ unsigned* rle = 0;
+ unsigned* rle_bits = 0; /* Extra bits for rle values 16, 17 and 18. */
+ size_t rle_size = 0; /* Size of rle array. */
+ size_t rle_bits_size = 0; /* Should have same value as rle_size. */
+ unsigned hlit = 29; /* 286 - 257 */
+ unsigned hdist = 29; /* 32 - 1, but gzip does not like hdist > 29.*/
+ unsigned hclen;
+ unsigned hlit2;
+ size_t i, j;
+ size_t clcounts[19];
+ unsigned clcl[19]; /* Code length code lengths. */
+ unsigned clsymbols[19];
+ /* The order in which code length code lengths are encoded as per deflate. */
+ static const unsigned order[19] = {
+ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
+ };
+ int size_only = !out;
+ size_t result_size = 0;
+
+ for(i = 0; i < 19; i++) clcounts[i] = 0;
+
+ /* Trim zeros. */
+ while (hlit > 0 && ll_lengths[257 + hlit - 1] == 0) hlit--;
+ while (hdist > 0 && d_lengths[1 + hdist - 1] == 0) hdist--;
+ hlit2 = hlit + 257;
+
+ lld_total = hlit2 + hdist + 1;
+
+ for (i = 0; i < lld_total; i++) {
+ /* This is an encoding of a huffman tree, so now the length is a symbol */
+ unsigned char symbol = i < hlit2 ? ll_lengths[i] : d_lengths[i - hlit2];
+ unsigned count = 1;
+ if(use_16 || (symbol == 0 && (use_17 || use_18))) {
+ for (j = i + 1; j < lld_total && symbol ==
+ (j < hlit2 ? ll_lengths[j] : d_lengths[j - hlit2]); j++) {
+ count++;
+ }
+ }
+ i += count - 1;
+
+ /* Repetitions of zeroes */
+ if (symbol == 0 && count >= 3) {
+ if (use_18) {
+ while (count >= 11) {
+ unsigned count2 = count > 138 ? 138 : count;
+ if (!size_only) {
+ ZOPFLI_APPEND_DATA(18, &rle, &rle_size);
+ ZOPFLI_APPEND_DATA(count2 - 11, &rle_bits, &rle_bits_size);
+ }
+ clcounts[18]++;
+ count -= count2;
+ }
+ }
+ if (use_17) {
+ while (count >= 3) {
+ unsigned count2 = count > 10 ? 10 : count;
+ if (!size_only) {
+ ZOPFLI_APPEND_DATA(17, &rle, &rle_size);
+ ZOPFLI_APPEND_DATA(count2 - 3, &rle_bits, &rle_bits_size);