19e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* infback.c -- inflate using a call-back interface
2ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes * Copyright (C) 1995-2011 Mark Adler
39e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project * For conditions of distribution and use, see copyright notice in zlib.h
49e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project */
59e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
69e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/*
79e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   This code is largely copied from inflate.c.  Normally either infback.o or
89e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   inflate.o would be linked into an application--not both.  The interface
99e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   with inffast.c is retained so that optimized assembler-coded versions of
109e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   inflate_fast() can be used with either inflate.c or infback.c.
119e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project */
129e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
139e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#include "zutil.h"
149e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#include "inftrees.h"
159e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#include "inflate.h"
169e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#include "inffast.h"
179e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
189e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* function prototypes */
199e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectlocal void fixedtables OF((struct inflate_state FAR *state));
209e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
219e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/*
229e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   strm provides memory allocation functions in zalloc and zfree, or
239e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   Z_NULL to use the library memory allocation functions.
249e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
259e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   windowBits is in the range 8..15, and window is a user-supplied
269e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   window and output buffer that is 2**windowBits bytes.
279e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project */
289e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectint ZEXPORT inflateBackInit_(strm, windowBits, window, version, stream_size)
299e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectz_streamp strm;
309e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectint windowBits;
319e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectunsigned char FAR *window;
329e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectconst char *version;
339e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectint stream_size;
349e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project{
359e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    struct inflate_state FAR *state;
369e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
379e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
389e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        stream_size != (int)(sizeof(z_stream)))
399e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        return Z_VERSION_ERROR;
409e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    if (strm == Z_NULL || window == Z_NULL ||
419e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        windowBits < 8 || windowBits > 15)
429e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        return Z_STREAM_ERROR;
439e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    strm->msg = Z_NULL;                 /* in case we return an error */
449e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    if (strm->zalloc == (alloc_func)0) {
45ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes#ifdef Z_SOLO
46ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes        return Z_STREAM_ERROR;
47ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes#else
489e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        strm->zalloc = zcalloc;
499e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        strm->opaque = (voidpf)0;
50ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes#endif
519e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    }
52ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes    if (strm->zfree == (free_func)0)
53ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes#ifdef Z_SOLO
54ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes        return Z_STREAM_ERROR;
55ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes#else
56ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes    strm->zfree = zcfree;
57ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes#endif
589e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    state = (struct inflate_state FAR *)ZALLOC(strm, 1,
599e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                                               sizeof(struct inflate_state));
609e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    if (state == Z_NULL) return Z_MEM_ERROR;
619e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    Tracev((stderr, "inflate: allocated\n"));
629e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    strm->state = (struct internal_state FAR *)state;
639e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    state->dmax = 32768U;
649e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    state->wbits = windowBits;
659e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    state->wsize = 1U << windowBits;
669e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    state->window = window;
67381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state->wnext = 0;
689e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    state->whave = 0;
699e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    return Z_OK;
709e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project}
719e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
729e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/*
739e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   Return state with length and distance decoding tables and index sizes set to
749e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   fixed code decoding.  Normally this returns fixed tables from inffixed.h.
759e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   If BUILDFIXED is defined, then instead this routine builds the tables the
769e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   first time it's called, and returns those tables the first time and
779e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   thereafter.  This reduces the size of the code by about 2K bytes, in
789e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   exchange for a little execution time.  However, BUILDFIXED should not be
799e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   used for threaded applications, since the rewriting of the tables and virgin
809e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   may not be thread-safe.
819e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project */
829e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectlocal void fixedtables(state)
839e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectstruct inflate_state FAR *state;
849e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project{
859e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#ifdef BUILDFIXED
869e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    static int virgin = 1;
879e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    static code *lenfix, *distfix;
889e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    static code fixed[544];
899e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
909e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* build fixed huffman tables if first call (may not be thread safe) */
919e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    if (virgin) {
929e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        unsigned sym, bits;
939e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        static code *next;
949e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
959e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        /* literal/length table */
969e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        sym = 0;
979e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        while (sym < 144) state->lens[sym++] = 8;
989e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        while (sym < 256) state->lens[sym++] = 9;
999e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        while (sym < 280) state->lens[sym++] = 7;
1009e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        while (sym < 288) state->lens[sym++] = 8;
1019e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        next = fixed;
1029e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        lenfix = next;
1039e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        bits = 9;
1049e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work);
1059e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
1069e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        /* distance table */
1079e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        sym = 0;
1089e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        while (sym < 32) state->lens[sym++] = 5;
1099e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        distfix = next;
1109e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        bits = 5;
1119e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work);
1129e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
1139e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        /* do this just once */
1149e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        virgin = 0;
1159e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    }
1169e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#else /* !BUILDFIXED */
1179e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#   include "inffixed.h"
1189e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#endif /* BUILDFIXED */
1199e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    state->lencode = lenfix;
1209e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    state->lenbits = 9;
1219e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    state->distcode = distfix;
1229e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    state->distbits = 5;
1239e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project}
1249e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
1259e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* Macros for inflateBack(): */
1269e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
1279e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* Load returned state from inflate_fast() */
1289e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#define LOAD() \
1299e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    do { \
1309e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        put = strm->next_out; \
1319e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        left = strm->avail_out; \
1329e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        next = strm->next_in; \
1339e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        have = strm->avail_in; \
1349e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        hold = state->hold; \
1359e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        bits = state->bits; \
1369e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    } while (0)
1379e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
1389e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* Set state from registers for inflate_fast() */
1399e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#define RESTORE() \
1409e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    do { \
1419e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        strm->next_out = put; \
1429e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        strm->avail_out = left; \
1439e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        strm->next_in = next; \
1449e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        strm->avail_in = have; \
1459e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        state->hold = hold; \
1469e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        state->bits = bits; \
1479e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    } while (0)
1489e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
1499e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* Clear the input bit accumulator */
1509e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#define INITBITS() \
1519e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    do { \
1529e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        hold = 0; \
1539e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        bits = 0; \
1549e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    } while (0)
1559e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
1569e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* Assure that some input is available.  If input is requested, but denied,
1579e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   then return a Z_BUF_ERROR from inflateBack(). */
1589e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#define PULL() \
1599e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    do { \
1609e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        if (have == 0) { \
1619e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            have = in(in_desc, &next); \
1629e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            if (have == 0) { \
1639e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                next = Z_NULL; \
1649e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                ret = Z_BUF_ERROR; \
1659e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                goto inf_leave; \
1669e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            } \
1679e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        } \
1689e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    } while (0)
1699e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
1709e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* Get a byte of input into the bit accumulator, or return from inflateBack()
1719e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   with an error if there is no input available. */
1729e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#define PULLBYTE() \
1739e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    do { \
1749e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        PULL(); \
1759e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        have--; \
1769e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        hold += (unsigned long)(*next++) << bits; \
1779e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        bits += 8; \
1789e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    } while (0)
1799e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
1809e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* Assure that there are at least n bits in the bit accumulator.  If there is
1819e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   not enough available input to do that, then return from inflateBack() with
1829e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   an error. */
1839e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#define NEEDBITS(n) \
1849e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    do { \
1859e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        while (bits < (unsigned)(n)) \
1869e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            PULLBYTE(); \
1879e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    } while (0)
1889e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
1899e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* Return the low n bits of the bit accumulator (n < 16) */
1909e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#define BITS(n) \
1919e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    ((unsigned)hold & ((1U << (n)) - 1))
1929e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
1939e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* Remove n bits from the bit accumulator */
1949e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#define DROPBITS(n) \
1959e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    do { \
1969e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        hold >>= (n); \
1979e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        bits -= (unsigned)(n); \
1989e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    } while (0)
1999e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
2009e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* Remove zero to seven bits as needed to go to a byte boundary */
2019e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#define BYTEBITS() \
2029e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    do { \
2039e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        hold >>= bits & 7; \
2049e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        bits -= bits & 7; \
2059e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    } while (0)
2069e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
2079e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* Assure that some output space is available, by writing out the window
2089e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   if it's full.  If the write fails, return from inflateBack() with a
2099e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   Z_BUF_ERROR. */
2109e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#define ROOM() \
2119e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    do { \
2129e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        if (left == 0) { \
2139e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            put = state->window; \
2149e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            left = state->wsize; \
2159e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            state->whave = left; \
2169e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            if (out(out_desc, put, left)) { \
2179e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                ret = Z_BUF_ERROR; \
2189e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                goto inf_leave; \
2199e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            } \
2209e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        } \
2219e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    } while (0)
2229e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
2239e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/*
2249e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   strm provides the memory allocation functions and window buffer on input,
2259e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   and provides information on the unused input on return.  For Z_DATA_ERROR
2269e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   returns, strm will also provide an error message.
2279e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
2289e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   in() and out() are the call-back input and output functions.  When
2299e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   inflateBack() needs more input, it calls in().  When inflateBack() has
2309e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   filled the window with output, or when it completes with data in the
2319e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   window, it calls out() to write out the data.  The application must not
2329e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   change the provided input until in() is called again or inflateBack()
2339e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   returns.  The application must not change the window/output buffer until
2349e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   inflateBack() returns.
2359e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
2369e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   in() and out() are called with a descriptor parameter provided in the
2379e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   inflateBack() call.  This parameter can be a structure that provides the
2389e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   information required to do the read or write, as well as accumulated
2399e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   information on the input and output such as totals and check values.
2409e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
2419e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   in() should return zero on failure.  out() should return non-zero on
2429e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   failure.  If either in() or out() fails, than inflateBack() returns a
2439e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   Z_BUF_ERROR.  strm->next_in can be checked for Z_NULL to see whether it
2449e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   was in() or out() that caused in the error.  Otherwise,  inflateBack()
2459e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format
2469e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   error, or Z_MEM_ERROR if it could not allocate memory for the state.
2479e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   inflateBack() can also return Z_STREAM_ERROR if the input parameters
2489e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   are not correct, i.e. strm is Z_NULL or the state was not initialized.
2499e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project */
2509e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectint ZEXPORT inflateBack(strm, in, in_desc, out, out_desc)
2519e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectz_streamp strm;
2529e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectin_func in;
2539e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectvoid FAR *in_desc;
2549e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectout_func out;
2559e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectvoid FAR *out_desc;
2569e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project{
2579e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    struct inflate_state FAR *state;
25804351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes    z_const unsigned char FAR *next;    /* next input */
2599e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    unsigned char FAR *put;     /* next output */
2609e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    unsigned have, left;        /* available input and output */
2619e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    unsigned long hold;         /* bit buffer */
2629e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    unsigned bits;              /* bits in bit buffer */
2639e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    unsigned copy;              /* number of stored or match bytes to copy */
2649e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    unsigned char FAR *from;    /* where to copy match bytes from */
265381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    code here;                  /* current decoding table entry */
2669e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    code last;                  /* parent table entry */
2679e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    unsigned len;               /* length to copy for repeats, bits to drop */
2689e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    int ret;                    /* return code */
2699e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    static const unsigned short order[19] = /* permutation of code lengths */
2709e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
2719e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
2729e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* Check that the strm exists and that the state was initialized */
2739e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    if (strm == Z_NULL || strm->state == Z_NULL)
2749e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        return Z_STREAM_ERROR;
2759e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    state = (struct inflate_state FAR *)strm->state;
2769e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
2779e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* Reset the state */
2789e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    strm->msg = Z_NULL;
2799e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    state->mode = TYPE;
2809e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    state->last = 0;
2819e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    state->whave = 0;
2829e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    next = strm->next_in;
2839e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    have = next != Z_NULL ? strm->avail_in : 0;
2849e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    hold = 0;
2859e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    bits = 0;
2869e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    put = state->window;
2879e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    left = state->wsize;
2889e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
2899e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* Inflate until end of block marked as last */
2909e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    for (;;)
2919e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        switch (state->mode) {
2929e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        case TYPE:
2939e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            /* determine and dispatch block type */
2949e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            if (state->last) {
2959e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                BYTEBITS();
2969e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                state->mode = DONE;
2979e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                break;
2989e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            }
2999e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            NEEDBITS(3);
3009e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            state->last = BITS(1);
3019e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            DROPBITS(1);
3029e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            switch (BITS(2)) {
3039e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            case 0:                             /* stored block */
3049e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                Tracev((stderr, "inflate:     stored block%s\n",
3059e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                        state->last ? " (last)" : ""));
3069e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                state->mode = STORED;
3079e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                break;
3089e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            case 1:                             /* fixed block */
3099e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                fixedtables(state);
3109e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                Tracev((stderr, "inflate:     fixed codes block%s\n",
3119e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                        state->last ? " (last)" : ""));
3129e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                state->mode = LEN;              /* decode codes */
3139e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                break;
3149e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            case 2:                             /* dynamic block */
3159e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                Tracev((stderr, "inflate:     dynamic codes block%s\n",
3169e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                        state->last ? " (last)" : ""));
3179e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                state->mode = TABLE;
3189e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                break;
3199e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            case 3:
3209e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                strm->msg = (char *)"invalid block type";
3219e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                state->mode = BAD;
3229e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            }
3239e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            DROPBITS(2);
3249e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            break;
3259e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
3269e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        case STORED:
3279e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            /* get and verify stored block length */
3289e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            BYTEBITS();                         /* go to byte boundary */
3299e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            NEEDBITS(32);
3309e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
3319e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                strm->msg = (char *)"invalid stored block lengths";
3329e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                state->mode = BAD;
3339e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                break;
3349e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            }
3359e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            state->length = (unsigned)hold & 0xffff;
3369e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            Tracev((stderr, "inflate:       stored length %u\n",
3379e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                    state->length));
3389e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            INITBITS();
3399e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
3409e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            /* copy stored block from input to output */
3419e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            while (state->length != 0) {
3429e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                copy = state->length;
3439e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                PULL();
3449e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                ROOM();
3459e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                if (copy > have) copy = have;
3469e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                if (copy > left) copy = left;
3479e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                zmemcpy(put, next, copy);
3489e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                have -= copy;
3499e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                next += copy;
3509e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                left -= copy;
3519e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                put += copy;
3529e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                state->length -= copy;
3539e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            }
3549e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            Tracev((stderr, "inflate:       stored end\n"));
3559e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            state->mode = TYPE;
3569e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            break;
3579e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
3589e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        case TABLE:
3599e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            /* get dynamic table entries descriptor */
3609e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            NEEDBITS(14);
3619e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            state->nlen = BITS(5) + 257;
3629e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            DROPBITS(5);
3639e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            state->ndist = BITS(5) + 1;
3649e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            DROPBITS(5);
3659e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            state->ncode = BITS(4) + 4;
3669e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            DROPBITS(4);
3679e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#ifndef PKZIP_BUG_WORKAROUND
3689e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            if (state->nlen > 286 || state->ndist > 30) {
3699e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                strm->msg = (char *)"too many length or distance symbols";
3709e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                state->mode = BAD;
3719e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                break;
3729e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            }
3739e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#endif
3749e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            Tracev((stderr, "inflate:       table sizes ok\n"));
3759e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
3769e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            /* get code length code lengths (not a typo) */
3779e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            state->have = 0;
3789e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            while (state->have < state->ncode) {
3799e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                NEEDBITS(3);
3809e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                state->lens[order[state->have++]] = (unsigned short)BITS(3);
3819e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                DROPBITS(3);
3829e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            }
3839e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            while (state->have < 19)
3849e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                state->lens[order[state->have++]] = 0;
3859e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            state->next = state->codes;
3869e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            state->lencode = (code const FAR *)(state->next);
3879e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            state->lenbits = 7;
3889e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            ret = inflate_table(CODES, state->lens, 19, &(state->next),
3899e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                                &(state->lenbits), state->work);
3909e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            if (ret) {
3919e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                strm->msg = (char *)"invalid code lengths set";
3929e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                state->mode = BAD;
3939e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                break;
3949e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            }
3959e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            Tracev((stderr, "inflate:       code lengths ok\n"));
3969e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
3979e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            /* get length and distance code code lengths */
3989e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            state->have = 0;
3999e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            while (state->have < state->nlen + state->ndist) {
4009e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                for (;;) {
401381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                    here = state->lencode[BITS(state->lenbits)];
402381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                    if ((unsigned)(here.bits) <= bits) break;
4039e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                    PULLBYTE();
4049e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                }
405381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                if (here.val < 16) {
406381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                    DROPBITS(here.bits);
407381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                    state->lens[state->have++] = here.val;
4089e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                }
4099e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                else {
410381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                    if (here.val == 16) {
411381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                        NEEDBITS(here.bits + 2);
412381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                        DROPBITS(here.bits);
4139e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                        if (state->have == 0) {
4149e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                            strm->msg = (char *)"invalid bit length repeat";
4159e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                            state->mode = BAD;
4169e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                            break;
4179e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                        }
4189e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                        len = (unsigned)(state->lens[state->have - 1]);
4199e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                        copy = 3 + BITS(2);
4209e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                        DROPBITS(2);
4219e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                    }
422381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                    else if (here.val == 17) {
423381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                        NEEDBITS(here.bits + 3);
424381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                        DROPBITS(here.bits);
4259e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                        len = 0;
4269e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                        copy = 3 + BITS(3);
4279e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                        DROPBITS(3);
4289e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                    }
4299e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                    else {
430381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                        NEEDBITS(here.bits + 7);
431381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                        DROPBITS(here.bits);
4329e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                        len = 0;
4339e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                        copy = 11 + BITS(7);
4349e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                        DROPBITS(7);
4359e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                    }
4369e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                    if (state->have + copy > state->nlen + state->ndist) {
4379e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                        strm->msg = (char *)"invalid bit length repeat";
4389e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                        state->mode = BAD;
4399e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                        break;
4409e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                    }
4419e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                    while (copy--)
4429e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                        state->lens[state->have++] = (unsigned short)len;
4439e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                }
4449e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            }
4459e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
4469e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            /* handle error breaks in while */
4479e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            if (state->mode == BAD) break;
4489e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
449381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            /* check for end-of-block code (better have one) */
450381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            if (state->lens[256] == 0) {
451381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                strm->msg = (char *)"invalid code -- missing end-of-block";
452381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                state->mode = BAD;
453381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                break;
454381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            }
455381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
456381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            /* build code tables -- note: do not change the lenbits or distbits
457381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes               values here (9 and 6) without reading the comments in inftrees.h
458381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes               concerning the ENOUGH constants, which depend on those values */
4599e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            state->next = state->codes;
4609e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            state->lencode = (code const FAR *)(state->next);
4619e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            state->lenbits = 9;
4629e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
4639e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                                &(state->lenbits), state->work);
4649e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            if (ret) {
4659e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                strm->msg = (char *)"invalid literal/lengths set";
4669e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                state->mode = BAD;
4679e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                break;
4689e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            }
4699e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            state->distcode = (code const FAR *)(state->next);
4709e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            state->distbits = 6;
4719e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
4729e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                            &(state->next), &(state->distbits), state->work);
4739e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            if (ret) {
4749e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                strm->msg = (char *)"invalid distances set";
4759e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                state->mode = BAD;
4769e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                break;
4779e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            }
4789e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            Tracev((stderr, "inflate:       codes ok\n"));
4799e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            state->mode = LEN;
4809e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
4819e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        case LEN:
4829e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            /* use inflate_fast() if we have enough input and output */
4839e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            if (have >= 6 && left >= 258) {
4849e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                RESTORE();
4859e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                if (state->whave < state->wsize)
4869e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                    state->whave = state->wsize - left;
4879e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                inflate_fast(strm, state->wsize);
4889e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                LOAD();
4899e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                break;
4909e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            }
4919e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
4929e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            /* get a literal, length, or end-of-block code */
4939e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            for (;;) {
494381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                here = state->lencode[BITS(state->lenbits)];
495381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                if ((unsigned)(here.bits) <= bits) break;
4969e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                PULLBYTE();
4979e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            }
498381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            if (here.op && (here.op & 0xf0) == 0) {
499381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                last = here;
5009e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                for (;;) {
501381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                    here = state->lencode[last.val +
5029e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                            (BITS(last.bits + last.op) >> last.bits)];
503381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                    if ((unsigned)(last.bits + here.bits) <= bits) break;
5049e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                    PULLBYTE();
5059e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                }
5069e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                DROPBITS(last.bits);
5079e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            }
508381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            DROPBITS(here.bits);
509381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            state->length = (unsigned)here.val;
5109e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
5119e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            /* process literal */
512381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            if (here.op == 0) {
513381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
5149e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                        "inflate:         literal '%c'\n" :
515381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                        "inflate:         literal 0x%02x\n", here.val));
5169e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                ROOM();
5179e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                *put++ = (unsigned char)(state->length);
5189e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                left--;
5199e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                state->mode = LEN;
5209e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                break;
5219e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            }
5229e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
5239e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            /* process end of block */
524381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            if (here.op & 32) {
5259e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                Tracevv((stderr, "inflate:         end of block\n"));
5269e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                state->mode = TYPE;
5279e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                break;
5289e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            }
5299e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
5309e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            /* invalid code */
531381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            if (here.op & 64) {
5329e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                strm->msg = (char *)"invalid literal/length code";
5339e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                state->mode = BAD;
5349e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                break;
5359e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            }
5369e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
5379e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            /* length code -- get extra bits, if any */
538381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            state->extra = (unsigned)(here.op) & 15;
5399e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            if (state->extra != 0) {
5409e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                NEEDBITS(state->extra);
5419e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                state->length += BITS(state->extra);
5429e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                DROPBITS(state->extra);
5439e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            }
5449e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            Tracevv((stderr, "inflate:         length %u\n", state->length));
5459e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
5469e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            /* get distance code */
5479e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            for (;;) {
548381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                here = state->distcode[BITS(state->distbits)];
549381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                if ((unsigned)(here.bits) <= bits) break;
5509e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                PULLBYTE();
5519e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            }
552381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            if ((here.op & 0xf0) == 0) {
553381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                last = here;
5549e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                for (;;) {
555381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                    here = state->distcode[last.val +
5569e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                            (BITS(last.bits + last.op) >> last.bits)];
557381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                    if ((unsigned)(last.bits + here.bits) <= bits) break;
5589e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                    PULLBYTE();
5599e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                }
5609e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                DROPBITS(last.bits);
5619e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            }
562381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            DROPBITS(here.bits);
563381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            if (here.op & 64) {
5649e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                strm->msg = (char *)"invalid distance code";
5659e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                state->mode = BAD;
5669e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                break;
5679e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            }
568381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            state->offset = (unsigned)here.val;
5699e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
5709e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            /* get distance extra bits, if any */
571381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            state->extra = (unsigned)(here.op) & 15;
5729e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            if (state->extra != 0) {
5739e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                NEEDBITS(state->extra);
5749e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                state->offset += BITS(state->extra);
5759e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                DROPBITS(state->extra);
5769e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            }
5779e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            if (state->offset > state->wsize - (state->whave < state->wsize ?
5789e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                                                left : 0)) {
5799e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                strm->msg = (char *)"invalid distance too far back";
5809e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                state->mode = BAD;
5819e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                break;
5829e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            }
5839e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            Tracevv((stderr, "inflate:         distance %u\n", state->offset));
5849e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
5859e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            /* copy match from window to output */
5869e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            do {
5879e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                ROOM();
5889e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                copy = state->wsize - state->offset;
5899e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                if (copy < left) {
5909e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                    from = put + copy;
5919e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                    copy = left - copy;
5929e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                }
5939e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                else {
5949e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                    from = put - state->offset;
5959e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                    copy = left;
5969e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                }
5979e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                if (copy > state->length) copy = state->length;
5989e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                state->length -= copy;
5999e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                left -= copy;
6009e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                do {
6019e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                    *put++ = *from++;
6029e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                } while (--copy);
6039e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            } while (state->length != 0);
6049e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            break;
6059e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
6069e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        case DONE:
6079e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            /* inflate stream terminated properly -- write leftover output */
6089e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            ret = Z_STREAM_END;
6099e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            if (left < state->wsize) {
6109e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                if (out(out_desc, state->window, state->wsize - left))
6119e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                    ret = Z_BUF_ERROR;
6129e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            }
6139e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            goto inf_leave;
6149e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
6159e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        case BAD:
6169e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            ret = Z_DATA_ERROR;
6179e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            goto inf_leave;
6189e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
6199e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        default:                /* can't happen, but makes compilers happy */
6209e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            ret = Z_STREAM_ERROR;
6219e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            goto inf_leave;
6229e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        }
6239e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
6249e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* Return unused input */
6259e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project  inf_leave:
6269e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    strm->next_in = next;
6279e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    strm->avail_in = have;
6289e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    return ret;
6299e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project}
6309e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
6319e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectint ZEXPORT inflateBackEnd(strm)
6329e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectz_streamp strm;
6339e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project{
6349e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0)
6359e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        return Z_STREAM_ERROR;
6369e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    ZFREE(strm, strm->state);
6379e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    strm->state = Z_NULL;
6389e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    Tracev((stderr, "inflate: end\n"));
6399e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    return Z_OK;
6409e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project}
641