]>
git.saurik.com Git - wxWidgets.git/blob - src/zlib/inffast.c
   1 /* inffast.c -- fast decoding 
   2  * Copyright (C) 1995-2004 Mark Adler 
   3  * For conditions of distribution and use, see copyright notice in zlib.h 
  13 /* Allow machine dependent optimization for post-increment or pre-increment. 
  14    Based on testing to date, 
  15    Pre-increment preferred for: 
  17    - MIPS R5000 (Randers-Pehrson) 
  18    Post-increment preferred for: 
  20    No measurable difference: 
  21    - Pentium III (Anderson) 
  26 #  define PUP(a) *(a)++ 
  29 #  define PUP(a) *++(a) 
  33    Decode literal, length, and distance codes and write out the resulting 
  34    literal and match bytes until either not enough input or output is 
  35    available, an end-of-block is encountered, or a data error is encountered. 
  36    When large enough input and output buffers are supplied to inflate(), for 
  37    example, a 16K input buffer and a 64K output buffer, more than 95% of the 
  38    inflate execution time is spent in this routine. 
  44         strm->avail_out >= 258 
  45         start >= strm->avail_out 
  48    On return, state->mode is one of: 
  50         LEN -- ran out of enough output space or enough available input 
  51         TYPE -- reached end of block code, inflate() to interpret next block 
  52         BAD -- error in block data 
  56     - The maximum input bits used by a length/distance pair is 15 bits for the 
  57       length code, 5 bits for the length extra, 15 bits for the distance code, 
  58       and 13 bits for the distance extra.  This totals 48 bits, or six bytes. 
  59       Therefore if strm->avail_in >= 6, then there is enough input to avoid 
  60       checking for available input while decoding. 
  62     - The maximum bytes that a single length/distance pair can output is 258 
  63       bytes, which is the maximum length that can be coded.  inflate_fast() 
  64       requires strm->avail_out >= 258 for each loop to avoid checking for 
  67 void inflate_fast(strm
, start
) 
  69 unsigned start
;         /* inflate()'s starting value for strm->avail_out */ 
  71     struct inflate_state FAR 
*state
; 
  72     unsigned char FAR 
*in
;      /* local strm->next_in */ 
  73     unsigned char FAR 
*last
;    /* while in < last, enough input available */ 
  74     unsigned char FAR 
*out
;     /* local strm->next_out */ 
  75     unsigned char FAR 
*beg
;     /* inflate()'s initial strm->next_out */ 
  76     unsigned char FAR 
*end
;     /* while out < end, enough space available */ 
  78     unsigned dmax
;              /* maximum distance from zlib header */ 
  80     unsigned wsize
;             /* window size or zero if not using window */ 
  81     unsigned whave
;             /* valid bytes in the window */ 
  82     unsigned write
;             /* window write index */ 
  83     unsigned char FAR 
*window
;  /* allocated sliding window, if wsize != 0 */ 
  84     unsigned long hold
;         /* local strm->hold */ 
  85     unsigned bits
;              /* local strm->bits */ 
  86     code 
const FAR 
*lcode
;      /* local strm->lencode */ 
  87     code 
const FAR 
*dcode
;      /* local strm->distcode */ 
  88     unsigned lmask
;             /* mask for first level of length codes */ 
  89     unsigned dmask
;             /* mask for first level of distance codes */ 
  90     code 
this;                  /* retrieved table entry */ 
  91     unsigned op
;                /* code bits, operation, extra bits, or */ 
  92                                 /*  window position, window bytes to copy */ 
  93     unsigned len
;               /* match length, unused bytes */ 
  94     unsigned dist
;              /* match distance */ 
  95     unsigned char FAR 
*from
;    /* where to copy match from */ 
  97     /* copy state to local variables */ 
  98     state 
= (struct inflate_state FAR 
*)strm
->state
; 
  99     in 
= strm
->next_in 
- OFF
; 
 100     last 
= in 
+ (strm
->avail_in 
- 5); 
 101     out 
= strm
->next_out 
- OFF
; 
 102     beg 
= out 
- (start 
- strm
->avail_out
); 
 103     end 
= out 
+ (strm
->avail_out 
- 257); 
 104 #ifdef INFLATE_STRICT 
 107     wsize 
= state
->wsize
; 
 108     whave 
= state
->whave
; 
 109     write 
= state
->write
; 
 110     window 
= state
->window
; 
 113     lcode 
= state
->lencode
; 
 114     dcode 
= state
->distcode
; 
 115     lmask 
= (1U << state
->lenbits
) - 1; 
 116     dmask 
= (1U << state
->distbits
) - 1; 
 118     /* decode literals and length/distances until end-of-block or not enough 
 119        input data or output space */ 
 122             hold 
+= (unsigned long)(PUP(in
)) << bits
; 
 124             hold 
+= (unsigned long)(PUP(in
)) << bits
; 
 127         this = lcode
[hold 
& lmask
]; 
 129         op 
= (unsigned)(this.bits
); 
 132         op 
= (unsigned)(this.op
); 
 133         if (op 
== 0) {                          /* literal */ 
 134             Tracevv((stderr
, this.val 
>= 0x20 && this.val 
< 0x7f ? 
 135                     "inflate:         literal '%c'\n" : 
 136                     "inflate:         literal 0x%02x\n", this.val
)); 
 137             PUP(out
) = (unsigned char)(this.val
); 
 139         else if (op 
& 16) {                     /* length base */ 
 140             len 
= (unsigned)(this.val
); 
 141             op 
&= 15;                           /* number of extra bits */ 
 144                     hold 
+= (unsigned long)(PUP(in
)) << bits
; 
 147                 len 
+= (unsigned)hold 
& ((1U << op
) - 1); 
 151             Tracevv((stderr
, "inflate:         length %u\n", len
)); 
 153                 hold 
+= (unsigned long)(PUP(in
)) << bits
; 
 155                 hold 
+= (unsigned long)(PUP(in
)) << bits
; 
 158             this = dcode
[hold 
& dmask
]; 
 160             op 
= (unsigned)(this.bits
); 
 163             op 
= (unsigned)(this.op
); 
 164             if (op 
& 16) {                      /* distance base */ 
 165                 dist 
= (unsigned)(this.val
); 
 166                 op 
&= 15;                       /* number of extra bits */ 
 168                     hold 
+= (unsigned long)(PUP(in
)) << bits
; 
 171                         hold 
+= (unsigned long)(PUP(in
)) << bits
; 
 175                 dist 
+= (unsigned)hold 
& ((1U << op
) - 1); 
 176 #ifdef INFLATE_STRICT 
 178                     strm
->msg 
= (char *)"invalid distance too far back"; 
 185                 Tracevv((stderr
, "inflate:         distance %u\n", dist
)); 
 186                 op 
= (unsigned)(out 
- beg
);     /* max distance in output */ 
 187                 if (dist 
> op
) {                /* see if copy from window */ 
 188                     op 
= dist 
- op
;             /* distance back in window */ 
 190                         strm
->msg 
= (char *)"invalid distance too far back"; 
 195                     if (write 
== 0) {           /* very common case */ 
 197                         if (op 
< len
) {         /* some from window */ 
 200                                 PUP(out
) = PUP(from
); 
 202                             from 
= out 
- dist
;  /* rest from output */ 
 205                     else if (write 
< op
) {      /* wrap around window */ 
 206                         from 
+= wsize 
+ write 
- op
; 
 208                         if (op 
< len
) {         /* some from end of window */ 
 211                                 PUP(out
) = PUP(from
); 
 214                             if (write 
< len
) {  /* some from start of window */ 
 218                                     PUP(out
) = PUP(from
); 
 220                                 from 
= out 
- dist
;      /* rest from output */ 
 224                     else {                      /* contiguous in window */ 
 226                         if (op 
< len
) {         /* some from window */ 
 229                                 PUP(out
) = PUP(from
); 
 231                             from 
= out 
- dist
;  /* rest from output */ 
 235                         PUP(out
) = PUP(from
); 
 236                         PUP(out
) = PUP(from
); 
 237                         PUP(out
) = PUP(from
); 
 241                         PUP(out
) = PUP(from
); 
 243                             PUP(out
) = PUP(from
); 
 247                     from 
= out 
- dist
;          /* copy direct from output */ 
 248                     do {                        /* minimum length is three */ 
 249                         PUP(out
) = PUP(from
); 
 250                         PUP(out
) = PUP(from
); 
 251                         PUP(out
) = PUP(from
); 
 255                         PUP(out
) = PUP(from
); 
 257                             PUP(out
) = PUP(from
); 
 261             else if ((op 
& 64) == 0) {          /* 2nd level distance code */ 
 262                 this = dcode
[this.val 
+ (hold 
& ((1U << op
) - 1))]; 
 266                 strm
->msg 
= (char *)"invalid distance code"; 
 271         else if ((op 
& 64) == 0) {              /* 2nd level length code */ 
 272             this = lcode
[this.val 
+ (hold 
& ((1U << op
) - 1))]; 
 275         else if (op 
& 32) {                     /* end-of-block */ 
 276             Tracevv((stderr
, "inflate:         end of block\n")); 
 281             strm
->msg 
= (char *)"invalid literal/length code"; 
 285     } while (in 
< last 
&& out 
< end
); 
 287     /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ 
 291     hold 
&= (1U << bits
) - 1; 
 293     /* update state and return */ 
 294     strm
->next_in 
= in 
+ OFF
; 
 295     strm
->next_out 
= out 
+ OFF
; 
 296     strm
->avail_in 
= (unsigned)(in 
< last 
? 5 + (last 
- in
) : 5 - (in 
- last
)); 
 297     strm
->avail_out 
= (unsigned)(out 
< end 
? 
 298                                  257 + (end 
- out
) : 257 - (out 
- end
)); 
 305    inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe): 
 306    - Using bit fields for code structure 
 307    - Different op definition to avoid & for extra bits (do & for table bits) 
 308    - Three separate decoding do-loops for direct, window, and write == 0 
 309    - Special case for distance > 1 copies to do overlapped load and store copy 
 310    - Explicit branch predictions (based on measured branch probabilities) 
 311    - Deferring match copy and interspersed it with decoding subsequent codes 
 312    - Swapping literal/length else 
 313    - Swapping window/direct else 
 314    - Larger unrolled copy loops (three is about right) 
 315    - Moving len -= 3 statement into middle of loop