19e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* infback9.c -- inflate deflate64 data using a call-back interface
2381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes * Copyright (C) 1995-2008 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#include "zutil.h"
79e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#include "infback9.h"
89e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#include "inftree9.h"
99e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#include "inflate9.h"
109e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
119e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#define WSIZE 65536UL
129e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
139e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/*
149e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   strm provides memory allocation functions in zalloc and zfree, or
159e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   Z_NULL to use the library memory allocation functions.
169e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
179e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   window is a user-supplied window and output buffer that is 64K bytes.
189e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project */
199e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectint ZEXPORT inflateBack9Init_(strm, window, version, stream_size)
209e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectz_stream FAR *strm;
219e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectunsigned char FAR *window;
229e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectconst char *version;
239e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectint stream_size;
249e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project{
259e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    struct inflate_state FAR *state;
269e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
279e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
289e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        stream_size != (int)(sizeof(z_stream)))
299e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        return Z_VERSION_ERROR;
309e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    if (strm == Z_NULL || window == Z_NULL)
319e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        return Z_STREAM_ERROR;
329e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    strm->msg = Z_NULL;                 /* in case we return an error */
339e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    if (strm->zalloc == (alloc_func)0) {
349e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        strm->zalloc = zcalloc;
359e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        strm->opaque = (voidpf)0;
369e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    }
379e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    if (strm->zfree == (free_func)0) strm->zfree = zcfree;
389e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    state = (struct inflate_state FAR *)ZALLOC(strm, 1,
399e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                                               sizeof(struct inflate_state));
409e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    if (state == Z_NULL) return Z_MEM_ERROR;
419e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    Tracev((stderr, "inflate: allocated\n"));
429e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    strm->state = (voidpf)state;
439e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    state->window = window;
449e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    return Z_OK;
459e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project}
469e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
479e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/*
489e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   Build and output length and distance decoding tables for fixed code
499e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   decoding.
509e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project */
519e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#ifdef MAKEFIXED
529e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#include <stdio.h>
539e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
549e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectvoid makefixed9(void)
559e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project{
569e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    unsigned sym, bits, low, size;
579e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    code *next, *lenfix, *distfix;
589e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    struct inflate_state state;
599e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    code fixed[544];
609e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
619e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* literal/length table */
629e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    sym = 0;
639e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    while (sym < 144) state.lens[sym++] = 8;
649e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    while (sym < 256) state.lens[sym++] = 9;
659e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    while (sym < 280) state.lens[sym++] = 7;
669e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    while (sym < 288) state.lens[sym++] = 8;
679e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    next = fixed;
689e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    lenfix = next;
699e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    bits = 9;
709e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    inflate_table9(LENS, state.lens, 288, &(next), &(bits), state.work);
719e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
729e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* distance table */
739e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    sym = 0;
749e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    while (sym < 32) state.lens[sym++] = 5;
759e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    distfix = next;
769e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    bits = 5;
779e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    inflate_table9(DISTS, state.lens, 32, &(next), &(bits), state.work);
789e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
799e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* write tables */
809e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    puts("    /* inffix9.h -- table for decoding deflate64 fixed codes");
819e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    puts("     * Generated automatically by makefixed9().");
829e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    puts("     */");
839e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    puts("");
849e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    puts("    /* WARNING: this file should *not* be used by applications.");
859e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    puts("       It is part of the implementation of this library and is");
869e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    puts("       subject to change. Applications should only use zlib.h.");
879e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    puts("     */");
889e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    puts("");
899e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    size = 1U << 9;
909e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    printf("    static const code lenfix[%u] = {", size);
919e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    low = 0;
929e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    for (;;) {
939e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        if ((low % 6) == 0) printf("\n        ");
949e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        printf("{%u,%u,%d}", lenfix[low].op, lenfix[low].bits,
959e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project               lenfix[low].val);
969e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        if (++low == size) break;
979e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        putchar(',');
989e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    }
999e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    puts("\n    };");
1009e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    size = 1U << 5;
1019e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    printf("\n    static const code distfix[%u] = {", size);
1029e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    low = 0;
1039e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    for (;;) {
1049e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        if ((low % 5) == 0) printf("\n        ");
1059e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        printf("{%u,%u,%d}", distfix[low].op, distfix[low].bits,
1069e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project               distfix[low].val);
1079e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        if (++low == size) break;
1089e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        putchar(',');
1099e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    }
1109e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    puts("\n    };");
1119e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project}
1129e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#endif /* MAKEFIXED */
1139e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
1149e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* Macros for inflateBack(): */
1159e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
1169e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* Clear the input bit accumulator */
1179e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#define INITBITS() \
1189e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    do { \
1199e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        hold = 0; \
1209e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        bits = 0; \
1219e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    } while (0)
1229e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
1239e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* Assure that some input is available.  If input is requested, but denied,
1249e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   then return a Z_BUF_ERROR from inflateBack(). */
1259e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#define PULL() \
1269e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    do { \
1279e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        if (have == 0) { \
1289e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            have = in(in_desc, &next); \
1299e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            if (have == 0) { \
1309e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                next = Z_NULL; \
1319e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                ret = Z_BUF_ERROR; \
1329e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                goto inf_leave; \
1339e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            } \
1349e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        } \
1359e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    } while (0)
1369e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
1379e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* Get a byte of input into the bit accumulator, or return from inflateBack()
1389e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   with an error if there is no input available. */
1399e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#define PULLBYTE() \
1409e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    do { \
1419e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        PULL(); \
1429e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        have--; \
1439e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        hold += (unsigned long)(*next++) << bits; \
1449e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        bits += 8; \
1459e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    } while (0)
1469e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
1479e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* Assure that there are at least n bits in the bit accumulator.  If there is
1489e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   not enough available input to do that, then return from inflateBack() with
1499e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   an error. */
1509e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#define NEEDBITS(n) \
1519e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    do { \
1529e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        while (bits < (unsigned)(n)) \
1539e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            PULLBYTE(); \
1549e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    } while (0)
1559e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
1569e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* Return the low n bits of the bit accumulator (n <= 16) */
1579e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#define BITS(n) \
1589e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    ((unsigned)hold & ((1U << (n)) - 1))
1599e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
1609e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* Remove n bits from the bit accumulator */
1619e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#define DROPBITS(n) \
1629e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    do { \
1639e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        hold >>= (n); \
1649e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        bits -= (unsigned)(n); \
1659e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    } while (0)
1669e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
1679e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* Remove zero to seven bits as needed to go to a byte boundary */
1689e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#define BYTEBITS() \
1699e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    do { \
1709e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        hold >>= bits & 7; \
1719e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        bits -= bits & 7; \
1729e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    } while (0)
1739e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
1749e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* Assure that some output space is available, by writing out the window
1759e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   if it's full.  If the write fails, return from inflateBack() with a
1769e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   Z_BUF_ERROR. */
1779e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#define ROOM() \
1789e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    do { \
1799e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        if (left == 0) { \
1809e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            put = window; \
1819e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            left = WSIZE; \
1829e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            wrap = 1; \
1839e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            if (out(out_desc, put, (unsigned)left)) { \
1849e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                ret = Z_BUF_ERROR; \
1859e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                goto inf_leave; \
1869e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            } \
1879e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        } \
1889e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    } while (0)
1899e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
1909e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/*
1919e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   strm provides the memory allocation functions and window buffer on input,
1929e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   and provides information on the unused input on return.  For Z_DATA_ERROR
1939e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   returns, strm will also provide an error message.
1949e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
1959e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   in() and out() are the call-back input and output functions.  When
1969e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   inflateBack() needs more input, it calls in().  When inflateBack() has
1979e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   filled the window with output, or when it completes with data in the
1989e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   window, it calls out() to write out the data.  The application must not
1999e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   change the provided input until in() is called again or inflateBack()
2009e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   returns.  The application must not change the window/output buffer until
2019e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   inflateBack() returns.
2029e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
2039e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   in() and out() are called with a descriptor parameter provided in the
2049e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   inflateBack() call.  This parameter can be a structure that provides the
2059e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   information required to do the read or write, as well as accumulated
2069e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   information on the input and output such as totals and check values.
2079e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
2089e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   in() should return zero on failure.  out() should return non-zero on
2099e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   failure.  If either in() or out() fails, than inflateBack() returns a
2109e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   Z_BUF_ERROR.  strm->next_in can be checked for Z_NULL to see whether it
2119e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   was in() or out() that caused in the error.  Otherwise,  inflateBack()
2129e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format
2139e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   error, or Z_MEM_ERROR if it could not allocate memory for the state.
2149e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   inflateBack() can also return Z_STREAM_ERROR if the input parameters
2159e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project   are not correct, i.e. strm is Z_NULL or the state was not initialized.
2169e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project */
2179e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectint ZEXPORT inflateBack9(strm, in, in_desc, out, out_desc)
2189e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectz_stream FAR *strm;
2199e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectin_func in;
2209e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectvoid FAR *in_desc;
2219e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectout_func out;
2229e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectvoid FAR *out_desc;
2239e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project{
2249e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    struct inflate_state FAR *state;
22504351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes    z_const unsigned char FAR *next;    /* next input */
2269e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    unsigned char FAR *put;     /* next output */
2279e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    unsigned have;              /* available input */
2289e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    unsigned long left;         /* available output */
2299e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    inflate_mode mode;          /* current inflate mode */
2309e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    int lastblock;              /* true if processing last block */
2319e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    int wrap;                   /* true if the window has wrapped */
2329e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    unsigned char FAR *window;  /* allocated sliding window, if needed */
2339e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    unsigned long hold;         /* bit buffer */
2349e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    unsigned bits;              /* bits in bit buffer */
2359e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    unsigned extra;             /* extra bits needed */
2369e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    unsigned long length;       /* literal or length of data to copy */
2379e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    unsigned long offset;       /* distance back to copy string from */
2389e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    unsigned long copy;         /* number of stored or match bytes to copy */
2399e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    unsigned char FAR *from;    /* where to copy match bytes from */
2409e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    code const FAR *lencode;    /* starting table for length/literal codes */
2419e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    code const FAR *distcode;   /* starting table for distance codes */
2429e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    unsigned lenbits;           /* index bits for lencode */
2439e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    unsigned distbits;          /* index bits for distcode */
244381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    code here;                  /* current decoding table entry */
2459e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    code last;                  /* parent table entry */
2469e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    unsigned len;               /* length to copy for repeats, bits to drop */
2479e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    int ret;                    /* return code */
2489e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    static const unsigned short order[19] = /* permutation of code lengths */
2499e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
2509e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#include "inffix9.h"
2519e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
2529e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* Check that the strm exists and that the state was initialized */
2539e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    if (strm == Z_NULL || strm->state == Z_NULL)
2549e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        return Z_STREAM_ERROR;
2559e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    state = (struct inflate_state FAR *)strm->state;
2569e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
2579e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* Reset the state */
2589e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    strm->msg = Z_NULL;
2599e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    mode = TYPE;
2609e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    lastblock = 0;
2619e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    wrap = 0;
2629e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    window = state->window;
2639e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    next = strm->next_in;
2649e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    have = next != Z_NULL ? strm->avail_in : 0;
2659e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    hold = 0;
2669e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    bits = 0;
2679e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    put = window;
2689e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    left = WSIZE;
2699e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    lencode = Z_NULL;
2709e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    distcode = Z_NULL;
2719e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
2729e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* Inflate until end of block marked as last */
2739e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    for (;;)
2749e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        switch (mode) {
2759e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        case TYPE:
2769e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            /* determine and dispatch block type */
2779e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            if (lastblock) {
2789e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                BYTEBITS();
2799e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                mode = DONE;
2809e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                break;
2819e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            }
2829e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            NEEDBITS(3);
2839e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            lastblock = BITS(1);
2849e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            DROPBITS(1);
2859e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            switch (BITS(2)) {
2869e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            case 0:                             /* stored block */
2879e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                Tracev((stderr, "inflate:     stored block%s\n",
2889e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                        lastblock ? " (last)" : ""));
2899e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                mode = STORED;
2909e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                break;
2919e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            case 1:                             /* fixed block */
2929e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                lencode = lenfix;
2939e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                lenbits = 9;
2949e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                distcode = distfix;
2959e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                distbits = 5;
2969e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                Tracev((stderr, "inflate:     fixed codes block%s\n",
2979e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                        lastblock ? " (last)" : ""));
2989e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                mode = LEN;                     /* decode codes */
2999e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                break;
3009e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            case 2:                             /* dynamic block */
3019e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                Tracev((stderr, "inflate:     dynamic codes block%s\n",
3029e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                        lastblock ? " (last)" : ""));
3039e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                mode = TABLE;
3049e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                break;
3059e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            case 3:
3069e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                strm->msg = (char *)"invalid block type";
3079e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                mode = BAD;
3089e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            }
3099e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            DROPBITS(2);
3109e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            break;
3119e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
3129e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        case STORED:
3139e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            /* get and verify stored block length */
3149e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            BYTEBITS();                         /* go to byte boundary */
3159e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            NEEDBITS(32);
3169e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
3179e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                strm->msg = (char *)"invalid stored block lengths";
3189e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                mode = BAD;
3199e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                break;
3209e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            }
3219e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            length = (unsigned)hold & 0xffff;
3229e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            Tracev((stderr, "inflate:       stored length %lu\n",
3239e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                    length));
3249e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            INITBITS();
3259e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
3269e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            /* copy stored block from input to output */
3279e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            while (length != 0) {
3289e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                copy = length;
3299e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                PULL();
3309e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                ROOM();
3319e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                if (copy > have) copy = have;
3329e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                if (copy > left) copy = left;
3339e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                zmemcpy(put, next, copy);
3349e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                have -= copy;
3359e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                next += copy;
3369e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                left -= copy;
3379e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                put += copy;
3389e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                length -= copy;
3399e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            }
3409e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            Tracev((stderr, "inflate:       stored end\n"));
3419e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            mode = TYPE;
3429e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            break;
3439e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
3449e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        case TABLE:
3459e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            /* get dynamic table entries descriptor */
3469e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            NEEDBITS(14);
3479e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            state->nlen = BITS(5) + 257;
3489e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            DROPBITS(5);
3499e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            state->ndist = BITS(5) + 1;
3509e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            DROPBITS(5);
3519e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            state->ncode = BITS(4) + 4;
3529e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            DROPBITS(4);
3539e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            if (state->nlen > 286) {
3549e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                strm->msg = (char *)"too many length symbols";
3559e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                mode = BAD;
3569e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                break;
3579e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            }
3589e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            Tracev((stderr, "inflate:       table sizes ok\n"));
3599e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
3609e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            /* get code length code lengths (not a typo) */
3619e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            state->have = 0;
3629e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            while (state->have < state->ncode) {
3639e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                NEEDBITS(3);
3649e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                state->lens[order[state->have++]] = (unsigned short)BITS(3);
3659e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                DROPBITS(3);
3669e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            }
3679e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            while (state->have < 19)
3689e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                state->lens[order[state->have++]] = 0;
3699e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            state->next = state->codes;
3709e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            lencode = (code const FAR *)(state->next);
3719e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            lenbits = 7;
3729e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            ret = inflate_table9(CODES, state->lens, 19, &(state->next),
3739e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                                &(lenbits), state->work);
3749e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            if (ret) {
3759e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                strm->msg = (char *)"invalid code lengths set";
3769e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                mode = BAD;
3779e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                break;
3789e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            }
3799e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            Tracev((stderr, "inflate:       code lengths ok\n"));
3809e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
3819e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            /* get length and distance code code lengths */
3829e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            state->have = 0;
3839e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            while (state->have < state->nlen + state->ndist) {
3849e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                for (;;) {
385381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                    here = lencode[BITS(lenbits)];
386381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                    if ((unsigned)(here.bits) <= bits) break;
3879e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                    PULLBYTE();
3889e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                }
389381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                if (here.val < 16) {
390381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                    NEEDBITS(here.bits);
391381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                    DROPBITS(here.bits);
392381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                    state->lens[state->have++] = here.val;
3939e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                }
3949e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                else {
395381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                    if (here.val == 16) {
396381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                        NEEDBITS(here.bits + 2);
397381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                        DROPBITS(here.bits);
3989e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                        if (state->have == 0) {
3999e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                            strm->msg = (char *)"invalid bit length repeat";
4009e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                            mode = BAD;
4019e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                            break;
4029e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                        }
4039e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                        len = (unsigned)(state->lens[state->have - 1]);
4049e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                        copy = 3 + BITS(2);
4059e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                        DROPBITS(2);
4069e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                    }
407381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                    else if (here.val == 17) {
408381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                        NEEDBITS(here.bits + 3);
409381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                        DROPBITS(here.bits);
4109e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                        len = 0;
4119e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                        copy = 3 + BITS(3);
4129e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                        DROPBITS(3);
4139e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                    }
4149e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                    else {
415381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                        NEEDBITS(here.bits + 7);
416381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                        DROPBITS(here.bits);
4179e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                        len = 0;
4189e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                        copy = 11 + BITS(7);
4199e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                        DROPBITS(7);
4209e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                    }
4219e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                    if (state->have + copy > state->nlen + state->ndist) {
4229e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                        strm->msg = (char *)"invalid bit length repeat";
4239e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                        mode = BAD;
4249e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                        break;
4259e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                    }
4269e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                    while (copy--)
4279e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                        state->lens[state->have++] = (unsigned short)len;
4289e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                }
4299e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            }
4309e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
4319e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            /* handle error breaks in while */
4329e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            if (mode == BAD) break;
4339e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
434381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            /* check for end-of-block code (better have one) */
435381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            if (state->lens[256] == 0) {
436381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                strm->msg = (char *)"invalid code -- missing end-of-block";
437381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                mode = BAD;
438381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                break;
439381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            }
440381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
441381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            /* build code tables -- note: do not change the lenbits or distbits
442381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes               values here (9 and 6) without reading the comments in inftree9.h
443381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes               concerning the ENOUGH constants, which depend on those values */
4449e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            state->next = state->codes;
4459e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            lencode = (code const FAR *)(state->next);
4469e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            lenbits = 9;
4479e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            ret = inflate_table9(LENS, state->lens, state->nlen,
4489e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                            &(state->next), &(lenbits), state->work);
4499e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            if (ret) {
4509e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                strm->msg = (char *)"invalid literal/lengths set";
4519e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                mode = BAD;
4529e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                break;
4539e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            }
4549e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            distcode = (code const FAR *)(state->next);
4559e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            distbits = 6;
4569e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            ret = inflate_table9(DISTS, state->lens + state->nlen,
4579e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                            state->ndist, &(state->next), &(distbits),
4589e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                            state->work);
4599e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            if (ret) {
4609e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                strm->msg = (char *)"invalid distances set";
4619e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                mode = BAD;
4629e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                break;
4639e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            }
4649e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            Tracev((stderr, "inflate:       codes ok\n"));
4659e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            mode = LEN;
4669e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
4679e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        case LEN:
4689e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            /* get a literal, length, or end-of-block code */
4699e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            for (;;) {
470381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                here = lencode[BITS(lenbits)];
471381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                if ((unsigned)(here.bits) <= bits) break;
4729e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                PULLBYTE();
4739e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            }
474381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            if (here.op && (here.op & 0xf0) == 0) {
475381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                last = here;
4769e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                for (;;) {
477381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                    here = lencode[last.val +
4789e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                            (BITS(last.bits + last.op) >> last.bits)];
479381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                    if ((unsigned)(last.bits + here.bits) <= bits) break;
4809e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                    PULLBYTE();
4819e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                }
4829e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                DROPBITS(last.bits);
4839e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            }
484381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            DROPBITS(here.bits);
485381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            length = (unsigned)here.val;
4869e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
4879e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            /* process literal */
488381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            if (here.op == 0) {
489381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
4909e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                        "inflate:         literal '%c'\n" :
491381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                        "inflate:         literal 0x%02x\n", here.val));
4929e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                ROOM();
4939e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                *put++ = (unsigned char)(length);
4949e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                left--;
4959e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                mode = LEN;
4969e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                break;
4979e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            }
4989e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
4999e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            /* process end of block */
500381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            if (here.op & 32) {
5019e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                Tracevv((stderr, "inflate:         end of block\n"));
5029e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                mode = TYPE;
5039e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                break;
5049e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            }
5059e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
5069e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            /* invalid code */
507381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            if (here.op & 64) {
5089e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                strm->msg = (char *)"invalid literal/length code";
5099e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                mode = BAD;
5109e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                break;
5119e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            }
5129e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
5139e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            /* length code -- get extra bits, if any */
514381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            extra = (unsigned)(here.op) & 31;
5159e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            if (extra != 0) {
5169e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                NEEDBITS(extra);
5179e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                length += BITS(extra);
5189e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                DROPBITS(extra);
5199e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            }
5209e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            Tracevv((stderr, "inflate:         length %lu\n", length));
5219e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
5229e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            /* get distance code */
5239e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            for (;;) {
524381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                here = distcode[BITS(distbits)];
525381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                if ((unsigned)(here.bits) <= bits) break;
5269e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                PULLBYTE();
5279e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            }
528381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            if ((here.op & 0xf0) == 0) {
529381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                last = here;
5309e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                for (;;) {
531381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                    here = distcode[last.val +
5329e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                            (BITS(last.bits + last.op) >> last.bits)];
533381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                    if ((unsigned)(last.bits + here.bits) <= bits) break;
5349e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                    PULLBYTE();
5359e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                }
5369e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                DROPBITS(last.bits);
5379e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            }
538381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            DROPBITS(here.bits);
539381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            if (here.op & 64) {
5409e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                strm->msg = (char *)"invalid distance code";
5419e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                mode = BAD;
5429e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                break;
5439e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            }
544381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            offset = (unsigned)here.val;
5459e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
5469e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            /* get distance extra bits, if any */
547381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            extra = (unsigned)(here.op) & 15;
5489e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            if (extra != 0) {
5499e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                NEEDBITS(extra);
5509e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                offset += BITS(extra);
5519e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                DROPBITS(extra);
5529e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            }
5539e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            if (offset > WSIZE - (wrap ? 0: left)) {
5549e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                strm->msg = (char *)"invalid distance too far back";
5559e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                mode = BAD;
5569e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                break;
5579e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            }
5589e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            Tracevv((stderr, "inflate:         distance %lu\n", offset));
5599e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
5609e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            /* copy match from window to output */
5619e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            do {
5629e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                ROOM();
5639e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                copy = WSIZE - offset;
5649e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                if (copy < left) {
5659e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                    from = put + copy;
5669e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                    copy = left - copy;
5679e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                }
5689e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                else {
5699e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                    from = put - offset;
5709e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                    copy = left;
5719e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                }
5729e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                if (copy > length) copy = length;
5739e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                length -= copy;
5749e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                left -= copy;
5759e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                do {
5769e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                    *put++ = *from++;
5779e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                } while (--copy);
5789e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            } while (length != 0);
5799e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            break;
5809e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
5819e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        case DONE:
5829e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            /* inflate stream terminated properly -- write leftover output */
5839e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            ret = Z_STREAM_END;
5849e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            if (left < WSIZE) {
5859e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                if (out(out_desc, window, (unsigned)(WSIZE - left)))
5869e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project                    ret = Z_BUF_ERROR;
5879e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            }
5889e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            goto inf_leave;
5899e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
5909e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        case BAD:
5919e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            ret = Z_DATA_ERROR;
5929e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            goto inf_leave;
5939e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
5949e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        default:                /* can't happen, but makes compilers happy */
5959e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            ret = Z_STREAM_ERROR;
5969e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project            goto inf_leave;
5979e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        }
5989e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
5999e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    /* Return unused input */
6009e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project  inf_leave:
6019e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    strm->next_in = next;
6029e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    strm->avail_in = have;
6039e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    return ret;
6049e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project}
6059e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project
6069e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectint ZEXPORT inflateBack9End(strm)
6079e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectz_stream FAR *strm;
6089e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project{
6099e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0)
6109e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project        return Z_STREAM_ERROR;
6119e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    ZFREE(strm, strm->state);
6129e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    strm->state = Z_NULL;
6139e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    Tracev((stderr, "inflate: end\n"));
6149e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project    return Z_OK;
6159e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project}
616