core/zlib/inflate.c
author David Anderson <dvander@alliedmods.net>
Fri Feb 16 04:16:31 2007 +0000 (2007-02-16)
changeset 502 4530ea065a8b
parent 159 43c471413f70
permissions -rw-r--r--
fixed a serious potential bug with swapping plugins to debug mode, leaving stale function pointers without plugin removal
dvander@159
     1
/* inflate.c -- zlib decompression
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
 * Change history:
dvander@159
     8
 *
dvander@159
     9
 * 1.2.beta0    24 Nov 2002
dvander@159
    10
 * - First version -- complete rewrite of inflate to simplify code, avoid
dvander@159
    11
 *   creation of window when not needed, minimize use of window when it is
dvander@159
    12
 *   needed, make inffast.c even faster, implement gzip decoding, and to
dvander@159
    13
 *   improve code readability and style over the previous zlib inflate code
dvander@159
    14
 *
dvander@159
    15
 * 1.2.beta1    25 Nov 2002
dvander@159
    16
 * - Use pointers for available input and output checking in inffast.c
dvander@159
    17
 * - Remove input and output counters in inffast.c
dvander@159
    18
 * - Change inffast.c entry and loop from avail_in >= 7 to >= 6
dvander@159
    19
 * - Remove unnecessary second byte pull from length extra in inffast.c
dvander@159
    20
 * - Unroll direct copy to three copies per loop in inffast.c
dvander@159
    21
 *
dvander@159
    22
 * 1.2.beta2    4 Dec 2002
dvander@159
    23
 * - Change external routine names to reduce potential conflicts
dvander@159
    24
 * - Correct filename to inffixed.h for fixed tables in inflate.c
dvander@159
    25
 * - Make hbuf[] unsigned char to match parameter type in inflate.c
dvander@159
    26
 * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset)
dvander@159
    27
 *   to avoid negation problem on Alphas (64 bit) in inflate.c
dvander@159
    28
 *
dvander@159
    29
 * 1.2.beta3    22 Dec 2002
dvander@159
    30
 * - Add comments on state->bits assertion in inffast.c
dvander@159
    31
 * - Add comments on op field in inftrees.h
dvander@159
    32
 * - Fix bug in reuse of allocated window after inflateReset()
dvander@159
    33
 * - Remove bit fields--back to byte structure for speed
dvander@159
    34
 * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths
dvander@159
    35
 * - Change post-increments to pre-increments in inflate_fast(), PPC biased?
dvander@159
    36
 * - Add compile time option, POSTINC, to use post-increments instead (Intel?)
dvander@159
    37
 * - Make MATCH copy in inflate() much faster for when inflate_fast() not used
dvander@159
    38
 * - Use local copies of stream next and avail values, as well as local bit
dvander@159
    39
 *   buffer and bit count in inflate()--for speed when inflate_fast() not used
dvander@159
    40
 *
dvander@159
    41
 * 1.2.beta4    1 Jan 2003
dvander@159
    42
 * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings
dvander@159
    43
 * - Move a comment on output buffer sizes from inffast.c to inflate.c
dvander@159
    44
 * - Add comments in inffast.c to introduce the inflate_fast() routine
dvander@159
    45
 * - Rearrange window copies in inflate_fast() for speed and simplification
dvander@159
    46
 * - Unroll last copy for window match in inflate_fast()
dvander@159
    47
 * - Use local copies of window variables in inflate_fast() for speed
dvander@159
    48
 * - Pull out common write == 0 case for speed in inflate_fast()
dvander@159
    49
 * - Make op and len in inflate_fast() unsigned for consistency
dvander@159
    50
 * - Add FAR to lcode and dcode declarations in inflate_fast()
dvander@159
    51
 * - Simplified bad distance check in inflate_fast()
dvander@159
    52
 * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new
dvander@159
    53
 *   source file infback.c to provide a call-back interface to inflate for
dvander@159
    54
 *   programs like gzip and unzip -- uses window as output buffer to avoid
dvander@159
    55
 *   window copying
dvander@159
    56
 *
dvander@159
    57
 * 1.2.beta5    1 Jan 2003
dvander@159
    58
 * - Improved inflateBack() interface to allow the caller to provide initial
dvander@159
    59
 *   input in strm.
dvander@159
    60
 * - Fixed stored blocks bug in inflateBack()
dvander@159
    61
 *
dvander@159
    62
 * 1.2.beta6    4 Jan 2003
dvander@159
    63
 * - Added comments in inffast.c on effectiveness of POSTINC
dvander@159
    64
 * - Typecasting all around to reduce compiler warnings
dvander@159
    65
 * - Changed loops from while (1) or do {} while (1) to for (;;), again to
dvander@159
    66
 *   make compilers happy
dvander@159
    67
 * - Changed type of window in inflateBackInit() to unsigned char *
dvander@159
    68
 *
dvander@159
    69
 * 1.2.beta7    27 Jan 2003
dvander@159
    70
 * - Changed many types to unsigned or unsigned short to avoid warnings
dvander@159
    71
 * - Added inflateCopy() function
dvander@159
    72
 *
dvander@159
    73
 * 1.2.0        9 Mar 2003
dvander@159
    74
 * - Changed inflateBack() interface to provide separate opaque descriptors
dvander@159
    75
 *   for the in() and out() functions
dvander@159
    76
 * - Changed inflateBack() argument and in_func typedef to swap the length
dvander@159
    77
 *   and buffer address return values for the input function
dvander@159
    78
 * - Check next_in and next_out for Z_NULL on entry to inflate()
dvander@159
    79
 *
dvander@159
    80
 * The history for versions after 1.2.0 are in ChangeLog in zlib distribution.
dvander@159
    81
 */
dvander@159
    82
dvander@159
    83
#include "zutil.h"
dvander@159
    84
#include "inftrees.h"
dvander@159
    85
#include "inflate.h"
dvander@159
    86
#include "inffast.h"
dvander@159
    87
dvander@159
    88
#ifdef MAKEFIXED
dvander@159
    89
#  ifndef BUILDFIXED
dvander@159
    90
#    define BUILDFIXED
dvander@159
    91
#  endif
dvander@159
    92
#endif
dvander@159
    93
dvander@159
    94
/* function prototypes */
dvander@159
    95
local void fixedtables OF((struct inflate_state FAR *state));
dvander@159
    96
local int updatewindow OF((z_streamp strm, unsigned out));
dvander@159
    97
#ifdef BUILDFIXED
dvander@159
    98
   void makefixed OF((void));
dvander@159
    99
#endif
dvander@159
   100
local unsigned syncsearch OF((unsigned FAR *have, unsigned char FAR *buf,
dvander@159
   101
                              unsigned len));
dvander@159
   102
dvander@159
   103
int ZEXPORT inflateReset(strm)
dvander@159
   104
z_streamp strm;
dvander@159
   105
{
dvander@159
   106
    struct inflate_state FAR *state;
dvander@159
   107
dvander@159
   108
    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
dvander@159
   109
    state = (struct inflate_state FAR *)strm->state;
dvander@159
   110
    strm->total_in = strm->total_out = state->total = 0;
dvander@159
   111
    strm->msg = Z_NULL;
dvander@159
   112
    strm->adler = 1;        /* to support ill-conceived Java test suite */
dvander@159
   113
    state->mode = HEAD;
dvander@159
   114
    state->last = 0;
dvander@159
   115
    state->havedict = 0;
dvander@159
   116
    state->dmax = 32768U;
dvander@159
   117
    state->head = Z_NULL;
dvander@159
   118
    state->wsize = 0;
dvander@159
   119
    state->whave = 0;
dvander@159
   120
    state->write = 0;
dvander@159
   121
    state->hold = 0;
dvander@159
   122
    state->bits = 0;
dvander@159
   123
    state->lencode = state->distcode = state->next = state->codes;
dvander@159
   124
    Tracev((stderr, "inflate: reset\n"));
dvander@159
   125
    return Z_OK;
dvander@159
   126
}
dvander@159
   127
dvander@159
   128
int ZEXPORT inflatePrime(strm, bits, value)
dvander@159
   129
z_streamp strm;
dvander@159
   130
int bits;
dvander@159
   131
int value;
dvander@159
   132
{
dvander@159
   133
    struct inflate_state FAR *state;
dvander@159
   134
dvander@159
   135
    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
dvander@159
   136
    state = (struct inflate_state FAR *)strm->state;
dvander@159
   137
    if (bits > 16 || state->bits + bits > 32) return Z_STREAM_ERROR;
dvander@159
   138
    value &= (1L << bits) - 1;
dvander@159
   139
    state->hold += value << state->bits;
dvander@159
   140
    state->bits += bits;
dvander@159
   141
    return Z_OK;
dvander@159
   142
}
dvander@159
   143
dvander@159
   144
int ZEXPORT inflateInit2_(strm, windowBits, version, stream_size)
dvander@159
   145
z_streamp strm;
dvander@159
   146
int windowBits;
dvander@159
   147
const char *version;
dvander@159
   148
int stream_size;
dvander@159
   149
{
dvander@159
   150
    struct inflate_state FAR *state;
dvander@159
   151
dvander@159
   152
    if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
dvander@159
   153
        stream_size != (int)(sizeof(z_stream)))
dvander@159
   154
        return Z_VERSION_ERROR;
dvander@159
   155
    if (strm == Z_NULL) return Z_STREAM_ERROR;
dvander@159
   156
    strm->msg = Z_NULL;                 /* in case we return an error */
dvander@159
   157
    if (strm->zalloc == (alloc_func)0) {
dvander@159
   158
        strm->zalloc = zcalloc;
dvander@159
   159
        strm->opaque = (voidpf)0;
dvander@159
   160
    }
dvander@159
   161
    if (strm->zfree == (free_func)0) strm->zfree = zcfree;
dvander@159
   162
    state = (struct inflate_state FAR *)
dvander@159
   163
            ZALLOC(strm, 1, sizeof(struct inflate_state));
dvander@159
   164
    if (state == Z_NULL) return Z_MEM_ERROR;
dvander@159
   165
    Tracev((stderr, "inflate: allocated\n"));
dvander@159
   166
    strm->state = (struct internal_state FAR *)state;
dvander@159
   167
    if (windowBits < 0) {
dvander@159
   168
        state->wrap = 0;
dvander@159
   169
        windowBits = -windowBits;
dvander@159
   170
    }
dvander@159
   171
    else {
dvander@159
   172
        state->wrap = (windowBits >> 4) + 1;
dvander@159
   173
#ifdef GUNZIP
dvander@159
   174
        if (windowBits < 48) windowBits &= 15;
dvander@159
   175
#endif
dvander@159
   176
    }
dvander@159
   177
    if (windowBits < 8 || windowBits > 15) {
dvander@159
   178
        ZFREE(strm, state);
dvander@159
   179
        strm->state = Z_NULL;
dvander@159
   180
        return Z_STREAM_ERROR;
dvander@159
   181
    }
dvander@159
   182
    state->wbits = (unsigned)windowBits;
dvander@159
   183
    state->window = Z_NULL;
dvander@159
   184
    return inflateReset(strm);
dvander@159
   185
}
dvander@159
   186
dvander@159
   187
int ZEXPORT inflateInit_(strm, version, stream_size)
dvander@159
   188
z_streamp strm;
dvander@159
   189
const char *version;
dvander@159
   190
int stream_size;
dvander@159
   191
{
dvander@159
   192
    return inflateInit2_(strm, DEF_WBITS, version, stream_size);
dvander@159
   193
}
dvander@159
   194
dvander@159
   195
/*
dvander@159
   196
   Return state with length and distance decoding tables and index sizes set to
dvander@159
   197
   fixed code decoding.  Normally this returns fixed tables from inffixed.h.
dvander@159
   198
   If BUILDFIXED is defined, then instead this routine builds the tables the
dvander@159
   199
   first time it's called, and returns those tables the first time and
dvander@159
   200
   thereafter.  This reduces the size of the code by about 2K bytes, in
dvander@159
   201
   exchange for a little execution time.  However, BUILDFIXED should not be
dvander@159
   202
   used for threaded applications, since the rewriting of the tables and virgin
dvander@159
   203
   may not be thread-safe.
dvander@159
   204
 */
dvander@159
   205
local void fixedtables(state)
dvander@159
   206
struct inflate_state FAR *state;
dvander@159
   207
{
dvander@159
   208
#ifdef BUILDFIXED
dvander@159
   209
    static int virgin = 1;
dvander@159
   210
    static code *lenfix, *distfix;
dvander@159
   211
    static code fixed[544];
dvander@159
   212
dvander@159
   213
    /* build fixed huffman tables if first call (may not be thread safe) */
dvander@159
   214
    if (virgin) {
dvander@159
   215
        unsigned sym, bits;
dvander@159
   216
        static code *next;
dvander@159
   217
dvander@159
   218
        /* literal/length table */
dvander@159
   219
        sym = 0;
dvander@159
   220
        while (sym < 144) state->lens[sym++] = 8;
dvander@159
   221
        while (sym < 256) state->lens[sym++] = 9;
dvander@159
   222
        while (sym < 280) state->lens[sym++] = 7;
dvander@159
   223
        while (sym < 288) state->lens[sym++] = 8;
dvander@159
   224
        next = fixed;
dvander@159
   225
        lenfix = next;
dvander@159
   226
        bits = 9;
dvander@159
   227
        inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work);
dvander@159
   228
dvander@159
   229
        /* distance table */
dvander@159
   230
        sym = 0;
dvander@159
   231
        while (sym < 32) state->lens[sym++] = 5;
dvander@159
   232
        distfix = next;
dvander@159
   233
        bits = 5;
dvander@159
   234
        inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work);
dvander@159
   235
dvander@159
   236
        /* do this just once */
dvander@159
   237
        virgin = 0;
dvander@159
   238
    }
dvander@159
   239
#else /* !BUILDFIXED */
dvander@159
   240
#   include "inffixed.h"
dvander@159
   241
#endif /* BUILDFIXED */
dvander@159
   242
    state->lencode = lenfix;
dvander@159
   243
    state->lenbits = 9;
dvander@159
   244
    state->distcode = distfix;
dvander@159
   245
    state->distbits = 5;
dvander@159
   246
}
dvander@159
   247
dvander@159
   248
#ifdef MAKEFIXED
dvander@159
   249
#include <stdio.h>
dvander@159
   250
dvander@159
   251
/*
dvander@159
   252
   Write out the inffixed.h that is #include'd above.  Defining MAKEFIXED also
dvander@159
   253
   defines BUILDFIXED, so the tables are built on the fly.  makefixed() writes
dvander@159
   254
   those tables to stdout, which would be piped to inffixed.h.  A small program
dvander@159
   255
   can simply call makefixed to do this:
dvander@159
   256
dvander@159
   257
    void makefixed(void);
dvander@159
   258
dvander@159
   259
    int main(void)
dvander@159
   260
    {
dvander@159
   261
        makefixed();
dvander@159
   262
        return 0;
dvander@159
   263
    }
dvander@159
   264
dvander@159
   265
   Then that can be linked with zlib built with MAKEFIXED defined and run:
dvander@159
   266
dvander@159
   267
    a.out > inffixed.h
dvander@159
   268
 */
dvander@159
   269
void makefixed()
dvander@159
   270
{
dvander@159
   271
    unsigned low, size;
dvander@159
   272
    struct inflate_state state;
dvander@159
   273
dvander@159
   274
    fixedtables(&state);
dvander@159
   275
    puts("    /* inffixed.h -- table for decoding fixed codes");
dvander@159
   276
    puts("     * Generated automatically by makefixed().");
dvander@159
   277
    puts("     */");
dvander@159
   278
    puts("");
dvander@159
   279
    puts("    /* WARNING: this file should *not* be used by applications.");
dvander@159
   280
    puts("       It is part of the implementation of this library and is");
dvander@159
   281
    puts("       subject to change. Applications should only use zlib.h.");
dvander@159
   282
    puts("     */");
dvander@159
   283
    puts("");
dvander@159
   284
    size = 1U << 9;
dvander@159
   285
    printf("    static const code lenfix[%u] = {", size);
dvander@159
   286
    low = 0;
dvander@159
   287
    for (;;) {
dvander@159
   288
        if ((low % 7) == 0) printf("\n        ");
dvander@159
   289
        printf("{%u,%u,%d}", state.lencode[low].op, state.lencode[low].bits,
dvander@159
   290
               state.lencode[low].val);
dvander@159
   291
        if (++low == size) break;
dvander@159
   292
        putchar(',');
dvander@159
   293
    }
dvander@159
   294
    puts("\n    };");
dvander@159
   295
    size = 1U << 5;
dvander@159
   296
    printf("\n    static const code distfix[%u] = {", size);
dvander@159
   297
    low = 0;
dvander@159
   298
    for (;;) {
dvander@159
   299
        if ((low % 6) == 0) printf("\n        ");
dvander@159
   300
        printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits,
dvander@159
   301
               state.distcode[low].val);
dvander@159
   302
        if (++low == size) break;
dvander@159
   303
        putchar(',');
dvander@159
   304
    }
dvander@159
   305
    puts("\n    };");
dvander@159
   306
}
dvander@159
   307
#endif /* MAKEFIXED */
dvander@159
   308
dvander@159
   309
/*
dvander@159
   310
   Update the window with the last wsize (normally 32K) bytes written before
dvander@159
   311
   returning.  If window does not exist yet, create it.  This is only called
dvander@159
   312
   when a window is already in use, or when output has been written during this
dvander@159
   313
   inflate call, but the end of the deflate stream has not been reached yet.
dvander@159
   314
   It is also called to create a window for dictionary data when a dictionary
dvander@159
   315
   is loaded.
dvander@159
   316
dvander@159
   317
   Providing output buffers larger than 32K to inflate() should provide a speed
dvander@159
   318
   advantage, since only the last 32K of output is copied to the sliding window
dvander@159
   319
   upon return from inflate(), and since all distances after the first 32K of
dvander@159
   320
   output will fall in the output data, making match copies simpler and faster.
dvander@159
   321
   The advantage may be dependent on the size of the processor's data caches.
dvander@159
   322
 */
dvander@159
   323
local int updatewindow(strm, out)
dvander@159
   324
z_streamp strm;
dvander@159
   325
unsigned out;
dvander@159
   326
{
dvander@159
   327
    struct inflate_state FAR *state;
dvander@159
   328
    unsigned copy, dist;
dvander@159
   329
dvander@159
   330
    state = (struct inflate_state FAR *)strm->state;
dvander@159
   331
dvander@159
   332
    /* if it hasn't been done already, allocate space for the window */
dvander@159
   333
    if (state->window == Z_NULL) {
dvander@159
   334
        state->window = (unsigned char FAR *)
dvander@159
   335
                        ZALLOC(strm, 1U << state->wbits,
dvander@159
   336
                               sizeof(unsigned char));
dvander@159
   337
        if (state->window == Z_NULL) return 1;
dvander@159
   338
    }
dvander@159
   339
dvander@159
   340
    /* if window not in use yet, initialize */
dvander@159
   341
    if (state->wsize == 0) {
dvander@159
   342
        state->wsize = 1U << state->wbits;
dvander@159
   343
        state->write = 0;
dvander@159
   344
        state->whave = 0;
dvander@159
   345
    }
dvander@159
   346
dvander@159
   347
    /* copy state->wsize or less output bytes into the circular window */
dvander@159
   348
    copy = out - strm->avail_out;
dvander@159
   349
    if (copy >= state->wsize) {
dvander@159
   350
        zmemcpy(state->window, strm->next_out - state->wsize, state->wsize);
dvander@159
   351
        state->write = 0;
dvander@159
   352
        state->whave = state->wsize;
dvander@159
   353
    }
dvander@159
   354
    else {
dvander@159
   355
        dist = state->wsize - state->write;
dvander@159
   356
        if (dist > copy) dist = copy;
dvander@159
   357
        zmemcpy(state->window + state->write, strm->next_out - copy, dist);
dvander@159
   358
        copy -= dist;
dvander@159
   359
        if (copy) {
dvander@159
   360
            zmemcpy(state->window, strm->next_out - copy, copy);
dvander@159
   361
            state->write = copy;
dvander@159
   362
            state->whave = state->wsize;
dvander@159
   363
        }
dvander@159
   364
        else {
dvander@159
   365
            state->write += dist;
dvander@159
   366
            if (state->write == state->wsize) state->write = 0;
dvander@159
   367
            if (state->whave < state->wsize) state->whave += dist;
dvander@159
   368
        }
dvander@159
   369
    }
dvander@159
   370
    return 0;
dvander@159
   371
}
dvander@159
   372
dvander@159
   373
/* Macros for inflate(): */
dvander@159
   374
dvander@159
   375
/* check function to use adler32() for zlib or crc32() for gzip */
dvander@159
   376
#ifdef GUNZIP
dvander@159
   377
#  define UPDATE(check, buf, len) \
dvander@159
   378
    (state->flags ? crc32(check, buf, len) : adler32(check, buf, len))
dvander@159
   379
#else
dvander@159
   380
#  define UPDATE(check, buf, len) adler32(check, buf, len)
dvander@159
   381
#endif
dvander@159
   382
dvander@159
   383
/* check macros for header crc */
dvander@159
   384
#ifdef GUNZIP
dvander@159
   385
#  define CRC2(check, word) \
dvander@159
   386
    do { \
dvander@159
   387
        hbuf[0] = (unsigned char)(word); \
dvander@159
   388
        hbuf[1] = (unsigned char)((word) >> 8); \
dvander@159
   389
        check = crc32(check, hbuf, 2); \
dvander@159
   390
    } while (0)
dvander@159
   391
dvander@159
   392
#  define CRC4(check, word) \
dvander@159
   393
    do { \
dvander@159
   394
        hbuf[0] = (unsigned char)(word); \
dvander@159
   395
        hbuf[1] = (unsigned char)((word) >> 8); \
dvander@159
   396
        hbuf[2] = (unsigned char)((word) >> 16); \
dvander@159
   397
        hbuf[3] = (unsigned char)((word) >> 24); \
dvander@159
   398
        check = crc32(check, hbuf, 4); \
dvander@159
   399
    } while (0)
dvander@159
   400
#endif
dvander@159
   401
dvander@159
   402
/* Load registers with state in inflate() for speed */
dvander@159
   403
#define LOAD() \
dvander@159
   404
    do { \
dvander@159
   405
        put = strm->next_out; \
dvander@159
   406
        left = strm->avail_out; \
dvander@159
   407
        next = strm->next_in; \
dvander@159
   408
        have = strm->avail_in; \
dvander@159
   409
        hold = state->hold; \
dvander@159
   410
        bits = state->bits; \
dvander@159
   411
    } while (0)
dvander@159
   412
dvander@159
   413
/* Restore state from registers in inflate() */
dvander@159
   414
#define RESTORE() \
dvander@159
   415
    do { \
dvander@159
   416
        strm->next_out = put; \
dvander@159
   417
        strm->avail_out = left; \
dvander@159
   418
        strm->next_in = next; \
dvander@159
   419
        strm->avail_in = have; \
dvander@159
   420
        state->hold = hold; \
dvander@159
   421
        state->bits = bits; \
dvander@159
   422
    } while (0)
dvander@159
   423
dvander@159
   424
/* Clear the input bit accumulator */
dvander@159
   425
#define INITBITS() \
dvander@159
   426
    do { \
dvander@159
   427
        hold = 0; \
dvander@159
   428
        bits = 0; \
dvander@159
   429
    } while (0)
dvander@159
   430
dvander@159
   431
/* Get a byte of input into the bit accumulator, or return from inflate()
dvander@159
   432
   if there is no input available. */
dvander@159
   433
#define PULLBYTE() \
dvander@159
   434
    do { \
dvander@159
   435
        if (have == 0) goto inf_leave; \
dvander@159
   436
        have--; \
dvander@159
   437
        hold += (unsigned long)(*next++) << bits; \
dvander@159
   438
        bits += 8; \
dvander@159
   439
    } while (0)
dvander@159
   440
dvander@159
   441
/* Assure that there are at least n bits in the bit accumulator.  If there is
dvander@159
   442
   not enough available input to do that, then return from inflate(). */
dvander@159
   443
#define NEEDBITS(n) \
dvander@159
   444
    do { \
dvander@159
   445
        while (bits < (unsigned)(n)) \
dvander@159
   446
            PULLBYTE(); \
dvander@159
   447
    } while (0)
dvander@159
   448
dvander@159
   449
/* Return the low n bits of the bit accumulator (n < 16) */
dvander@159
   450
#define BITS(n) \
dvander@159
   451
    ((unsigned)hold & ((1U << (n)) - 1))
dvander@159
   452
dvander@159
   453
/* Remove n bits from the bit accumulator */
dvander@159
   454
#define DROPBITS(n) \
dvander@159
   455
    do { \
dvander@159
   456
        hold >>= (n); \
dvander@159
   457
        bits -= (unsigned)(n); \
dvander@159
   458
    } while (0)
dvander@159
   459
dvander@159
   460
/* Remove zero to seven bits as needed to go to a byte boundary */
dvander@159
   461
#define BYTEBITS() \
dvander@159
   462
    do { \
dvander@159
   463
        hold >>= bits & 7; \
dvander@159
   464
        bits -= bits & 7; \
dvander@159
   465
    } while (0)
dvander@159
   466
dvander@159
   467
/* Reverse the bytes in a 32-bit value */
dvander@159
   468
#define REVERSE(q) \
dvander@159
   469
    ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \
dvander@159
   470
     (((q) & 0xff00) << 8) + (((q) & 0xff) << 24))
dvander@159
   471
dvander@159
   472
/*
dvander@159
   473
   inflate() uses a state machine to process as much input data and generate as
dvander@159
   474
   much output data as possible before returning.  The state machine is
dvander@159
   475
   structured roughly as follows:
dvander@159
   476
dvander@159
   477
    for (;;) switch (state) {
dvander@159
   478
    ...
dvander@159
   479
    case STATEn:
dvander@159
   480
        if (not enough input data or output space to make progress)
dvander@159
   481
            return;
dvander@159
   482
        ... make progress ...
dvander@159
   483
        state = STATEm;
dvander@159
   484
        break;
dvander@159
   485
    ...
dvander@159
   486
    }
dvander@159
   487
dvander@159
   488
   so when inflate() is called again, the same case is attempted again, and
dvander@159
   489
   if the appropriate resources are provided, the machine proceeds to the
dvander@159
   490
   next state.  The NEEDBITS() macro is usually the way the state evaluates
dvander@159
   491
   whether it can proceed or should return.  NEEDBITS() does the return if
dvander@159
   492
   the requested bits are not available.  The typical use of the BITS macros
dvander@159
   493
   is:
dvander@159
   494
dvander@159
   495
        NEEDBITS(n);
dvander@159
   496
        ... do something with BITS(n) ...
dvander@159
   497
        DROPBITS(n);
dvander@159
   498
dvander@159
   499
   where NEEDBITS(n) either returns from inflate() if there isn't enough
dvander@159
   500
   input left to load n bits into the accumulator, or it continues.  BITS(n)
dvander@159
   501
   gives the low n bits in the accumulator.  When done, DROPBITS(n) drops
dvander@159
   502
   the low n bits off the accumulator.  INITBITS() clears the accumulator
dvander@159
   503
   and sets the number of available bits to zero.  BYTEBITS() discards just
dvander@159
   504
   enough bits to put the accumulator on a byte boundary.  After BYTEBITS()
dvander@159
   505
   and a NEEDBITS(8), then BITS(8) would return the next byte in the stream.
dvander@159
   506
dvander@159
   507
   NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return
dvander@159
   508
   if there is no input available.  The decoding of variable length codes uses
dvander@159
   509
   PULLBYTE() directly in order to pull just enough bytes to decode the next
dvander@159
   510
   code, and no more.
dvander@159
   511
dvander@159
   512
   Some states loop until they get enough input, making sure that enough
dvander@159
   513
   state information is maintained to continue the loop where it left off
dvander@159
   514
   if NEEDBITS() returns in the loop.  For example, want, need, and keep
dvander@159
   515
   would all have to actually be part of the saved state in case NEEDBITS()
dvander@159
   516
   returns:
dvander@159
   517
dvander@159
   518
    case STATEw:
dvander@159
   519
        while (want < need) {
dvander@159
   520
            NEEDBITS(n);
dvander@159
   521
            keep[want++] = BITS(n);
dvander@159
   522
            DROPBITS(n);
dvander@159
   523
        }
dvander@159
   524
        state = STATEx;
dvander@159
   525
    case STATEx:
dvander@159
   526
dvander@159
   527
   As shown above, if the next state is also the next case, then the break
dvander@159
   528
   is omitted.
dvander@159
   529
dvander@159
   530
   A state may also return if there is not enough output space available to
dvander@159
   531
   complete that state.  Those states are copying stored data, writing a
dvander@159
   532
   literal byte, and copying a matching string.
dvander@159
   533
dvander@159
   534
   When returning, a "goto inf_leave" is used to update the total counters,
dvander@159
   535
   update the check value, and determine whether any progress has been made
dvander@159
   536
   during that inflate() call in order to return the proper return code.
dvander@159
   537
   Progress is defined as a change in either strm->avail_in or strm->avail_out.
dvander@159
   538
   When there is a window, goto inf_leave will update the window with the last
dvander@159
   539
   output written.  If a goto inf_leave occurs in the middle of decompression
dvander@159
   540
   and there is no window currently, goto inf_leave will create one and copy
dvander@159
   541
   output to the window for the next call of inflate().
dvander@159
   542
dvander@159
   543
   In this implementation, the flush parameter of inflate() only affects the
dvander@159
   544
   return code (per zlib.h).  inflate() always writes as much as possible to
dvander@159
   545
   strm->next_out, given the space available and the provided input--the effect
dvander@159
   546
   documented in zlib.h of Z_SYNC_FLUSH.  Furthermore, inflate() always defers
dvander@159
   547
   the allocation of and copying into a sliding window until necessary, which
dvander@159
   548
   provides the effect documented in zlib.h for Z_FINISH when the entire input
dvander@159
   549
   stream available.  So the only thing the flush parameter actually does is:
dvander@159
   550
   when flush is set to Z_FINISH, inflate() cannot return Z_OK.  Instead it
dvander@159
   551
   will return Z_BUF_ERROR if it has not reached the end of the stream.
dvander@159
   552
 */
dvander@159
   553
dvander@159
   554
int ZEXPORT inflate(strm, flush)
dvander@159
   555
z_streamp strm;
dvander@159
   556
int flush;
dvander@159
   557
{
dvander@159
   558
    struct inflate_state FAR *state;
dvander@159
   559
    unsigned char FAR *next;    /* next input */
dvander@159
   560
    unsigned char FAR *put;     /* next output */
dvander@159
   561
    unsigned have, left;        /* available input and output */
dvander@159
   562
    unsigned long hold;         /* bit buffer */
dvander@159
   563
    unsigned bits;              /* bits in bit buffer */
dvander@159
   564
    unsigned in, out;           /* save starting available input and output */
dvander@159
   565
    unsigned copy;              /* number of stored or match bytes to copy */
dvander@159
   566
    unsigned char FAR *from;    /* where to copy match bytes from */
dvander@159
   567
    code this;                  /* current decoding table entry */
dvander@159
   568
    code last;                  /* parent table entry */
dvander@159
   569
    unsigned len;               /* length to copy for repeats, bits to drop */
dvander@159
   570
    int ret;                    /* return code */
dvander@159
   571
#ifdef GUNZIP
dvander@159
   572
    unsigned char hbuf[4];      /* buffer for gzip header crc calculation */
dvander@159
   573
#endif
dvander@159
   574
    static const unsigned short order[19] = /* permutation of code lengths */
dvander@159
   575
        {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
dvander@159
   576
dvander@159
   577
    if (strm == Z_NULL || strm->state == Z_NULL || strm->next_out == Z_NULL ||
dvander@159
   578
        (strm->next_in == Z_NULL && strm->avail_in != 0))
dvander@159
   579
        return Z_STREAM_ERROR;
dvander@159
   580
dvander@159
   581
    state = (struct inflate_state FAR *)strm->state;
dvander@159
   582
    if (state->mode == TYPE) state->mode = TYPEDO;      /* skip check */
dvander@159
   583
    LOAD();
dvander@159
   584
    in = have;
dvander@159
   585
    out = left;
dvander@159
   586
    ret = Z_OK;
dvander@159
   587
    for (;;)
dvander@159
   588
        switch (state->mode) {
dvander@159
   589
        case HEAD:
dvander@159
   590
            if (state->wrap == 0) {
dvander@159
   591
                state->mode = TYPEDO;
dvander@159
   592
                break;
dvander@159
   593
            }
dvander@159
   594
            NEEDBITS(16);
dvander@159
   595
#ifdef GUNZIP
dvander@159
   596
            if ((state->wrap & 2) && hold == 0x8b1f) {  /* gzip header */
dvander@159
   597
                state->check = crc32(0L, Z_NULL, 0);
dvander@159
   598
                CRC2(state->check, hold);
dvander@159
   599
                INITBITS();
dvander@159
   600
                state->mode = FLAGS;
dvander@159
   601
                break;
dvander@159
   602
            }
dvander@159
   603
            state->flags = 0;           /* expect zlib header */
dvander@159
   604
            if (state->head != Z_NULL)
dvander@159
   605
                state->head->done = -1;
dvander@159
   606
            if (!(state->wrap & 1) ||   /* check if zlib header allowed */
dvander@159
   607
#else
dvander@159
   608
            if (
dvander@159
   609
#endif
dvander@159
   610
                ((BITS(8) << 8) + (hold >> 8)) % 31) {
dvander@159
   611
                strm->msg = (char *)"incorrect header check";
dvander@159
   612
                state->mode = BAD;
dvander@159
   613
                break;
dvander@159
   614
            }
dvander@159
   615
            if (BITS(4) != Z_DEFLATED) {
dvander@159
   616
                strm->msg = (char *)"unknown compression method";
dvander@159
   617
                state->mode = BAD;
dvander@159
   618
                break;
dvander@159
   619
            }
dvander@159
   620
            DROPBITS(4);
dvander@159
   621
            len = BITS(4) + 8;
dvander@159
   622
            if (len > state->wbits) {
dvander@159
   623
                strm->msg = (char *)"invalid window size";
dvander@159
   624
                state->mode = BAD;
dvander@159
   625
                break;
dvander@159
   626
            }
dvander@159
   627
            state->dmax = 1U << len;
dvander@159
   628
            Tracev((stderr, "inflate:   zlib header ok\n"));
dvander@159
   629
            strm->adler = state->check = adler32(0L, Z_NULL, 0);
dvander@159
   630
            state->mode = hold & 0x200 ? DICTID : TYPE;
dvander@159
   631
            INITBITS();
dvander@159
   632
            break;
dvander@159
   633
#ifdef GUNZIP
dvander@159
   634
        case FLAGS:
dvander@159
   635
            NEEDBITS(16);
dvander@159
   636
            state->flags = (int)(hold);
dvander@159
   637
            if ((state->flags & 0xff) != Z_DEFLATED) {
dvander@159
   638
                strm->msg = (char *)"unknown compression method";
dvander@159
   639
                state->mode = BAD;
dvander@159
   640
                break;
dvander@159
   641
            }
dvander@159
   642
            if (state->flags & 0xe000) {
dvander@159
   643
                strm->msg = (char *)"unknown header flags set";
dvander@159
   644
                state->mode = BAD;
dvander@159
   645
                break;
dvander@159
   646
            }
dvander@159
   647
            if (state->head != Z_NULL)
dvander@159
   648
                state->head->text = (int)((hold >> 8) & 1);
dvander@159
   649
            if (state->flags & 0x0200) CRC2(state->check, hold);
dvander@159
   650
            INITBITS();
dvander@159
   651
            state->mode = TIME;
dvander@159
   652
        case TIME:
dvander@159
   653
            NEEDBITS(32);
dvander@159
   654
            if (state->head != Z_NULL)
dvander@159
   655
                state->head->time = hold;
dvander@159
   656
            if (state->flags & 0x0200) CRC4(state->check, hold);
dvander@159
   657
            INITBITS();
dvander@159
   658
            state->mode = OS;
dvander@159
   659
        case OS:
dvander@159
   660
            NEEDBITS(16);
dvander@159
   661
            if (state->head != Z_NULL) {
dvander@159
   662
                state->head->xflags = (int)(hold & 0xff);
dvander@159
   663
                state->head->os = (int)(hold >> 8);
dvander@159
   664
            }
dvander@159
   665
            if (state->flags & 0x0200) CRC2(state->check, hold);
dvander@159
   666
            INITBITS();
dvander@159
   667
            state->mode = EXLEN;
dvander@159
   668
        case EXLEN:
dvander@159
   669
            if (state->flags & 0x0400) {
dvander@159
   670
                NEEDBITS(16);
dvander@159
   671
                state->length = (unsigned)(hold);
dvander@159
   672
                if (state->head != Z_NULL)
dvander@159
   673
                    state->head->extra_len = (unsigned)hold;
dvander@159
   674
                if (state->flags & 0x0200) CRC2(state->check, hold);
dvander@159
   675
                INITBITS();
dvander@159
   676
            }
dvander@159
   677
            else if (state->head != Z_NULL)
dvander@159
   678
                state->head->extra = Z_NULL;
dvander@159
   679
            state->mode = EXTRA;
dvander@159
   680
        case EXTRA:
dvander@159
   681
            if (state->flags & 0x0400) {
dvander@159
   682
                copy = state->length;
dvander@159
   683
                if (copy > have) copy = have;
dvander@159
   684
                if (copy) {
dvander@159
   685
                    if (state->head != Z_NULL &&
dvander@159
   686
                        state->head->extra != Z_NULL) {
dvander@159
   687
                        len = state->head->extra_len - state->length;
dvander@159
   688
                        zmemcpy(state->head->extra + len, next,
dvander@159
   689
                                len + copy > state->head->extra_max ?
dvander@159
   690
                                state->head->extra_max - len : copy);
dvander@159
   691
                    }
dvander@159
   692
                    if (state->flags & 0x0200)
dvander@159
   693
                        state->check = crc32(state->check, next, copy);
dvander@159
   694
                    have -= copy;
dvander@159
   695
                    next += copy;
dvander@159
   696
                    state->length -= copy;
dvander@159
   697
                }
dvander@159
   698
                if (state->length) goto inf_leave;
dvander@159
   699
            }
dvander@159
   700
            state->length = 0;
dvander@159
   701
            state->mode = NAME;
dvander@159
   702
        case NAME:
dvander@159
   703
            if (state->flags & 0x0800) {
dvander@159
   704
                if (have == 0) goto inf_leave;
dvander@159
   705
                copy = 0;
dvander@159
   706
                do {
dvander@159
   707
                    len = (unsigned)(next[copy++]);
dvander@159
   708
                    if (state->head != Z_NULL &&
dvander@159
   709
                            state->head->name != Z_NULL &&
dvander@159
   710
                            state->length < state->head->name_max)
dvander@159
   711
                        state->head->name[state->length++] = len;
dvander@159
   712
                } while (len && copy < have);
dvander@159
   713
                if (state->flags & 0x0200)
dvander@159
   714
                    state->check = crc32(state->check, next, copy);
dvander@159
   715
                have -= copy;
dvander@159
   716
                next += copy;
dvander@159
   717
                if (len) goto inf_leave;
dvander@159
   718
            }
dvander@159
   719
            else if (state->head != Z_NULL)
dvander@159
   720
                state->head->name = Z_NULL;
dvander@159
   721
            state->length = 0;
dvander@159
   722
            state->mode = COMMENT;
dvander@159
   723
        case COMMENT:
dvander@159
   724
            if (state->flags & 0x1000) {
dvander@159
   725
                if (have == 0) goto inf_leave;
dvander@159
   726
                copy = 0;
dvander@159
   727
                do {
dvander@159
   728
                    len = (unsigned)(next[copy++]);
dvander@159
   729
                    if (state->head != Z_NULL &&
dvander@159
   730
                            state->head->comment != Z_NULL &&
dvander@159
   731
                            state->length < state->head->comm_max)
dvander@159
   732
                        state->head->comment[state->length++] = len;
dvander@159
   733
                } while (len && copy < have);
dvander@159
   734
                if (state->flags & 0x0200)
dvander@159
   735
                    state->check = crc32(state->check, next, copy);
dvander@159
   736
                have -= copy;
dvander@159
   737
                next += copy;
dvander@159
   738
                if (len) goto inf_leave;
dvander@159
   739
            }
dvander@159
   740
            else if (state->head != Z_NULL)
dvander@159
   741
                state->head->comment = Z_NULL;
dvander@159
   742
            state->mode = HCRC;
dvander@159
   743
        case HCRC:
dvander@159
   744
            if (state->flags & 0x0200) {
dvander@159
   745
                NEEDBITS(16);
dvander@159
   746
                if (hold != (state->check & 0xffff)) {
dvander@159
   747
                    strm->msg = (char *)"header crc mismatch";
dvander@159
   748
                    state->mode = BAD;
dvander@159
   749
                    break;
dvander@159
   750
                }
dvander@159
   751
                INITBITS();
dvander@159
   752
            }
dvander@159
   753
            if (state->head != Z_NULL) {
dvander@159
   754
                state->head->hcrc = (int)((state->flags >> 9) & 1);
dvander@159
   755
                state->head->done = 1;
dvander@159
   756
            }
dvander@159
   757
            strm->adler = state->check = crc32(0L, Z_NULL, 0);
dvander@159
   758
            state->mode = TYPE;
dvander@159
   759
            break;
dvander@159
   760
#endif
dvander@159
   761
        case DICTID:
dvander@159
   762
            NEEDBITS(32);
dvander@159
   763
            strm->adler = state->check = REVERSE(hold);
dvander@159
   764
            INITBITS();
dvander@159
   765
            state->mode = DICT;
dvander@159
   766
        case DICT:
dvander@159
   767
            if (state->havedict == 0) {
dvander@159
   768
                RESTORE();
dvander@159
   769
                return Z_NEED_DICT;
dvander@159
   770
            }
dvander@159
   771
            strm->adler = state->check = adler32(0L, Z_NULL, 0);
dvander@159
   772
            state->mode = TYPE;
dvander@159
   773
        case TYPE:
dvander@159
   774
            if (flush == Z_BLOCK) goto inf_leave;
dvander@159
   775
        case TYPEDO:
dvander@159
   776
            if (state->last) {
dvander@159
   777
                BYTEBITS();
dvander@159
   778
                state->mode = CHECK;
dvander@159
   779
                break;
dvander@159
   780
            }
dvander@159
   781
            NEEDBITS(3);
dvander@159
   782
            state->last = BITS(1);
dvander@159
   783
            DROPBITS(1);
dvander@159
   784
            switch (BITS(2)) {
dvander@159
   785
            case 0:                             /* stored block */
dvander@159
   786
                Tracev((stderr, "inflate:     stored block%s\n",
dvander@159
   787
                        state->last ? " (last)" : ""));
dvander@159
   788
                state->mode = STORED;
dvander@159
   789
                break;
dvander@159
   790
            case 1:                             /* fixed block */
dvander@159
   791
                fixedtables(state);
dvander@159
   792
                Tracev((stderr, "inflate:     fixed codes block%s\n",
dvander@159
   793
                        state->last ? " (last)" : ""));
dvander@159
   794
                state->mode = LEN;              /* decode codes */
dvander@159
   795
                break;
dvander@159
   796
            case 2:                             /* dynamic block */
dvander@159
   797
                Tracev((stderr, "inflate:     dynamic codes block%s\n",
dvander@159
   798
                        state->last ? " (last)" : ""));
dvander@159
   799
                state->mode = TABLE;
dvander@159
   800
                break;
dvander@159
   801
            case 3:
dvander@159
   802
                strm->msg = (char *)"invalid block type";
dvander@159
   803
                state->mode = BAD;
dvander@159
   804
            }
dvander@159
   805
            DROPBITS(2);
dvander@159
   806
            break;
dvander@159
   807
        case STORED:
dvander@159
   808
            BYTEBITS();                         /* go to byte boundary */
dvander@159
   809
            NEEDBITS(32);
dvander@159
   810
            if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
dvander@159
   811
                strm->msg = (char *)"invalid stored block lengths";
dvander@159
   812
                state->mode = BAD;
dvander@159
   813
                break;
dvander@159
   814
            }
dvander@159
   815
            state->length = (unsigned)hold & 0xffff;
dvander@159
   816
            Tracev((stderr, "inflate:       stored length %u\n",
dvander@159
   817
                    state->length));
dvander@159
   818
            INITBITS();
dvander@159
   819
            state->mode = COPY;
dvander@159
   820
        case COPY:
dvander@159
   821
            copy = state->length;
dvander@159
   822
            if (copy) {
dvander@159
   823
                if (copy > have) copy = have;
dvander@159
   824
                if (copy > left) copy = left;
dvander@159
   825
                if (copy == 0) goto inf_leave;
dvander@159
   826
                zmemcpy(put, next, copy);
dvander@159
   827
                have -= copy;
dvander@159
   828
                next += copy;
dvander@159
   829
                left -= copy;
dvander@159
   830
                put += copy;
dvander@159
   831
                state->length -= copy;
dvander@159
   832
                break;
dvander@159
   833
            }
dvander@159
   834
            Tracev((stderr, "inflate:       stored end\n"));
dvander@159
   835
            state->mode = TYPE;
dvander@159
   836
            break;
dvander@159
   837
        case TABLE:
dvander@159
   838
            NEEDBITS(14);
dvander@159
   839
            state->nlen = BITS(5) + 257;
dvander@159
   840
            DROPBITS(5);
dvander@159
   841
            state->ndist = BITS(5) + 1;
dvander@159
   842
            DROPBITS(5);
dvander@159
   843
            state->ncode = BITS(4) + 4;
dvander@159
   844
            DROPBITS(4);
dvander@159
   845
#ifndef PKZIP_BUG_WORKAROUND
dvander@159
   846
            if (state->nlen > 286 || state->ndist > 30) {
dvander@159
   847
                strm->msg = (char *)"too many length or distance symbols";
dvander@159
   848
                state->mode = BAD;
dvander@159
   849
                break;
dvander@159
   850
            }
dvander@159
   851
#endif
dvander@159
   852
            Tracev((stderr, "inflate:       table sizes ok\n"));
dvander@159
   853
            state->have = 0;
dvander@159
   854
            state->mode = LENLENS;
dvander@159
   855
        case LENLENS:
dvander@159
   856
            while (state->have < state->ncode) {
dvander@159
   857
                NEEDBITS(3);
dvander@159
   858
                state->lens[order[state->have++]] = (unsigned short)BITS(3);
dvander@159
   859
                DROPBITS(3);
dvander@159
   860
            }
dvander@159
   861
            while (state->have < 19)
dvander@159
   862
                state->lens[order[state->have++]] = 0;
dvander@159
   863
            state->next = state->codes;
dvander@159
   864
            state->lencode = (code const FAR *)(state->next);
dvander@159
   865
            state->lenbits = 7;
dvander@159
   866
            ret = inflate_table(CODES, state->lens, 19, &(state->next),
dvander@159
   867
                                &(state->lenbits), state->work);
dvander@159
   868
            if (ret) {
dvander@159
   869
                strm->msg = (char *)"invalid code lengths set";
dvander@159
   870
                state->mode = BAD;
dvander@159
   871
                break;
dvander@159
   872
            }
dvander@159
   873
            Tracev((stderr, "inflate:       code lengths ok\n"));
dvander@159
   874
            state->have = 0;
dvander@159
   875
            state->mode = CODELENS;
dvander@159
   876
        case CODELENS:
dvander@159
   877
            while (state->have < state->nlen + state->ndist) {
dvander@159
   878
                for (;;) {
dvander@159
   879
                    this = state->lencode[BITS(state->lenbits)];
dvander@159
   880
                    if ((unsigned)(this.bits) <= bits) break;
dvander@159
   881
                    PULLBYTE();
dvander@159
   882
                }
dvander@159
   883
                if (this.val < 16) {
dvander@159
   884
                    NEEDBITS(this.bits);
dvander@159
   885
                    DROPBITS(this.bits);
dvander@159
   886
                    state->lens[state->have++] = this.val;
dvander@159
   887
                }
dvander@159
   888
                else {
dvander@159
   889
                    if (this.val == 16) {
dvander@159
   890
                        NEEDBITS(this.bits + 2);
dvander@159
   891
                        DROPBITS(this.bits);
dvander@159
   892
                        if (state->have == 0) {
dvander@159
   893
                            strm->msg = (char *)"invalid bit length repeat";
dvander@159
   894
                            state->mode = BAD;
dvander@159
   895
                            break;
dvander@159
   896
                        }
dvander@159
   897
                        len = state->lens[state->have - 1];
dvander@159
   898
                        copy = 3 + BITS(2);
dvander@159
   899
                        DROPBITS(2);
dvander@159
   900
                    }
dvander@159
   901
                    else if (this.val == 17) {
dvander@159
   902
                        NEEDBITS(this.bits + 3);
dvander@159
   903
                        DROPBITS(this.bits);
dvander@159
   904
                        len = 0;
dvander@159
   905
                        copy = 3 + BITS(3);
dvander@159
   906
                        DROPBITS(3);
dvander@159
   907
                    }
dvander@159
   908
                    else {
dvander@159
   909
                        NEEDBITS(this.bits + 7);
dvander@159
   910
                        DROPBITS(this.bits);
dvander@159
   911
                        len = 0;
dvander@159
   912
                        copy = 11 + BITS(7);
dvander@159
   913
                        DROPBITS(7);
dvander@159
   914
                    }
dvander@159
   915
                    if (state->have + copy > state->nlen + state->ndist) {
dvander@159
   916
                        strm->msg = (char *)"invalid bit length repeat";
dvander@159
   917
                        state->mode = BAD;
dvander@159
   918
                        break;
dvander@159
   919
                    }
dvander@159
   920
                    while (copy--)
dvander@159
   921
                        state->lens[state->have++] = (unsigned short)len;
dvander@159
   922
                }
dvander@159
   923
            }
dvander@159
   924
dvander@159
   925
            /* handle error breaks in while */
dvander@159
   926
            if (state->mode == BAD) break;
dvander@159
   927
dvander@159
   928
            /* build code tables */
dvander@159
   929
            state->next = state->codes;
dvander@159
   930
            state->lencode = (code const FAR *)(state->next);
dvander@159
   931
            state->lenbits = 9;
dvander@159
   932
            ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
dvander@159
   933
                                &(state->lenbits), state->work);
dvander@159
   934
            if (ret) {
dvander@159
   935
                strm->msg = (char *)"invalid literal/lengths set";
dvander@159
   936
                state->mode = BAD;
dvander@159
   937
                break;
dvander@159
   938
            }
dvander@159
   939
            state->distcode = (code const FAR *)(state->next);
dvander@159
   940
            state->distbits = 6;
dvander@159
   941
            ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
dvander@159
   942
                            &(state->next), &(state->distbits), state->work);
dvander@159
   943
            if (ret) {
dvander@159
   944
                strm->msg = (char *)"invalid distances set";
dvander@159
   945
                state->mode = BAD;
dvander@159
   946
                break;
dvander@159
   947
            }
dvander@159
   948
            Tracev((stderr, "inflate:       codes ok\n"));
dvander@159
   949
            state->mode = LEN;
dvander@159
   950
        case LEN:
dvander@159
   951
            if (have >= 6 && left >= 258) {
dvander@159
   952
                RESTORE();
dvander@159
   953
                inflate_fast(strm, out);
dvander@159
   954
                LOAD();
dvander@159
   955
                break;
dvander@159
   956
            }
dvander@159
   957
            for (;;) {
dvander@159
   958
                this = state->lencode[BITS(state->lenbits)];
dvander@159
   959
                if ((unsigned)(this.bits) <= bits) break;
dvander@159
   960
                PULLBYTE();
dvander@159
   961
            }
dvander@159
   962
            if (this.op && (this.op & 0xf0) == 0) {
dvander@159
   963
                last = this;
dvander@159
   964
                for (;;) {
dvander@159
   965
                    this = state->lencode[last.val +
dvander@159
   966
                            (BITS(last.bits + last.op) >> last.bits)];
dvander@159
   967
                    if ((unsigned)(last.bits + this.bits) <= bits) break;
dvander@159
   968
                    PULLBYTE();
dvander@159
   969
                }
dvander@159
   970
                DROPBITS(last.bits);
dvander@159
   971
            }
dvander@159
   972
            DROPBITS(this.bits);
dvander@159
   973
            state->length = (unsigned)this.val;
dvander@159
   974
            if ((int)(this.op) == 0) {
dvander@159
   975
                Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ?
dvander@159
   976
                        "inflate:         literal '%c'\n" :
dvander@159
   977
                        "inflate:         literal 0x%02x\n", this.val));
dvander@159
   978
                state->mode = LIT;
dvander@159
   979
                break;
dvander@159
   980
            }
dvander@159
   981
            if (this.op & 32) {
dvander@159
   982
                Tracevv((stderr, "inflate:         end of block\n"));
dvander@159
   983
                state->mode = TYPE;
dvander@159
   984
                break;
dvander@159
   985
            }
dvander@159
   986
            if (this.op & 64) {
dvander@159
   987
                strm->msg = (char *)"invalid literal/length code";
dvander@159
   988
                state->mode = BAD;
dvander@159
   989
                break;
dvander@159
   990
            }
dvander@159
   991
            state->extra = (unsigned)(this.op) & 15;
dvander@159
   992
            state->mode = LENEXT;
dvander@159
   993
        case LENEXT:
dvander@159
   994
            if (state->extra) {
dvander@159
   995
                NEEDBITS(state->extra);
dvander@159
   996
                state->length += BITS(state->extra);
dvander@159
   997
                DROPBITS(state->extra);
dvander@159
   998
            }
dvander@159
   999
            Tracevv((stderr, "inflate:         length %u\n", state->length));
dvander@159
  1000
            state->mode = DIST;
dvander@159
  1001
        case DIST:
dvander@159
  1002
            for (;;) {
dvander@159
  1003
                this = state->distcode[BITS(state->distbits)];
dvander@159
  1004
                if ((unsigned)(this.bits) <= bits) break;
dvander@159
  1005
                PULLBYTE();
dvander@159
  1006
            }
dvander@159
  1007
            if ((this.op & 0xf0) == 0) {
dvander@159
  1008
                last = this;
dvander@159
  1009
                for (;;) {
dvander@159
  1010
                    this = state->distcode[last.val +
dvander@159
  1011
                            (BITS(last.bits + last.op) >> last.bits)];
dvander@159
  1012
                    if ((unsigned)(last.bits + this.bits) <= bits) break;
dvander@159
  1013
                    PULLBYTE();
dvander@159
  1014
                }
dvander@159
  1015
                DROPBITS(last.bits);
dvander@159
  1016
            }
dvander@159
  1017
            DROPBITS(this.bits);
dvander@159
  1018
            if (this.op & 64) {
dvander@159
  1019
                strm->msg = (char *)"invalid distance code";
dvander@159
  1020
                state->mode = BAD;
dvander@159
  1021
                break;
dvander@159
  1022
            }
dvander@159
  1023
            state->offset = (unsigned)this.val;
dvander@159
  1024
            state->extra = (unsigned)(this.op) & 15;
dvander@159
  1025
            state->mode = DISTEXT;
dvander@159
  1026
        case DISTEXT:
dvander@159
  1027
            if (state->extra) {
dvander@159
  1028
                NEEDBITS(state->extra);
dvander@159
  1029
                state->offset += BITS(state->extra);
dvander@159
  1030
                DROPBITS(state->extra);
dvander@159
  1031
            }
dvander@159
  1032
#ifdef INFLATE_STRICT
dvander@159
  1033
            if (state->offset > state->dmax) {
dvander@159
  1034
                strm->msg = (char *)"invalid distance too far back";
dvander@159
  1035
                state->mode = BAD;
dvander@159
  1036
                break;
dvander@159
  1037
            }
dvander@159
  1038
#endif
dvander@159
  1039
            if (state->offset > state->whave + out - left) {
dvander@159
  1040
                strm->msg = (char *)"invalid distance too far back";
dvander@159
  1041
                state->mode = BAD;
dvander@159
  1042
                break;
dvander@159
  1043
            }
dvander@159
  1044
            Tracevv((stderr, "inflate:         distance %u\n", state->offset));
dvander@159
  1045
            state->mode = MATCH;
dvander@159
  1046
        case MATCH:
dvander@159
  1047
            if (left == 0) goto inf_leave;
dvander@159
  1048
            copy = out - left;
dvander@159
  1049
            if (state->offset > copy) {         /* copy from window */
dvander@159
  1050
                copy = state->offset - copy;
dvander@159
  1051
                if (copy > state->write) {
dvander@159
  1052
                    copy -= state->write;
dvander@159
  1053
                    from = state->window + (state->wsize - copy);
dvander@159
  1054
                }
dvander@159
  1055
                else
dvander@159
  1056
                    from = state->window + (state->write - copy);
dvander@159
  1057
                if (copy > state->length) copy = state->length;
dvander@159
  1058
            }
dvander@159
  1059
            else {                              /* copy from output */
dvander@159
  1060
                from = put - state->offset;
dvander@159
  1061
                copy = state->length;
dvander@159
  1062
            }
dvander@159
  1063
            if (copy > left) copy = left;
dvander@159
  1064
            left -= copy;
dvander@159
  1065
            state->length -= copy;
dvander@159
  1066
            do {
dvander@159
  1067
                *put++ = *from++;
dvander@159
  1068
            } while (--copy);
dvander@159
  1069
            if (state->length == 0) state->mode = LEN;
dvander@159
  1070
            break;
dvander@159
  1071
        case LIT:
dvander@159
  1072
            if (left == 0) goto inf_leave;
dvander@159
  1073
            *put++ = (unsigned char)(state->length);
dvander@159
  1074
            left--;
dvander@159
  1075
            state->mode = LEN;
dvander@159
  1076
            break;
dvander@159
  1077
        case CHECK:
dvander@159
  1078
            if (state->wrap) {
dvander@159
  1079
                NEEDBITS(32);
dvander@159
  1080
                out -= left;
dvander@159
  1081
                strm->total_out += out;
dvander@159
  1082
                state->total += out;
dvander@159
  1083
                if (out)
dvander@159
  1084
                    strm->adler = state->check =
dvander@159
  1085
                        UPDATE(state->check, put - out, out);
dvander@159
  1086
                out = left;
dvander@159
  1087
                if ((
dvander@159
  1088
#ifdef GUNZIP
dvander@159
  1089
                     state->flags ? hold :
dvander@159
  1090
#endif
dvander@159
  1091
                     REVERSE(hold)) != state->check) {
dvander@159
  1092
                    strm->msg = (char *)"incorrect data check";
dvander@159
  1093
                    state->mode = BAD;
dvander@159
  1094
                    break;
dvander@159
  1095
                }
dvander@159
  1096
                INITBITS();
dvander@159
  1097
                Tracev((stderr, "inflate:   check matches trailer\n"));
dvander@159
  1098
            }
dvander@159
  1099
#ifdef GUNZIP
dvander@159
  1100
            state->mode = LENGTH;
dvander@159
  1101
        case LENGTH:
dvander@159
  1102
            if (state->wrap && state->flags) {
dvander@159
  1103
                NEEDBITS(32);
dvander@159
  1104
                if (hold != (state->total & 0xffffffffUL)) {
dvander@159
  1105
                    strm->msg = (char *)"incorrect length check";
dvander@159
  1106
                    state->mode = BAD;
dvander@159
  1107
                    break;
dvander@159
  1108
                }
dvander@159
  1109
                INITBITS();
dvander@159
  1110
                Tracev((stderr, "inflate:   length matches trailer\n"));
dvander@159
  1111
            }
dvander@159
  1112
#endif
dvander@159
  1113
            state->mode = DONE;
dvander@159
  1114
        case DONE:
dvander@159
  1115
            ret = Z_STREAM_END;
dvander@159
  1116
            goto inf_leave;
dvander@159
  1117
        case BAD:
dvander@159
  1118
            ret = Z_DATA_ERROR;
dvander@159
  1119
            goto inf_leave;
dvander@159
  1120
        case MEM:
dvander@159
  1121
            return Z_MEM_ERROR;
dvander@159
  1122
        case SYNC:
dvander@159
  1123
        default:
dvander@159
  1124
            return Z_STREAM_ERROR;
dvander@159
  1125
        }
dvander@159
  1126
dvander@159
  1127
    /*
dvander@159
  1128
       Return from inflate(), updating the total counts and the check value.
dvander@159
  1129
       If there was no progress during the inflate() call, return a buffer
dvander@159
  1130
       error.  Call updatewindow() to create and/or update the window state.
dvander@159
  1131
       Note: a memory error from inflate() is non-recoverable.
dvander@159
  1132
     */
dvander@159
  1133
  inf_leave:
dvander@159
  1134
    RESTORE();
dvander@159
  1135
    if (state->wsize || (state->mode < CHECK && out != strm->avail_out))
dvander@159
  1136
        if (updatewindow(strm, out)) {
dvander@159
  1137
            state->mode = MEM;
dvander@159
  1138
            return Z_MEM_ERROR;
dvander@159
  1139
        }
dvander@159
  1140
    in -= strm->avail_in;
dvander@159
  1141
    out -= strm->avail_out;
dvander@159
  1142
    strm->total_in += in;
dvander@159
  1143
    strm->total_out += out;
dvander@159
  1144
    state->total += out;
dvander@159
  1145
    if (state->wrap && out)
dvander@159
  1146
        strm->adler = state->check =
dvander@159
  1147
            UPDATE(state->check, strm->next_out - out, out);
dvander@159
  1148
    strm->data_type = state->bits + (state->last ? 64 : 0) +
dvander@159
  1149
                      (state->mode == TYPE ? 128 : 0);
dvander@159
  1150
    if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK)
dvander@159
  1151
        ret = Z_BUF_ERROR;
dvander@159
  1152
    return ret;
dvander@159
  1153
}
dvander@159
  1154
dvander@159
  1155
int ZEXPORT inflateEnd(strm)
dvander@159
  1156
z_streamp strm;
dvander@159
  1157
{
dvander@159
  1158
    struct inflate_state FAR *state;
dvander@159
  1159
    if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0)
dvander@159
  1160
        return Z_STREAM_ERROR;
dvander@159
  1161
    state = (struct inflate_state FAR *)strm->state;
dvander@159
  1162
    if (state->window != Z_NULL) ZFREE(strm, state->window);
dvander@159
  1163
    ZFREE(strm, strm->state);
dvander@159
  1164
    strm->state = Z_NULL;
dvander@159
  1165
    Tracev((stderr, "inflate: end\n"));
dvander@159
  1166
    return Z_OK;
dvander@159
  1167
}
dvander@159
  1168
dvander@159
  1169
int ZEXPORT inflateSetDictionary(strm, dictionary, dictLength)
dvander@159
  1170
z_streamp strm;
dvander@159
  1171
const Bytef *dictionary;
dvander@159
  1172
uInt dictLength;
dvander@159
  1173
{
dvander@159
  1174
    struct inflate_state FAR *state;
dvander@159
  1175
    unsigned long id;
dvander@159
  1176
dvander@159
  1177
    /* check state */
dvander@159
  1178
    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
dvander@159
  1179
    state = (struct inflate_state FAR *)strm->state;
dvander@159
  1180
    if (state->wrap != 0 && state->mode != DICT)
dvander@159
  1181
        return Z_STREAM_ERROR;
dvander@159
  1182
dvander@159
  1183
    /* check for correct dictionary id */
dvander@159
  1184
    if (state->mode == DICT) {
dvander@159
  1185
        id = adler32(0L, Z_NULL, 0);
dvander@159
  1186
        id = adler32(id, dictionary, dictLength);
dvander@159
  1187
        if (id != state->check)
dvander@159
  1188
            return Z_DATA_ERROR;
dvander@159
  1189
    }
dvander@159
  1190
dvander@159
  1191
    /* copy dictionary to window */
dvander@159
  1192
    if (updatewindow(strm, strm->avail_out)) {
dvander@159
  1193
        state->mode = MEM;
dvander@159
  1194
        return Z_MEM_ERROR;
dvander@159
  1195
    }
dvander@159
  1196
    if (dictLength > state->wsize) {
dvander@159
  1197
        zmemcpy(state->window, dictionary + dictLength - state->wsize,
dvander@159
  1198
                state->wsize);
dvander@159
  1199
        state->whave = state->wsize;
dvander@159
  1200
    }
dvander@159
  1201
    else {
dvander@159
  1202
        zmemcpy(state->window + state->wsize - dictLength, dictionary,
dvander@159
  1203
                dictLength);
dvander@159
  1204
        state->whave = dictLength;
dvander@159
  1205
    }
dvander@159
  1206
    state->havedict = 1;
dvander@159
  1207
    Tracev((stderr, "inflate:   dictionary set\n"));
dvander@159
  1208
    return Z_OK;
dvander@159
  1209
}
dvander@159
  1210
dvander@159
  1211
int ZEXPORT inflateGetHeader(strm, head)
dvander@159
  1212
z_streamp strm;
dvander@159
  1213
gz_headerp head;
dvander@159
  1214
{
dvander@159
  1215
    struct inflate_state FAR *state;
dvander@159
  1216
dvander@159
  1217
    /* check state */
dvander@159
  1218
    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
dvander@159
  1219
    state = (struct inflate_state FAR *)strm->state;
dvander@159
  1220
    if ((state->wrap & 2) == 0) return Z_STREAM_ERROR;
dvander@159
  1221
dvander@159
  1222
    /* save header structure */
dvander@159
  1223
    state->head = head;
dvander@159
  1224
    head->done = 0;
dvander@159
  1225
    return Z_OK;
dvander@159
  1226
}
dvander@159
  1227
dvander@159
  1228
/*
dvander@159
  1229
   Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff.  Return when found
dvander@159
  1230
   or when out of input.  When called, *have is the number of pattern bytes
dvander@159
  1231
   found in order so far, in 0..3.  On return *have is updated to the new
dvander@159
  1232
   state.  If on return *have equals four, then the pattern was found and the
dvander@159
  1233
   return value is how many bytes were read including the last byte of the
dvander@159
  1234
   pattern.  If *have is less than four, then the pattern has not been found
dvander@159
  1235
   yet and the return value is len.  In the latter case, syncsearch() can be
dvander@159
  1236
   called again with more data and the *have state.  *have is initialized to
dvander@159
  1237
   zero for the first call.
dvander@159
  1238
 */
dvander@159
  1239
local unsigned syncsearch(have, buf, len)
dvander@159
  1240
unsigned FAR *have;
dvander@159
  1241
unsigned char FAR *buf;
dvander@159
  1242
unsigned len;
dvander@159
  1243
{
dvander@159
  1244
    unsigned got;
dvander@159
  1245
    unsigned next;
dvander@159
  1246
dvander@159
  1247
    got = *have;
dvander@159
  1248
    next = 0;
dvander@159
  1249
    while (next < len && got < 4) {
dvander@159
  1250
        if ((int)(buf[next]) == (got < 2 ? 0 : 0xff))
dvander@159
  1251
            got++;
dvander@159
  1252
        else if (buf[next])
dvander@159
  1253
            got = 0;
dvander@159
  1254
        else
dvander@159
  1255
            got = 4 - got;
dvander@159
  1256
        next++;
dvander@159
  1257
    }
dvander@159
  1258
    *have = got;
dvander@159
  1259
    return next;
dvander@159
  1260
}
dvander@159
  1261
dvander@159
  1262
int ZEXPORT inflateSync(strm)
dvander@159
  1263
z_streamp strm;
dvander@159
  1264
{
dvander@159
  1265
    unsigned len;               /* number of bytes to look at or looked at */
dvander@159
  1266
    unsigned long in, out;      /* temporary to save total_in and total_out */
dvander@159
  1267
    unsigned char buf[4];       /* to restore bit buffer to byte string */
dvander@159
  1268
    struct inflate_state FAR *state;
dvander@159
  1269
dvander@159
  1270
    /* check parameters */
dvander@159
  1271
    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
dvander@159
  1272
    state = (struct inflate_state FAR *)strm->state;
dvander@159
  1273
    if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR;
dvander@159
  1274
dvander@159
  1275
    /* if first time, start search in bit buffer */
dvander@159
  1276
    if (state->mode != SYNC) {
dvander@159
  1277
        state->mode = SYNC;
dvander@159
  1278
        state->hold <<= state->bits & 7;
dvander@159
  1279
        state->bits -= state->bits & 7;
dvander@159
  1280
        len = 0;
dvander@159
  1281
        while (state->bits >= 8) {
dvander@159
  1282
            buf[len++] = (unsigned char)(state->hold);
dvander@159
  1283
            state->hold >>= 8;
dvander@159
  1284
            state->bits -= 8;
dvander@159
  1285
        }
dvander@159
  1286
        state->have = 0;
dvander@159
  1287
        syncsearch(&(state->have), buf, len);
dvander@159
  1288
    }
dvander@159
  1289
dvander@159
  1290
    /* search available input */
dvander@159
  1291
    len = syncsearch(&(state->have), strm->next_in, strm->avail_in);
dvander@159
  1292
    strm->avail_in -= len;
dvander@159
  1293
    strm->next_in += len;
dvander@159
  1294
    strm->total_in += len;
dvander@159
  1295
dvander@159
  1296
    /* return no joy or set up to restart inflate() on a new block */
dvander@159
  1297
    if (state->have != 4) return Z_DATA_ERROR;
dvander@159
  1298
    in = strm->total_in;  out = strm->total_out;
dvander@159
  1299
    inflateReset(strm);
dvander@159
  1300
    strm->total_in = in;  strm->total_out = out;
dvander@159
  1301
    state->mode = TYPE;
dvander@159
  1302
    return Z_OK;
dvander@159
  1303
}
dvander@159
  1304
dvander@159
  1305
/*
dvander@159
  1306
   Returns true if inflate is currently at the end of a block generated by
dvander@159
  1307
   Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP
dvander@159
  1308
   implementation to provide an additional safety check. PPP uses
dvander@159
  1309
   Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored
dvander@159
  1310
   block. When decompressing, PPP checks that at the end of input packet,
dvander@159
  1311
   inflate is waiting for these length bytes.
dvander@159
  1312
 */
dvander@159
  1313
int ZEXPORT inflateSyncPoint(strm)
dvander@159
  1314
z_streamp strm;
dvander@159
  1315
{
dvander@159
  1316
    struct inflate_state FAR *state;
dvander@159
  1317
dvander@159
  1318
    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
dvander@159
  1319
    state = (struct inflate_state FAR *)strm->state;
dvander@159
  1320
    return state->mode == STORED && state->bits == 0;
dvander@159
  1321
}
dvander@159
  1322
dvander@159
  1323
int ZEXPORT inflateCopy(dest, source)
dvander@159
  1324
z_streamp dest;
dvander@159
  1325
z_streamp source;
dvander@159
  1326
{
dvander@159
  1327
    struct inflate_state FAR *state;
dvander@159
  1328
    struct inflate_state FAR *copy;
dvander@159
  1329
    unsigned char FAR *window;
dvander@159
  1330
    unsigned wsize;
dvander@159
  1331
dvander@159
  1332
    /* check input */
dvander@159
  1333
    if (dest == Z_NULL || source == Z_NULL || source->state == Z_NULL ||
dvander@159
  1334
        source->zalloc == (alloc_func)0 || source->zfree == (free_func)0)
dvander@159
  1335
        return Z_STREAM_ERROR;
dvander@159
  1336
    state = (struct inflate_state FAR *)source->state;
dvander@159
  1337
dvander@159
  1338
    /* allocate space */
dvander@159
  1339
    copy = (struct inflate_state FAR *)
dvander@159
  1340
           ZALLOC(source, 1, sizeof(struct inflate_state));
dvander@159
  1341
    if (copy == Z_NULL) return Z_MEM_ERROR;
dvander@159
  1342
    window = Z_NULL;
dvander@159
  1343
    if (state->window != Z_NULL) {
dvander@159
  1344
        window = (unsigned char FAR *)
dvander@159
  1345
                 ZALLOC(source, 1U << state->wbits, sizeof(unsigned char));
dvander@159
  1346
        if (window == Z_NULL) {
dvander@159
  1347
            ZFREE(source, copy);
dvander@159
  1348
            return Z_MEM_ERROR;
dvander@159
  1349
        }
dvander@159
  1350
    }
dvander@159
  1351
dvander@159
  1352
    /* copy state */
dvander@159
  1353
    zmemcpy(dest, source, sizeof(z_stream));
dvander@159
  1354
    zmemcpy(copy, state, sizeof(struct inflate_state));
dvander@159
  1355
    if (state->lencode >= state->codes &&
dvander@159
  1356
        state->lencode <= state->codes + ENOUGH - 1) {
dvander@159
  1357
        copy->lencode = copy->codes + (state->lencode - state->codes);
dvander@159
  1358
        copy->distcode = copy->codes + (state->distcode - state->codes);
dvander@159
  1359
    }
dvander@159
  1360
    copy->next = copy->codes + (state->next - state->codes);
dvander@159
  1361
    if (window != Z_NULL) {
dvander@159
  1362
        wsize = 1U << state->wbits;
dvander@159
  1363
        zmemcpy(window, state->window, wsize);
dvander@159
  1364
    }
dvander@159
  1365
    copy->window = window;
dvander@159
  1366
    dest->state = (struct internal_state FAR *)copy;
dvander@159
  1367
    return Z_OK;
dvander@159
  1368
}