1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * Copyright 2003 Sun Microsystems, Inc. All rights reserved. 3*0Sstevel@tonic-gate * Use is subject to license terms. 4*0Sstevel@tonic-gate */ 5*0Sstevel@tonic-gate 6*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 7*0Sstevel@tonic-gate 8*0Sstevel@tonic-gate /* 9*0Sstevel@tonic-gate * inffast.c -- process literals and length/distance pairs fast 10*0Sstevel@tonic-gate * Copyright (C) 1995-1998 Mark Adler 11*0Sstevel@tonic-gate * For conditions of distribution and use, see copyright notice in zlib.h 12*0Sstevel@tonic-gate */ 13*0Sstevel@tonic-gate 14*0Sstevel@tonic-gate #include "zutil.h" 15*0Sstevel@tonic-gate #include "inftrees.h" 16*0Sstevel@tonic-gate #include "infblock.h" 17*0Sstevel@tonic-gate #include "infcodes.h" 18*0Sstevel@tonic-gate #include "infutil.h" 19*0Sstevel@tonic-gate #include "inffast.h" 20*0Sstevel@tonic-gate 21*0Sstevel@tonic-gate /* simplify the use of the inflate_huft type with some defines */ 22*0Sstevel@tonic-gate #define exop word.what.Exop 23*0Sstevel@tonic-gate #define bits word.what.Bits 24*0Sstevel@tonic-gate 25*0Sstevel@tonic-gate /* macros for bit input with no checking and for returning unused bytes */ 26*0Sstevel@tonic-gate #define GRABBITS(j) {while(k<(j)){b|=((uLong)NEXTBYTE)<<k;k+=8;}} 27*0Sstevel@tonic-gate #define UNGRAB {c=z->avail_in-n;c=(k>>3)<c?k>>3:c;n+=c;p-=c;k-=c<<3;} 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate /* Called with number of bytes left to write in window at least 258 30*0Sstevel@tonic-gate (the maximum string length) and number of input bytes available 31*0Sstevel@tonic-gate at least ten. The ten bytes are six bytes for the longest length/ 32*0Sstevel@tonic-gate distance pair plus four bytes for overloading the bit buffer. */ 33*0Sstevel@tonic-gate 34*0Sstevel@tonic-gate int inflate_fast(bl, bd, tl, td, s, z) 35*0Sstevel@tonic-gate uInt bl, bd; 36*0Sstevel@tonic-gate inflate_huft *tl; 37*0Sstevel@tonic-gate inflate_huft *td; /* need separate declaration for Borland C++ */ 38*0Sstevel@tonic-gate inflate_blocks_statef *s; 39*0Sstevel@tonic-gate z_streamp z; 40*0Sstevel@tonic-gate { 41*0Sstevel@tonic-gate inflate_huft *t; /* temporary pointer */ 42*0Sstevel@tonic-gate uInt e; /* extra bits or operation */ 43*0Sstevel@tonic-gate uLong b; /* bit buffer */ 44*0Sstevel@tonic-gate uInt k; /* bits in bit buffer */ 45*0Sstevel@tonic-gate Bytef *p; /* input data pointer */ 46*0Sstevel@tonic-gate uInt n; /* bytes available there */ 47*0Sstevel@tonic-gate Bytef *q; /* output window write pointer */ 48*0Sstevel@tonic-gate uInt m; /* bytes to end of window or read pointer */ 49*0Sstevel@tonic-gate uInt ml; /* mask for literal/length tree */ 50*0Sstevel@tonic-gate uInt md; /* mask for distance tree */ 51*0Sstevel@tonic-gate uInt c; /* bytes to copy */ 52*0Sstevel@tonic-gate uInt d; /* distance back to copy from */ 53*0Sstevel@tonic-gate Bytef *r; /* copy source pointer */ 54*0Sstevel@tonic-gate 55*0Sstevel@tonic-gate /* load input, output, bit values */ 56*0Sstevel@tonic-gate LOAD 57*0Sstevel@tonic-gate 58*0Sstevel@tonic-gate /* initialize masks */ 59*0Sstevel@tonic-gate ml = inflate_mask[bl]; 60*0Sstevel@tonic-gate md = inflate_mask[bd]; 61*0Sstevel@tonic-gate 62*0Sstevel@tonic-gate /* do until not enough input or output space for fast loop */ 63*0Sstevel@tonic-gate do { /* assume called with m >= 258 && n >= 10 */ 64*0Sstevel@tonic-gate /* get literal/length code */ 65*0Sstevel@tonic-gate GRABBITS(20) /* max bits for literal/length code */ 66*0Sstevel@tonic-gate if ((e = (t = tl + ((uInt)b & ml))->exop) == 0) 67*0Sstevel@tonic-gate { 68*0Sstevel@tonic-gate DUMPBITS(t->bits) 69*0Sstevel@tonic-gate Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ? 70*0Sstevel@tonic-gate "inflate: * literal '%c'\n" : 71*0Sstevel@tonic-gate "inflate: * literal 0x%02x\n", t->base)); 72*0Sstevel@tonic-gate *q++ = (Byte)t->base; 73*0Sstevel@tonic-gate m--; 74*0Sstevel@tonic-gate continue; 75*0Sstevel@tonic-gate } 76*0Sstevel@tonic-gate do { 77*0Sstevel@tonic-gate DUMPBITS(t->bits) 78*0Sstevel@tonic-gate if (e & 16) 79*0Sstevel@tonic-gate { 80*0Sstevel@tonic-gate /* get extra bits for length */ 81*0Sstevel@tonic-gate e &= 15; 82*0Sstevel@tonic-gate c = t->base + ((uInt)b & inflate_mask[e]); 83*0Sstevel@tonic-gate DUMPBITS(e) 84*0Sstevel@tonic-gate Tracevv((stderr, "inflate: * length %u\n", c)); 85*0Sstevel@tonic-gate 86*0Sstevel@tonic-gate /* decode distance base of block to copy */ 87*0Sstevel@tonic-gate GRABBITS(15); /* max bits for distance code */ 88*0Sstevel@tonic-gate e = (t = td + ((uInt)b & md))->exop; 89*0Sstevel@tonic-gate do { 90*0Sstevel@tonic-gate DUMPBITS(t->bits) 91*0Sstevel@tonic-gate if (e & 16) 92*0Sstevel@tonic-gate { 93*0Sstevel@tonic-gate /* get extra bits to add to distance base */ 94*0Sstevel@tonic-gate e &= 15; 95*0Sstevel@tonic-gate GRABBITS(e) /* get extra bits (up to 13) */ 96*0Sstevel@tonic-gate d = t->base + ((uInt)b & inflate_mask[e]); 97*0Sstevel@tonic-gate DUMPBITS(e) 98*0Sstevel@tonic-gate Tracevv((stderr, "inflate: * distance %u\n", d)); 99*0Sstevel@tonic-gate 100*0Sstevel@tonic-gate /* do the copy */ 101*0Sstevel@tonic-gate m -= c; 102*0Sstevel@tonic-gate if ((uInt)(q - s->window) >= d) /* offset before dest */ 103*0Sstevel@tonic-gate { /* just copy */ 104*0Sstevel@tonic-gate r = q - d; 105*0Sstevel@tonic-gate *q++ = *r++; c--; /* minimum count is three, */ 106*0Sstevel@tonic-gate *q++ = *r++; c--; /* so unroll loop a little */ 107*0Sstevel@tonic-gate } 108*0Sstevel@tonic-gate else /* else offset after destination */ 109*0Sstevel@tonic-gate { 110*0Sstevel@tonic-gate e = d - (uInt)(q - s->window); /* bytes from offset to end */ 111*0Sstevel@tonic-gate r = s->end - e; /* pointer to offset */ 112*0Sstevel@tonic-gate if (c > e) /* if source crosses, */ 113*0Sstevel@tonic-gate { 114*0Sstevel@tonic-gate c -= e; /* copy to end of window */ 115*0Sstevel@tonic-gate do { 116*0Sstevel@tonic-gate *q++ = *r++; 117*0Sstevel@tonic-gate } while (--e); 118*0Sstevel@tonic-gate r = s->window; /* copy rest from start of window */ 119*0Sstevel@tonic-gate } 120*0Sstevel@tonic-gate } 121*0Sstevel@tonic-gate do { /* copy all or what's left */ 122*0Sstevel@tonic-gate *q++ = *r++; 123*0Sstevel@tonic-gate } while (--c); 124*0Sstevel@tonic-gate break; 125*0Sstevel@tonic-gate } 126*0Sstevel@tonic-gate else if ((e & 64) == 0) 127*0Sstevel@tonic-gate { 128*0Sstevel@tonic-gate t += t->base; 129*0Sstevel@tonic-gate e = (t += ((uInt)b & inflate_mask[e]))->exop; 130*0Sstevel@tonic-gate } 131*0Sstevel@tonic-gate else 132*0Sstevel@tonic-gate { 133*0Sstevel@tonic-gate z->msg = (char*)"invalid distance code"; 134*0Sstevel@tonic-gate UNGRAB 135*0Sstevel@tonic-gate UPDATE 136*0Sstevel@tonic-gate return Z_DATA_ERROR; 137*0Sstevel@tonic-gate } 138*0Sstevel@tonic-gate /*CONSTCOND*/ 139*0Sstevel@tonic-gate } while (1); 140*0Sstevel@tonic-gate break; 141*0Sstevel@tonic-gate } 142*0Sstevel@tonic-gate if ((e & 64) == 0) 143*0Sstevel@tonic-gate { 144*0Sstevel@tonic-gate t += t->base; 145*0Sstevel@tonic-gate if ((e = (t += ((uInt)b & inflate_mask[e]))->exop) == 0) 146*0Sstevel@tonic-gate { 147*0Sstevel@tonic-gate DUMPBITS(t->bits) 148*0Sstevel@tonic-gate Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ? 149*0Sstevel@tonic-gate "inflate: * literal '%c'\n" : 150*0Sstevel@tonic-gate "inflate: * literal 0x%02x\n", t->base)); 151*0Sstevel@tonic-gate *q++ = (Byte)t->base; 152*0Sstevel@tonic-gate m--; 153*0Sstevel@tonic-gate break; 154*0Sstevel@tonic-gate } 155*0Sstevel@tonic-gate } 156*0Sstevel@tonic-gate else if (e & 32) 157*0Sstevel@tonic-gate { 158*0Sstevel@tonic-gate Tracevv((stderr, "inflate: * end of block\n")); 159*0Sstevel@tonic-gate UNGRAB 160*0Sstevel@tonic-gate UPDATE 161*0Sstevel@tonic-gate return Z_STREAM_END; 162*0Sstevel@tonic-gate } 163*0Sstevel@tonic-gate else 164*0Sstevel@tonic-gate { 165*0Sstevel@tonic-gate z->msg = (char*)"invalid literal/length code"; 166*0Sstevel@tonic-gate UNGRAB 167*0Sstevel@tonic-gate UPDATE 168*0Sstevel@tonic-gate return Z_DATA_ERROR; 169*0Sstevel@tonic-gate } 170*0Sstevel@tonic-gate /*CONSTCOND*/ 171*0Sstevel@tonic-gate } while (1); 172*0Sstevel@tonic-gate } while (m >= 258 && n >= 10); 173*0Sstevel@tonic-gate 174*0Sstevel@tonic-gate /* not enough input or output--restore pointers and return */ 175*0Sstevel@tonic-gate UNGRAB 176*0Sstevel@tonic-gate UPDATE 177*0Sstevel@tonic-gate return Z_OK; 178*0Sstevel@tonic-gate } 179