xref: /onnv-gate/usr/src/uts/common/zmod/inffast.c (revision 0:68f95e015346)
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