Diff for /embedaddon/rsync/zlib/inffast.c between versions 1.1 and 1.1.1.3

version 1.1, 2012/02/17 15:09:30 version 1.1.1.3, 2021/03/17 00:32:36
Line 1 Line 1
 /* inffast.c -- fast decoding  /* inffast.c -- fast decoding
 * Copyright (C) 1995-2004 Mark Adler * Copyright (C) 1995-2008, 2010, 2013 Mark Adler
  * For conditions of distribution and use, see copyright notice in zlib.h   * For conditions of distribution and use, see copyright notice in zlib.h
  */   */
   
Line 10 Line 10
   
 #ifndef ASMINF  #ifndef ASMINF
   
 /* Allow machine dependent optimization for post-increment or pre-increment.  
    Based on testing to date,  
    Pre-increment preferred for:  
    - PowerPC G3 (Adler)  
    - MIPS R5000 (Randers-Pehrson)  
    Post-increment preferred for:  
    - none  
    No measurable difference:  
    - Pentium III (Anderson)  
    - M68060 (Nikl)  
  */  
 #ifdef POSTINC  
 #  define OFF 0  
 #  define PUP(a) *(a)++  
 #else  
 #  define OFF 1  
 #  define PUP(a) *++(a)  
 #endif  
   
 /*  /*
    Decode literal, length, and distance codes and write out the resulting     Decode literal, length, and distance codes and write out the resulting
    literal and match bytes until either not enough input or output is     literal and match bytes until either not enough input or output is
Line 64 Line 45
       requires strm->avail_out >= 258 for each loop to avoid checking for        requires strm->avail_out >= 258 for each loop to avoid checking for
       output space.        output space.
  */   */
void inflate_fast(strm, start)void ZLIB_INTERNAL inflate_fast(strm, start)
 z_streamp strm;  z_streamp strm;
 unsigned start;         /* inflate()'s starting value for strm->avail_out */  unsigned start;         /* inflate()'s starting value for strm->avail_out */
 {  {
     struct inflate_state FAR *state;      struct inflate_state FAR *state;
    unsigned char FAR *in;      /* local strm->next_in */    z_const unsigned char FAR *in;      /* local strm->next_in */
    unsigned char FAR *last;    /* while in < last, enough input available */    z_const unsigned char FAR *last;    /* have enough input while in < last */
     unsigned char FAR *out;     /* local strm->next_out */      unsigned char FAR *out;     /* local strm->next_out */
     unsigned char FAR *beg;     /* inflate()'s initial strm->next_out */      unsigned char FAR *beg;     /* inflate()'s initial strm->next_out */
     unsigned char FAR *end;     /* while out < end, enough space available */      unsigned char FAR *end;     /* while out < end, enough space available */
Line 79  unsigned start;         /* inflate()'s starting value  Line 60  unsigned start;         /* inflate()'s starting value 
 #endif  #endif
     unsigned wsize;             /* window size or zero if not using window */      unsigned wsize;             /* window size or zero if not using window */
     unsigned whave;             /* valid bytes in the window */      unsigned whave;             /* valid bytes in the window */
    unsigned write;             /* window write index */    unsigned wnext;             /* window write index */
     unsigned char FAR *window;  /* allocated sliding window, if wsize != 0 */      unsigned char FAR *window;  /* allocated sliding window, if wsize != 0 */
     unsigned long hold;         /* local strm->hold */      unsigned long hold;         /* local strm->hold */
     unsigned bits;              /* local strm->bits */      unsigned bits;              /* local strm->bits */
Line 87  unsigned start;         /* inflate()'s starting value  Line 68  unsigned start;         /* inflate()'s starting value 
     code const FAR *dcode;      /* local strm->distcode */      code const FAR *dcode;      /* local strm->distcode */
     unsigned lmask;             /* mask for first level of length codes */      unsigned lmask;             /* mask for first level of length codes */
     unsigned dmask;             /* mask for first level of distance codes */      unsigned dmask;             /* mask for first level of distance codes */
    code this;                  /* retrieved table entry */    code here;                  /* retrieved table entry */
     unsigned op;                /* code bits, operation, extra bits, or */      unsigned op;                /* code bits, operation, extra bits, or */
                                 /*  window position, window bytes to copy */                                  /*  window position, window bytes to copy */
     unsigned len;               /* match length, unused bytes */      unsigned len;               /* match length, unused bytes */
Line 96  unsigned start;         /* inflate()'s starting value  Line 77  unsigned start;         /* inflate()'s starting value 
   
     /* copy state to local variables */      /* copy state to local variables */
     state = (struct inflate_state FAR *)strm->state;      state = (struct inflate_state FAR *)strm->state;
    in = strm->next_in - OFF;    in = strm->next_in;
     last = in + (strm->avail_in - 5);      last = in + (strm->avail_in - 5);
    out = strm->next_out - OFF;    out = strm->next_out;
     beg = out - (start - strm->avail_out);      beg = out - (start - strm->avail_out);
     end = out + (strm->avail_out - 257);      end = out + (strm->avail_out - 257);
 #ifdef INFLATE_STRICT  #ifdef INFLATE_STRICT
Line 106  unsigned start;         /* inflate()'s starting value  Line 87  unsigned start;         /* inflate()'s starting value 
 #endif  #endif
     wsize = state->wsize;      wsize = state->wsize;
     whave = state->whave;      whave = state->whave;
    write = state->write;    wnext = state->wnext;
     window = state->window;      window = state->window;
     hold = state->hold;      hold = state->hold;
     bits = state->bits;      bits = state->bits;
Line 119  unsigned start;         /* inflate()'s starting value  Line 100  unsigned start;         /* inflate()'s starting value 
        input data or output space */         input data or output space */
     do {      do {
         if (bits < 15) {          if (bits < 15) {
            hold += (unsigned long)(PUP(in)) << bits;            hold += (unsigned long)(*in++) << bits;
             bits += 8;              bits += 8;
            hold += (unsigned long)(PUP(in)) << bits;            hold += (unsigned long)(*in++) << bits;
             bits += 8;              bits += 8;
         }          }
        this = lcode[hold & lmask];        here = lcode[hold & lmask];
       dolen:        dolen:
        op = (unsigned)(this.bits);        op = (unsigned)(here.bits);
         hold >>= op;          hold >>= op;
         bits -= op;          bits -= op;
        op = (unsigned)(this.op);        op = (unsigned)(here.op);
         if (op == 0) {                          /* literal */          if (op == 0) {                          /* literal */
            Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ?            Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
                     "inflate:         literal '%c'\n" :                      "inflate:         literal '%c'\n" :
                    "inflate:         literal 0x%02x\n", this.val));                    "inflate:         literal 0x%02x\n", here.val));
            PUP(out) = (unsigned char)(this.val);            *out++ = (unsigned char)(here.val);
         }          }
         else if (op & 16) {                     /* length base */          else if (op & 16) {                     /* length base */
            len = (unsigned)(this.val);            len = (unsigned)(here.val);
             op &= 15;                           /* number of extra bits */              op &= 15;                           /* number of extra bits */
             if (op) {              if (op) {
                 if (bits < op) {                  if (bits < op) {
                    hold += (unsigned long)(PUP(in)) << bits;                    hold += (unsigned long)(*in++) << bits;
                     bits += 8;                      bits += 8;
                 }                  }
                 len += (unsigned)hold & ((1U << op) - 1);                  len += (unsigned)hold & ((1U << op) - 1);
Line 150  unsigned start;         /* inflate()'s starting value  Line 131  unsigned start;         /* inflate()'s starting value 
             }              }
             Tracevv((stderr, "inflate:         length %u\n", len));              Tracevv((stderr, "inflate:         length %u\n", len));
             if (bits < 15) {              if (bits < 15) {
                hold += (unsigned long)(PUP(in)) << bits;                hold += (unsigned long)(*in++) << bits;
                 bits += 8;                  bits += 8;
                hold += (unsigned long)(PUP(in)) << bits;                hold += (unsigned long)(*in++) << bits;
                 bits += 8;                  bits += 8;
             }              }
            this = dcode[hold & dmask];            here = dcode[hold & dmask];
           dodist:            dodist:
            op = (unsigned)(this.bits);            op = (unsigned)(here.bits);
             hold >>= op;              hold >>= op;
             bits -= op;              bits -= op;
            op = (unsigned)(this.op);            op = (unsigned)(here.op);
             if (op & 16) {                      /* distance base */              if (op & 16) {                      /* distance base */
                dist = (unsigned)(this.val);                dist = (unsigned)(here.val);
                 op &= 15;                       /* number of extra bits */                  op &= 15;                       /* number of extra bits */
                 if (bits < op) {                  if (bits < op) {
                    hold += (unsigned long)(PUP(in)) << bits;                    hold += (unsigned long)(*in++) << bits;
                     bits += 8;                      bits += 8;
                     if (bits < op) {                      if (bits < op) {
                        hold += (unsigned long)(PUP(in)) << bits;                        hold += (unsigned long)(*in++) << bits;
                         bits += 8;                          bits += 8;
                     }                      }
                 }                  }
Line 187  unsigned start;         /* inflate()'s starting value  Line 168  unsigned start;         /* inflate()'s starting value 
                 if (dist > op) {                /* see if copy from window */                  if (dist > op) {                /* see if copy from window */
                     op = dist - op;             /* distance back in window */                      op = dist - op;             /* distance back in window */
                     if (op > whave) {                      if (op > whave) {
                        strm->msg = (char *)"invalid distance too far back";                        if (state->sane) {
                        state->mode = BAD;                            strm->msg =
                        break;                                (char *)"invalid distance too far back";
                             state->mode = BAD;
                             break;
                         }
 #ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
                         if (len <= op - whave) {
                             do {
                                 *out++ = 0;
                             } while (--len);
                             continue;
                         }
                         len -= op - whave;
                         do {
                             *out++ = 0;
                         } while (--op > whave);
                         if (op == 0) {
                             from = out - dist;
                             do {
                                 *out++ = *from++;
                             } while (--len);
                             continue;
                         }
 #endif
                     }                      }
                    from = window - OFF;                    from = window;
                    if (write == 0) {           /* very common case */                    if (wnext == 0) {           /* very common case */
                         from += wsize - op;                          from += wsize - op;
                         if (op < len) {         /* some from window */                          if (op < len) {         /* some from window */
                             len -= op;                              len -= op;
                             do {                              do {
                                PUP(out) = PUP(from);                                *out++ = *from++;
                             } while (--op);                              } while (--op);
                             from = out - dist;  /* rest from output */                              from = out - dist;  /* rest from output */
                         }                          }
                     }                      }
                    else if (write < op) {      /* wrap around window */                    else if (wnext < op) {      /* wrap around window */
                        from += wsize + write - op;                        from += wsize + wnext - op;
                        op -= write;                        op -= wnext;
                         if (op < len) {         /* some from end of window */                          if (op < len) {         /* some from end of window */
                             len -= op;                              len -= op;
                             do {                              do {
                                PUP(out) = PUP(from);                                *out++ = *from++;
                             } while (--op);                              } while (--op);
                            from = window - OFF;                            from = window;
                            if (write < len) {  /* some from start of window */                            if (wnext < len) {  /* some from start of window */
                                op = write;                                op = wnext;
                                 len -= op;                                  len -= op;
                                 do {                                  do {
                                    PUP(out) = PUP(from);                                    *out++ = *from++;
                                 } while (--op);                                  } while (--op);
                                 from = out - dist;      /* rest from output */                                  from = out - dist;      /* rest from output */
                             }                              }
                         }                          }
                     }                      }
                     else {                      /* contiguous in window */                      else {                      /* contiguous in window */
                        from += write - op;                        from += wnext - op;
                         if (op < len) {         /* some from window */                          if (op < len) {         /* some from window */
                             len -= op;                              len -= op;
                             do {                              do {
                                PUP(out) = PUP(from);                                *out++ = *from++;
                             } while (--op);                              } while (--op);
                             from = out - dist;  /* rest from output */                              from = out - dist;  /* rest from output */
                         }                          }
                     }                      }
                     while (len > 2) {                      while (len > 2) {
                        PUP(out) = PUP(from);                        *out++ = *from++;
                        PUP(out) = PUP(from);                        *out++ = *from++;
                        PUP(out) = PUP(from);                        *out++ = *from++;
                         len -= 3;                          len -= 3;
                     }                      }
                     if (len) {                      if (len) {
                        PUP(out) = PUP(from);                        *out++ = *from++;
                         if (len > 1)                          if (len > 1)
                            PUP(out) = PUP(from);                            *out++ = *from++;
                     }                      }
                 }                  }
                 else {                  else {
                     from = out - dist;          /* copy direct from output */                      from = out - dist;          /* copy direct from output */
                     do {                        /* minimum length is three */                      do {                        /* minimum length is three */
                        PUP(out) = PUP(from);                        *out++ = *from++;
                        PUP(out) = PUP(from);                        *out++ = *from++;
                        PUP(out) = PUP(from);                        *out++ = *from++;
                         len -= 3;                          len -= 3;
                     } while (len > 2);                      } while (len > 2);
                     if (len) {                      if (len) {
                        PUP(out) = PUP(from);                        *out++ = *from++;
                         if (len > 1)                          if (len > 1)
                            PUP(out) = PUP(from);                            *out++ = *from++;
                     }                      }
                 }                  }
             }              }
             else if ((op & 64) == 0) {          /* 2nd level distance code */              else if ((op & 64) == 0) {          /* 2nd level distance code */
                this = dcode[this.val + (hold & ((1U << op) - 1))];                here = dcode[here.val + (hold & ((1U << op) - 1))];
                 goto dodist;                  goto dodist;
             }              }
             else {              else {
Line 269  unsigned start;         /* inflate()'s starting value  Line 272  unsigned start;         /* inflate()'s starting value 
             }              }
         }          }
         else if ((op & 64) == 0) {              /* 2nd level length code */          else if ((op & 64) == 0) {              /* 2nd level length code */
            this = lcode[this.val + (hold & ((1U << op) - 1))];            here = lcode[here.val + (hold & ((1U << op) - 1))];
             goto dolen;              goto dolen;
         }          }
         else if (op & 32) {                     /* end-of-block */          else if (op & 32) {                     /* end-of-block */
Line 291  unsigned start;         /* inflate()'s starting value  Line 294  unsigned start;         /* inflate()'s starting value 
     hold &= (1U << bits) - 1;      hold &= (1U << bits) - 1;
   
     /* update state and return */      /* update state and return */
    strm->next_in = in + OFF;    strm->next_in = in;
    strm->next_out = out + OFF;    strm->next_out = out;
     strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last));      strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last));
     strm->avail_out = (unsigned)(out < end ?      strm->avail_out = (unsigned)(out < end ?
                                  257 + (end - out) : 257 - (out - end));                                   257 + (end - out) : 257 - (out - end));
Line 305  unsigned start;         /* inflate()'s starting value  Line 308  unsigned start;         /* inflate()'s starting value 
    inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe):     inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe):
    - Using bit fields for code structure     - Using bit fields for code structure
    - Different op definition to avoid & for extra bits (do & for table bits)     - Different op definition to avoid & for extra bits (do & for table bits)
   - Three separate decoding do-loops for direct, window, and write == 0   - Three separate decoding do-loops for direct, window, and wnext == 0
    - Special case for distance > 1 copies to do overlapped load and store copy     - Special case for distance > 1 copies to do overlapped load and store copy
    - Explicit branch predictions (based on measured branch probabilities)     - Explicit branch predictions (based on measured branch probabilities)
    - Deferring match copy and interspersed it with decoding subsequent codes     - Deferring match copy and interspersed it with decoding subsequent codes

Removed from v.1.1  
changed lines
  Added in v.1.1.1.3


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>