19e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* blast.c
204351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes * Copyright (C) 2003, 2012 Mark Adler
39e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project * For conditions of distribution and use, see copyright notice in blast.h
404351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes * version 1.2, 24 Oct 2012
59e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project *
69e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project * blast.c decompresses data compressed by the PKWare Compression Library.
79e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project * This function provides functionality similar to the explode() function of
89e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project * the PKWare library, hence the name "blast".
99e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project *
109e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project * This decompressor is based on the excellent format description provided by
119e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project * Ben Rudiak-Gould in comp.compression on August 13, 2001.  Interestingly, the
129e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project * example Ben provided in the post is incorrect.  The distance 110001 should
139e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project * instead be 111000.  When corrected, the example byte stream becomes:
149e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project *
159e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project *    00 04 82 24 25 8f 80 7f
169e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project *
179e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project * which decompresses to "AIAIAIAIAIAIA" (without the quotes).
189e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project */
199e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
209e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/*
219e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project * Change history:
229e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project *
239e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project * 1.0  12 Feb 2003     - First version
249e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project * 1.1  16 Feb 2003     - Fixed distance check for > 4 GB uncompressed data
2504351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes * 1.2  24 Oct 2012     - Add note about using binary mode in stdio
2604351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes *                      - Fix comparisons of differently signed integers
279e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project */
289e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
299e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#include <setjmp.h>             /* for setjmp(), longjmp(), and jmp_buf */
309e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#include "blast.h"              /* prototype for blast() */
319e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
329e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#define local static            /* for local function definitions */
339e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#define MAXBITS 13              /* maximum code length */
349e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#define MAXWIN 4096             /* maximum window size */
359e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
369e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* input and output state */
379e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectstruct state {
389e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* input state */
399e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    blast_in infun;             /* input function provided by user */
409e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    void *inhow;                /* opaque information passed to infun() */
419e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    unsigned char *in;          /* next input location */
429e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    unsigned left;              /* available input at in */
439e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    int bitbuf;                 /* bit buffer */
449e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    int bitcnt;                 /* number of bits in bit buffer */
459e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
469e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* input limit error return state for bits() and decode() */
479e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    jmp_buf env;
489e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
499e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* output state */
509e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    blast_out outfun;           /* output function provided by user */
519e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    void *outhow;               /* opaque information passed to outfun() */
529e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    unsigned next;              /* index of next write location in out[] */
539e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    int first;                  /* true to check distances (for first 4K) */
549e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    unsigned char out[MAXWIN];  /* output buffer and sliding window */
559e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project};
569e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
579e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/*
589e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project * Return need bits from the input stream.  This always leaves less than
599e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project * eight bits in the buffer.  bits() works properly for need == 0.
609e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project *
619e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project * Format notes:
629e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project *
639e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project * - Bits are stored in bytes from the least significant bit to the most
649e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project *   significant bit.  Therefore bits are dropped from the bottom of the bit
659e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project *   buffer, using shift right, and new bytes are appended to the top of the
669e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project *   bit buffer, using shift left.
679e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project */
689e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectlocal int bits(struct state *s, int need)
699e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project{
709e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    int val;            /* bit accumulator */
719e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
729e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* load at least need bits into val */
739e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    val = s->bitbuf;
749e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    while (s->bitcnt < need) {
759e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        if (s->left == 0) {
769e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            s->left = s->infun(s->inhow, &(s->in));
779e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            if (s->left == 0) longjmp(s->env, 1);       /* out of input */
789e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        }
799e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        val |= (int)(*(s->in)++) << s->bitcnt;          /* load eight bits */
809e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        s->left--;
819e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        s->bitcnt += 8;
829e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    }
839e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
849e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* drop need bits and update buffer, always zero to seven bits left */
859e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    s->bitbuf = val >> need;
869e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    s->bitcnt -= need;
879e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
889e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* return need bits, zeroing the bits above that */
899e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    return val & ((1 << need) - 1);
909e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project}
919e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
929e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/*
939e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project * Huffman code decoding tables.  count[1..MAXBITS] is the number of symbols of
949e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project * each length, which for a canonical code are stepped through in order.
959e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project * symbol[] are the symbol values in canonical order, where the number of
969e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project * entries is the sum of the counts in count[].  The decoding process can be
979e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project * seen in the function decode() below.
989e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project */
999e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectstruct huffman {
1009e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    short *count;       /* number of symbols of each length */
1019e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    short *symbol;      /* canonically ordered symbols */
1029e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project};
1039e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
1049e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/*
1059e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project * Decode a code from the stream s using huffman table h.  Return the symbol or
1069e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project * a negative value if there is an error.  If all of the lengths are zero, i.e.
1079e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project * an empty code, or if the code is incomplete and an invalid code is received,
1089e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project * then -9 is returned after reading MAXBITS bits.
1099e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project *
1109e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project * Format notes:
1119e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project *
1129e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project * - The codes as stored in the compressed data are bit-reversed relative to
1139e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project *   a simple integer ordering of codes of the same lengths.  Hence below the
1149e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project *   bits are pulled from the compressed data one at a time and used to
1159e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project *   build the code value reversed from what is in the stream in order to
1169e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project *   permit simple integer comparisons for decoding.
1179e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project *
1189e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project * - The first code for the shortest length is all ones.  Subsequent codes of
1199e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project *   the same length are simply integer decrements of the previous code.  When
1209e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project *   moving up a length, a one bit is appended to the code.  For a complete
1219e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project *   code, the last code of the longest length will be all zeros.  To support
1229e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project *   this ordering, the bits pulled during decoding are inverted to apply the
1239e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project *   more "natural" ordering starting with all zeros and incrementing.
1249e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project */
1259e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectlocal int decode(struct state *s, struct huffman *h)
1269e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project{
1279e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    int len;            /* current number of bits in code */
1289e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    int code;           /* len bits being decoded */
1299e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    int first;          /* first code of length len */
1309e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    int count;          /* number of codes of length len */
1319e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    int index;          /* index of first code of length len in symbol table */
1329e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    int bitbuf;         /* bits from stream */
1339e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    int left;           /* bits left in next or left to process */
1349e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    short *next;        /* next number of codes */
1359e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
1369e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    bitbuf = s->bitbuf;
1379e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    left = s->bitcnt;
1389e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    code = first = index = 0;
1399e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    len = 1;
1409e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    next = h->count + 1;
1419e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    while (1) {
1429e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        while (left--) {
1439e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            code |= (bitbuf & 1) ^ 1;   /* invert code */
1449e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            bitbuf >>= 1;
1459e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            count = *next++;
1469e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            if (code < first + count) { /* if length len, return symbol */
1479e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                s->bitbuf = bitbuf;
1489e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                s->bitcnt = (s->bitcnt - len) & 7;
1499e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                return h->symbol[index + (code - first)];
1509e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            }
1519e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            index += count;             /* else update for next length */
1529e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            first += count;
1539e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            first <<= 1;
1549e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            code <<= 1;
1559e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            len++;
1569e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        }
1579e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        left = (MAXBITS+1) - len;
1589e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        if (left == 0) break;
1599e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        if (s->left == 0) {
1609e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            s->left = s->infun(s->inhow, &(s->in));
1619e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            if (s->left == 0) longjmp(s->env, 1);       /* out of input */
1629e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        }
1639e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        bitbuf = *(s->in)++;
1649e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        s->left--;
1659e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        if (left > 8) left = 8;
1669e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    }
1679e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    return -9;                          /* ran out of codes */
1689e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project}
1699e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
1709e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/*
1719e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project * Given a list of repeated code lengths rep[0..n-1], where each byte is a
1729e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project * count (high four bits + 1) and a code length (low four bits), generate the
1739e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project * list of code lengths.  This compaction reduces the size of the object code.
1749e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project * Then given the list of code lengths length[0..n-1] representing a canonical
1759e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project * Huffman code for n symbols, construct the tables required to decode those
1769e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project * codes.  Those tables are the number of codes of each length, and the symbols
1779e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project * sorted by length, retaining their original order within each length.  The
1789e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project * return value is zero for a complete code set, negative for an over-
1799e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project * subscribed code set, and positive for an incomplete code set.  The tables
1809e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project * can be used if the return value is zero or positive, but they cannot be used
1819e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project * if the return value is negative.  If the return value is zero, it is not
1829e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project * possible for decode() using that table to return an error--any stream of
1839e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project * enough bits will resolve to a symbol.  If the return value is positive, then
1849e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project * it is possible for decode() using that table to return an error for received
1859e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project * codes past the end of the incomplete lengths.
1869e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project */
1879e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectlocal int construct(struct huffman *h, const unsigned char *rep, int n)
1889e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project{
1899e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    int symbol;         /* current symbol when stepping through length[] */
1909e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    int len;            /* current length when stepping through h->count[] */
1919e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    int left;           /* number of possible codes left of current length */
1929e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    short offs[MAXBITS+1];      /* offsets in symbol table for each length */
1939e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    short length[256];  /* code lengths */
1949e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
1959e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* convert compact repeat counts into symbol bit length list */
1969e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    symbol = 0;
1979e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    do {
1989e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        len = *rep++;
1999e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        left = (len >> 4) + 1;
2009e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        len &= 15;
2019e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        do {
2029e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            length[symbol++] = len;
2039e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        } while (--left);
2049e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    } while (--n);
2059e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    n = symbol;
2069e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
2079e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* count number of codes of each length */
2089e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    for (len = 0; len <= MAXBITS; len++)
2099e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        h->count[len] = 0;
2109e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    for (symbol = 0; symbol < n; symbol++)
2119e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        (h->count[length[symbol]])++;   /* assumes lengths are within bounds */
2129e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    if (h->count[0] == n)               /* no codes! */
2139e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        return 0;                       /* complete, but decode() will fail */
2149e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
2159e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* check for an over-subscribed or incomplete set of lengths */
2169e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    left = 1;                           /* one possible code of zero length */
2179e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    for (len = 1; len <= MAXBITS; len++) {
2189e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        left <<= 1;                     /* one more bit, double codes left */
2199e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        left -= h->count[len];          /* deduct count from possible codes */
2209e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        if (left < 0) return left;      /* over-subscribed--return negative */
2219e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    }                                   /* left > 0 means incomplete */
2229e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
2239e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* generate offsets into symbol table for each length for sorting */
2249e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    offs[1] = 0;
2259e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    for (len = 1; len < MAXBITS; len++)
2269e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        offs[len + 1] = offs[len] + h->count[len];
2279e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
2289e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /*
2299e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project     * put symbols in table sorted by length, by symbol order within each
2309e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project     * length
2319e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project     */
2329e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    for (symbol = 0; symbol < n; symbol++)
2339e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        if (length[symbol] != 0)
2349e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            h->symbol[offs[length[symbol]]++] = symbol;
2359e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
2369e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* return zero for complete set, positive for incomplete set */
2379e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    return left;
2389e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project}
2399e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
2409e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/*
2419e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project * Decode PKWare Compression Library stream.
2429e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project *
2439e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project * Format notes:
2449e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project *
2459e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project * - First byte is 0 if literals are uncoded or 1 if they are coded.  Second
2469e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project *   byte is 4, 5, or 6 for the number of extra bits in the distance code.
2479e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project *   This is the base-2 logarithm of the dictionary size minus six.
2489e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project *
2499e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project * - Compressed data is a combination of literals and length/distance pairs
2509e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project *   terminated by an end code.  Literals are either Huffman coded or
2519e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project *   uncoded bytes.  A length/distance pair is a coded length followed by a
2529e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project *   coded distance to represent a string that occurs earlier in the
2539e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project *   uncompressed data that occurs again at the current location.
2549e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project *
2559e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project * - A bit preceding a literal or length/distance pair indicates which comes
2569e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project *   next, 0 for literals, 1 for length/distance.
2579e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project *
2589e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project * - If literals are uncoded, then the next eight bits are the literal, in the
2599e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project *   normal bit order in th stream, i.e. no bit-reversal is needed. Similarly,
2609e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project *   no bit reversal is needed for either the length extra bits or the distance
2619e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project *   extra bits.
2629e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project *
2639e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project * - Literal bytes are simply written to the output.  A length/distance pair is
2649e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project *   an instruction to copy previously uncompressed bytes to the output.  The
2659e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project *   copy is from distance bytes back in the output stream, copying for length
2669e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project *   bytes.
2679e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project *
2689e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project * - Distances pointing before the beginning of the output data are not
2699e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project *   permitted.
2709e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project *
2719e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project * - Overlapped copies, where the length is greater than the distance, are
2729e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project *   allowed and common.  For example, a distance of one and a length of 518
2739e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project *   simply copies the last byte 518 times.  A distance of four and a length of
2749e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project *   twelve copies the last four bytes three times.  A simple forward copy
2759e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project *   ignoring whether the length is greater than the distance or not implements
2769e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project *   this correctly.
2779e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project */
2789e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectlocal int decomp(struct state *s)
2799e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project{
2809e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    int lit;            /* true if literals are coded */
2819e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    int dict;           /* log2(dictionary size) - 6 */
2829e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    int symbol;         /* decoded symbol, extra bits for distance */
2839e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    int len;            /* length for copy */
28404351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes    unsigned dist;      /* distance for copy */
2859e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    int copy;           /* copy counter */
2869e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    unsigned char *from, *to;   /* copy pointers */
2879e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    static int virgin = 1;                              /* build tables once */
2889e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    static short litcnt[MAXBITS+1], litsym[256];        /* litcode memory */
2899e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    static short lencnt[MAXBITS+1], lensym[16];         /* lencode memory */
2909e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    static short distcnt[MAXBITS+1], distsym[64];       /* distcode memory */
2919e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    static struct huffman litcode = {litcnt, litsym};   /* length code */
2929e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    static struct huffman lencode = {lencnt, lensym};   /* length code */
2939e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    static struct huffman distcode = {distcnt, distsym};/* distance code */
2949e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        /* bit lengths of literal codes */
2959e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    static const unsigned char litlen[] = {
2969e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        11, 124, 8, 7, 28, 7, 188, 13, 76, 4, 10, 8, 12, 10, 12, 10, 8, 23, 8,
2979e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        9, 7, 6, 7, 8, 7, 6, 55, 8, 23, 24, 12, 11, 7, 9, 11, 12, 6, 7, 22, 5,
2989e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        7, 24, 6, 11, 9, 6, 7, 22, 7, 11, 38, 7, 9, 8, 25, 11, 8, 11, 9, 12,
2999e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        8, 12, 5, 38, 5, 38, 5, 11, 7, 5, 6, 21, 6, 10, 53, 8, 7, 24, 10, 27,
3009e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        44, 253, 253, 253, 252, 252, 252, 13, 12, 45, 12, 45, 12, 61, 12, 45,
3019e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        44, 173};
3029e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        /* bit lengths of length codes 0..15 */
3039e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    static const unsigned char lenlen[] = {2, 35, 36, 53, 38, 23};
3049e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        /* bit lengths of distance codes 0..63 */
3059e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    static const unsigned char distlen[] = {2, 20, 53, 230, 247, 151, 248};
3069e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    static const short base[16] = {     /* base for length codes */
3079e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        3, 2, 4, 5, 6, 7, 8, 9, 10, 12, 16, 24, 40, 72, 136, 264};
3089e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    static const char extra[16] = {     /* extra bits for length codes */
3099e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8};
3109e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
3119e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* set up decoding tables (once--might not be thread-safe) */
3129e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    if (virgin) {
3139e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        construct(&litcode, litlen, sizeof(litlen));
3149e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        construct(&lencode, lenlen, sizeof(lenlen));
3159e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        construct(&distcode, distlen, sizeof(distlen));
3169e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        virgin = 0;
3179e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    }
3189e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
3199e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* read header */
3209e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    lit = bits(s, 8);
3219e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    if (lit > 1) return -1;
3229e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    dict = bits(s, 8);
3239e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    if (dict < 4 || dict > 6) return -2;
3249e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
3259e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* decode literals and length/distance pairs */
3269e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    do {
3279e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        if (bits(s, 1)) {
3289e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            /* get length */
3299e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            symbol = decode(s, &lencode);
3309e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            len = base[symbol] + bits(s, extra[symbol]);
3319e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            if (len == 519) break;              /* end code */
3329e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
3339e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            /* get distance */
3349e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            symbol = len == 2 ? 2 : dict;
3359e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            dist = decode(s, &distcode) << symbol;
3369e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            dist += bits(s, symbol);
3379e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            dist++;
3389e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            if (s->first && dist > s->next)
3399e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                return -3;              /* distance too far back */
3409e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
3419e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            /* copy length bytes from distance bytes back */
3429e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            do {
3439e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                to = s->out + s->next;
3449e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                from = to - dist;
3459e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                copy = MAXWIN;
3469e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                if (s->next < dist) {
3479e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                    from += copy;
3489e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                    copy = dist;
3499e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                }
3509e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                copy -= s->next;
3519e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                if (copy > len) copy = len;
3529e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                len -= copy;
3539e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                s->next += copy;
3549e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                do {
3559e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                    *to++ = *from++;
3569e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                } while (--copy);
3579e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                if (s->next == MAXWIN) {
3589e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                    if (s->outfun(s->outhow, s->out, s->next)) return 1;
3599e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                    s->next = 0;
3609e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                    s->first = 0;
3619e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                }
3629e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            } while (len != 0);
3639e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        }
3649e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        else {
3659e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            /* get literal and write it */
3669e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            symbol = lit ? decode(s, &litcode) : bits(s, 8);
3679e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            s->out[s->next++] = symbol;
3689e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            if (s->next == MAXWIN) {
3699e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                if (s->outfun(s->outhow, s->out, s->next)) return 1;
3709e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                s->next = 0;
3719e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                s->first = 0;
3729e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            }
3739e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        }
3749e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    } while (1);
3759e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    return 0;
3769e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project}
3779e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
3789e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* See comments in blast.h */
3799e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectint blast(blast_in infun, void *inhow, blast_out outfun, void *outhow)
3809e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project{
3819e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    struct state s;             /* input/output state */
3829e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    int err;                    /* return value */
3839e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
3849e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* initialize input state */
3859e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    s.infun = infun;
3869e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    s.inhow = inhow;
3879e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    s.left = 0;
3889e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    s.bitbuf = 0;
3899e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    s.bitcnt = 0;
3909e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
3919e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* initialize output state */
3929e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    s.outfun = outfun;
3939e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    s.outhow = outhow;
3949e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    s.next = 0;
3959e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    s.first = 1;
3969e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
3979e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* return if bits() or decode() tries to read past available input */
3989e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    if (setjmp(s.env) != 0)             /* if came back here via longjmp(), */
3999e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        err = 2;                        /*  then skip decomp(), return error */
4009e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    else
4019e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        err = decomp(&s);               /* decompress */
4029e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
4039e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* write any leftover output and update the error code if needed */
4049e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    if (err != 1 && s.next && s.outfun(s.outhow, s.out, s.next) && err == 0)
4059e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        err = 1;
4069e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    return err;
4079e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project}
4089e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
4099e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#ifdef TEST
4109e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* Example of how to use blast() */
4119e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#include <stdio.h>
4129e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#include <stdlib.h>
4139e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
4149e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#define CHUNK 16384
4159e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
4169e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectlocal unsigned inf(void *how, unsigned char **buf)
4179e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project{
4189e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    static unsigned char hold[CHUNK];
4199e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
4209e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    *buf = hold;
4219e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    return fread(hold, 1, CHUNK, (FILE *)how);
4229e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project}
4239e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
4249e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectlocal int outf(void *how, unsigned char *buf, unsigned len)
4259e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project{
4269e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    return fwrite(buf, 1, len, (FILE *)how) != len;
4279e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project}
4289e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
4299e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* Decompress a PKWare Compression Library stream from stdin to stdout */
4309e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectint main(void)
4319e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project{
4329e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    int ret, n;
4339e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
4349e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* decompress to stdout */
4359e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    ret = blast(inf, stdin, outf, stdout);
4369e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    if (ret != 0) fprintf(stderr, "blast error: %d\n", ret);
4379e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
4389e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* see if there are any leftover bytes */
4399e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    n = 0;
4409e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    while (getchar() != EOF) n++;
4419e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    if (n) fprintf(stderr, "blast warning: %d unused bytes of input\n", n);
4429e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
4439e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* return blast() error code */
4449e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    return ret;
4459e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project}
4469e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#endif
447