inflate.c revision 3f54fd611f536639ec30dd53c48e5ec1897cc7d9
a79fe3aad8743ea57e473ea5f66a723244cb9c0eMarkus Roggenbach/* inflate.c -- zlib decompression
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder * Copyright (C) 1995-2005 Mark Adler
bb83db66bd9b3b4ce67be66419daf29886175276Andy Gimblett * For conditions of distribution and use, see copyright notice in zlib.h
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder */
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder
98890889ffb2e8f6f722b00e265a211f13b5a861Corneliu-Claudiu Prodescu/*
a79fe3aad8743ea57e473ea5f66a723244cb9c0eMarkus Roggenbach * Change history:
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder *
a79fe3aad8743ea57e473ea5f66a723244cb9c0eMarkus Roggenbach * 1.2.beta0 24 Nov 2002
a79fe3aad8743ea57e473ea5f66a723244cb9c0eMarkus Roggenbach * - First version -- complete rewrite of inflate to simplify code, avoid
a79fe3aad8743ea57e473ea5f66a723244cb9c0eMarkus Roggenbach * creation of window when not needed, minimize use of window when it is
bb83db66bd9b3b4ce67be66419daf29886175276Andy Gimblett * needed, make inffast.c even faster, implement gzip decoding, and to
bb83db66bd9b3b4ce67be66419daf29886175276Andy Gimblett * improve code readability and style over the previous zlib inflate code
78718c37b1a50086a27e0f031db4cf82bea934aeChristian Maeder *
a79fe3aad8743ea57e473ea5f66a723244cb9c0eMarkus Roggenbach * 1.2.beta1 25 Nov 2002
a79fe3aad8743ea57e473ea5f66a723244cb9c0eMarkus Roggenbach * - Use pointers for available input and output checking in inffast.c
a79fe3aad8743ea57e473ea5f66a723244cb9c0eMarkus Roggenbach * - Remove input and output counters in inffast.c
a79fe3aad8743ea57e473ea5f66a723244cb9c0eMarkus Roggenbach * - Change inffast.c entry and loop from avail_in >= 7 to >= 6
a79fe3aad8743ea57e473ea5f66a723244cb9c0eMarkus Roggenbach * - Remove unnecessary second byte pull from length extra in inffast.c
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder * - Unroll direct copy to three copies per loop in inffast.c
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder *
5cc369fbceee1b13bd0f06e43620c46541d1d4f8Christian Maeder * 1.2.beta2 4 Dec 2002
dfc58f5ec6492d1a9b9babd9cdcdbb15baa6e657Christian Maeder * - Change external routine names to reduce potential conflicts
a79fe3aad8743ea57e473ea5f66a723244cb9c0eMarkus Roggenbach * - Correct filename to inffixed.h for fixed tables in inflate.c
12b2ae689353ecbaad720a9af9f9be01c1a3fe2dChristian Maeder * - Make hbuf[] unsigned char to match parameter type in inflate.c
12b2ae689353ecbaad720a9af9f9be01c1a3fe2dChristian Maeder * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset)
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder * to avoid negation problem on Alphas (64 bit) in inflate.c
1538a6e8d77301d6de757616ffc69ee61f1482e4Andy Gimblett *
a79fe3aad8743ea57e473ea5f66a723244cb9c0eMarkus Roggenbach * 1.2.beta3 22 Dec 2002
a79fe3aad8743ea57e473ea5f66a723244cb9c0eMarkus Roggenbach * - Add comments on state->bits assertion in inffast.c
70a691ea12f53381209a3709cdd325df5fc0a0c8Christian Maeder * - Add comments on op field in inftrees.h
a79fe3aad8743ea57e473ea5f66a723244cb9c0eMarkus Roggenbach * - Fix bug in reuse of allocated window after inflateReset()
792df0347edab377785d98c63e2be8e2ce0a8bdeChristian Maeder * - Remove bit fields--back to byte structure for speed
2a5b885d9350ec6dd8bc4992ee91d2f68aa592f4Christian Maeder * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths
0ea916d1e6aea10fd7b84f802fb5148a79d8c20aAndy Gimblett * - Change post-increments to pre-increments in inflate_fast(), PPC biased?
04ceed96d1528b939f2e592d0656290d81d1c045Andy Gimblett * - Add compile time option, POSTINC, to use post-increments instead (Intel?)
d9e78002fb0bf01a9b72d3d3415fdf9790bdfee8Andy Gimblett * - Make MATCH copy in inflate() much faster for when inflate_fast() not used
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly * - Use local copies of stream next and avail values, as well as local bit
9f93b2a8b552789cd939d599504d39732672dc84Christian Maeder * buffer and bit count in inflate()--for speed when inflate_fast() not used
1538a6e8d77301d6de757616ffc69ee61f1482e4Andy Gimblett *
3b48e17c1da54ee669e70b626d9fbc32ce495b2cChristian Maeder * 1.2.beta4 1 Jan 2003
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly * - Move a comment on output buffer sizes from inffast.c to inflate.c
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder * - Add comments in inffast.c to introduce the inflate_fast() routine
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder * - Rearrange window copies in inflate_fast() for speed and simplification
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder * - Unroll last copy for window match in inflate_fast()
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder * - Use local copies of window variables in inflate_fast() for speed
c4b2418421546a337f83332fe0db04742dcd735dAndy Gimblett * - Pull out common write == 0 case for speed in inflate_fast()
bcd914850de931848b86d7728192a149f9c0108bChristian Maeder * - Make op and len in inflate_fast() unsigned for consistency
12b2ae689353ecbaad720a9af9f9be01c1a3fe2dChristian Maeder * - Add FAR to lcode and dcode declarations in inflate_fast()
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder * - Simplified bad distance check in inflate_fast()
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder * source file infback.c to provide a call-back interface to inflate for
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder * programs like gzip and unzip -- uses window as output buffer to avoid
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder * window copying
e54c5af823b9775dd2c058185ea5bdf7593950faAndy Gimblett *
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder * 1.2.beta5 1 Jan 2003
12b2ae689353ecbaad720a9af9f9be01c1a3fe2dChristian Maeder * - Improved inflateBack() interface to allow the caller to provide initial
12b2ae689353ecbaad720a9af9f9be01c1a3fe2dChristian Maeder * input in strm.
a78bb62cd6f0beb2dab862db865357fc9d3c25feChristian Maeder * - Fixed stored blocks bug in inflateBack()
a78bb62cd6f0beb2dab862db865357fc9d3c25feChristian Maeder *
12b2ae689353ecbaad720a9af9f9be01c1a3fe2dChristian Maeder * 1.2.beta6 4 Jan 2003
12b2ae689353ecbaad720a9af9f9be01c1a3fe2dChristian Maeder * - Added comments in inffast.c on effectiveness of POSTINC
12b2ae689353ecbaad720a9af9f9be01c1a3fe2dChristian Maeder * - Typecasting all around to reduce compiler warnings
7e7d791d2f643ffd82843b78e424b6f9f68c24eeChristian Maeder * - Changed loops from while (1) or do {} while (1) to for (;;), again to
12b2ae689353ecbaad720a9af9f9be01c1a3fe2dChristian Maeder * make compilers happy
12b2ae689353ecbaad720a9af9f9be01c1a3fe2dChristian Maeder * - Changed type of window in inflateBackInit() to unsigned char *
bcd914850de931848b86d7728192a149f9c0108bChristian Maeder *
12b2ae689353ecbaad720a9af9f9be01c1a3fe2dChristian Maeder * 1.2.beta7 27 Jan 2003
12b2ae689353ecbaad720a9af9f9be01c1a3fe2dChristian Maeder * - Changed many types to unsigned or unsigned short to avoid warnings
12b2ae689353ecbaad720a9af9f9be01c1a3fe2dChristian Maeder * - Added inflateCopy() function
bcd914850de931848b86d7728192a149f9c0108bChristian Maeder *
ad872d5e07383c8fec42bddf02a13d1fbcac52b2Christian Maeder * 1.2.0 9 Mar 2003
ad872d5e07383c8fec42bddf02a13d1fbcac52b2Christian Maeder * - Changed inflateBack() interface to provide separate opaque descriptors
ad872d5e07383c8fec42bddf02a13d1fbcac52b2Christian Maeder * for the in() and out() functions
12b2ae689353ecbaad720a9af9f9be01c1a3fe2dChristian Maeder * - Changed inflateBack() argument and in_func typedef to swap the length
8db2221917c1bc569614f3481bcdb3b988facaedChristian Maeder * and buffer address return values for the input function
ad872d5e07383c8fec42bddf02a13d1fbcac52b2Christian Maeder * - Check next_in and next_out for Z_NULL on entry to inflate()
12b2ae689353ecbaad720a9af9f9be01c1a3fe2dChristian Maeder *
e771539425f4a0abef9f94cf4b63690f3603f682Andy Gimblett * The history for versions after 1.2.0 are in ChangeLog in zlib distribution.
bb83db66bd9b3b4ce67be66419daf29886175276Andy Gimblett */
d297a45fc73aa6c4a1f9d073c3170611415f324bAndy Gimblett
bb83db66bd9b3b4ce67be66419daf29886175276Andy Gimblett#include "zutil.h"
2f35e5f6757968746dbab385be21fcae52378a3fLiam O'Reilly#include "inftrees.h"
fbc0c2baf563fe5b664f0152674a8d3acecca58cAndy Gimblett#include "inflate.h"
31f039ffdb33d78cb31d24b71d3155b11a323975Andy Gimblett#include "inffast.h"
e771539425f4a0abef9f94cf4b63690f3603f682Andy Gimblett
e771539425f4a0abef9f94cf4b63690f3603f682Andy Gimblett#ifdef MAKEFIXED
d326dac41dadbe2b84bb7021cbfd91f4dd4a19bcAndy Gimblett# ifndef BUILDFIXED
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder# define BUILDFIXED
f4a5178450076ee54f3a9adb4f91e241aea3ba75Christian Maeder# endif
f4a5178450076ee54f3a9adb4f91e241aea3ba75Christian Maeder#endif
90047eafd2de482c67bcd13103c6064e9b0cb254Andy Gimblett
bb83db66bd9b3b4ce67be66419daf29886175276Andy Gimblett/* function prototypes */
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maederlocal void fixedtables OF((struct inflate_state FAR *state));
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maederlocal int updatewindow OF((z_streamp strm, unsigned out));
d297a45fc73aa6c4a1f9d073c3170611415f324bAndy Gimblett#ifdef BUILDFIXED
d297a45fc73aa6c4a1f9d073c3170611415f324bAndy Gimblett void makefixed OF((void));
4314e26a12954cb1c9be4dea10aa8103edac5bbbChristian Maeder#endif
842ae753ab848a8508c4832ab64296b929167a97Christian Maederlocal unsigned syncsearch OF((unsigned FAR *have, unsigned char FAR *buf,
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder unsigned len));
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder
842ae753ab848a8508c4832ab64296b929167a97Christian Maederint ZEXPORT inflateReset(strm)
842ae753ab848a8508c4832ab64296b929167a97Christian Maederz_streamp strm;
2a5b885d9350ec6dd8bc4992ee91d2f68aa592f4Christian Maeder{
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder struct inflate_state FAR *state;
2a5b885d9350ec6dd8bc4992ee91d2f68aa592f4Christian Maeder
d297a45fc73aa6c4a1f9d073c3170611415f324bAndy Gimblett if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
bb83db66bd9b3b4ce67be66419daf29886175276Andy Gimblett state = (struct inflate_state FAR *)strm->state;
a79fe3aad8743ea57e473ea5f66a723244cb9c0eMarkus Roggenbach strm->total_in = strm->total_out = state->total = 0;
bb83db66bd9b3b4ce67be66419daf29886175276Andy Gimblett strm->msg = Z_NULL;
ad872d5e07383c8fec42bddf02a13d1fbcac52b2Christian Maeder strm->adler = 1; /* to support ill-conceived Java test suite */
ad872d5e07383c8fec42bddf02a13d1fbcac52b2Christian Maeder state->mode = HEAD;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder state->last = 0;
dfc58f5ec6492d1a9b9babd9cdcdbb15baa6e657Christian Maeder state->havedict = 0;
dfc58f5ec6492d1a9b9babd9cdcdbb15baa6e657Christian Maeder state->dmax = 32768U;
05cc55892e6c93bdd7b9c3f100ab1bb65fe6a21eLiam O'Reilly state->head = Z_NULL;
05cc55892e6c93bdd7b9c3f100ab1bb65fe6a21eLiam O'Reilly state->wsize = 0;
05cc55892e6c93bdd7b9c3f100ab1bb65fe6a21eLiam O'Reilly state->whave = 0;
05cc55892e6c93bdd7b9c3f100ab1bb65fe6a21eLiam O'Reilly state->write = 0;
05cc55892e6c93bdd7b9c3f100ab1bb65fe6a21eLiam O'Reilly state->hold = 0;
05cc55892e6c93bdd7b9c3f100ab1bb65fe6a21eLiam O'Reilly state->bits = 0;
ad872d5e07383c8fec42bddf02a13d1fbcac52b2Christian Maeder state->lencode = state->distcode = state->next = state->codes;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder Tracev((stderr, "inflate: reset\n"));
ad872d5e07383c8fec42bddf02a13d1fbcac52b2Christian Maeder return Z_OK;
d297a45fc73aa6c4a1f9d073c3170611415f324bAndy Gimblett}
bb83db66bd9b3b4ce67be66419daf29886175276Andy Gimblett
d297a45fc73aa6c4a1f9d073c3170611415f324bAndy Gimblettint ZEXPORT inflatePrime(strm, bits, value)
bb83db66bd9b3b4ce67be66419daf29886175276Andy Gimblettz_streamp strm;
4314e26a12954cb1c9be4dea10aa8103edac5bbbChristian Maederint bits;
e54c5af823b9775dd2c058185ea5bdf7593950faAndy Gimblettint value;
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly{
d326dac41dadbe2b84bb7021cbfd91f4dd4a19bcAndy Gimblett struct inflate_state FAR *state;
d326dac41dadbe2b84bb7021cbfd91f4dd4a19bcAndy Gimblett
d297a45fc73aa6c4a1f9d073c3170611415f324bAndy Gimblett if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly state = (struct inflate_state FAR *)strm->state;
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly if (bits > 16 || state->bits + bits > 32) return Z_STREAM_ERROR;
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly value &= (1L << bits) - 1;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder state->hold += value << state->bits;
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly state->bits += bits;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder return Z_OK;
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly}
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reillyint ZEXPORT inflateInit2_(strm, windowBits, version, stream_size)
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reillyz_streamp strm;
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reillyint windowBits;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maederconst char *version;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maederint stream_size;
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly{
f4a5178450076ee54f3a9adb4f91e241aea3ba75Christian Maeder struct inflate_state FAR *state;
f4a5178450076ee54f3a9adb4f91e241aea3ba75Christian Maeder
d297a45fc73aa6c4a1f9d073c3170611415f324bAndy Gimblett if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
bb83db66bd9b3b4ce67be66419daf29886175276Andy Gimblett stream_size != (int)(sizeof(z_stream)))
d297a45fc73aa6c4a1f9d073c3170611415f324bAndy Gimblett return Z_VERSION_ERROR;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder if (strm == Z_NULL) return Z_STREAM_ERROR;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder strm->msg = Z_NULL; /* in case we return an error */
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder if (strm->zalloc == (alloc_func)0) {
0b8146e4f675518993a34eb2255ad7ddd7bf82a4Christian Maeder strm->zalloc = zcalloc;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder strm->opaque = (voidpf)0;
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly }
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly if (strm->zfree == (free_func)0) strm->zfree = zcfree;
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly state = (struct inflate_state FAR *)
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly ZALLOC(strm, 1, sizeof(struct inflate_state));
4620f04678d4221ed3547f5bcab117d41ffd86f4Christian Maeder if (state == Z_NULL) return Z_MEM_ERROR;
4620f04678d4221ed3547f5bcab117d41ffd86f4Christian Maeder Tracev((stderr, "inflate: allocated\n"));
2a5b885d9350ec6dd8bc4992ee91d2f68aa592f4Christian Maeder strm->state = (struct internal_state FAR *)state;
05cc55892e6c93bdd7b9c3f100ab1bb65fe6a21eLiam O'Reilly if (windowBits < 0) {
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly state->wrap = 0;
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly windowBits = -windowBits;
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly }
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly else {
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly state->wrap = (windowBits >> 4) + 1;
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly#ifdef GUNZIP
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly if (windowBits < 48) windowBits &= 15;
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly#endif
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly }
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly if (windowBits < 8 || windowBits > 15) {
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly ZFREE(strm, state);
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly strm->state = Z_NULL;
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly return Z_STREAM_ERROR;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder }
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder state->wbits = (unsigned)windowBits;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder state->window = Z_NULL;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder return inflateReset(strm);
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder}
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reillyint ZEXPORT inflateInit_(strm, version, stream_size)
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reillyz_streamp strm;
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reillyconst char *version;
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reillyint stream_size;
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly{
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly return inflateInit2_(strm, DEF_WBITS, version, stream_size);
05cc55892e6c93bdd7b9c3f100ab1bb65fe6a21eLiam O'Reilly}
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly
05cc55892e6c93bdd7b9c3f100ab1bb65fe6a21eLiam O'Reilly/*
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly Return state with length and distance decoding tables and index sizes set to
bb83db66bd9b3b4ce67be66419daf29886175276Andy Gimblett fixed code decoding. Normally this returns fixed tables from inffixed.h.
ad872d5e07383c8fec42bddf02a13d1fbcac52b2Christian Maeder If BUILDFIXED is defined, then instead this routine builds the tables the
ad872d5e07383c8fec42bddf02a13d1fbcac52b2Christian Maeder first time it's called, and returns those tables the first time and
ad872d5e07383c8fec42bddf02a13d1fbcac52b2Christian Maeder thereafter. This reduces the size of the code by about 2K bytes, in
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder exchange for a little execution time. However, BUILDFIXED should not be
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder used for threaded applications, since the rewriting of the tables and virgin
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder may not be thread-safe.
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly */
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reillylocal void fixedtables(state)
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reillystruct inflate_state FAR *state;
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly{
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly#ifdef BUILDFIXED
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly static int virgin = 1;
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly static code *lenfix, *distfix;
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly static code fixed[544];
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly
05cc55892e6c93bdd7b9c3f100ab1bb65fe6a21eLiam O'Reilly /* build fixed huffman tables if first call (may not be thread safe) */
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly if (virgin) {
05cc55892e6c93bdd7b9c3f100ab1bb65fe6a21eLiam O'Reilly unsigned sym, bits;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder static code *next;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder /* literal/length table */
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder sym = 0;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder while (sym < 144) state->lens[sym++] = 8;
0b8146e4f675518993a34eb2255ad7ddd7bf82a4Christian Maeder while (sym < 256) state->lens[sym++] = 9;
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly while (sym < 280) state->lens[sym++] = 7;
ad872d5e07383c8fec42bddf02a13d1fbcac52b2Christian Maeder while (sym < 288) state->lens[sym++] = 8;
05cc55892e6c93bdd7b9c3f100ab1bb65fe6a21eLiam O'Reilly next = fixed;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder lenfix = next;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder bits = 9;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work);
7e7d791d2f643ffd82843b78e424b6f9f68c24eeChristian Maeder
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder /* distance table */
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder sym = 0;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder while (sym < 32) state->lens[sym++] = 5;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder distfix = next;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder bits = 5;
bcd914850de931848b86d7728192a149f9c0108bChristian Maeder inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work);
05cc55892e6c93bdd7b9c3f100ab1bb65fe6a21eLiam O'Reilly
d326dac41dadbe2b84bb7021cbfd91f4dd4a19bcAndy Gimblett /* do this just once */
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder virgin = 0;
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly }
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly#else /* !BUILDFIXED */
fd4ad12563262ebe380d810df8f7755cfab5fb42Liam O'Reilly# include "inffixed.h"
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder#endif /* BUILDFIXED */
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder state->lencode = lenfix;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder state->lenbits = 9;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder state->distcode = distfix;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder state->distbits = 5;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder}
e95030058b77cb83593c85aa4c506caf154f63b7Andy Gimblett
bb83db66bd9b3b4ce67be66419daf29886175276Andy Gimblett#ifdef MAKEFIXED
2f35e5f6757968746dbab385be21fcae52378a3fLiam O'Reilly#include <stdio.h>
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder/*
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder Write out the inffixed.h that is #include'd above. Defining MAKEFIXED also
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder defines BUILDFIXED, so the tables are built on the fly. makefixed() writes
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder those tables to stdout, which would be piped to inffixed.h. A small program
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder can simply call makefixed to do this:
e8c03c10d7987b223a9f6bfd5c0c54da21da5b86Andy Gimblett
bb83db66bd9b3b4ce67be66419daf29886175276Andy Gimblett void makefixed(void);
fbc0c2baf563fe5b664f0152674a8d3acecca58cAndy Gimblett
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder int main(void)
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder {
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder makefixed();
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder return 0;
ad872d5e07383c8fec42bddf02a13d1fbcac52b2Christian Maeder }
ad872d5e07383c8fec42bddf02a13d1fbcac52b2Christian Maeder
ad872d5e07383c8fec42bddf02a13d1fbcac52b2Christian Maeder Then that can be linked with zlib built with MAKEFIXED defined and run:
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly
d04c328b10f17ec78001a94d694f7188ebd8c03cAndy Gimblett a.out > inffixed.h
06a77f038c0e1740672274377901d37d0113226dLiam O'Reilly */
ad872d5e07383c8fec42bddf02a13d1fbcac52b2Christian Maedervoid makefixed()
06a77f038c0e1740672274377901d37d0113226dLiam O'Reilly{
816c50f9135a598dfdcfb2af8a80390bc42a9b24Liam O'Reilly unsigned low, size;
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly struct inflate_state state;
d04c328b10f17ec78001a94d694f7188ebd8c03cAndy Gimblett
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder fixedtables(&state);
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder puts(" /* inffixed.h -- table for decoding fixed codes");
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly puts(" * Generated automatically by makefixed().");
d04c328b10f17ec78001a94d694f7188ebd8c03cAndy Gimblett puts(" */");
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder puts("");
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder puts(" /* WARNING: this file should *not* be used by applications.");
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly puts(" It is part of the implementation of this library and is");
d04c328b10f17ec78001a94d694f7188ebd8c03cAndy Gimblett puts(" subject to change. Applications should only use zlib.h.");
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder puts(" */");
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder puts("");
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly size = 1U << 9;
d04c328b10f17ec78001a94d694f7188ebd8c03cAndy Gimblett printf(" static const code lenfix[%u] = {", size);
fd4ad12563262ebe380d810df8f7755cfab5fb42Liam O'Reilly low = 0;
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly for (;;) {
816c50f9135a598dfdcfb2af8a80390bc42a9b24Liam O'Reilly if ((low % 7) == 0) printf("\n ");
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly printf("{%u,%u,%d}", state.lencode[low].op, state.lencode[low].bits,
d04c328b10f17ec78001a94d694f7188ebd8c03cAndy Gimblett state.lencode[low].val);
fd4ad12563262ebe380d810df8f7755cfab5fb42Liam O'Reilly if (++low == size) break;
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly putchar(',');
816c50f9135a598dfdcfb2af8a80390bc42a9b24Liam O'Reilly }
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly puts("\n };");
d04c328b10f17ec78001a94d694f7188ebd8c03cAndy Gimblett size = 1U << 5;
ad872d5e07383c8fec42bddf02a13d1fbcac52b2Christian Maeder printf("\n static const code distfix[%u] = {", size);
ad872d5e07383c8fec42bddf02a13d1fbcac52b2Christian Maeder low = 0;
ad872d5e07383c8fec42bddf02a13d1fbcac52b2Christian Maeder for (;;) {
ad872d5e07383c8fec42bddf02a13d1fbcac52b2Christian Maeder if ((low % 6) == 0) printf("\n ");
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits,
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder state.distcode[low].val);
816c50f9135a598dfdcfb2af8a80390bc42a9b24Liam O'Reilly if (++low == size) break;
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly putchar(',');
d04c328b10f17ec78001a94d694f7188ebd8c03cAndy Gimblett }
ad872d5e07383c8fec42bddf02a13d1fbcac52b2Christian Maeder puts("\n };");
ad872d5e07383c8fec42bddf02a13d1fbcac52b2Christian Maeder}
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder#endif /* MAKEFIXED */
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder
816c50f9135a598dfdcfb2af8a80390bc42a9b24Liam O'Reilly/*
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly Update the window with the last wsize (normally 32K) bytes written before
d04c328b10f17ec78001a94d694f7188ebd8c03cAndy Gimblett returning. If window does not exist yet, create it. This is only called
ad872d5e07383c8fec42bddf02a13d1fbcac52b2Christian Maeder when a window is already in use, or when output has been written during this
ad872d5e07383c8fec42bddf02a13d1fbcac52b2Christian Maeder inflate call, but the end of the deflate stream has not been reached yet.
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder It is also called to create a window for dictionary data when a dictionary
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder is loaded.
816c50f9135a598dfdcfb2af8a80390bc42a9b24Liam O'Reilly
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly Providing output buffers larger than 32K to inflate() should provide a speed
d04c328b10f17ec78001a94d694f7188ebd8c03cAndy Gimblett advantage, since only the last 32K of output is copied to the sliding window
ad872d5e07383c8fec42bddf02a13d1fbcac52b2Christian Maeder upon return from inflate(), and since all distances after the first 32K of
ad872d5e07383c8fec42bddf02a13d1fbcac52b2Christian Maeder output will fall in the output data, making match copies simpler and faster.
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder The advantage may be dependent on the size of the processor's data caches.
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder */
816c50f9135a598dfdcfb2af8a80390bc42a9b24Liam O'Reillylocal int updatewindow(strm, out)
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reillyz_streamp strm;
d04c328b10f17ec78001a94d694f7188ebd8c03cAndy Gimblettunsigned out;
ad872d5e07383c8fec42bddf02a13d1fbcac52b2Christian Maeder{
ad872d5e07383c8fec42bddf02a13d1fbcac52b2Christian Maeder struct inflate_state FAR *state;
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder unsigned copy, dist;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder
816c50f9135a598dfdcfb2af8a80390bc42a9b24Liam O'Reilly state = (struct inflate_state FAR *)strm->state;
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly
d04c328b10f17ec78001a94d694f7188ebd8c03cAndy Gimblett /* if it hasn't been done already, allocate space for the window */
ad872d5e07383c8fec42bddf02a13d1fbcac52b2Christian Maeder if (state->window == Z_NULL) {
ad872d5e07383c8fec42bddf02a13d1fbcac52b2Christian Maeder state->window = (unsigned char FAR *)
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder ZALLOC(strm, 1U << state->wbits,
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder sizeof(unsigned char));
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly if (state->window == Z_NULL) return 1;
816c50f9135a598dfdcfb2af8a80390bc42a9b24Liam O'Reilly }
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly
d04c328b10f17ec78001a94d694f7188ebd8c03cAndy Gimblett /* if window not in use yet, initialize */
ad872d5e07383c8fec42bddf02a13d1fbcac52b2Christian Maeder if (state->wsize == 0) {
fd4ad12563262ebe380d810df8f7755cfab5fb42Liam O'Reilly state->wsize = 1U << state->wbits;
ad872d5e07383c8fec42bddf02a13d1fbcac52b2Christian Maeder state->write = 0;
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder state->whave = 0;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder }
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly
816c50f9135a598dfdcfb2af8a80390bc42a9b24Liam O'Reilly /* copy state->wsize or less output bytes into the circular window */
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly copy = out - strm->avail_out;
d04c328b10f17ec78001a94d694f7188ebd8c03cAndy Gimblett if (copy >= state->wsize) {
ad872d5e07383c8fec42bddf02a13d1fbcac52b2Christian Maeder zmemcpy(state->window, strm->next_out - state->wsize, state->wsize);
fd4ad12563262ebe380d810df8f7755cfab5fb42Liam O'Reilly state->write = 0;
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly state->whave = state->wsize;
fd4ad12563262ebe380d810df8f7755cfab5fb42Liam O'Reilly }
ad872d5e07383c8fec42bddf02a13d1fbcac52b2Christian Maeder else {
5858e6262048894b0e933b547852f04aed009b58Andy Gimblett dist = state->wsize - state->write;
5858e6262048894b0e933b547852f04aed009b58Andy Gimblett if (dist > copy) dist = copy;
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder zmemcpy(state->window + state->write, strm->next_out - copy, dist);
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder copy -= dist;
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly if (copy) {
816c50f9135a598dfdcfb2af8a80390bc42a9b24Liam O'Reilly zmemcpy(state->window, strm->next_out - copy, copy);
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly state->write = copy;
d04c328b10f17ec78001a94d694f7188ebd8c03cAndy Gimblett state->whave = state->wsize;
ad872d5e07383c8fec42bddf02a13d1fbcac52b2Christian Maeder }
fd4ad12563262ebe380d810df8f7755cfab5fb42Liam O'Reilly else {
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder state->write += dist;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder if (state->write == state->wsize) state->write = 0;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder if (state->whave < state->wsize) state->whave += dist;
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly }
d04c328b10f17ec78001a94d694f7188ebd8c03cAndy Gimblett }
ad872d5e07383c8fec42bddf02a13d1fbcac52b2Christian Maeder return 0;
5a859092c242b0e37183a44c3c79479125b2920aChristian Maeder}
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder
5a859092c242b0e37183a44c3c79479125b2920aChristian Maeder/* Macros for inflate(): */
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder
816c50f9135a598dfdcfb2af8a80390bc42a9b24Liam O'Reilly/* check function to use adler32() for zlib or crc32() for gzip */
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly#ifdef GUNZIP
d04c328b10f17ec78001a94d694f7188ebd8c03cAndy Gimblett# define UPDATE(check, buf, len) \
ad872d5e07383c8fec42bddf02a13d1fbcac52b2Christian Maeder (state->flags ? crc32(check, buf, len) : adler32(check, buf, len))
ad872d5e07383c8fec42bddf02a13d1fbcac52b2Christian Maeder#else
2f35e5f6757968746dbab385be21fcae52378a3fLiam O'Reilly# define UPDATE(check, buf, len) adler32(check, buf, len)
ad872d5e07383c8fec42bddf02a13d1fbcac52b2Christian Maeder#endif
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder/* check macros for header crc */
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder#ifdef GUNZIP
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder# define CRC2(check, word) \
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly do { \
7cbbd12f559c5c700f521a52424b098db198f1b4Liam O'Reilly hbuf[0] = (unsigned char)(word); \
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly hbuf[1] = (unsigned char)((word) >> 8); \
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly check = crc32(check, hbuf, 2); \
a09bfcbcb0fba5663fca1968aa82daebf2e092c4Andy Gimblett } while (0)
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder# define CRC4(check, word) \
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder do { \
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder hbuf[0] = (unsigned char)(word); \
ad872d5e07383c8fec42bddf02a13d1fbcac52b2Christian Maeder hbuf[1] = (unsigned char)((word) >> 8); \
ad872d5e07383c8fec42bddf02a13d1fbcac52b2Christian Maeder hbuf[2] = (unsigned char)((word) >> 16); \
ad872d5e07383c8fec42bddf02a13d1fbcac52b2Christian Maeder hbuf[3] = (unsigned char)((word) >> 24); \
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly check = crc32(check, hbuf, 4); \
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly } while (0)
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly#endif
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder/* Load registers with state in inflate() for speed */
06a77f038c0e1740672274377901d37d0113226dLiam O'Reilly#define LOAD() \
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly do { \
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly put = strm->next_out; \
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly left = strm->avail_out; \
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly next = strm->next_in; \
05cc55892e6c93bdd7b9c3f100ab1bb65fe6a21eLiam O'Reilly have = strm->avail_in; \
05cc55892e6c93bdd7b9c3f100ab1bb65fe6a21eLiam O'Reilly hold = state->hold; \
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder bits = state->bits; \
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder } while (0)
05cc55892e6c93bdd7b9c3f100ab1bb65fe6a21eLiam O'Reilly
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder/* Restore state from registers in inflate() */
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder#define RESTORE() \
05cc55892e6c93bdd7b9c3f100ab1bb65fe6a21eLiam O'Reilly do { \
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder strm->next_out = put; \
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder strm->avail_out = left; \
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder strm->next_in = next; \
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder strm->avail_in = have; \
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder state->hold = hold; \
06a77f038c0e1740672274377901d37d0113226dLiam O'Reilly state->bits = bits; \
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder } while (0)
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder/* Clear the input bit accumulator */
ad872d5e07383c8fec42bddf02a13d1fbcac52b2Christian Maeder#define INITBITS() \
ad872d5e07383c8fec42bddf02a13d1fbcac52b2Christian Maeder do { \
ad872d5e07383c8fec42bddf02a13d1fbcac52b2Christian Maeder hold = 0; \
ad872d5e07383c8fec42bddf02a13d1fbcac52b2Christian Maeder bits = 0; \
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder } while (0)
2f615f62c47e2c0ae9964f37f5bac6905d86f475Andy Gimblett
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder/* Get a byte of input into the bit accumulator, or return from inflate()
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder if there is no input available. */
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder#define PULLBYTE() \
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder do { \
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder if (have == 0) goto inf_leave; \
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder have--; \
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder hold += (unsigned long)(*next++) << bits; \
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder bits += 8; \
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder } while (0)
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder
c56c0630e0299eca5dd603cdac49aab4463c0671Liam O'Reilly/* Assure that there are at least n bits in the bit accumulator. If there is
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder not enough available input to do that, then return from inflate(). */
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder#define NEEDBITS(n) \
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder do { \
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder while (bits < (unsigned)(n)) \
2f615f62c47e2c0ae9964f37f5bac6905d86f475Andy Gimblett PULLBYTE(); \
bb83db66bd9b3b4ce67be66419daf29886175276Andy Gimblett } while (0)
2f615f62c47e2c0ae9964f37f5bac6905d86f475Andy Gimblett
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder/* Return the low n bits of the bit accumulator (n < 16) */
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder#define BITS(n) \
fd4ad12563262ebe380d810df8f7755cfab5fb42Liam O'Reilly ((unsigned)hold & ((1U << (n)) - 1))
fd4ad12563262ebe380d810df8f7755cfab5fb42Liam O'Reilly
fd4ad12563262ebe380d810df8f7755cfab5fb42Liam O'Reilly/* Remove n bits from the bit accumulator */
fd4ad12563262ebe380d810df8f7755cfab5fb42Liam O'Reilly#define DROPBITS(n) \
fd4ad12563262ebe380d810df8f7755cfab5fb42Liam O'Reilly do { \
fd4ad12563262ebe380d810df8f7755cfab5fb42Liam O'Reilly hold >>= (n); \
0b8146e4f675518993a34eb2255ad7ddd7bf82a4Christian Maeder bits -= (unsigned)(n); \
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder } while (0)
fd4ad12563262ebe380d810df8f7755cfab5fb42Liam O'Reilly
fd4ad12563262ebe380d810df8f7755cfab5fb42Liam O'Reilly/* Remove zero to seven bits as needed to go to a byte boundary */
fd4ad12563262ebe380d810df8f7755cfab5fb42Liam O'Reilly#define BYTEBITS() \
dd7da1b5fedc05b92ba023ebd803e6f4a662503bChristian Maeder do { \
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly hold >>= bits & 7; \
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder bits -= bits & 7; \
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder } while (0)
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly/* Reverse the bytes in a 32-bit value */
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly#define REVERSE(q) \
70a691ea12f53381209a3709cdd325df5fc0a0c8Christian Maeder ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly (((q) & 0xff00) << 8) + (((q) & 0xff) << 24))
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder/*
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder inflate() uses a state machine to process as much input data and generate as
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder much output data as possible before returning. The state machine is
096d1f4ecffdbaa9e8543b712f24a636ba5accffLiam O'Reilly structured roughly as follows:
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly for (;;) switch (state) {
70a691ea12f53381209a3709cdd325df5fc0a0c8Christian Maeder ...
70a691ea12f53381209a3709cdd325df5fc0a0c8Christian Maeder case STATEn:
70a691ea12f53381209a3709cdd325df5fc0a0c8Christian Maeder if (not enough input data or output space to make progress)
70a691ea12f53381209a3709cdd325df5fc0a0c8Christian Maeder return;
70a691ea12f53381209a3709cdd325df5fc0a0c8Christian Maeder ... make progress ...
70a691ea12f53381209a3709cdd325df5fc0a0c8Christian Maeder state = STATEm;
70a691ea12f53381209a3709cdd325df5fc0a0c8Christian Maeder break;
70a691ea12f53381209a3709cdd325df5fc0a0c8Christian Maeder ...
2a5b885d9350ec6dd8bc4992ee91d2f68aa592f4Christian Maeder }
0b8146e4f675518993a34eb2255ad7ddd7bf82a4Christian Maeder
0b8146e4f675518993a34eb2255ad7ddd7bf82a4Christian Maeder so when inflate() is called again, the same case is attempted again, and
0b8146e4f675518993a34eb2255ad7ddd7bf82a4Christian Maeder if the appropriate resources are provided, the machine proceeds to the
70a691ea12f53381209a3709cdd325df5fc0a0c8Christian Maeder next state. The NEEDBITS() macro is usually the way the state evaluates
0b8146e4f675518993a34eb2255ad7ddd7bf82a4Christian Maeder whether it can proceed or should return. NEEDBITS() does the return if
0b8146e4f675518993a34eb2255ad7ddd7bf82a4Christian Maeder the requested bits are not available. The typical use of the BITS macros
0b8146e4f675518993a34eb2255ad7ddd7bf82a4Christian Maeder is:
0b8146e4f675518993a34eb2255ad7ddd7bf82a4Christian Maeder
0b8146e4f675518993a34eb2255ad7ddd7bf82a4Christian Maeder NEEDBITS(n);
0b8146e4f675518993a34eb2255ad7ddd7bf82a4Christian Maeder ... do something with BITS(n) ...
70a691ea12f53381209a3709cdd325df5fc0a0c8Christian Maeder DROPBITS(n);
70a691ea12f53381209a3709cdd325df5fc0a0c8Christian Maeder
0b8146e4f675518993a34eb2255ad7ddd7bf82a4Christian Maeder where NEEDBITS(n) either returns from inflate() if there isn't enough
70a691ea12f53381209a3709cdd325df5fc0a0c8Christian Maeder input left to load n bits into the accumulator, or it continues. BITS(n)
70a691ea12f53381209a3709cdd325df5fc0a0c8Christian Maeder gives the low n bits in the accumulator. When done, DROPBITS(n) drops
70a691ea12f53381209a3709cdd325df5fc0a0c8Christian Maeder the low n bits off the accumulator. INITBITS() clears the accumulator
70a691ea12f53381209a3709cdd325df5fc0a0c8Christian Maeder and sets the number of available bits to zero. BYTEBITS() discards just
70a691ea12f53381209a3709cdd325df5fc0a0c8Christian Maeder enough bits to put the accumulator on a byte boundary. After BYTEBITS()
70a691ea12f53381209a3709cdd325df5fc0a0c8Christian Maeder and a NEEDBITS(8), then BITS(8) would return the next byte in the stream.
70a691ea12f53381209a3709cdd325df5fc0a0c8Christian Maeder
70a691ea12f53381209a3709cdd325df5fc0a0c8Christian Maeder NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return
70a691ea12f53381209a3709cdd325df5fc0a0c8Christian Maeder if there is no input available. The decoding of variable length codes uses
70a691ea12f53381209a3709cdd325df5fc0a0c8Christian Maeder PULLBYTE() directly in order to pull just enough bytes to decode the next
0b8146e4f675518993a34eb2255ad7ddd7bf82a4Christian Maeder code, and no more.
70a691ea12f53381209a3709cdd325df5fc0a0c8Christian Maeder
70a691ea12f53381209a3709cdd325df5fc0a0c8Christian Maeder Some states loop until they get enough input, making sure that enough
70a691ea12f53381209a3709cdd325df5fc0a0c8Christian Maeder state information is maintained to continue the loop where it left off
70a691ea12f53381209a3709cdd325df5fc0a0c8Christian Maeder if NEEDBITS() returns in the loop. For example, want, need, and keep
70a691ea12f53381209a3709cdd325df5fc0a0c8Christian Maeder would all have to actually be part of the saved state in case NEEDBITS()
bb83db66bd9b3b4ce67be66419daf29886175276Andy Gimblett returns:
fbc0c2baf563fe5b664f0152674a8d3acecca58cAndy Gimblett
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder case STATEw:
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder while (want < need) {
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder NEEDBITS(n);
ad872d5e07383c8fec42bddf02a13d1fbcac52b2Christian Maeder keep[want++] = BITS(n);
ad872d5e07383c8fec42bddf02a13d1fbcac52b2Christian Maeder DROPBITS(n);
ad872d5e07383c8fec42bddf02a13d1fbcac52b2Christian Maeder }
2bb060537a37352251aa04d8dc09aa53aad5d4bfLiam O'Reilly state = STATEx;
9f31535736c3d43a98f0157efaa7f87ea73c9be0Liam O'Reilly case STATEx:
9f31535736c3d43a98f0157efaa7f87ea73c9be0Liam O'Reilly
ad872d5e07383c8fec42bddf02a13d1fbcac52b2Christian Maeder As shown above, if the next state is also the next case, then the break
9f31535736c3d43a98f0157efaa7f87ea73c9be0Liam O'Reilly is omitted.
9f31535736c3d43a98f0157efaa7f87ea73c9be0Liam O'Reilly
9f31535736c3d43a98f0157efaa7f87ea73c9be0Liam O'Reilly A state may also return if there is not enough output space available to
9f31535736c3d43a98f0157efaa7f87ea73c9be0Liam O'Reilly complete that state. Those states are copying stored data, writing a
9f31535736c3d43a98f0157efaa7f87ea73c9be0Liam O'Reilly literal byte, and copying a matching string.
9f31535736c3d43a98f0157efaa7f87ea73c9be0Liam O'Reilly
9f31535736c3d43a98f0157efaa7f87ea73c9be0Liam O'Reilly When returning, a "goto inf_leave" is used to update the total counters,
9f31535736c3d43a98f0157efaa7f87ea73c9be0Liam O'Reilly update the check value, and determine whether any progress has been made
9f31535736c3d43a98f0157efaa7f87ea73c9be0Liam O'Reilly during that inflate() call in order to return the proper return code.
9f31535736c3d43a98f0157efaa7f87ea73c9be0Liam O'Reilly Progress is defined as a change in either strm->avail_in or strm->avail_out.
9f31535736c3d43a98f0157efaa7f87ea73c9be0Liam O'Reilly When there is a window, goto inf_leave will update the window with the last
2bb060537a37352251aa04d8dc09aa53aad5d4bfLiam O'Reilly output written. If a goto inf_leave occurs in the middle of decompression
9f31535736c3d43a98f0157efaa7f87ea73c9be0Liam O'Reilly and there is no window currently, goto inf_leave will create one and copy
9f31535736c3d43a98f0157efaa7f87ea73c9be0Liam O'Reilly output to the window for the next call of inflate().
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder In this implementation, the flush parameter of inflate() only affects the
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder return code (per zlib.h). inflate() always writes as much as possible to
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder strm->next_out, given the space available and the provided input--the effect
ad872d5e07383c8fec42bddf02a13d1fbcac52b2Christian Maeder documented in zlib.h of Z_SYNC_FLUSH. Furthermore, inflate() always defers
9f31535736c3d43a98f0157efaa7f87ea73c9be0Liam O'Reilly the allocation of and copying into a sliding window until necessary, which
2bb060537a37352251aa04d8dc09aa53aad5d4bfLiam O'Reilly provides the effect documented in zlib.h for Z_FINISH when the entire input
9f31535736c3d43a98f0157efaa7f87ea73c9be0Liam O'Reilly stream available. So the only thing the flush parameter actually does is:
9f31535736c3d43a98f0157efaa7f87ea73c9be0Liam O'Reilly when flush is set to Z_FINISH, inflate() cannot return Z_OK. Instead it
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder will return Z_BUF_ERROR if it has not reached the end of the stream.
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder */
9f31535736c3d43a98f0157efaa7f87ea73c9be0Liam O'Reilly
9f31535736c3d43a98f0157efaa7f87ea73c9be0Liam O'Reillyint ZEXPORT inflate(strm, flush)
9f31535736c3d43a98f0157efaa7f87ea73c9be0Liam O'Reillyz_streamp strm;
9f31535736c3d43a98f0157efaa7f87ea73c9be0Liam O'Reillyint flush;
9f31535736c3d43a98f0157efaa7f87ea73c9be0Liam O'Reilly{
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder struct inflate_state FAR *state;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder unsigned char FAR *next; /* next input */
9f31535736c3d43a98f0157efaa7f87ea73c9be0Liam O'Reilly unsigned char FAR *put; /* next output */
9f31535736c3d43a98f0157efaa7f87ea73c9be0Liam O'Reilly unsigned have, left; /* available input and output */
2bb060537a37352251aa04d8dc09aa53aad5d4bfLiam O'Reilly unsigned long hold; /* bit buffer */
fd4ad12563262ebe380d810df8f7755cfab5fb42Liam O'Reilly unsigned bits; /* bits in bit buffer */
fd4ad12563262ebe380d810df8f7755cfab5fb42Liam O'Reilly unsigned in, out; /* save starting available input and output */
7cbbd12f559c5c700f521a52424b098db198f1b4Liam O'Reilly unsigned copy; /* number of stored or match bytes to copy */
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder unsigned char FAR *from; /* where to copy match bytes from */
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder code this; /* current decoding table entry */
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder code last; /* parent table entry */
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder unsigned len; /* length to copy for repeats, bits to drop */
ad872d5e07383c8fec42bddf02a13d1fbcac52b2Christian Maeder int ret; /* return code */
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder#ifdef GUNZIP
ad872d5e07383c8fec42bddf02a13d1fbcac52b2Christian Maeder unsigned char hbuf[4]; /* buffer for gzip header crc calculation */
ad872d5e07383c8fec42bddf02a13d1fbcac52b2Christian Maeder#endif
7cbbd12f559c5c700f521a52424b098db198f1b4Liam O'Reilly static const unsigned short order[19] = /* permutation of code lengths */
7cbbd12f559c5c700f521a52424b098db198f1b4Liam O'Reilly {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder
7cbbd12f559c5c700f521a52424b098db198f1b4Liam O'Reilly if (strm == Z_NULL || strm->state == Z_NULL || strm->next_out == Z_NULL ||
7cbbd12f559c5c700f521a52424b098db198f1b4Liam O'Reilly (strm->next_in == Z_NULL && strm->avail_in != 0))
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder return Z_STREAM_ERROR;
7cbbd12f559c5c700f521a52424b098db198f1b4Liam O'Reilly
9f31535736c3d43a98f0157efaa7f87ea73c9be0Liam O'Reilly state = (struct inflate_state FAR *)strm->state;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder if (state->mode == TYPE) state->mode = TYPEDO; /* skip check */
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder LOAD();
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder in = have;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder out = left;
9f31535736c3d43a98f0157efaa7f87ea73c9be0Liam O'Reilly ret = Z_OK;
9f31535736c3d43a98f0157efaa7f87ea73c9be0Liam O'Reilly for (;;)
9f31535736c3d43a98f0157efaa7f87ea73c9be0Liam O'Reilly switch (state->mode) {
9f31535736c3d43a98f0157efaa7f87ea73c9be0Liam O'Reilly case HEAD:
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder if (state->wrap == 0) {
9f31535736c3d43a98f0157efaa7f87ea73c9be0Liam O'Reilly state->mode = TYPEDO;
9f31535736c3d43a98f0157efaa7f87ea73c9be0Liam O'Reilly break;
9f31535736c3d43a98f0157efaa7f87ea73c9be0Liam O'Reilly }
9f31535736c3d43a98f0157efaa7f87ea73c9be0Liam O'Reilly NEEDBITS(16);
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder#ifdef GUNZIP
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder state->check = crc32(0L, Z_NULL, 0);
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder CRC2(state->check, hold);
ad872d5e07383c8fec42bddf02a13d1fbcac52b2Christian Maeder INITBITS();
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder state->mode = FLAGS;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder break;
ad872d5e07383c8fec42bddf02a13d1fbcac52b2Christian Maeder }
a731366827a80af216ce6bfd4aa6388260577791Andy Gimblett state->flags = 0; /* expect zlib header */
a731366827a80af216ce6bfd4aa6388260577791Andy Gimblett if (state->head != Z_NULL)
2a5b885d9350ec6dd8bc4992ee91d2f68aa592f4Christian Maeder state->head->done = -1;
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder if (!(state->wrap & 1) || /* check if zlib header allowed */
a731366827a80af216ce6bfd4aa6388260577791Andy Gimblett#else
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder if (
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder#endif
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder ((BITS(8) << 8) + (hold >> 8)) % 31) {
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder strm->msg = (char *)"incorrect header check";
ad872d5e07383c8fec42bddf02a13d1fbcac52b2Christian Maeder state->mode = BAD;
2f615f62c47e2c0ae9964f37f5bac6905d86f475Andy Gimblett break;
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder }
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder if (BITS(4) != Z_DEFLATED) {
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder strm->msg = (char *)"unknown compression method";
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder state->mode = BAD;
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder break;
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder }
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder DROPBITS(4);
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder len = BITS(4) + 8;
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder if (len > state->wbits) {
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder strm->msg = (char *)"invalid window size";
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder state->mode = BAD;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder break;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder }
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder state->dmax = 1U << len;
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder Tracev((stderr, "inflate: zlib header ok\n"));
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder strm->adler = state->check = adler32(0L, Z_NULL, 0);
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder state->mode = hold & 0x200 ? DICTID : TYPE;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder INITBITS();
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder break;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder#ifdef GUNZIP
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder case FLAGS:
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder NEEDBITS(16);
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder state->flags = (int)(hold);
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder if ((state->flags & 0xff) != Z_DEFLATED) {
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder strm->msg = (char *)"unknown compression method";
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder state->mode = BAD;
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder break;
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder }
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder if (state->flags & 0xe000) {
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder strm->msg = (char *)"unknown header flags set";
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder state->mode = BAD;
2a5b885d9350ec6dd8bc4992ee91d2f68aa592f4Christian Maeder break;
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder }
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder if (state->head != Z_NULL)
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder state->head->text = (int)((hold >> 8) & 1);
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder if (state->flags & 0x0200) CRC2(state->check, hold);
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder INITBITS();
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder state->mode = TIME;
a731366827a80af216ce6bfd4aa6388260577791Andy Gimblett case TIME:
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder NEEDBITS(32);
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder if (state->head != Z_NULL)
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder state->head->time = hold;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder if (state->flags & 0x0200) CRC4(state->check, hold);
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder INITBITS();
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder state->mode = OS;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder case OS:
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder NEEDBITS(16);
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder if (state->head != Z_NULL) {
9582375827616730f146b77f9d5a4fd0cc78bc47Andy Gimblett state->head->xflags = (int)(hold & 0xff);
9582375827616730f146b77f9d5a4fd0cc78bc47Andy Gimblett state->head->os = (int)(hold >> 8);
a731366827a80af216ce6bfd4aa6388260577791Andy Gimblett }
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder if (state->flags & 0x0200) CRC2(state->check, hold);
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder INITBITS();
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder state->mode = EXLEN;
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder case EXLEN:
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder if (state->flags & 0x0400) {
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder NEEDBITS(16);
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder state->length = (unsigned)(hold);
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder if (state->head != Z_NULL)
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder state->head->extra_len = (unsigned)hold;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder if (state->flags & 0x0200) CRC2(state->check, hold);
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder INITBITS();
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder }
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder else if (state->head != Z_NULL)
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder state->head->extra = Z_NULL;
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder state->mode = EXTRA;
f18cf8a4e7d512a2f57365ab1e9e7fdbb98ba257Andy Gimblett case EXTRA:
bb83db66bd9b3b4ce67be66419daf29886175276Andy Gimblett if (state->flags & 0x0400) {
c679188b6762edb198e353f724e77c74aa64a7e4Andy Gimblett copy = state->length;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder if (copy > have) copy = have;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder if (copy) {
fd4ad12563262ebe380d810df8f7755cfab5fb42Liam O'Reilly if (state->head != Z_NULL &&
fd4ad12563262ebe380d810df8f7755cfab5fb42Liam O'Reilly state->head->extra != Z_NULL) {
fd4ad12563262ebe380d810df8f7755cfab5fb42Liam O'Reilly len = state->head->extra_len - state->length;
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder zmemcpy(state->head->extra + len, next,
bba1e274cf727c39b4f1dd8970539a2bb967f20fLiam O'Reilly len + copy > state->head->extra_max ?
fd4ad12563262ebe380d810df8f7755cfab5fb42Liam O'Reilly state->head->extra_max - len : copy);
fd4ad12563262ebe380d810df8f7755cfab5fb42Liam O'Reilly }
fd4ad12563262ebe380d810df8f7755cfab5fb42Liam O'Reilly if (state->flags & 0x0200)
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder state->check = crc32(state->check, next, copy);
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder have -= copy;
bba1e274cf727c39b4f1dd8970539a2bb967f20fLiam O'Reilly next += copy;
bba1e274cf727c39b4f1dd8970539a2bb967f20fLiam O'Reilly state->length -= copy;
fd4ad12563262ebe380d810df8f7755cfab5fb42Liam O'Reilly }
fd4ad12563262ebe380d810df8f7755cfab5fb42Liam O'Reilly if (state->length) goto inf_leave;
fd4ad12563262ebe380d810df8f7755cfab5fb42Liam O'Reilly }
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder state->length = 0;
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder state->mode = NAME;
fd4ad12563262ebe380d810df8f7755cfab5fb42Liam O'Reilly case NAME:
fd4ad12563262ebe380d810df8f7755cfab5fb42Liam O'Reilly if (state->flags & 0x0800) {
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder if (have == 0) goto inf_leave;
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder copy = 0;
fd4ad12563262ebe380d810df8f7755cfab5fb42Liam O'Reilly do {
fd4ad12563262ebe380d810df8f7755cfab5fb42Liam O'Reilly len = (unsigned)(next[copy++]);
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder if (state->head != Z_NULL &&
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder state->head->name != Z_NULL &&
fd4ad12563262ebe380d810df8f7755cfab5fb42Liam O'Reilly state->length < state->head->name_max)
fd4ad12563262ebe380d810df8f7755cfab5fb42Liam O'Reilly state->head->name[state->length++] = len;
fd4ad12563262ebe380d810df8f7755cfab5fb42Liam O'Reilly } while (len && copy < have);
fd4ad12563262ebe380d810df8f7755cfab5fb42Liam O'Reilly if (state->flags & 0x0200)
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder state->check = crc32(state->check, next, copy);
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder have -= copy;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder next += copy;
fd4ad12563262ebe380d810df8f7755cfab5fb42Liam O'Reilly if (len) goto inf_leave;
c679188b6762edb198e353f724e77c74aa64a7e4Andy Gimblett }
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder else if (state->head != Z_NULL)
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder state->head->name = Z_NULL;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder state->length = 0;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder state->mode = COMMENT;
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder case COMMENT:
bb83db66bd9b3b4ce67be66419daf29886175276Andy Gimblett if (state->flags & 0x1000) {
c679188b6762edb198e353f724e77c74aa64a7e4Andy Gimblett if (have == 0) goto inf_leave;
2a5b885d9350ec6dd8bc4992ee91d2f68aa592f4Christian Maeder copy = 0;
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder do {
c679188b6762edb198e353f724e77c74aa64a7e4Andy Gimblett len = (unsigned)(next[copy++]);
5a859092c242b0e37183a44c3c79479125b2920aChristian Maeder if (state->head != Z_NULL &&
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder state->head->comment != Z_NULL &&
c679188b6762edb198e353f724e77c74aa64a7e4Andy Gimblett state->length < state->head->comm_max)
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder state->head->comment[state->length++] = len;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder } while (len && copy < have);
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder if (state->flags & 0x0200)
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder state->check = crc32(state->check, next, copy);
c679188b6762edb198e353f724e77c74aa64a7e4Andy Gimblett have -= copy;
c679188b6762edb198e353f724e77c74aa64a7e4Andy Gimblett next += copy;
e7ddd5495421698701a2bbc57a5b3390a11d12caChristian Maeder if (len) goto inf_leave;
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder }
c679188b6762edb198e353f724e77c74aa64a7e4Andy Gimblett else if (state->head != Z_NULL)
e7ddd5495421698701a2bbc57a5b3390a11d12caChristian Maeder state->head->comment = Z_NULL;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder state->mode = HCRC;
c679188b6762edb198e353f724e77c74aa64a7e4Andy Gimblett case HCRC:
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder if (state->flags & 0x0200) {
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder NEEDBITS(16);
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder if (hold != (state->check & 0xffff)) {
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder strm->msg = (char *)"header crc mismatch";
f18cf8a4e7d512a2f57365ab1e9e7fdbb98ba257Andy Gimblett state->mode = BAD;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder break;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder }
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder INITBITS();
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder }
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder if (state->head != Z_NULL) {
dd7da1b5fedc05b92ba023ebd803e6f4a662503bChristian Maeder state->head->hcrc = (int)((state->flags >> 9) & 1);
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder state->head->done = 1;
f18cf8a4e7d512a2f57365ab1e9e7fdbb98ba257Andy Gimblett }
5b5db1d788d5240070930175f1322dab56279f99Andy Gimblett strm->adler = state->check = crc32(0L, Z_NULL, 0);
5b5db1d788d5240070930175f1322dab56279f99Andy Gimblett state->mode = TYPE;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder break;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder#endif
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder case DICTID:
ad872d5e07383c8fec42bddf02a13d1fbcac52b2Christian Maeder NEEDBITS(32);
ad872d5e07383c8fec42bddf02a13d1fbcac52b2Christian Maeder strm->adler = state->check = REVERSE(hold);
ad872d5e07383c8fec42bddf02a13d1fbcac52b2Christian Maeder INITBITS();
d04c328b10f17ec78001a94d694f7188ebd8c03cAndy Gimblett state->mode = DICT;
d04c328b10f17ec78001a94d694f7188ebd8c03cAndy Gimblett case DICT:
d04c328b10f17ec78001a94d694f7188ebd8c03cAndy Gimblett if (state->havedict == 0) {
ad872d5e07383c8fec42bddf02a13d1fbcac52b2Christian Maeder RESTORE();
c909c215242232fe78ce335e677e6f22264a0ee9Christian Maeder return Z_NEED_DICT;
d04c328b10f17ec78001a94d694f7188ebd8c03cAndy Gimblett }
5b5db1d788d5240070930175f1322dab56279f99Andy Gimblett strm->adler = state->check = adler32(0L, Z_NULL, 0);
5cc369fbceee1b13bd0f06e43620c46541d1d4f8Christian Maeder state->mode = TYPE;
5cc369fbceee1b13bd0f06e43620c46541d1d4f8Christian Maeder case TYPE:
5cc369fbceee1b13bd0f06e43620c46541d1d4f8Christian Maeder if (flush == Z_BLOCK) goto inf_leave;
5cc369fbceee1b13bd0f06e43620c46541d1d4f8Christian Maeder case TYPEDO:
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder if (state->last) {
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder BYTEBITS();
ad872d5e07383c8fec42bddf02a13d1fbcac52b2Christian Maeder state->mode = CHECK;
ad872d5e07383c8fec42bddf02a13d1fbcac52b2Christian Maeder break;
ad872d5e07383c8fec42bddf02a13d1fbcac52b2Christian Maeder }
bb83db66bd9b3b4ce67be66419daf29886175276Andy Gimblett NEEDBITS(3);
bb83db66bd9b3b4ce67be66419daf29886175276Andy Gimblett state->last = BITS(1);
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder DROPBITS(1);
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder switch (BITS(2)) {
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder case 0: /* stored block */
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder Tracev((stderr, "inflate: stored block%s\n",
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder state->last ? " (last)" : ""));
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder state->mode = STORED;
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder break;
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder case 1: /* fixed block */
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder fixedtables(state);
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder Tracev((stderr, "inflate: fixed codes block%s\n",
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder state->last ? " (last)" : ""));
842ae753ab848a8508c4832ab64296b929167a97Christian Maeder state->mode = LEN; /* decode codes */
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder break;
5b5db1d788d5240070930175f1322dab56279f99Andy Gimblett case 2: /* dynamic block */
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder Tracev((stderr, "inflate: dynamic codes block%s\n",
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder state->last ? " (last)" : ""));
5b5db1d788d5240070930175f1322dab56279f99Andy Gimblett state->mode = TABLE;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder break;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder case 3:
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder strm->msg = (char *)"invalid block type";
ad872d5e07383c8fec42bddf02a13d1fbcac52b2Christian Maeder state->mode = BAD;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder }
ad872d5e07383c8fec42bddf02a13d1fbcac52b2Christian Maeder DROPBITS(2);
7cbbd12f559c5c700f521a52424b098db198f1b4Liam O'Reilly break;
5b5db1d788d5240070930175f1322dab56279f99Andy Gimblett case STORED:
5b5db1d788d5240070930175f1322dab56279f99Andy Gimblett BYTEBITS(); /* go to byte boundary */
5b5db1d788d5240070930175f1322dab56279f99Andy Gimblett NEEDBITS(32);
ad872d5e07383c8fec42bddf02a13d1fbcac52b2Christian Maeder if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
5b5db1d788d5240070930175f1322dab56279f99Andy Gimblett strm->msg = (char *)"invalid stored block lengths";
5b5db1d788d5240070930175f1322dab56279f99Andy Gimblett state->mode = BAD;
5b5db1d788d5240070930175f1322dab56279f99Andy Gimblett break;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder }
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder state->length = (unsigned)hold & 0xffff;
ad872d5e07383c8fec42bddf02a13d1fbcac52b2Christian Maeder Tracev((stderr, "inflate: stored length %u\n",
ad872d5e07383c8fec42bddf02a13d1fbcac52b2Christian Maeder state->length));
ad872d5e07383c8fec42bddf02a13d1fbcac52b2Christian Maeder INITBITS();
ad872d5e07383c8fec42bddf02a13d1fbcac52b2Christian Maeder state->mode = COPY;
5b5db1d788d5240070930175f1322dab56279f99Andy Gimblett case COPY:
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder copy = state->length;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder if (copy) {
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder if (copy > have) copy = have;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder if (copy > left) copy = left;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder if (copy == 0) goto inf_leave;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder zmemcpy(put, next, copy);
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder have -= copy;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder next += copy;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder left -= copy;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder put += copy;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder state->length -= copy;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder break;
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder }
7f24d24e63854a9a2539c2dac55198f746ad57dbChristian Maeder Tracev((stderr, "inflate: stored end\n"));
state->mode = TYPE;
break;
case TABLE:
NEEDBITS(14);
state->nlen = BITS(5) + 257;
DROPBITS(5);
state->ndist = BITS(5) + 1;
DROPBITS(5);
state->ncode = BITS(4) + 4;
DROPBITS(4);
#ifndef PKZIP_BUG_WORKAROUND
if (state->nlen > 286 || state->ndist > 30) {
strm->msg = (char *)"too many length or distance symbols";
state->mode = BAD;
break;
}
#endif
Tracev((stderr, "inflate: table sizes ok\n"));
state->have = 0;
state->mode = LENLENS;
case LENLENS:
while (state->have < state->ncode) {
NEEDBITS(3);
state->lens[order[state->have++]] = (unsigned short)BITS(3);
DROPBITS(3);
}
while (state->have < 19)
state->lens[order[state->have++]] = 0;
state->next = state->codes;
state->lencode = (code const FAR *)(state->next);
state->lenbits = 7;
ret = inflate_table(CODES, state->lens, 19, &(state->next),
&(state->lenbits), state->work);
if (ret) {
strm->msg = (char *)"invalid code lengths set";
state->mode = BAD;
break;
}
Tracev((stderr, "inflate: code lengths ok\n"));
state->have = 0;
state->mode = CODELENS;
case CODELENS:
while (state->have < state->nlen + state->ndist) {
for (;;) {
this = state->lencode[BITS(state->lenbits)];
if ((unsigned)(this.bits) <= bits) break;
PULLBYTE();
}
if (this.val < 16) {
NEEDBITS(this.bits);
DROPBITS(this.bits);
state->lens[state->have++] = this.val;
}
else {
if (this.val == 16) {
NEEDBITS(this.bits + 2);
DROPBITS(this.bits);
if (state->have == 0) {
strm->msg = (char *)"invalid bit length repeat";
state->mode = BAD;
break;
}
len = state->lens[state->have - 1];
copy = 3 + BITS(2);
DROPBITS(2);
}
else if (this.val == 17) {
NEEDBITS(this.bits + 3);
DROPBITS(this.bits);
len = 0;
copy = 3 + BITS(3);
DROPBITS(3);
}
else {
NEEDBITS(this.bits + 7);
DROPBITS(this.bits);
len = 0;
copy = 11 + BITS(7);
DROPBITS(7);
}
if (state->have + copy > state->nlen + state->ndist) {
strm->msg = (char *)"invalid bit length repeat";
state->mode = BAD;
break;
}
while (copy--)
state->lens[state->have++] = (unsigned short)len;
}
}
/* handle error breaks in while */
if (state->mode == BAD) break;
/* build code tables */
state->next = state->codes;
state->lencode = (code const FAR *)(state->next);
state->lenbits = 9;
ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
&(state->lenbits), state->work);
if (ret) {
strm->msg = (char *)"invalid literal/lengths set";
state->mode = BAD;
break;
}
state->distcode = (code const FAR *)(state->next);
state->distbits = 6;
ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
&(state->next), &(state->distbits), state->work);
if (ret) {
strm->msg = (char *)"invalid distances set";
state->mode = BAD;
break;
}
Tracev((stderr, "inflate: codes ok\n"));
state->mode = LEN;
case LEN:
if (have >= 6 && left >= 258) {
RESTORE();
inflate_fast(strm, out);
LOAD();
break;
}
for (;;) {
this = state->lencode[BITS(state->lenbits)];
if ((unsigned)(this.bits) <= bits) break;
PULLBYTE();
}
if (this.op && (this.op & 0xf0) == 0) {
last = this;
for (;;) {
this = state->lencode[last.val +
(BITS(last.bits + last.op) >> last.bits)];
if ((unsigned)(last.bits + this.bits) <= bits) break;
PULLBYTE();
}
DROPBITS(last.bits);
}
DROPBITS(this.bits);
state->length = (unsigned)this.val;
if ((int)(this.op) == 0) {
Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ?
"inflate: literal '%c'\n" :
"inflate: literal 0x%02x\n", this.val));
state->mode = LIT;
break;
}
if (this.op & 32) {
Tracevv((stderr, "inflate: end of block\n"));
state->mode = TYPE;
break;
}
if (this.op & 64) {
strm->msg = (char *)"invalid literal/length code";
state->mode = BAD;
break;
}
state->extra = (unsigned)(this.op) & 15;
state->mode = LENEXT;
case LENEXT:
if (state->extra) {
NEEDBITS(state->extra);
state->length += BITS(state->extra);
DROPBITS(state->extra);
}
Tracevv((stderr, "inflate: length %u\n", state->length));
state->mode = DIST;
case DIST:
for (;;) {
this = state->distcode[BITS(state->distbits)];
if ((unsigned)(this.bits) <= bits) break;
PULLBYTE();
}
if ((this.op & 0xf0) == 0) {
last = this;
for (;;) {
this = state->distcode[last.val +
(BITS(last.bits + last.op) >> last.bits)];
if ((unsigned)(last.bits + this.bits) <= bits) break;
PULLBYTE();
}
DROPBITS(last.bits);
}
DROPBITS(this.bits);
if (this.op & 64) {
strm->msg = (char *)"invalid distance code";
state->mode = BAD;
break;
}
state->offset = (unsigned)this.val;
state->extra = (unsigned)(this.op) & 15;
state->mode = DISTEXT;
case DISTEXT:
if (state->extra) {
NEEDBITS(state->extra);
state->offset += BITS(state->extra);
DROPBITS(state->extra);
}
#ifdef INFLATE_STRICT
if (state->offset > state->dmax) {
strm->msg = (char *)"invalid distance too far back";
state->mode = BAD;
break;
}
#endif
if (state->offset > state->whave + out - left) {
strm->msg = (char *)"invalid distance too far back";
state->mode = BAD;
break;
}
Tracevv((stderr, "inflate: distance %u\n", state->offset));
state->mode = MATCH;
case MATCH:
if (left == 0) goto inf_leave;
copy = out - left;
if (state->offset > copy) { /* copy from window */
copy = state->offset - copy;
if (copy > state->write) {
copy -= state->write;
from = state->window + (state->wsize - copy);
}
else
from = state->window + (state->write - copy);
if (copy > state->length) copy = state->length;
}
else { /* copy from output */
from = put - state->offset;
copy = state->length;
}
if (copy > left) copy = left;
left -= copy;
state->length -= copy;
do {
*put++ = *from++;
} while (--copy);
if (state->length == 0) state->mode = LEN;
break;
case LIT:
if (left == 0) goto inf_leave;
*put++ = (unsigned char)(state->length);
left--;
state->mode = LEN;
break;
case CHECK:
if (state->wrap) {
NEEDBITS(32);
out -= left;
strm->total_out += out;
state->total += out;
if (out)
strm->adler = state->check =
UPDATE(state->check, put - out, out);
out = left;
if ((
#ifdef GUNZIP
state->flags ? hold :
#endif
REVERSE(hold)) != state->check) {
strm->msg = (char *)"incorrect data check";
state->mode = BAD;
break;
}
INITBITS();
Tracev((stderr, "inflate: check matches trailer\n"));
}
#ifdef GUNZIP
state->mode = LENGTH;
case LENGTH:
if (state->wrap && state->flags) {
NEEDBITS(32);
if (hold != (state->total & 0xffffffffUL)) {
strm->msg = (char *)"incorrect length check";
state->mode = BAD;
break;
}
INITBITS();
Tracev((stderr, "inflate: length matches trailer\n"));
}
#endif
state->mode = DONE;
case DONE:
ret = Z_STREAM_END;
goto inf_leave;
case BAD:
ret = Z_DATA_ERROR;
goto inf_leave;
case MEM:
return Z_MEM_ERROR;
case SYNC:
default:
return Z_STREAM_ERROR;
}
/*
Return from inflate(), updating the total counts and the check value.
If there was no progress during the inflate() call, return a buffer
error. Call updatewindow() to create and/or update the window state.
Note: a memory error from inflate() is non-recoverable.
*/
inf_leave:
RESTORE();
if (state->wsize || (state->mode < CHECK && out != strm->avail_out))
if (updatewindow(strm, out)) {
state->mode = MEM;
return Z_MEM_ERROR;
}
in -= strm->avail_in;
out -= strm->avail_out;
strm->total_in += in;
strm->total_out += out;
state->total += out;
if (state->wrap && out)
strm->adler = state->check =
UPDATE(state->check, strm->next_out - out, out);
strm->data_type = state->bits + (state->last ? 64 : 0) +
(state->mode == TYPE ? 128 : 0);
if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK)
ret = Z_BUF_ERROR;
return ret;
}
int ZEXPORT inflateEnd(strm)
z_streamp strm;
{
struct inflate_state FAR *state;
if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0)
return Z_STREAM_ERROR;
state = (struct inflate_state FAR *)strm->state;
if (state->window != Z_NULL) ZFREE(strm, state->window);
ZFREE(strm, strm->state);
strm->state = Z_NULL;
Tracev((stderr, "inflate: end\n"));
return Z_OK;
}
int ZEXPORT inflateSetDictionary(strm, dictionary, dictLength)
z_streamp strm;
const Bytef *dictionary;
uInt dictLength;
{
struct inflate_state FAR *state;
unsigned long id;
/* check state */
if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
state = (struct inflate_state FAR *)strm->state;
if (state->wrap != 0 && state->mode != DICT)
return Z_STREAM_ERROR;
/* check for correct dictionary id */
if (state->mode == DICT) {
id = adler32(0L, Z_NULL, 0);
id = adler32(id, dictionary, dictLength);
if (id != state->check)
return Z_DATA_ERROR;
}
/* copy dictionary to window */
if (updatewindow(strm, strm->avail_out)) {
state->mode = MEM;
return Z_MEM_ERROR;
}
if (dictLength > state->wsize) {
zmemcpy(state->window, dictionary + dictLength - state->wsize,
state->wsize);
state->whave = state->wsize;
}
else {
zmemcpy(state->window + state->wsize - dictLength, dictionary,
dictLength);
state->whave = dictLength;
}
state->havedict = 1;
Tracev((stderr, "inflate: dictionary set\n"));
return Z_OK;
}
int ZEXPORT inflateGetHeader(strm, head)
z_streamp strm;
gz_headerp head;
{
struct inflate_state FAR *state;
/* check state */
if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
state = (struct inflate_state FAR *)strm->state;
if ((state->wrap & 2) == 0) return Z_STREAM_ERROR;
/* save header structure */
state->head = head;
head->done = 0;
return Z_OK;
}
/*
Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff. Return when found
or when out of input. When called, *have is the number of pattern bytes
found in order so far, in 0..3. On return *have is updated to the new
state. If on return *have equals four, then the pattern was found and the
return value is how many bytes were read including the last byte of the
pattern. If *have is less than four, then the pattern has not been found
yet and the return value is len. In the latter case, syncsearch() can be
called again with more data and the *have state. *have is initialized to
zero for the first call.
*/
local unsigned syncsearch(have, buf, len)
unsigned FAR *have;
unsigned char FAR *buf;
unsigned len;
{
unsigned got;
unsigned next;
got = *have;
next = 0;
while (next < len && got < 4) {
if ((int)(buf[next]) == (got < 2 ? 0 : 0xff))
got++;
else if (buf[next])
got = 0;
else
got = 4 - got;
next++;
}
*have = got;
return next;
}
int ZEXPORT inflateSync(strm)
z_streamp strm;
{
unsigned len; /* number of bytes to look at or looked at */
unsigned long in, out; /* temporary to save total_in and total_out */
unsigned char buf[4]; /* to restore bit buffer to byte string */
struct inflate_state FAR *state;
/* check parameters */
if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
state = (struct inflate_state FAR *)strm->state;
if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR;
/* if first time, start search in bit buffer */
if (state->mode != SYNC) {
state->mode = SYNC;
state->hold <<= state->bits & 7;
state->bits -= state->bits & 7;
len = 0;
while (state->bits >= 8) {
buf[len++] = (unsigned char)(state->hold);
state->hold >>= 8;
state->bits -= 8;
}
state->have = 0;
syncsearch(&(state->have), buf, len);
}
/* search available input */
len = syncsearch(&(state->have), strm->next_in, strm->avail_in);
strm->avail_in -= len;
strm->next_in += len;
strm->total_in += len;
/* return no joy or set up to restart inflate() on a new block */
if (state->have != 4) return Z_DATA_ERROR;
in = strm->total_in; out = strm->total_out;
inflateReset(strm);
strm->total_in = in; strm->total_out = out;
state->mode = TYPE;
return Z_OK;
}
/*
Returns true if inflate is currently at the end of a block generated by
Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP
implementation to provide an additional safety check. PPP uses
Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored
block. When decompressing, PPP checks that at the end of input packet,
inflate is waiting for these length bytes.
*/
int ZEXPORT inflateSyncPoint(strm)
z_streamp strm;
{
struct inflate_state FAR *state;
if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
state = (struct inflate_state FAR *)strm->state;
return state->mode == STORED && state->bits == 0;
}
int ZEXPORT inflateCopy(dest, source)
z_streamp dest;
z_streamp source;
{
struct inflate_state FAR *state;
struct inflate_state FAR *copy;
unsigned char FAR *window;
unsigned wsize;
/* check input */
if (dest == Z_NULL || source == Z_NULL || source->state == Z_NULL ||
source->zalloc == (alloc_func)0 || source->zfree == (free_func)0)
return Z_STREAM_ERROR;
state = (struct inflate_state FAR *)source->state;
/* allocate space */
copy = (struct inflate_state FAR *)
ZALLOC(source, 1, sizeof(struct inflate_state));
if (copy == Z_NULL) return Z_MEM_ERROR;
window = Z_NULL;
if (state->window != Z_NULL) {
window = (unsigned char FAR *)
ZALLOC(source, 1U << state->wbits, sizeof(unsigned char));
if (window == Z_NULL) {
ZFREE(source, copy);
return Z_MEM_ERROR;
}
}
/* copy state */
zmemcpy(dest, source, sizeof(z_stream));
zmemcpy(copy, state, sizeof(struct inflate_state));
if (state->lencode >= state->codes &&
state->lencode <= state->codes + ENOUGH - 1) {
copy->lencode = copy->codes + (state->lencode - state->codes);
copy->distcode = copy->codes + (state->distcode - state->codes);
}
copy->next = copy->codes + (state->next - state->codes);
if (window != Z_NULL) {
wsize = 1U << state->wbits;
zmemcpy(window, state->window, wsize);
}
copy->window = window;
dest->state = (struct internal_state FAR *)copy;
return Z_OK;
}