diff options
Diffstat (limited to 'lib/zlib/inffast.c')
| -rw-r--r-- | lib/zlib/inffast.c | 51 | 
1 files changed, 40 insertions, 11 deletions
| diff --git a/lib/zlib/inffast.c b/lib/zlib/inffast.c index 5e2a65ad4d2..b5a0adcce69 100644 --- a/lib/zlib/inffast.c +++ b/lib/zlib/inffast.c @@ -236,18 +236,47 @@ unsigned start;         /* inflate()'s starting value for strm->avail_out */                      }                  }                  else { +		    unsigned short *sout; +		    unsigned long loops; +                      from = out - dist;          /* copy direct from output */ -                    do {                        /* minimum length is three */ -                        *out++ = *from++; -                        *out++ = *from++; -                        *out++ = *from++; -                        len -= 3; -                    } while (len > 2); -                    if (len) { -                        *out++ = *from++; -                        if (len > 1) -                            *out++ = *from++; -                    } +                    /* minimum length is three */ +		    /* Align out addr */ +		    if (!((long)(out - 1) & 1)) { +			*out++ = *from++; +			len--; +		    } +		    sout = (unsigned short *)out; +		    if (dist > 2 ) { +			unsigned short *sfrom; + +			sfrom = (unsigned short *)from; +			loops = len >> 1; +			do +			    *sout++ = get_unaligned(sfrom++); +			while (--loops); +			out = (unsigned char *)sout; +			from = (unsigned char *)sfrom; +		    } else { /* dist == 1 or dist == 2 */ +			unsigned short pat16; + +			pat16 = *(sout - 1); +			if (dist == 1) +#if defined(__BIG_ENDIAN) +			    pat16 = (pat16 & 0xff) | ((pat16 & 0xff ) << 8); +#elif defined(__LITTLE_ENDIAN) +			    pat16 = (pat16 & 0xff00) | ((pat16 & 0xff00 ) >> 8); +#else +#error __BIG_ENDIAN nor __LITTLE_ENDIAN is defined +#endif +			loops = len >> 1; +			do +			    *sout++ = pat16; +			while (--loops); +			out = (unsigned char *)sout; +		    } +		    if (len & 1) +			*out++ = *from++;                  }              }              else if ((op & 64) == 0) {          /* 2nd level distance code */ | 
