diff options
author | unknown <konstantin@mysql.com> | 2004-07-21 17:36:26 -0700 |
---|---|---|
committer | unknown <konstantin@mysql.com> | 2004-07-21 17:36:26 -0700 |
commit | 9fe0a2fa8dbd83359722e077f761a01e37901bb8 (patch) | |
tree | e1c502ab20782af7b4564054ae3c46a321ccbb4e /zlib/infback.c | |
parent | 2f26571fdcfc4eb701273079ede7fce7afa89e46 (diff) | |
download | mariadb-git-9fe0a2fa8dbd83359722e077f761a01e37901bb8.tar.gz |
First step of implementation of WL#1518 "make bundled zlib
usable for unix builds": zlib 1.2.1 imported
BitKeeper/deleted/.del-Make_vms.com~95dd9cc7505c3153:
Delete: zlib/Make_vms.com
BitKeeper/deleted/.del-Makefile.riscos~f85c6493d3e51733:
Delete: zlib/Makefile.riscos
BitKeeper/deleted/.del-Makefile.pup~b0e9ed99224cc5f4:
Delete: zlib/amiga/Makefile.pup
BitKeeper/deleted/.del-Makefile.sas~be103e936c85b66a:
Delete: zlib/amiga/Makefile.sas
BitKeeper/deleted/.del-README.contrib~2924ba28ef1f9fab:
Delete: zlib/contrib/README.contrib
BitKeeper/deleted/.del-gvmat32.asm~edf721a2de30e964:
Delete: zlib/contrib/asm386/gvmat32.asm
BitKeeper/deleted/.del-visual-basic.txt~859fcbcb668ffbb3:
Delete: zlib/contrib/visual-basic.txt
BitKeeper/deleted/.del-gvmat32c.c~2e97d7d65dd59113:
Delete: zlib/contrib/asm386/gvmat32c.c
BitKeeper/deleted/.del-mkgvmt32.bat~5a92cf0febe3dc81:
Delete: zlib/contrib/asm386/mkgvmt32.bat
BitKeeper/deleted/.del-zlibvc.def~67961fa7815b9267:
Delete: zlib/contrib/asm386/zlibvc.def
BitKeeper/deleted/.del-zlibvc.dsp~a3323c77bcd12995:
Delete: zlib/contrib/asm386/zlibvc.dsp
BitKeeper/deleted/.del-match.s~51b8fef5136642ed:
Delete: zlib/contrib/asm586/match.s
BitKeeper/deleted/.del-readme.586~cb1bb7136b0803bb:
Delete: zlib/contrib/asm586/readme.586
BitKeeper/deleted/.del-zlibvc.dsw~e3dca9d8f342e64e:
Delete: zlib/contrib/asm386/zlibvc.dsw
BitKeeper/deleted/.del-match.s~e4bbe1fa486d1c6c:
Delete: zlib/contrib/asm686/match.s
BitKeeper/deleted/.del-readme.686~98a220c13809fce5:
Delete: zlib/contrib/asm686/readme.686
BitKeeper/deleted/.del-zlib.mak~70f7c5f6947fd807:
Delete: zlib/contrib/delphi/zlib.mak
BitKeeper/deleted/.del-d_zlib.bpr~cefb1beee520d6e8:
Delete: zlib/contrib/delphi2/d_zlib.bpr
BitKeeper/deleted/.del-d_zlib.cpp~62dff1931881afa6:
Delete: zlib/contrib/delphi2/d_zlib.cpp
BitKeeper/deleted/.del-zlibdef.pas~780244c8d12b6c53:
Delete: zlib/contrib/delphi/zlibdef.pas
BitKeeper/deleted/.del-readme.txt~8222e54ca00f2729:
Delete: zlib/contrib/delphi2/readme.txt
BitKeeper/deleted/.del-zlib.bpg~fbd9308275ad8e3:
Delete: zlib/contrib/delphi2/zlib.bpg
BitKeeper/deleted/.del-zlib.bpr~fe8bf5d1c4a2ce5a:
Delete: zlib/contrib/delphi2/zlib.bpr
BitKeeper/deleted/.del-zlib.cpp~bb0c3df062410f5c:
Delete: zlib/contrib/delphi2/zlib.cpp
BitKeeper/deleted/.del-zlib.pas~1d5285e2449b50a3:
Delete: zlib/contrib/delphi2/zlib.pas
BitKeeper/deleted/.del-zlib32.bpr~c2a9f0aa47a1d9ad:
Delete: zlib/contrib/delphi2/zlib32.bpr
BitKeeper/deleted/.del-test.cpp~4480297b204dc360:
Delete: zlib/contrib/iostream/test.cpp
BitKeeper/deleted/.del-zfstream.cpp~943ecbd558e86dde:
Delete: zlib/contrib/iostream/zfstream.cpp
BitKeeper/deleted/.del-zlib32.cpp~bbb4a200d2fe6497:
Delete: zlib/contrib/delphi2/zlib32.cpp
BitKeeper/deleted/.del-ChangeLogUnzip~a3ae0ba899cadd:
Delete: zlib/contrib/minizip/ChangeLogUnzip
BitKeeper/deleted/.del-zfstream.h~71ee057bdc6366ac:
Delete: zlib/contrib/iostream/zfstream.h
BitKeeper/deleted/.del-zstream.h~a6f6be5634962c81:
Delete: zlib/contrib/iostream2/zstream.h
BitKeeper/deleted/.del-zstream_test.cpp~e471b51e7fb553ec:
Delete: zlib/contrib/iostream2/zstream_test.cpp
BitKeeper/deleted/.del-miniunz.c~9da181975b3a48:
Delete: zlib/contrib/minizip/miniunz.c
BitKeeper/deleted/.del-minizip.c~4a49a0addb97272b:
Delete: zlib/contrib/minizip/minizip.c
BitKeeper/deleted/.del-readme.txt~174eb00680149f6b:
Delete: zlib/contrib/minizip/readme.txt
BitKeeper/deleted/.del-unzip.c~662c5ba4edbb3a19:
Delete: zlib/contrib/minizip/unzip.c
BitKeeper/deleted/.del-unzip.def~8a0ad6f745ee5cd4:
Delete: zlib/contrib/minizip/unzip.def
BitKeeper/deleted/.del-unzip.h~d5e800088a368c32:
Delete: zlib/contrib/minizip/unzip.h
BitKeeper/deleted/.del-zip.c~9750c19a123f3057:
Delete: zlib/contrib/minizip/zip.c
BitKeeper/deleted/.del-zip.def~4ffe888e9fd7b5aa:
Delete: zlib/contrib/minizip/zip.def
BitKeeper/deleted/.del-zip.h~4c72b8fcc492f055:
Delete: zlib/contrib/minizip/zip.h
BitKeeper/deleted/.del-zlibvc.def~dd272b3ed71647ba:
Delete: zlib/contrib/minizip/zlibvc.def
BitKeeper/deleted/.del-zlibvc.dsp~ad83fb048811e2d2:
Delete: zlib/contrib/minizip/zlibvc.dsp
BitKeeper/deleted/.del-zlibvc.dsw~c66b33a2d52f37c5:
Delete: zlib/contrib/minizip/zlibvc.dsw
BitKeeper/deleted/.del-makefile.w32~6507530fa1b017c:
Delete: zlib/contrib/untgz/makefile.w32
BitKeeper/deleted/.del-untgz.c~4e8f1a3a2c145373:
Delete: zlib/contrib/untgz/untgz.c
BitKeeper/deleted/.del-Makefile.os2~8ab058477b24d1ff:
Delete: zlib/os2/Makefile.os2
BitKeeper/deleted/.del-zlib.def~385b56ed82784ff3:
Delete: zlib/os2/zlib.def
BitKeeper/deleted/.del-Makefile.b32~10ffaac6cc41847a:
Delete: zlib/msdos/Makefile.b32
BitKeeper/deleted/.del-Makefile.bor~121b2bc837b6367:
Delete: zlib/msdos/Makefile.bor
BitKeeper/deleted/.del-Makefile.dj2~a069623cad6ce7f4:
Delete: zlib/msdos/Makefile.dj2
BitKeeper/deleted/.del-Makefile.emx~11a9e6c8a719ba60:
Delete: zlib/msdos/Makefile.emx
BitKeeper/deleted/.del-Makefile.msc~ba5ad7709ff22aab:
Delete: zlib/msdos/Makefile.msc
BitKeeper/deleted/.del-Makefile.tc~d1398368648e8836:
Delete: zlib/msdos/Makefile.tc
BitKeeper/deleted/.del-Makefile.w32~921a473e873d94d1:
Delete: zlib/msdos/Makefile.w32
BitKeeper/deleted/.del-Makefile.wat~b2b51cbc2c2bc2f4:
Delete: zlib/msdos/Makefile.wat
BitKeeper/deleted/.del-zlib.def~189fba701e5e4b9c:
Delete: zlib/msdos/zlib.def
BitKeeper/deleted/.del-zlib.rc~e5ce22c7c915ec00:
Delete: zlib/msdos/zlib.rc
BitKeeper/deleted/.del-Makefile.emx~b5fa0633cbe6fe01:
Delete: zlib/nt/Makefile.emx
BitKeeper/deleted/.del-Makefile.gcc~7fcd3dd326341fa0:
Delete: zlib/nt/Makefile.gcc
BitKeeper/deleted/.del-Makefile.nt~9910c98f5da056de:
Delete: zlib/nt/Makefile.nt
BitKeeper/deleted/.del-zlib.dnt~8160c636eb3eeed7:
Delete: zlib/nt/zlib.dnt
BitKeeper/deleted/.del-zlib.dsp~a8abac2fb721276e:
Delete: zlib/zlib.dsp
BitKeeper/deleted/.del-zlib.html~2e74efd497dcd4d0:
Delete: zlib/zlib.html
BitKeeper/deleted/.del-minigzip.c~1f21a5863f457cb0:
Delete: zlib/minigzip.c
BitKeeper/deleted/.del-example.c~5ea43c929ccd2a4f:
Delete: zlib/example.c
BitKeeper/deleted/.del-descrip.mms~51cd5d1792d76b9c:
Delete: zlib/descrip.mms
BitKeeper/deleted/.del-infblock.h~7d4f40c3a1d4cdf8:
Delete: zlib/infblock.h
BitKeeper/deleted/.del-infblock.c~3c866934e0f44c43:
Delete: zlib/infblock.c
BitKeeper/deleted/.del-infutil.c~43d2340436244b52:
Delete: zlib/infutil.c
BitKeeper/deleted/.del-infutil.h~a6bd0dcbbdc187ac:
Delete: zlib/infutil.h
BitKeeper/deleted/.del-infcodes.h~c9f64a612c2cc56a:
Delete: zlib/infcodes.h
BitKeeper/deleted/.del-infcodes.c~7ed73df8a54d6d55:
Delete: zlib/infcodes.c
BitKeeper/deleted/.del-maketree.c~846b8b96ac6872d8:
Delete: zlib/maketree.c
VC++Files/zlib/zlib.dsp:
Modified to suit zlib upgrade.
mysys/my_crc32.c:
Modified to suit zlib upgrade.
zlib/ChangeLog:
zlib 1.2.1 imported
zlib/FAQ:
zlib 1.2.1 imported
zlib/INDEX:
zlib 1.2.1 imported
zlib/README:
zlib 1.2.1 imported
zlib/adler32.c:
zlib 1.2.1 imported
zlib/algorithm.txt:
zlib 1.2.1 imported
zlib/compress.c:
zlib 1.2.1 imported
zlib/crc32.c:
zlib 1.2.1 imported
zlib/deflate.c:
zlib 1.2.1 imported
zlib/deflate.h:
zlib 1.2.1 imported
zlib/gzio.c:
zlib 1.2.1 imported
zlib/inffast.c:
zlib 1.2.1 imported
zlib/inffast.h:
zlib 1.2.1 imported
zlib/inffixed.h:
zlib 1.2.1 imported
zlib/inflate.c:
zlib 1.2.1 imported
zlib/inftrees.c:
zlib 1.2.1 imported
zlib/inftrees.h:
zlib 1.2.1 imported
zlib/trees.c:
zlib 1.2.1 imported
zlib/uncompr.c:
zlib 1.2.1 imported
zlib/zconf.h:
zlib 1.2.1 imported
zlib/zlib.3:
zlib 1.2.1 imported
zlib/zlib.h:
zlib 1.2.1 imported
zlib/zutil.c:
zlib 1.2.1 imported
zlib/zutil.h:
zlib 1.2.1 imported
Diffstat (limited to 'zlib/infback.c')
-rw-r--r-- | zlib/infback.c | 619 |
1 files changed, 619 insertions, 0 deletions
diff --git a/zlib/infback.c b/zlib/infback.c new file mode 100644 index 00000000000..110b03b857f --- /dev/null +++ b/zlib/infback.c @@ -0,0 +1,619 @@ +/* infback.c -- inflate using a call-back interface + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + This code is largely copied from inflate.c. Normally either infback.o or + inflate.o would be linked into an application--not both. The interface + with inffast.c is retained so that optimized assembler-coded versions of + inflate_fast() can be used with either inflate.c or infback.c. + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +/* function prototypes */ +local void fixedtables OF((struct inflate_state FAR *state)); + +/* + strm provides memory allocation functions in zalloc and zfree, or + Z_NULL to use the library memory allocation functions. + + windowBits is in the range 8..15, and window is a user-supplied + window and output buffer that is 2**windowBits bytes. + */ +int ZEXPORT inflateBackInit_(strm, windowBits, window, version, stream_size) +z_stream FAR *strm; +int windowBits; +unsigned char FAR *window; +const char *version; +int stream_size; +{ + struct inflate_state FAR *state; + + if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || + stream_size != (int)(sizeof(z_stream))) + return Z_VERSION_ERROR; + if (strm == Z_NULL || window == Z_NULL || + windowBits < 8 || windowBits > 15) + return Z_STREAM_ERROR; + strm->msg = Z_NULL; /* in case we return an error */ + if (strm->zalloc == (alloc_func)0) { + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; + } + if (strm->zfree == (free_func)0) strm->zfree = zcfree; + state = (struct inflate_state FAR *)ZALLOC(strm, 1, + sizeof(struct inflate_state)); + if (state == Z_NULL) return Z_MEM_ERROR; + Tracev((stderr, "inflate: allocated\n")); + strm->state = (voidpf)state; + state->wbits = windowBits; + state->wsize = 1U << windowBits; + state->window = window; + state->write = 0; + state->whave = 0; + return Z_OK; +} + +/* + Return state with length and distance decoding tables and index sizes set to + fixed code decoding. Normally this returns fixed tables from inffixed.h. + If BUILDFIXED is defined, then instead this routine builds the tables the + first time it's called, and returns those tables the first time and + thereafter. This reduces the size of the code by about 2K bytes, in + exchange for a little execution time. However, BUILDFIXED should not be + used for threaded applications, since the rewriting of the tables and virgin + may not be thread-safe. + */ +local void fixedtables(state) +struct inflate_state FAR *state; +{ +#ifdef BUILDFIXED + static int virgin = 1; + static code *lenfix, *distfix; + static code fixed[544]; + + /* build fixed huffman tables if first call (may not be thread safe) */ + if (virgin) { + unsigned sym, bits; + static code *next; + + /* literal/length table */ + sym = 0; + while (sym < 144) state->lens[sym++] = 8; + while (sym < 256) state->lens[sym++] = 9; + while (sym < 280) state->lens[sym++] = 7; + while (sym < 288) state->lens[sym++] = 8; + next = fixed; + lenfix = next; + bits = 9; + inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); + + /* distance table */ + sym = 0; + while (sym < 32) state->lens[sym++] = 5; + distfix = next; + bits = 5; + inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); + + /* do this just once */ + virgin = 0; + } +#else /* !BUILDFIXED */ +# include "inffixed.h" +#endif /* BUILDFIXED */ + state->lencode = lenfix; + state->lenbits = 9; + state->distcode = distfix; + state->distbits = 5; +} + +/* Macros for inflateBack(): */ + +/* Load returned state from inflate_fast() */ +#define LOAD() \ + do { \ + put = strm->next_out; \ + left = strm->avail_out; \ + next = strm->next_in; \ + have = strm->avail_in; \ + hold = state->hold; \ + bits = state->bits; \ + } while (0) + +/* Set state from registers for inflate_fast() */ +#define RESTORE() \ + do { \ + strm->next_out = put; \ + strm->avail_out = left; \ + strm->next_in = next; \ + strm->avail_in = have; \ + state->hold = hold; \ + state->bits = bits; \ + } while (0) + +/* Clear the input bit accumulator */ +#define INITBITS() \ + do { \ + hold = 0; \ + bits = 0; \ + } while (0) + +/* Assure that some input is available. If input is requested, but denied, + then return a Z_BUF_ERROR from inflateBack(). */ +#define PULL() \ + do { \ + if (have == 0) { \ + have = in(in_desc, &next); \ + if (have == 0) { \ + next = Z_NULL; \ + ret = Z_BUF_ERROR; \ + goto inf_leave; \ + } \ + } \ + } while (0) + +/* Get a byte of input into the bit accumulator, or return from inflateBack() + with an error if there is no input available. */ +#define PULLBYTE() \ + do { \ + PULL(); \ + have--; \ + hold += (unsigned long)(*next++) << bits; \ + bits += 8; \ + } while (0) + +/* Assure that there are at least n bits in the bit accumulator. If there is + not enough available input to do that, then return from inflateBack() with + an error. */ +#define NEEDBITS(n) \ + do { \ + while (bits < (unsigned)(n)) \ + PULLBYTE(); \ + } while (0) + +/* Return the low n bits of the bit accumulator (n < 16) */ +#define BITS(n) \ + ((unsigned)hold & ((1U << (n)) - 1)) + +/* Remove n bits from the bit accumulator */ +#define DROPBITS(n) \ + do { \ + hold >>= (n); \ + bits -= (unsigned)(n); \ + } while (0) + +/* Remove zero to seven bits as needed to go to a byte boundary */ +#define BYTEBITS() \ + do { \ + hold >>= bits & 7; \ + bits -= bits & 7; \ + } while (0) + +/* Assure that some output space is available, by writing out the window + if it's full. If the write fails, return from inflateBack() with a + Z_BUF_ERROR. */ +#define ROOM() \ + do { \ + if (left == 0) { \ + put = state->window; \ + left = state->wsize; \ + state->whave = left; \ + if (out(out_desc, put, left)) { \ + ret = Z_BUF_ERROR; \ + goto inf_leave; \ + } \ + } \ + } while (0) + +/* + strm provides the memory allocation functions and window buffer on input, + and provides information on the unused input on return. For Z_DATA_ERROR + returns, strm will also provide an error message. + + in() and out() are the call-back input and output functions. When + inflateBack() needs more input, it calls in(). When inflateBack() has + filled the window with output, or when it completes with data in the + window, it calls out() to write out the data. The application must not + change the provided input until in() is called again or inflateBack() + returns. The application must not change the window/output buffer until + inflateBack() returns. + + in() and out() are called with a descriptor parameter provided in the + inflateBack() call. This parameter can be a structure that provides the + information required to do the read or write, as well as accumulated + information on the input and output such as totals and check values. + + in() should return zero on failure. out() should return non-zero on + failure. If either in() or out() fails, than inflateBack() returns a + Z_BUF_ERROR. strm->next_in can be checked for Z_NULL to see whether it + was in() or out() that caused in the error. Otherwise, inflateBack() + returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format + error, or Z_MEM_ERROR if it could not allocate memory for the state. + inflateBack() can also return Z_STREAM_ERROR if the input parameters + are not correct, i.e. strm is Z_NULL or the state was not initialized. + */ +int ZEXPORT inflateBack(strm, in, in_desc, out, out_desc) +z_stream FAR *strm; +in_func in; +void FAR *in_desc; +out_func out; +void FAR *out_desc; +{ + struct inflate_state FAR *state; + unsigned char FAR *next; /* next input */ + unsigned char FAR *put; /* next output */ + unsigned have, left; /* available input and output */ + unsigned long hold; /* bit buffer */ + unsigned bits; /* bits in bit buffer */ + unsigned copy; /* number of stored or match bytes to copy */ + unsigned char FAR *from; /* where to copy match bytes from */ + code this; /* current decoding table entry */ + code last; /* parent table entry */ + unsigned len; /* length to copy for repeats, bits to drop */ + int ret; /* return code */ + static const unsigned short order[19] = /* permutation of code lengths */ + {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + + /* Check that the strm exists and that the state was initialized */ + if (strm == Z_NULL || strm->state == Z_NULL) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + + /* Reset the state */ + strm->msg = Z_NULL; + state->mode = TYPE; + state->last = 0; + state->whave = 0; + next = strm->next_in; + have = next != Z_NULL ? strm->avail_in : 0; + hold = 0; + bits = 0; + put = state->window; + left = state->wsize; + + /* Inflate until end of block marked as last */ + for (;;) + switch (state->mode) { + case TYPE: + /* determine and dispatch block type */ + if (state->last) { + BYTEBITS(); + state->mode = DONE; + break; + } + NEEDBITS(3); + state->last = BITS(1); + DROPBITS(1); + switch (BITS(2)) { + case 0: /* stored block */ + Tracev((stderr, "inflate: stored block%s\n", + state->last ? " (last)" : "")); + state->mode = STORED; + break; + case 1: /* fixed block */ + fixedtables(state); + Tracev((stderr, "inflate: fixed codes block%s\n", + state->last ? " (last)" : "")); + state->mode = LEN; /* decode codes */ + break; + case 2: /* dynamic block */ + Tracev((stderr, "inflate: dynamic codes block%s\n", + state->last ? " (last)" : "")); + state->mode = TABLE; + break; + case 3: + strm->msg = (char *)"invalid block type"; + state->mode = BAD; + } + DROPBITS(2); + break; + + case STORED: + /* get and verify stored block length */ + BYTEBITS(); /* go to byte boundary */ + NEEDBITS(32); + if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { + strm->msg = (char *)"invalid stored block lengths"; + state->mode = BAD; + break; + } + state->length = (unsigned)hold & 0xffff; + Tracev((stderr, "inflate: stored length %u\n", + state->length)); + INITBITS(); + + /* copy stored block from input to output */ + while (state->length != 0) { + copy = state->length; + PULL(); + ROOM(); + if (copy > have) copy = have; + if (copy > left) copy = left; + zmemcpy(put, next, copy); + have -= copy; + next += copy; + left -= copy; + put += copy; + state->length -= copy; + } + Tracev((stderr, "inflate: stored end\n")); + state->mode = TYPE; + break; + + case TABLE: + /* get dynamic table entries descriptor */ + 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")); + + /* get code length code lengths (not a typo) */ + state->have = 0; + 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")); + + /* get length and distance code code lengths */ + state->have = 0; + 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 = (unsigned)(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; + } + } + + /* 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: + /* use inflate_fast() if we have enough input and output */ + if (have >= 6 && left >= 258) { + RESTORE(); + if (state->whave < state->wsize) + state->whave = state->wsize - left; + inflate_fast(strm, state->wsize); + LOAD(); + break; + } + + /* get a literal, length, or end-of-block code */ + 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; + + /* process literal */ + if (this.op == 0) { + Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", this.val)); + ROOM(); + *put++ = (unsigned char)(state->length); + left--; + state->mode = LEN; + break; + } + + /* process end of block */ + if (this.op & 32) { + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } + + /* invalid code */ + if (this.op & 64) { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + + /* length code -- get extra bits, if any */ + state->extra = (unsigned)(this.op) & 15; + if (state->extra != 0) { + NEEDBITS(state->extra); + state->length += BITS(state->extra); + DROPBITS(state->extra); + } + Tracevv((stderr, "inflate: length %u\n", state->length)); + + /* get distance code */ + 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; + + /* get distance extra bits, if any */ + state->extra = (unsigned)(this.op) & 15; + if (state->extra != 0) { + NEEDBITS(state->extra); + state->offset += BITS(state->extra); + DROPBITS(state->extra); + } + if (state->offset > state->wsize - (state->whave < state->wsize ? + left : 0)) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } + Tracevv((stderr, "inflate: distance %u\n", state->offset)); + + /* copy match from window to output */ + do { + ROOM(); + copy = state->wsize - state->offset; + if (copy < left) { + from = put + copy; + copy = left - copy; + } + else { + from = put - state->offset; + copy = left; + } + if (copy > state->length) copy = state->length; + state->length -= copy; + left -= copy; + do { + *put++ = *from++; + } while (--copy); + } while (state->length != 0); + break; + + case DONE: + /* inflate stream terminated properly -- write leftover output */ + ret = Z_STREAM_END; + if (left < state->wsize) { + if (out(out_desc, state->window, state->wsize - left)) + ret = Z_BUF_ERROR; + } + goto inf_leave; + + case BAD: + ret = Z_DATA_ERROR; + goto inf_leave; + + default: /* can't happen, but makes compilers happy */ + ret = Z_STREAM_ERROR; + goto inf_leave; + } + + /* Return unused input */ + inf_leave: + strm->next_in = next; + strm->avail_in = have; + return ret; +} + +int ZEXPORT inflateBackEnd(strm) +z_stream FAR *strm; +{ + if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) + return Z_STREAM_ERROR; + ZFREE(strm, strm->state); + strm->state = Z_NULL; + Tracev((stderr, "inflate: end\n")); + return Z_OK; +} |