19e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* fitblk.c: example of fitting compressed output to a specified size
29e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   Not copyrighted -- provided to the public domain
39e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   Version 1.1  25 November 2004  Mark Adler */
49e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
59e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* Version history:
69e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   1.0  24 Nov 2004  First version
79e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   1.1  25 Nov 2004  Change deflateInit2() to deflateInit()
89e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                     Use fixed-size, stack-allocated raw buffers
99e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                     Simplify code moving compression to subroutines
109e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                     Use assert() for internal errors
119e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                     Add detailed description of approach
129e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project */
139e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
149e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* Approach to just fitting a requested compressed size:
159e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
169e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   fitblk performs three compression passes on a portion of the input
179e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   data in order to determine how much of that input will compress to
189e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   nearly the requested output block size.  The first pass generates
199e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   enough deflate blocks to produce output to fill the requested
209e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   output size plus a specfied excess amount (see the EXCESS define
219e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   below).  The last deflate block may go quite a bit past that, but
229e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   is discarded.  The second pass decompresses and recompresses just
239e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   the compressed data that fit in the requested plus excess sized
249e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   buffer.  The deflate process is terminated after that amount of
259e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   input, which is less than the amount consumed on the first pass.
269e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   The last deflate block of the result will be of a comparable size
279e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   to the final product, so that the header for that deflate block and
289e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   the compression ratio for that block will be about the same as in
299e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   the final product.  The third compression pass decompresses the
309e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   result of the second step, but only the compressed data up to the
319e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   requested size minus an amount to allow the compressed stream to
329e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   complete (see the MARGIN define below).  That will result in a
339e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   final compressed stream whose length is less than or equal to the
349e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   requested size.  Assuming sufficient input and a requested size
359e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   greater than a few hundred bytes, the shortfall will typically be
369e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   less than ten bytes.
379e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
389e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   If the input is short enough that the first compression completes
399e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   before filling the requested output size, then that compressed
409e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   stream is return with no recompression.
419e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
429e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   EXCESS is chosen to be just greater than the shortfall seen in a
439e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   two pass approach similar to the above.  That shortfall is due to
449e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   the last deflate block compressing more efficiently with a smaller
459e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   header on the second pass.  EXCESS is set to be large enough so
469e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   that there is enough uncompressed data for the second pass to fill
479e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   out the requested size, and small enough so that the final deflate
489e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   block of the second pass will be close in size to the final deflate
499e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   block of the third and final pass.  MARGIN is chosen to be just
509e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   large enough to assure that the final compression has enough room
519e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   to complete in all cases.
529e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project */
539e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
549e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#include <stdio.h>
559e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#include <stdlib.h>
569e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#include <assert.h>
579e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#include "zlib.h"
589e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
599e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#define local static
609e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
619e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* print nastygram and leave */
629e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectlocal void quit(char *why)
639e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project{
649e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    fprintf(stderr, "fitblk abort: %s\n", why);
659e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    exit(1);
669e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project}
679e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
689e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#define RAWLEN 4096    /* intermediate uncompressed buffer size */
699e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
709e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* compress from file to def until provided buffer is full or end of
719e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   input reached; return last deflate() return value, or Z_ERRNO if
729e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   there was read error on the file */
739e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectlocal int partcompress(FILE *in, z_streamp def)
749e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project{
759e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    int ret, flush;
769e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    unsigned char raw[RAWLEN];
779e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
789e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    flush = Z_NO_FLUSH;
799e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    do {
809e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        def->avail_in = fread(raw, 1, RAWLEN, in);
819e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        if (ferror(in))
829e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            return Z_ERRNO;
839e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        def->next_in = raw;
849e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        if (feof(in))
859e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            flush = Z_FINISH;
869e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        ret = deflate(def, flush);
879e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        assert(ret != Z_STREAM_ERROR);
889e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    } while (def->avail_out != 0 && flush == Z_NO_FLUSH);
899e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    return ret;
909e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project}
919e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
929e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* recompress from inf's input to def's output; the input for inf and
939e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   the output for def are set in those structures before calling;
949e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   return last deflate() return value, or Z_MEM_ERROR if inflate()
959e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   was not able to allocate enough memory when it needed to */
969e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectlocal int recompress(z_streamp inf, z_streamp def)
979e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project{
989e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    int ret, flush;
999e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    unsigned char raw[RAWLEN];
1009e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
1019e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    flush = Z_NO_FLUSH;
1029e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    do {
1039e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        /* decompress */
1049e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        inf->avail_out = RAWLEN;
1059e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        inf->next_out = raw;
1069e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        ret = inflate(inf, Z_NO_FLUSH);
1079e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        assert(ret != Z_STREAM_ERROR && ret != Z_DATA_ERROR &&
1089e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project               ret != Z_NEED_DICT);
1099e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        if (ret == Z_MEM_ERROR)
1109e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            return ret;
1119e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
1129e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        /* compress what was decompresed until done or no room */
1139e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        def->avail_in = RAWLEN - inf->avail_out;
1149e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        def->next_in = raw;
1159e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        if (inf->avail_out != 0)
1169e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            flush = Z_FINISH;
1179e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        ret = deflate(def, flush);
1189e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        assert(ret != Z_STREAM_ERROR);
1199e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    } while (ret != Z_STREAM_END && def->avail_out != 0);
1209e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    return ret;
1219e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project}
1229e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
1239e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#define EXCESS 256      /* empirically determined stream overage */
1249e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#define MARGIN 8        /* amount to back off for completion */
1259e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
1269e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* compress from stdin to fixed-size block on stdout */
1279e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectint main(int argc, char **argv)
1289e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project{
1299e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    int ret;                /* return code */
1309e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    unsigned size;          /* requested fixed output block size */
1319e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    unsigned have;          /* bytes written by deflate() call */
1329e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    unsigned char *blk;     /* intermediate and final stream */
1339e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    unsigned char *tmp;     /* close to desired size stream */
1349e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    z_stream def, inf;      /* zlib deflate and inflate states */
1359e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
1369e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* get requested output size */
1379e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    if (argc != 2)
1389e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        quit("need one argument: size of output block");
1399e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    ret = strtol(argv[1], argv + 1, 10);
1409e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    if (argv[1][0] != 0)
1419e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        quit("argument must be a number");
1429e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    if (ret < 8)            /* 8 is minimum zlib stream size */
1439e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        quit("need positive size of 8 or greater");
1449e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    size = (unsigned)ret;
1459e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
1469e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* allocate memory for buffers and compression engine */
1479e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    blk = malloc(size + EXCESS);
1489e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    def.zalloc = Z_NULL;
1499e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    def.zfree = Z_NULL;
1509e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    def.opaque = Z_NULL;
1519e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    ret = deflateInit(&def, Z_DEFAULT_COMPRESSION);
1529e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    if (ret != Z_OK || blk == NULL)
1539e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        quit("out of memory");
1549e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
1559e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* compress from stdin until output full, or no more input */
1569e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    def.avail_out = size + EXCESS;
1579e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    def.next_out = blk;
1589e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    ret = partcompress(stdin, &def);
1599e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    if (ret == Z_ERRNO)
1609e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        quit("error reading input");
1619e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
1629e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* if it all fit, then size was undersubscribed -- done! */
1639e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    if (ret == Z_STREAM_END && def.avail_out >= EXCESS) {
1649e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        /* write block to stdout */
1659e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        have = size + EXCESS - def.avail_out;
1669e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        if (fwrite(blk, 1, have, stdout) != have || ferror(stdout))
1679e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            quit("error writing output");
1689e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
1699e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        /* clean up and print results to stderr */
1709e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        ret = deflateEnd(&def);
1719e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        assert(ret != Z_STREAM_ERROR);
1729e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        free(blk);
1739e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        fprintf(stderr,
1749e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                "%u bytes unused out of %u requested (all input)\n",
1759e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                size - have, size);
1769e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        return 0;
1779e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    }
1789e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
1799e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* it didn't all fit -- set up for recompression */
1809e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    inf.zalloc = Z_NULL;
1819e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    inf.zfree = Z_NULL;
1829e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    inf.opaque = Z_NULL;
1839e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    inf.avail_in = 0;
1849e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    inf.next_in = Z_NULL;
1859e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    ret = inflateInit(&inf);
1869e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    tmp = malloc(size + EXCESS);
1879e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    if (ret != Z_OK || tmp == NULL)
1889e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        quit("out of memory");
1899e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    ret = deflateReset(&def);
1909e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    assert(ret != Z_STREAM_ERROR);
1919e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
1929e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* do first recompression close to the right amount */
1939e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    inf.avail_in = size + EXCESS;
1949e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    inf.next_in = blk;
1959e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    def.avail_out = size + EXCESS;
1969e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    def.next_out = tmp;
1979e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    ret = recompress(&inf, &def);
1989e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    if (ret == Z_MEM_ERROR)
1999e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        quit("out of memory");
2009e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
2019e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* set up for next reocmpression */
2029e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    ret = inflateReset(&inf);
2039e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    assert(ret != Z_STREAM_ERROR);
2049e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    ret = deflateReset(&def);
2059e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    assert(ret != Z_STREAM_ERROR);
2069e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
2079e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* do second and final recompression (third compression) */
2089e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    inf.avail_in = size - MARGIN;   /* assure stream will complete */
2099e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    inf.next_in = tmp;
2109e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    def.avail_out = size;
2119e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    def.next_out = blk;
2129e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    ret = recompress(&inf, &def);
2139e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    if (ret == Z_MEM_ERROR)
2149e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        quit("out of memory");
2159e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    assert(ret == Z_STREAM_END);    /* otherwise MARGIN too small */
2169e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
2179e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* done -- write block to stdout */
2189e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    have = size - def.avail_out;
2199e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    if (fwrite(blk, 1, have, stdout) != have || ferror(stdout))
2209e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        quit("error writing output");
2219e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
2229e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* clean up and print results to stderr */
2239e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    free(tmp);
2249e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    ret = inflateEnd(&inf);
2259e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    assert(ret != Z_STREAM_ERROR);
2269e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    ret = deflateEnd(&def);
2279e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    assert(ret != Z_STREAM_ERROR);
2289e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    free(blk);
2299e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    fprintf(stderr,
2309e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            "%u bytes unused out of %u requested (%lu input)\n",
2319e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            size - have, size, def.total_in);
2329e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    return 0;
2339e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project}
234