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