18b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* infback.c -- inflate using a call-back interface
28b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Copyright (C) 1995-2005 Mark Adler
38b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * For conditions of distribution and use, see copyright notice in zlib.h
48b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
58b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
68b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
78b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   This code is largely copied from inflate.c.  Normally either infback.o or
88b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   inflate.o would be linked into an application--not both.  The interface
98b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   with inffast.c is retained so that optimized assembler-coded versions of
108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   inflate_fast() can be used with either inflate.c or infback.c.
118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "zutil.h"
148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "inftrees.h"
158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "inflate.h"
168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "inffast.h"
178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* function prototypes */
198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectlocal void fixedtables OF((struct inflate_state FAR *state));
208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   strm provides memory allocation functions in zalloc and zfree, or
238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   Z_NULL to use the library memory allocation functions.
248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   windowBits is in the range 8..15, and window is a user-supplied
268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   window and output buffer that is 2**windowBits bytes.
278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint ZEXPORT inflateBackInit_(strm, windowBits, window, version, stream_size)
298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectz_streamp strm;
308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint windowBits;
318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectunsigned char FAR *window;
328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectconst char *version;
338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint stream_size;
348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct inflate_state FAR *state;
368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        stream_size != (int)(sizeof(z_stream)))
398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return Z_VERSION_ERROR;
408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (strm == Z_NULL || window == Z_NULL ||
418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        windowBits < 8 || windowBits > 15)
428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return Z_STREAM_ERROR;
438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    strm->msg = Z_NULL;                 /* in case we return an error */
448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (strm->zalloc == (alloc_func)0) {
458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        strm->zalloc = zcalloc;
468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        strm->opaque = (voidpf)0;
478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (strm->zfree == (free_func)0) strm->zfree = zcfree;
498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    state = (struct inflate_state FAR *)ZALLOC(strm, 1,
508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                               sizeof(struct inflate_state));
518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (state == Z_NULL) return Z_MEM_ERROR;
528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    Tracev((stderr, "inflate: allocated\n"));
538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    strm->state = (struct internal_state FAR *)state;
548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    state->dmax = 32768U;
558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    state->wbits = windowBits;
568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    state->wsize = 1U << windowBits;
578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    state->window = window;
588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    state->write = 0;
598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    state->whave = 0;
608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return Z_OK;
618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   Return state with length and distance decoding tables and index sizes set to
658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   fixed code decoding.  Normally this returns fixed tables from inffixed.h.
668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   If BUILDFIXED is defined, then instead this routine builds the tables the
678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   first time it's called, and returns those tables the first time and
688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   thereafter.  This reduces the size of the code by about 2K bytes, in
698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   exchange for a little execution time.  However, BUILDFIXED should not be
708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   used for threaded applications, since the rewriting of the tables and virgin
718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   may not be thread-safe.
728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectlocal void fixedtables(state)
748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstruct inflate_state FAR *state;
758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef BUILDFIXED
778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    static int virgin = 1;
788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    static code *lenfix, *distfix;
798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    static code fixed[544];
808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* build fixed huffman tables if first call (may not be thread safe) */
828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (virgin) {
838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        unsigned sym, bits;
848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        static code *next;
858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* literal/length table */
878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        sym = 0;
888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        while (sym < 144) state->lens[sym++] = 8;
898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        while (sym < 256) state->lens[sym++] = 9;
908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        while (sym < 280) state->lens[sym++] = 7;
918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        while (sym < 288) state->lens[sym++] = 8;
928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        next = fixed;
938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        lenfix = next;
948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        bits = 9;
958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work);
968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* distance table */
988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        sym = 0;
998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        while (sym < 32) state->lens[sym++] = 5;
1008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        distfix = next;
1018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        bits = 5;
1028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work);
1038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* do this just once */
1058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        virgin = 0;
1068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else /* !BUILDFIXED */
1088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#   include "inffixed.h"
1098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif /* BUILDFIXED */
1108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    state->lencode = lenfix;
1118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    state->lenbits = 9;
1128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    state->distcode = distfix;
1138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    state->distbits = 5;
1148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Macros for inflateBack(): */
1178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Load returned state from inflate_fast() */
1198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define LOAD() \
1208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do { \
1218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        put = strm->next_out; \
1228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        left = strm->avail_out; \
1238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        next = strm->next_in; \
1248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        have = strm->avail_in; \
1258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        hold = state->hold; \
1268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        bits = state->bits; \
1278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } while (0)
1288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Set state from registers for inflate_fast() */
1308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define RESTORE() \
1318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do { \
1328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        strm->next_out = put; \
1338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        strm->avail_out = left; \
1348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        strm->next_in = next; \
1358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        strm->avail_in = have; \
1368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        state->hold = hold; \
1378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        state->bits = bits; \
1388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } while (0)
1398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Clear the input bit accumulator */
1418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define INITBITS() \
1428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do { \
1438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        hold = 0; \
1448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        bits = 0; \
1458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } while (0)
1468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Assure that some input is available.  If input is requested, but denied,
1488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   then return a Z_BUF_ERROR from inflateBack(). */
1498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define PULL() \
1508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do { \
1518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (have == 0) { \
1528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            have = in(in_desc, &next); \
1538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (have == 0) { \
1548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                next = Z_NULL; \
1558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                ret = Z_BUF_ERROR; \
1568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                goto inf_leave; \
1578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } \
1588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } \
1598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } while (0)
1608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Get a byte of input into the bit accumulator, or return from inflateBack()
1628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   with an error if there is no input available. */
1638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define PULLBYTE() \
1648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do { \
1658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        PULL(); \
1668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        have--; \
1678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        hold += (unsigned long)(*next++) << bits; \
1688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        bits += 8; \
1698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } while (0)
1708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Assure that there are at least n bits in the bit accumulator.  If there is
1728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   not enough available input to do that, then return from inflateBack() with
1738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   an error. */
1748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define NEEDBITS(n) \
1758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do { \
1768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        while (bits < (unsigned)(n)) \
1778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            PULLBYTE(); \
1788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } while (0)
1798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Return the low n bits of the bit accumulator (n < 16) */
1818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define BITS(n) \
1828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ((unsigned)hold & ((1U << (n)) - 1))
1838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Remove n bits from the bit accumulator */
1858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define DROPBITS(n) \
1868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do { \
1878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        hold >>= (n); \
1888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        bits -= (unsigned)(n); \
1898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } while (0)
1908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Remove zero to seven bits as needed to go to a byte boundary */
1928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define BYTEBITS() \
1938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do { \
1948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        hold >>= bits & 7; \
1958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        bits -= bits & 7; \
1968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } while (0)
1978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Assure that some output space is available, by writing out the window
1998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if it's full.  If the write fails, return from inflateBack() with a
2008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   Z_BUF_ERROR. */
2018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define ROOM() \
2028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do { \
2038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (left == 0) { \
2048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            put = state->window; \
2058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            left = state->wsize; \
2068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            state->whave = left; \
2078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (out(out_desc, put, left)) { \
2088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                ret = Z_BUF_ERROR; \
2098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                goto inf_leave; \
2108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } \
2118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } \
2128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } while (0)
2138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
2158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   strm provides the memory allocation functions and window buffer on input,
2168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   and provides information on the unused input on return.  For Z_DATA_ERROR
2178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   returns, strm will also provide an error message.
2188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   in() and out() are the call-back input and output functions.  When
2208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   inflateBack() needs more input, it calls in().  When inflateBack() has
2218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   filled the window with output, or when it completes with data in the
2228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   window, it calls out() to write out the data.  The application must not
2238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   change the provided input until in() is called again or inflateBack()
2248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   returns.  The application must not change the window/output buffer until
2258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   inflateBack() returns.
2268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   in() and out() are called with a descriptor parameter provided in the
2288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   inflateBack() call.  This parameter can be a structure that provides the
2298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   information required to do the read or write, as well as accumulated
2308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   information on the input and output such as totals and check values.
2318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   in() should return zero on failure.  out() should return non-zero on
2338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   failure.  If either in() or out() fails, than inflateBack() returns a
2348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   Z_BUF_ERROR.  strm->next_in can be checked for Z_NULL to see whether it
2358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   was in() or out() that caused in the error.  Otherwise,  inflateBack()
2368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format
2378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   error, or Z_MEM_ERROR if it could not allocate memory for the state.
2388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   inflateBack() can also return Z_STREAM_ERROR if the input parameters
2398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   are not correct, i.e. strm is Z_NULL or the state was not initialized.
2408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
2418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint ZEXPORT inflateBack(strm, in, in_desc, out, out_desc)
2428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectz_streamp strm;
2438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectin_func in;
2448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid FAR *in_desc;
2458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectout_func out;
2468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid FAR *out_desc;
2478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct inflate_state FAR *state;
2498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned char FAR *next;    /* next input */
2508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned char FAR *put;     /* next output */
2518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned have, left;        /* available input and output */
2528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned long hold;         /* bit buffer */
2538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned bits;              /* bits in bit buffer */
2548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned copy;              /* number of stored or match bytes to copy */
2558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned char FAR *from;    /* where to copy match bytes from */
2568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    code this;                  /* current decoding table entry */
2578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    code last;                  /* parent table entry */
2588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned len;               /* length to copy for repeats, bits to drop */
2598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int ret;                    /* return code */
2608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    static const unsigned short order[19] = /* permutation of code lengths */
2618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
2628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* Check that the strm exists and that the state was initialized */
2648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (strm == Z_NULL || strm->state == Z_NULL)
2658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return Z_STREAM_ERROR;
2668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    state = (struct inflate_state FAR *)strm->state;
2678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* Reset the state */
2698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    strm->msg = Z_NULL;
2708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    state->mode = TYPE;
2718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    state->last = 0;
2728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    state->whave = 0;
2738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    next = strm->next_in;
2748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    have = next != Z_NULL ? strm->avail_in : 0;
2758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    hold = 0;
2768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    bits = 0;
2778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    put = state->window;
2788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    left = state->wsize;
2798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* Inflate until end of block marked as last */
2818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (;;)
2828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch (state->mode) {
2838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case TYPE:
2848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* determine and dispatch block type */
2858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (state->last) {
2868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                BYTEBITS();
2878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                state->mode = DONE;
2888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
2898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
2908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            NEEDBITS(3);
2918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            state->last = BITS(1);
2928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            DROPBITS(1);
2938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            switch (BITS(2)) {
2948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 0:                             /* stored block */
2958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                Tracev((stderr, "inflate:     stored block%s\n",
2968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        state->last ? " (last)" : ""));
2978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                state->mode = STORED;
2988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
2998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 1:                             /* fixed block */
3008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                fixedtables(state);
3018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                Tracev((stderr, "inflate:     fixed codes block%s\n",
3028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        state->last ? " (last)" : ""));
3038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                state->mode = LEN;              /* decode codes */
3048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
3058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 2:                             /* dynamic block */
3068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                Tracev((stderr, "inflate:     dynamic codes block%s\n",
3078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        state->last ? " (last)" : ""));
3088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                state->mode = TABLE;
3098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
3108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 3:
3118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                strm->msg = (char *)"invalid block type";
3128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                state->mode = BAD;
3138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
3148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            DROPBITS(2);
3158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
3168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case STORED:
3188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* get and verify stored block length */
3198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            BYTEBITS();                         /* go to byte boundary */
3208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            NEEDBITS(32);
3218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
3228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                strm->msg = (char *)"invalid stored block lengths";
3238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                state->mode = BAD;
3248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
3258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
3268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            state->length = (unsigned)hold & 0xffff;
3278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            Tracev((stderr, "inflate:       stored length %u\n",
3288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    state->length));
3298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            INITBITS();
3308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* copy stored block from input to output */
3328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            while (state->length != 0) {
3338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                copy = state->length;
3348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                PULL();
3358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                ROOM();
3368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (copy > have) copy = have;
3378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (copy > left) copy = left;
3388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                zmemcpy(put, next, copy);
3398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                have -= copy;
3408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                next += copy;
3418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                left -= copy;
3428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                put += copy;
3438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                state->length -= copy;
3448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
3458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            Tracev((stderr, "inflate:       stored end\n"));
3468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            state->mode = TYPE;
3478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
3488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case TABLE:
3508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* get dynamic table entries descriptor */
3518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            NEEDBITS(14);
3528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            state->nlen = BITS(5) + 257;
3538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            DROPBITS(5);
3548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            state->ndist = BITS(5) + 1;
3558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            DROPBITS(5);
3568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            state->ncode = BITS(4) + 4;
3578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            DROPBITS(4);
3588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifndef PKZIP_BUG_WORKAROUND
3598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (state->nlen > 286 || state->ndist > 30) {
3608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                strm->msg = (char *)"too many length or distance symbols";
3618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                state->mode = BAD;
3628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
3638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
3648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
3658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            Tracev((stderr, "inflate:       table sizes ok\n"));
3668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* get code length code lengths (not a typo) */
3688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            state->have = 0;
3698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            while (state->have < state->ncode) {
3708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                NEEDBITS(3);
3718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                state->lens[order[state->have++]] = (unsigned short)BITS(3);
3728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                DROPBITS(3);
3738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
3748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            while (state->have < 19)
3758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                state->lens[order[state->have++]] = 0;
3768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            state->next = state->codes;
3778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            state->lencode = (code const FAR *)(state->next);
3788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            state->lenbits = 7;
3798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            ret = inflate_table(CODES, state->lens, 19, &(state->next),
3808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                &(state->lenbits), state->work);
3818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (ret) {
3828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                strm->msg = (char *)"invalid code lengths set";
3838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                state->mode = BAD;
3848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
3858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
3868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            Tracev((stderr, "inflate:       code lengths ok\n"));
3878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* get length and distance code code lengths */
3898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            state->have = 0;
3908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            while (state->have < state->nlen + state->ndist) {
3918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                for (;;) {
3928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    this = state->lencode[BITS(state->lenbits)];
3938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if ((unsigned)(this.bits) <= bits) break;
3948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    PULLBYTE();
3958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
3968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (this.val < 16) {
3978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    NEEDBITS(this.bits);
3988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    DROPBITS(this.bits);
3998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    state->lens[state->have++] = this.val;
4008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
4018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                else {
4028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (this.val == 16) {
4038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        NEEDBITS(this.bits + 2);
4048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        DROPBITS(this.bits);
4058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (state->have == 0) {
4068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            strm->msg = (char *)"invalid bit length repeat";
4078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            state->mode = BAD;
4088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
4098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
4108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        len = (unsigned)(state->lens[state->have - 1]);
4118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        copy = 3 + BITS(2);
4128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        DROPBITS(2);
4138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
4148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    else if (this.val == 17) {
4158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        NEEDBITS(this.bits + 3);
4168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        DROPBITS(this.bits);
4178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        len = 0;
4188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        copy = 3 + BITS(3);
4198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        DROPBITS(3);
4208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
4218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    else {
4228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        NEEDBITS(this.bits + 7);
4238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        DROPBITS(this.bits);
4248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        len = 0;
4258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        copy = 11 + BITS(7);
4268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        DROPBITS(7);
4278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
4288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (state->have + copy > state->nlen + state->ndist) {
4298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        strm->msg = (char *)"invalid bit length repeat";
4308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        state->mode = BAD;
4318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
4328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
4338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    while (copy--)
4348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        state->lens[state->have++] = (unsigned short)len;
4358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
4368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
4378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* handle error breaks in while */
4398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (state->mode == BAD) break;
4408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* build code tables */
4428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            state->next = state->codes;
4438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            state->lencode = (code const FAR *)(state->next);
4448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            state->lenbits = 9;
4458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
4468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                &(state->lenbits), state->work);
4478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (ret) {
4488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                strm->msg = (char *)"invalid literal/lengths set";
4498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                state->mode = BAD;
4508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
4518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
4528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            state->distcode = (code const FAR *)(state->next);
4538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            state->distbits = 6;
4548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
4558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            &(state->next), &(state->distbits), state->work);
4568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (ret) {
4578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                strm->msg = (char *)"invalid distances set";
4588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                state->mode = BAD;
4598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
4608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
4618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            Tracev((stderr, "inflate:       codes ok\n"));
4628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            state->mode = LEN;
4638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case LEN:
4658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* use inflate_fast() if we have enough input and output */
4668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (have >= 6 && left >= 258) {
4678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                RESTORE();
4688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (state->whave < state->wsize)
4698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    state->whave = state->wsize - left;
4708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                inflate_fast(strm, state->wsize);
4718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                LOAD();
4728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
4738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
4748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* get a literal, length, or end-of-block code */
4768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            for (;;) {
4778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                this = state->lencode[BITS(state->lenbits)];
4788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if ((unsigned)(this.bits) <= bits) break;
4798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                PULLBYTE();
4808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
4818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (this.op && (this.op & 0xf0) == 0) {
4828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                last = this;
4838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                for (;;) {
4848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    this = state->lencode[last.val +
4858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            (BITS(last.bits + last.op) >> last.bits)];
4868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if ((unsigned)(last.bits + this.bits) <= bits) break;
4878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    PULLBYTE();
4888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
4898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                DROPBITS(last.bits);
4908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
4918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            DROPBITS(this.bits);
4928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            state->length = (unsigned)this.val;
4938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* process literal */
4958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (this.op == 0) {
4968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ?
4978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        "inflate:         literal '%c'\n" :
4988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        "inflate:         literal 0x%02x\n", this.val));
4998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                ROOM();
5008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                *put++ = (unsigned char)(state->length);
5018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                left--;
5028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                state->mode = LEN;
5038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
5048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
5058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* process end of block */
5078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (this.op & 32) {
5088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                Tracevv((stderr, "inflate:         end of block\n"));
5098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                state->mode = TYPE;
5108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
5118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
5128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* invalid code */
5148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (this.op & 64) {
5158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                strm->msg = (char *)"invalid literal/length code";
5168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                state->mode = BAD;
5178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
5188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
5198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* length code -- get extra bits, if any */
5218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            state->extra = (unsigned)(this.op) & 15;
5228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (state->extra != 0) {
5238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                NEEDBITS(state->extra);
5248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                state->length += BITS(state->extra);
5258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                DROPBITS(state->extra);
5268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
5278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            Tracevv((stderr, "inflate:         length %u\n", state->length));
5288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* get distance code */
5308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            for (;;) {
5318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                this = state->distcode[BITS(state->distbits)];
5328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if ((unsigned)(this.bits) <= bits) break;
5338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                PULLBYTE();
5348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
5358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if ((this.op & 0xf0) == 0) {
5368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                last = this;
5378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                for (;;) {
5388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    this = state->distcode[last.val +
5398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            (BITS(last.bits + last.op) >> last.bits)];
5408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if ((unsigned)(last.bits + this.bits) <= bits) break;
5418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    PULLBYTE();
5428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
5438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                DROPBITS(last.bits);
5448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
5458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            DROPBITS(this.bits);
5468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (this.op & 64) {
5478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                strm->msg = (char *)"invalid distance code";
5488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                state->mode = BAD;
5498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
5508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
5518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            state->offset = (unsigned)this.val;
5528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* get distance extra bits, if any */
5548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            state->extra = (unsigned)(this.op) & 15;
5558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (state->extra != 0) {
5568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                NEEDBITS(state->extra);
5578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                state->offset += BITS(state->extra);
5588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                DROPBITS(state->extra);
5598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
5608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (state->offset > state->wsize - (state->whave < state->wsize ?
5618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                                left : 0)) {
5628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                strm->msg = (char *)"invalid distance too far back";
5638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                state->mode = BAD;
5648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
5658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
5668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            Tracevv((stderr, "inflate:         distance %u\n", state->offset));
5678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* copy match from window to output */
5698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            do {
5708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                ROOM();
5718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                copy = state->wsize - state->offset;
5728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (copy < left) {
5738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    from = put + copy;
5748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    copy = left - copy;
5758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
5768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                else {
5778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    from = put - state->offset;
5788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    copy = left;
5798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
5808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (copy > state->length) copy = state->length;
5818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                state->length -= copy;
5828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                left -= copy;
5838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                do {
5848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    *put++ = *from++;
5858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } while (--copy);
5868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } while (state->length != 0);
5878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
5888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case DONE:
5908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* inflate stream terminated properly -- write leftover output */
5918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            ret = Z_STREAM_END;
5928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (left < state->wsize) {
5938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (out(out_desc, state->window, state->wsize - left))
5948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    ret = Z_BUF_ERROR;
5958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
5968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goto inf_leave;
5978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case BAD:
5998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            ret = Z_DATA_ERROR;
6008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goto inf_leave;
6018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        default:                /* can't happen, but makes compilers happy */
6038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            ret = Z_STREAM_ERROR;
6048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goto inf_leave;
6058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
6068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* Return unused input */
6088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project  inf_leave:
6098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    strm->next_in = next;
6108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    strm->avail_in = have;
6118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return ret;
6128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint ZEXPORT inflateBackEnd(strm)
6158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectz_streamp strm;
6168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0)
6188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return Z_STREAM_ERROR;
6198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ZFREE(strm, strm->state);
6208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    strm->state = Z_NULL;
6218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    Tracev((stderr, "inflate: end\n"));
6228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return Z_OK;
6238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
624