/* $Log: infcodes.c,v $ Revision 1.1 2002/03/18 17:14:42 Administrator Moved. Updated to 1.1.4 Revision 1.5 2002/03/12 18:10:25 Official changes for 1.1.4 Official changes for 1.1.4. Better handling of modulo-window size. (Note: s->end - s->window is the window size, so the loop will terminate.) Revision 1.4 2002/02/05 19:35:01 Administrator Standardized chg log Revision 1.3 2002/01/30 16:07:42 forrest@mibsoftware.com rights=#1 Renamed some .h files Revision 1.2 2002/01/29 04:18:11 forrest@mibsoftware.com rights=#1 Lidesc and space/tab clean up Revision 1.1 2002/01/28 17:28:16 forrest@mibsoftware.com rights=#1 Initial rights#1 Copyright (c) Forrest J Cavalier III d-b-a Mib Software rights#1 License text in librock_LIDESC_HC=12440211096131f5976d36be0cddca4cd9152e45 librock_ACQUIRED: 2001-10-23 ftp://ftp.uu.net/graphics/png/src/zlib-1.1.3.tar.gz http://www.gzip.org/zlib/ */ #ifndef librock_ISOLATED /**************************************************************/ #define librock_IMPLEMENT_infcodes #include #include /**************************************************************/ #endif #ifdef librock_IMPL_LIDESC #ifndef librock_NOIMPL_LIDESC_infcodes /**************************************************************/ /* License awareness system. See http://www.mibsoftware.com/librock */ #include /* librock_LIDESC_HC=d49ece91d0f3402f1ca405bc4ae7b2a989a56ab2 */ #include /* librock_LIDESC_HC=12440211096131f5976d36be0cddca4cd9152e45 */ char *librock_LIDESC_infcodes[] = { "\n" __FILE__ librock_LIDESC_zlib "\n", "\n" __FILE__ librock_LIDESC_librock "\n", 0 }; /**************************************************************/ #endif #endif /* Copyright (C) 1995-1998 Jean-loup Gailly and Mark Adler This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. */ /* infcodes.c -- process literals and length/distance pairs * Copyright (C) 1995-2002 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ #include "zutil.h" #include "inftrees.h" #include "infblock.h" #include "infcodes.h" #include "infutil.h" #include "inffast.h" /* simplify the use of the inflate_huft type with some defines */ #define exop word.what.Exop #define bits word.what.Bits typedef enum { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */ START, /* x: set up for LEN */ LEN, /* i: get length/literal/eob next */ LENEXT, /* i: getting length extra (have base) */ DIST, /* i: get distance next */ DISTEXT, /* i: getting distance extra */ COPY, /* o: copying bytes in window, waiting for space */ LIT, /* o: got literal, waiting for output space */ WASH, /* o: got eob, possibly still output waiting */ END, /* x: got eob and all data flushed */ BADCODE} /* x: got error */ inflate_codes_mode; /* inflate codes private state */ struct inflate_codes_state { /* mode */ inflate_codes_mode mode; /* current inflate_codes mode */ /* mode dependent information */ uInt len; union { struct { inflate_huft *tree; /* pointer into tree */ uInt need; /* bits needed */ } code; /* if LEN or DIST, where in tree */ uInt lit; /* if LIT, literal */ struct { uInt get; /* bits to get for extra */ uInt dist; /* distance back to copy from */ } copy; /* if EXT or COPY, where and how much */ } sub; /* submode */ /* mode independent information */ Byte lbits; /* ltree bits decoded per branch */ Byte dbits; /* dtree bits decoder per branch */ inflate_huft *ltree; /* literal/length/eob tree */ inflate_huft *dtree; /* distance tree */ }; inflate_codes_statef *inflate_codes_new(bl, bd, tl, td, z) uInt bl, bd; inflate_huft *tl; inflate_huft *td; /* need separate declaration for Borland C++ */ z_streamp z; { inflate_codes_statef *c; if ((c = (inflate_codes_statef *) ZALLOC(z,1,sizeof(struct inflate_codes_state))) != Z_NULL) { c->mode = START; c->lbits = (Byte)bl; c->dbits = (Byte)bd; c->ltree = tl; c->dtree = td; Tracev((stderr, "inflate: codes new\n")); } return c; } int inflate_codes(s, z, r) inflate_blocks_statef *s; z_streamp z; int r; { uInt j; /* temporary storage */ inflate_huft *t; /* temporary pointer */ uInt e; /* extra bits or operation */ uLong b; /* bit buffer */ uInt k; /* bits in bit buffer */ Bytef *p; /* input data pointer */ uInt n; /* bytes available there */ Bytef *q; /* output window write pointer */ uInt m; /* bytes to end of window or read pointer */ Bytef *f; /* pointer to copy strings from */ inflate_codes_statef *c = s->sub.decode.codes; /* codes state */ /* copy input/output information to locals (UPDATE macro restores) */ LOAD /* process input and output based on current state */ while (1) switch (c->mode) { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */ case START: /* x: set up for LEN */ #ifndef SLOW if (m >= 258 && n >= 10) { UPDATE r = inflate_fast(c->lbits, c->dbits, c->ltree, c->dtree, s, z); LOAD if (r != Z_OK) { c->mode = r == Z_STREAM_END ? WASH : BADCODE; break; } } #endif /* !SLOW */ c->sub.code.need = c->lbits; c->sub.code.tree = c->ltree; c->mode = LEN; case LEN: /* i: get length/literal/eob next */ j = c->sub.code.need; NEEDBITS(j) t = c->sub.code.tree + ((uInt)b & inflate_mask[j]); DUMPBITS(t->bits) e = (uInt)(t->exop); if (e == 0) /* literal */ { c->sub.lit = t->base; Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ? "inflate: literal '%c'\n" : "inflate: literal 0x%02x\n", t->base)); c->mode = LIT; break; } if (e & 16) /* length */ { c->sub.copy.get = e & 15; c->len = t->base; c->mode = LENEXT; break; } if ((e & 64) == 0) /* next table */ { c->sub.code.need = e; c->sub.code.tree = t + t->base; break; } if (e & 32) /* end of block */ { Tracevv((stderr, "inflate: end of block\n")); c->mode = WASH; break; } c->mode = BADCODE; /* invalid code */ z->msg = (char*)"invalid literal/length code"; r = Z_DATA_ERROR; LEAVE case LENEXT: /* i: getting length extra (have base) */ j = c->sub.copy.get; NEEDBITS(j) c->len += (uInt)b & inflate_mask[j]; DUMPBITS(j) c->sub.code.need = c->dbits; c->sub.code.tree = c->dtree; Tracevv((stderr, "inflate: length %u\n", c->len)); c->mode = DIST; case DIST: /* i: get distance next */ j = c->sub.code.need; NEEDBITS(j) t = c->sub.code.tree + ((uInt)b & inflate_mask[j]); DUMPBITS(t->bits) e = (uInt)(t->exop); if (e & 16) /* distance */ { c->sub.copy.get = e & 15; c->sub.copy.dist = t->base; c->mode = DISTEXT; break; } if ((e & 64) == 0) /* next table */ { c->sub.code.need = e; c->sub.code.tree = t + t->base; break; } c->mode = BADCODE; /* invalid code */ z->msg = (char*)"invalid distance code"; r = Z_DATA_ERROR; LEAVE case DISTEXT: /* i: getting distance extra */ j = c->sub.copy.get; NEEDBITS(j) c->sub.copy.dist += (uInt)b & inflate_mask[j]; DUMPBITS(j) Tracevv((stderr, "inflate: distance %u\n", c->sub.copy.dist)); c->mode = COPY; case COPY: /* o: copying bytes in window, waiting for space */ f = q - c->sub.copy.dist; while (f < s->window) /* modulo window size-"while" instead */ f += s->end - s->window; /* of "if" handles invalid distances */ while (c->len) { NEEDOUT OUTBYTE(*f++) if (f == s->end) f = s->window; c->len--; } c->mode = START; break; case LIT: /* o: got literal, waiting for output space */ NEEDOUT OUTBYTE(c->sub.lit) c->mode = START; break; case WASH: /* o: got eob, possibly more output */ if (k > 7) /* return unused byte, if any */ { Assert(k < 16, "inflate_codes grabbed too many bytes") k -= 8; n++; p--; /* can always return one */ } FLUSH if (s->read != s->write) LEAVE c->mode = END; case END: r = Z_STREAM_END; LEAVE case BADCODE: /* x: got error */ r = Z_DATA_ERROR; LEAVE default: r = Z_STREAM_ERROR; LEAVE } #ifdef NEED_DUMMY_RETURN return Z_STREAM_ERROR; /* Some dumb compilers complain without this */ #endif } void inflate_codes_free(c, z) inflate_codes_statef *c; z_streamp z; { ZFREE(z, c); Tracev((stderr, "inflate: codes free\n")); }