core/zlib/infback.c
author David Anderson <dvander@alliedmods.net>
Mon Feb 26 09:21:08 2007 +0000 (2007-02-26)
changeset 539 fa7e8a232a18
parent 159 43c471413f70
permissions -rw-r--r--
fixed stupid export
dvander@159
     1
/* infback.c -- inflate using a call-back interface
dvander@159
     2
 * Copyright (C) 1995-2005 Mark Adler
dvander@159
     3
 * For conditions of distribution and use, see copyright notice in zlib.h
dvander@159
     4
 */
dvander@159
     5
dvander@159
     6
/*
dvander@159
     7
   This code is largely copied from inflate.c.  Normally either infback.o or
dvander@159
     8
   inflate.o would be linked into an application--not both.  The interface
dvander@159
     9
   with inffast.c is retained so that optimized assembler-coded versions of
dvander@159
    10
   inflate_fast() can be used with either inflate.c or infback.c.
dvander@159
    11
 */
dvander@159
    12
dvander@159
    13
#include "zutil.h"
dvander@159
    14
#include "inftrees.h"
dvander@159
    15
#include "inflate.h"
dvander@159
    16
#include "inffast.h"
dvander@159
    17
dvander@159
    18
/* function prototypes */
dvander@159
    19
local void fixedtables OF((struct inflate_state FAR *state));
dvander@159
    20
dvander@159
    21
/*
dvander@159
    22
   strm provides memory allocation functions in zalloc and zfree, or
dvander@159
    23
   Z_NULL to use the library memory allocation functions.
dvander@159
    24
dvander@159
    25
   windowBits is in the range 8..15, and window is a user-supplied
dvander@159
    26
   window and output buffer that is 2**windowBits bytes.
dvander@159
    27
 */
dvander@159
    28
int ZEXPORT inflateBackInit_(strm, windowBits, window, version, stream_size)
dvander@159
    29
z_streamp strm;
dvander@159
    30
int windowBits;
dvander@159
    31
unsigned char FAR *window;
dvander@159
    32
const char *version;
dvander@159
    33
int stream_size;
dvander@159
    34
{
dvander@159
    35
    struct inflate_state FAR *state;
dvander@159
    36
dvander@159
    37
    if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
dvander@159
    38
        stream_size != (int)(sizeof(z_stream)))
dvander@159
    39
        return Z_VERSION_ERROR;
dvander@159
    40
    if (strm == Z_NULL || window == Z_NULL ||
dvander@159
    41
        windowBits < 8 || windowBits > 15)
dvander@159
    42
        return Z_STREAM_ERROR;
dvander@159
    43
    strm->msg = Z_NULL;                 /* in case we return an error */
dvander@159
    44
    if (strm->zalloc == (alloc_func)0) {
dvander@159
    45
        strm->zalloc = zcalloc;
dvander@159
    46
        strm->opaque = (voidpf)0;
dvander@159
    47
    }
dvander@159
    48
    if (strm->zfree == (free_func)0) strm->zfree = zcfree;
dvander@159
    49
    state = (struct inflate_state FAR *)ZALLOC(strm, 1,
dvander@159
    50
                                               sizeof(struct inflate_state));
dvander@159
    51
    if (state == Z_NULL) return Z_MEM_ERROR;
dvander@159
    52
    Tracev((stderr, "inflate: allocated\n"));
dvander@159
    53
    strm->state = (struct internal_state FAR *)state;
dvander@159
    54
    state->dmax = 32768U;
dvander@159
    55
    state->wbits = windowBits;
dvander@159
    56
    state->wsize = 1U << windowBits;
dvander@159
    57
    state->window = window;
dvander@159
    58
    state->write = 0;
dvander@159
    59
    state->whave = 0;
dvander@159
    60
    return Z_OK;
dvander@159
    61
}
dvander@159
    62
dvander@159
    63
/*
dvander@159
    64
   Return state with length and distance decoding tables and index sizes set to
dvander@159
    65
   fixed code decoding.  Normally this returns fixed tables from inffixed.h.
dvander@159
    66
   If BUILDFIXED is defined, then instead this routine builds the tables the
dvander@159
    67
   first time it's called, and returns those tables the first time and
dvander@159
    68
   thereafter.  This reduces the size of the code by about 2K bytes, in
dvander@159
    69
   exchange for a little execution time.  However, BUILDFIXED should not be
dvander@159
    70
   used for threaded applications, since the rewriting of the tables and virgin
dvander@159
    71
   may not be thread-safe.
dvander@159
    72
 */
dvander@159
    73
local void fixedtables(state)
dvander@159
    74
struct inflate_state FAR *state;
dvander@159
    75
{
dvander@159
    76
#ifdef BUILDFIXED
dvander@159
    77
    static int virgin = 1;
dvander@159
    78
    static code *lenfix, *distfix;
dvander@159
    79
    static code fixed[544];
dvander@159
    80
dvander@159
    81
    /* build fixed huffman tables if first call (may not be thread safe) */
dvander@159
    82
    if (virgin) {
dvander@159
    83
        unsigned sym, bits;
dvander@159
    84
        static code *next;
dvander@159
    85
dvander@159
    86
        /* literal/length table */
dvander@159
    87
        sym = 0;
dvander@159
    88
        while (sym < 144) state->lens[sym++] = 8;
dvander@159
    89
        while (sym < 256) state->lens[sym++] = 9;
dvander@159
    90
        while (sym < 280) state->lens[sym++] = 7;
dvander@159
    91
        while (sym < 288) state->lens[sym++] = 8;
dvander@159
    92
        next = fixed;
dvander@159
    93
        lenfix = next;
dvander@159
    94
        bits = 9;
dvander@159
    95
        inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work);
dvander@159
    96
dvander@159
    97
        /* distance table */
dvander@159
    98
        sym = 0;
dvander@159
    99
        while (sym < 32) state->lens[sym++] = 5;
dvander@159
   100
        distfix = next;
dvander@159
   101
        bits = 5;
dvander@159
   102
        inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work);
dvander@159
   103
dvander@159
   104
        /* do this just once */
dvander@159
   105
        virgin = 0;
dvander@159
   106
    }
dvander@159
   107
#else /* !BUILDFIXED */
dvander@159
   108
#   include "inffixed.h"
dvander@159
   109
#endif /* BUILDFIXED */
dvander@159
   110
    state->lencode = lenfix;
dvander@159
   111
    state->lenbits = 9;
dvander@159
   112
    state->distcode = distfix;
dvander@159
   113
    state->distbits = 5;
dvander@159
   114
}
dvander@159
   115
dvander@159
   116
/* Macros for inflateBack(): */
dvander@159
   117
dvander@159
   118
/* Load returned state from inflate_fast() */
dvander@159
   119
#define LOAD() \
dvander@159
   120
    do { \
dvander@159
   121
        put = strm->next_out; \
dvander@159
   122
        left = strm->avail_out; \
dvander@159
   123
        next = strm->next_in; \
dvander@159
   124
        have = strm->avail_in; \
dvander@159
   125
        hold = state->hold; \
dvander@159
   126
        bits = state->bits; \
dvander@159
   127
    } while (0)
dvander@159
   128
dvander@159
   129
/* Set state from registers for inflate_fast() */
dvander@159
   130
#define RESTORE() \
dvander@159
   131
    do { \
dvander@159
   132
        strm->next_out = put; \
dvander@159
   133
        strm->avail_out = left; \
dvander@159
   134
        strm->next_in = next; \
dvander@159
   135
        strm->avail_in = have; \
dvander@159
   136
        state->hold = hold; \
dvander@159
   137
        state->bits = bits; \
dvander@159
   138
    } while (0)
dvander@159
   139
dvander@159
   140
/* Clear the input bit accumulator */
dvander@159
   141
#define INITBITS() \
dvander@159
   142
    do { \
dvander@159
   143
        hold = 0; \
dvander@159
   144
        bits = 0; \
dvander@159
   145
    } while (0)
dvander@159
   146
dvander@159
   147
/* Assure that some input is available.  If input is requested, but denied,
dvander@159
   148
   then return a Z_BUF_ERROR from inflateBack(). */
dvander@159
   149
#define PULL() \
dvander@159
   150
    do { \
dvander@159
   151
        if (have == 0) { \
dvander@159
   152
            have = in(in_desc, &next); \
dvander@159
   153
            if (have == 0) { \
dvander@159
   154
                next = Z_NULL; \
dvander@159
   155
                ret = Z_BUF_ERROR; \
dvander@159
   156
                goto inf_leave; \
dvander@159
   157
            } \
dvander@159
   158
        } \
dvander@159
   159
    } while (0)
dvander@159
   160
dvander@159
   161
/* Get a byte of input into the bit accumulator, or return from inflateBack()
dvander@159
   162
   with an error if there is no input available. */
dvander@159
   163
#define PULLBYTE() \
dvander@159
   164
    do { \
dvander@159
   165
        PULL(); \
dvander@159
   166
        have--; \
dvander@159
   167
        hold += (unsigned long)(*next++) << bits; \
dvander@159
   168
        bits += 8; \
dvander@159
   169
    } while (0)
dvander@159
   170
dvander@159
   171
/* Assure that there are at least n bits in the bit accumulator.  If there is
dvander@159
   172
   not enough available input to do that, then return from inflateBack() with
dvander@159
   173
   an error. */
dvander@159
   174
#define NEEDBITS(n) \
dvander@159
   175
    do { \
dvander@159
   176
        while (bits < (unsigned)(n)) \
dvander@159
   177
            PULLBYTE(); \
dvander@159
   178
    } while (0)
dvander@159
   179
dvander@159
   180
/* Return the low n bits of the bit accumulator (n < 16) */
dvander@159
   181
#define BITS(n) \
dvander@159
   182
    ((unsigned)hold & ((1U << (n)) - 1))
dvander@159
   183
dvander@159
   184
/* Remove n bits from the bit accumulator */
dvander@159
   185
#define DROPBITS(n) \
dvander@159
   186
    do { \
dvander@159
   187
        hold >>= (n); \
dvander@159
   188
        bits -= (unsigned)(n); \
dvander@159
   189
    } while (0)
dvander@159
   190
dvander@159
   191
/* Remove zero to seven bits as needed to go to a byte boundary */
dvander@159
   192
#define BYTEBITS() \
dvander@159
   193
    do { \
dvander@159
   194
        hold >>= bits & 7; \
dvander@159
   195
        bits -= bits & 7; \
dvander@159
   196
    } while (0)
dvander@159
   197
dvander@159
   198
/* Assure that some output space is available, by writing out the window
dvander@159
   199
   if it's full.  If the write fails, return from inflateBack() with a
dvander@159
   200
   Z_BUF_ERROR. */
dvander@159
   201
#define ROOM() \
dvander@159
   202
    do { \
dvander@159
   203
        if (left == 0) { \
dvander@159
   204
            put = state->window; \
dvander@159
   205
            left = state->wsize; \
dvander@159
   206
            state->whave = left; \
dvander@159
   207
            if (out(out_desc, put, left)) { \
dvander@159
   208
                ret = Z_BUF_ERROR; \
dvander@159
   209
                goto inf_leave; \
dvander@159
   210
            } \
dvander@159
   211
        } \
dvander@159
   212
    } while (0)
dvander@159
   213
dvander@159
   214
/*
dvander@159
   215
   strm provides the memory allocation functions and window buffer on input,
dvander@159
   216
   and provides information on the unused input on return.  For Z_DATA_ERROR
dvander@159
   217
   returns, strm will also provide an error message.
dvander@159
   218
dvander@159
   219
   in() and out() are the call-back input and output functions.  When
dvander@159
   220
   inflateBack() needs more input, it calls in().  When inflateBack() has
dvander@159
   221
   filled the window with output, or when it completes with data in the
dvander@159
   222
   window, it calls out() to write out the data.  The application must not
dvander@159
   223
   change the provided input until in() is called again or inflateBack()
dvander@159
   224
   returns.  The application must not change the window/output buffer until
dvander@159
   225
   inflateBack() returns.
dvander@159
   226
dvander@159
   227
   in() and out() are called with a descriptor parameter provided in the
dvander@159
   228
   inflateBack() call.  This parameter can be a structure that provides the
dvander@159
   229
   information required to do the read or write, as well as accumulated
dvander@159
   230
   information on the input and output such as totals and check values.
dvander@159
   231
dvander@159
   232
   in() should return zero on failure.  out() should return non-zero on
dvander@159
   233
   failure.  If either in() or out() fails, than inflateBack() returns a
dvander@159
   234
   Z_BUF_ERROR.  strm->next_in can be checked for Z_NULL to see whether it
dvander@159
   235
   was in() or out() that caused in the error.  Otherwise,  inflateBack()
dvander@159
   236
   returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format
dvander@159
   237
   error, or Z_MEM_ERROR if it could not allocate memory for the state.
dvander@159
   238
   inflateBack() can also return Z_STREAM_ERROR if the input parameters
dvander@159
   239
   are not correct, i.e. strm is Z_NULL or the state was not initialized.
dvander@159
   240
 */
dvander@159
   241
int ZEXPORT inflateBack(strm, in, in_desc, out, out_desc)
dvander@159
   242
z_streamp strm;
dvander@159
   243
in_func in;
dvander@159
   244
void FAR *in_desc;
dvander@159
   245
out_func out;
dvander@159
   246
void FAR *out_desc;
dvander@159
   247
{
dvander@159
   248
    struct inflate_state FAR *state;
dvander@159
   249
    unsigned char FAR *next;    /* next input */
dvander@159
   250
    unsigned char FAR *put;     /* next output */
dvander@159
   251
    unsigned have, left;        /* available input and output */
dvander@159
   252
    unsigned long hold;         /* bit buffer */
dvander@159
   253
    unsigned bits;              /* bits in bit buffer */
dvander@159
   254
    unsigned copy;              /* number of stored or match bytes to copy */
dvander@159
   255
    unsigned char FAR *from;    /* where to copy match bytes from */
dvander@159
   256
    code this;                  /* current decoding table entry */
dvander@159
   257
    code last;                  /* parent table entry */
dvander@159
   258
    unsigned len;               /* length to copy for repeats, bits to drop */
dvander@159
   259
    int ret;                    /* return code */
dvander@159
   260
    static const unsigned short order[19] = /* permutation of code lengths */
dvander@159
   261
        {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
dvander@159
   262
dvander@159
   263
    /* Check that the strm exists and that the state was initialized */
dvander@159
   264
    if (strm == Z_NULL || strm->state == Z_NULL)
dvander@159
   265
        return Z_STREAM_ERROR;
dvander@159
   266
    state = (struct inflate_state FAR *)strm->state;
dvander@159
   267
dvander@159
   268
    /* Reset the state */
dvander@159
   269
    strm->msg = Z_NULL;
dvander@159
   270
    state->mode = TYPE;
dvander@159
   271
    state->last = 0;
dvander@159
   272
    state->whave = 0;
dvander@159
   273
    next = strm->next_in;
dvander@159
   274
    have = next != Z_NULL ? strm->avail_in : 0;
dvander@159
   275
    hold = 0;
dvander@159
   276
    bits = 0;
dvander@159
   277
    put = state->window;
dvander@159
   278
    left = state->wsize;
dvander@159
   279
dvander@159
   280
    /* Inflate until end of block marked as last */
dvander@159
   281
    for (;;)
dvander@159
   282
        switch (state->mode) {
dvander@159
   283
        case TYPE:
dvander@159
   284
            /* determine and dispatch block type */
dvander@159
   285
            if (state->last) {
dvander@159
   286
                BYTEBITS();
dvander@159
   287
                state->mode = DONE;
dvander@159
   288
                break;
dvander@159
   289
            }
dvander@159
   290
            NEEDBITS(3);
dvander@159
   291
            state->last = BITS(1);
dvander@159
   292
            DROPBITS(1);
dvander@159
   293
            switch (BITS(2)) {
dvander@159
   294
            case 0:                             /* stored block */
dvander@159
   295
                Tracev((stderr, "inflate:     stored block%s\n",
dvander@159
   296
                        state->last ? " (last)" : ""));
dvander@159
   297
                state->mode = STORED;
dvander@159
   298
                break;
dvander@159
   299
            case 1:                             /* fixed block */
dvander@159
   300
                fixedtables(state);
dvander@159
   301
                Tracev((stderr, "inflate:     fixed codes block%s\n",
dvander@159
   302
                        state->last ? " (last)" : ""));
dvander@159
   303
                state->mode = LEN;              /* decode codes */
dvander@159
   304
                break;
dvander@159
   305
            case 2:                             /* dynamic block */
dvander@159
   306
                Tracev((stderr, "inflate:     dynamic codes block%s\n",
dvander@159
   307
                        state->last ? " (last)" : ""));
dvander@159
   308
                state->mode = TABLE;
dvander@159
   309
                break;
dvander@159
   310
            case 3:
dvander@159
   311
                strm->msg = (char *)"invalid block type";
dvander@159
   312
                state->mode = BAD;
dvander@159
   313
            }
dvander@159
   314
            DROPBITS(2);
dvander@159
   315
            break;
dvander@159
   316
dvander@159
   317
        case STORED:
dvander@159
   318
            /* get and verify stored block length */
dvander@159
   319
            BYTEBITS();                         /* go to byte boundary */
dvander@159
   320
            NEEDBITS(32);
dvander@159
   321
            if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
dvander@159
   322
                strm->msg = (char *)"invalid stored block lengths";
dvander@159
   323
                state->mode = BAD;
dvander@159
   324
                break;
dvander@159
   325
            }
dvander@159
   326
            state->length = (unsigned)hold & 0xffff;
dvander@159
   327
            Tracev((stderr, "inflate:       stored length %u\n",
dvander@159
   328
                    state->length));
dvander@159
   329
            INITBITS();
dvander@159
   330
dvander@159
   331
            /* copy stored block from input to output */
dvander@159
   332
            while (state->length != 0) {
dvander@159
   333
                copy = state->length;
dvander@159
   334
                PULL();
dvander@159
   335
                ROOM();
dvander@159
   336
                if (copy > have) copy = have;
dvander@159
   337
                if (copy > left) copy = left;
dvander@159
   338
                zmemcpy(put, next, copy);
dvander@159
   339
                have -= copy;
dvander@159
   340
                next += copy;
dvander@159
   341
                left -= copy;
dvander@159
   342
                put += copy;
dvander@159
   343
                state->length -= copy;
dvander@159
   344
            }
dvander@159
   345
            Tracev((stderr, "inflate:       stored end\n"));
dvander@159
   346
            state->mode = TYPE;
dvander@159
   347
            break;
dvander@159
   348
dvander@159
   349
        case TABLE:
dvander@159
   350
            /* get dynamic table entries descriptor */
dvander@159
   351
            NEEDBITS(14);
dvander@159
   352
            state->nlen = BITS(5) + 257;
dvander@159
   353
            DROPBITS(5);
dvander@159
   354
            state->ndist = BITS(5) + 1;
dvander@159
   355
            DROPBITS(5);
dvander@159
   356
            state->ncode = BITS(4) + 4;
dvander@159
   357
            DROPBITS(4);
dvander@159
   358
#ifndef PKZIP_BUG_WORKAROUND
dvander@159
   359
            if (state->nlen > 286 || state->ndist > 30) {
dvander@159
   360
                strm->msg = (char *)"too many length or distance symbols";
dvander@159
   361
                state->mode = BAD;
dvander@159
   362
                break;
dvander@159
   363
            }
dvander@159
   364
#endif
dvander@159
   365
            Tracev((stderr, "inflate:       table sizes ok\n"));
dvander@159
   366
dvander@159
   367
            /* get code length code lengths (not a typo) */
dvander@159
   368
            state->have = 0;
dvander@159
   369
            while (state->have < state->ncode) {
dvander@159
   370
                NEEDBITS(3);
dvander@159
   371
                state->lens[order[state->have++]] = (unsigned short)BITS(3);
dvander@159
   372
                DROPBITS(3);
dvander@159
   373
            }
dvander@159
   374
            while (state->have < 19)
dvander@159
   375
                state->lens[order[state->have++]] = 0;
dvander@159
   376
            state->next = state->codes;
dvander@159
   377
            state->lencode = (code const FAR *)(state->next);
dvander@159
   378
            state->lenbits = 7;
dvander@159
   379
            ret = inflate_table(CODES, state->lens, 19, &(state->next),
dvander@159
   380
                                &(state->lenbits), state->work);
dvander@159
   381
            if (ret) {
dvander@159
   382
                strm->msg = (char *)"invalid code lengths set";
dvander@159
   383
                state->mode = BAD;
dvander@159
   384
                break;
dvander@159
   385
            }
dvander@159
   386
            Tracev((stderr, "inflate:       code lengths ok\n"));
dvander@159
   387
dvander@159
   388
            /* get length and distance code code lengths */
dvander@159
   389
            state->have = 0;
dvander@159
   390
            while (state->have < state->nlen + state->ndist) {
dvander@159
   391
                for (;;) {
dvander@159
   392
                    this = state->lencode[BITS(state->lenbits)];
dvander@159
   393
                    if ((unsigned)(this.bits) <= bits) break;
dvander@159
   394
                    PULLBYTE();
dvander@159
   395
                }
dvander@159
   396
                if (this.val < 16) {
dvander@159
   397
                    NEEDBITS(this.bits);
dvander@159
   398
                    DROPBITS(this.bits);
dvander@159
   399
                    state->lens[state->have++] = this.val;
dvander@159
   400
                }
dvander@159
   401
                else {
dvander@159
   402
                    if (this.val == 16) {
dvander@159
   403
                        NEEDBITS(this.bits + 2);
dvander@159
   404
                        DROPBITS(this.bits);
dvander@159
   405
                        if (state->have == 0) {
dvander@159
   406
                            strm->msg = (char *)"invalid bit length repeat";
dvander@159
   407
                            state->mode = BAD;
dvander@159
   408
                            break;
dvander@159
   409
                        }
dvander@159
   410
                        len = (unsigned)(state->lens[state->have - 1]);
dvander@159
   411
                        copy = 3 + BITS(2);
dvander@159
   412
                        DROPBITS(2);
dvander@159
   413
                    }
dvander@159
   414
                    else if (this.val == 17) {
dvander@159
   415
                        NEEDBITS(this.bits + 3);
dvander@159
   416
                        DROPBITS(this.bits);
dvander@159
   417
                        len = 0;
dvander@159
   418
                        copy = 3 + BITS(3);
dvander@159
   419
                        DROPBITS(3);
dvander@159
   420
                    }
dvander@159
   421
                    else {
dvander@159
   422
                        NEEDBITS(this.bits + 7);
dvander@159
   423
                        DROPBITS(this.bits);
dvander@159
   424
                        len = 0;
dvander@159
   425
                        copy = 11 + BITS(7);
dvander@159
   426
                        DROPBITS(7);
dvander@159
   427
                    }
dvander@159
   428
                    if (state->have + copy > state->nlen + state->ndist) {
dvander@159
   429
                        strm->msg = (char *)"invalid bit length repeat";
dvander@159
   430
                        state->mode = BAD;
dvander@159
   431
                        break;
dvander@159
   432
                    }
dvander@159
   433
                    while (copy--)
dvander@159
   434
                        state->lens[state->have++] = (unsigned short)len;
dvander@159
   435
                }
dvander@159
   436
            }
dvander@159
   437
dvander@159
   438
            /* handle error breaks in while */
dvander@159
   439
            if (state->mode == BAD) break;
dvander@159
   440
dvander@159
   441
            /* build code tables */
dvander@159
   442
            state->next = state->codes;
dvander@159
   443
            state->lencode = (code const FAR *)(state->next);
dvander@159
   444
            state->lenbits = 9;
dvander@159
   445
            ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
dvander@159
   446
                                &(state->lenbits), state->work);
dvander@159
   447
            if (ret) {
dvander@159
   448
                strm->msg = (char *)"invalid literal/lengths set";
dvander@159
   449
                state->mode = BAD;
dvander@159
   450
                break;
dvander@159
   451
            }
dvander@159
   452
            state->distcode = (code const FAR *)(state->next);
dvander@159
   453
            state->distbits = 6;
dvander@159
   454
            ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
dvander@159
   455
                            &(state->next), &(state->distbits), state->work);
dvander@159
   456
            if (ret) {
dvander@159
   457
                strm->msg = (char *)"invalid distances set";
dvander@159
   458
                state->mode = BAD;
dvander@159
   459
                break;
dvander@159
   460
            }
dvander@159
   461
            Tracev((stderr, "inflate:       codes ok\n"));
dvander@159
   462
            state->mode = LEN;
dvander@159
   463
dvander@159
   464
        case LEN:
dvander@159
   465
            /* use inflate_fast() if we have enough input and output */
dvander@159
   466
            if (have >= 6 && left >= 258) {
dvander@159
   467
                RESTORE();
dvander@159
   468
                if (state->whave < state->wsize)
dvander@159
   469
                    state->whave = state->wsize - left;
dvander@159
   470
                inflate_fast(strm, state->wsize);
dvander@159
   471
                LOAD();
dvander@159
   472
                break;
dvander@159
   473
            }
dvander@159
   474
dvander@159
   475
            /* get a literal, length, or end-of-block code */
dvander@159
   476
            for (;;) {
dvander@159
   477
                this = state->lencode[BITS(state->lenbits)];
dvander@159
   478
                if ((unsigned)(this.bits) <= bits) break;
dvander@159
   479
                PULLBYTE();
dvander@159
   480
            }
dvander@159
   481
            if (this.op && (this.op & 0xf0) == 0) {
dvander@159
   482
                last = this;
dvander@159
   483
                for (;;) {
dvander@159
   484
                    this = state->lencode[last.val +
dvander@159
   485
                            (BITS(last.bits + last.op) >> last.bits)];
dvander@159
   486
                    if ((unsigned)(last.bits + this.bits) <= bits) break;
dvander@159
   487
                    PULLBYTE();
dvander@159
   488
                }
dvander@159
   489
                DROPBITS(last.bits);
dvander@159
   490
            }
dvander@159
   491
            DROPBITS(this.bits);
dvander@159
   492
            state->length = (unsigned)this.val;
dvander@159
   493
dvander@159
   494
            /* process literal */
dvander@159
   495
            if (this.op == 0) {
dvander@159
   496
                Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ?
dvander@159
   497
                        "inflate:         literal '%c'\n" :
dvander@159
   498
                        "inflate:         literal 0x%02x\n", this.val));
dvander@159
   499
                ROOM();
dvander@159
   500
                *put++ = (unsigned char)(state->length);
dvander@159
   501
                left--;
dvander@159
   502
                state->mode = LEN;
dvander@159
   503
                break;
dvander@159
   504
            }
dvander@159
   505
dvander@159
   506
            /* process end of block */
dvander@159
   507
            if (this.op & 32) {
dvander@159
   508
                Tracevv((stderr, "inflate:         end of block\n"));
dvander@159
   509
                state->mode = TYPE;
dvander@159
   510
                break;
dvander@159
   511
            }
dvander@159
   512
dvander@159
   513
            /* invalid code */
dvander@159
   514
            if (this.op & 64) {
dvander@159
   515
                strm->msg = (char *)"invalid literal/length code";
dvander@159
   516
                state->mode = BAD;
dvander@159
   517
                break;
dvander@159
   518
            }
dvander@159
   519
dvander@159
   520
            /* length code -- get extra bits, if any */
dvander@159
   521
            state->extra = (unsigned)(this.op) & 15;
dvander@159
   522
            if (state->extra != 0) {
dvander@159
   523
                NEEDBITS(state->extra);
dvander@159
   524
                state->length += BITS(state->extra);
dvander@159
   525
                DROPBITS(state->extra);
dvander@159
   526
            }
dvander@159
   527
            Tracevv((stderr, "inflate:         length %u\n", state->length));
dvander@159
   528
dvander@159
   529
            /* get distance code */
dvander@159
   530
            for (;;) {
dvander@159
   531
                this = state->distcode[BITS(state->distbits)];
dvander@159
   532
                if ((unsigned)(this.bits) <= bits) break;
dvander@159
   533
                PULLBYTE();
dvander@159
   534
            }
dvander@159
   535
            if ((this.op & 0xf0) == 0) {
dvander@159
   536
                last = this;
dvander@159
   537
                for (;;) {
dvander@159
   538
                    this = state->distcode[last.val +
dvander@159
   539
                            (BITS(last.bits + last.op) >> last.bits)];
dvander@159
   540
                    if ((unsigned)(last.bits + this.bits) <= bits) break;
dvander@159
   541
                    PULLBYTE();
dvander@159
   542
                }
dvander@159
   543
                DROPBITS(last.bits);
dvander@159
   544
            }
dvander@159
   545
            DROPBITS(this.bits);
dvander@159
   546
            if (this.op & 64) {
dvander@159
   547
                strm->msg = (char *)"invalid distance code";
dvander@159
   548
                state->mode = BAD;
dvander@159
   549
                break;
dvander@159
   550
            }
dvander@159
   551
            state->offset = (unsigned)this.val;
dvander@159
   552
dvander@159
   553
            /* get distance extra bits, if any */
dvander@159
   554
            state->extra = (unsigned)(this.op) & 15;
dvander@159
   555
            if (state->extra != 0) {
dvander@159
   556
                NEEDBITS(state->extra);
dvander@159
   557
                state->offset += BITS(state->extra);
dvander@159
   558
                DROPBITS(state->extra);
dvander@159
   559
            }
dvander@159
   560
            if (state->offset > state->wsize - (state->whave < state->wsize ?
dvander@159
   561
                                                left : 0)) {
dvander@159
   562
                strm->msg = (char *)"invalid distance too far back";
dvander@159
   563
                state->mode = BAD;
dvander@159
   564
                break;
dvander@159
   565
            }
dvander@159
   566
            Tracevv((stderr, "inflate:         distance %u\n", state->offset));
dvander@159
   567
dvander@159
   568
            /* copy match from window to output */
dvander@159
   569
            do {
dvander@159
   570
                ROOM();
dvander@159
   571
                copy = state->wsize - state->offset;
dvander@159
   572
                if (copy < left) {
dvander@159
   573
                    from = put + copy;
dvander@159
   574
                    copy = left - copy;
dvander@159
   575
                }
dvander@159
   576
                else {
dvander@159
   577
                    from = put - state->offset;
dvander@159
   578
                    copy = left;
dvander@159
   579
                }
dvander@159
   580
                if (copy > state->length) copy = state->length;
dvander@159
   581
                state->length -= copy;
dvander@159
   582
                left -= copy;
dvander@159
   583
                do {
dvander@159
   584
                    *put++ = *from++;
dvander@159
   585
                } while (--copy);
dvander@159
   586
            } while (state->length != 0);
dvander@159
   587
            break;
dvander@159
   588
dvander@159
   589
        case DONE:
dvander@159
   590
            /* inflate stream terminated properly -- write leftover output */
dvander@159
   591
            ret = Z_STREAM_END;
dvander@159
   592
            if (left < state->wsize) {
dvander@159
   593
                if (out(out_desc, state->window, state->wsize - left))
dvander@159
   594
                    ret = Z_BUF_ERROR;
dvander@159
   595
            }
dvander@159
   596
            goto inf_leave;
dvander@159
   597
dvander@159
   598
        case BAD:
dvander@159
   599
            ret = Z_DATA_ERROR;
dvander@159
   600
            goto inf_leave;
dvander@159
   601
dvander@159
   602
        default:                /* can't happen, but makes compilers happy */
dvander@159
   603
            ret = Z_STREAM_ERROR;
dvander@159
   604
            goto inf_leave;
dvander@159
   605
        }
dvander@159
   606
dvander@159
   607
    /* Return unused input */
dvander@159
   608
  inf_leave:
dvander@159
   609
    strm->next_in = next;
dvander@159
   610
    strm->avail_in = have;
dvander@159
   611
    return ret;
dvander@159
   612
}
dvander@159
   613
dvander@159
   614
int ZEXPORT inflateBackEnd(strm)
dvander@159
   615
z_streamp strm;
dvander@159
   616
{
dvander@159
   617
    if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0)
dvander@159
   618
        return Z_STREAM_ERROR;
dvander@159
   619
    ZFREE(strm, strm->state);
dvander@159
   620
    strm->state = Z_NULL;
dvander@159
   621
    Tracev((stderr, "inflate: end\n"));
dvander@159
   622
    return Z_OK;
dvander@159
   623
}