diff options
Diffstat (limited to 'inffast.c')
-rw-r--r-- | inffast.c | 83 |
1 files changed, 37 insertions, 46 deletions
@@ -7,6 +7,7 @@ #include "inftrees.h" #include "inflate.h" #include "inffast.h" +#include "memcopy.h" /* Return the low n bits of the bit accumulator (n < 16) */ #define BITS(n) \ @@ -195,10 +196,9 @@ void ZLIB_INTERNAL inflate_fast(z_stream *strm, unsigned long start) { input data or output space */ do { if (bits < 15) { - hold += (uint32_t)(*in++) << bits; - bits += 8; - hold += (uint32_t)(*in++) << bits; - bits += 8; + hold += load_short(in, bits); + in += 2; + bits += 16; } here = lcode[hold & lmask]; dolen: @@ -222,10 +222,9 @@ void ZLIB_INTERNAL inflate_fast(z_stream *strm, unsigned long start) { } Tracevv((stderr, "inflate: length %u\n", len)); if (bits < 15) { - hold += (uint32_t)(*in++) << bits; - bits += 8; - hold += (uint32_t)(*in++) << bits; - bits += 8; + hold += load_short(in, bits); + in += 2; + bits += 16; } here = dcode[hold & dmask]; dodist: @@ -303,10 +302,18 @@ void ZLIB_INTERNAL inflate_fast(z_stream *strm, unsigned long start) { if (op < len) { /* still need some from output */ len -= op; out = chunkcopysafe(out, from, op, safe); - out = chunkunroll(out, &dist, &len); - out = chunkcopysafe(out, out - dist, len, safe); + if (dist == 1) { + out = byte_memset(out, len); + } else { + out = chunkunroll(out, &dist, &len); + out = chunkcopysafe(out, out - dist, len, safe); + } } else { - out = chunkcopysafe(out, from, len, safe); + if (from - out == 1) { + out = byte_memset(out, len); + } else { + out = chunkcopysafe(out, from, len, safe); + } } #else from = window; @@ -347,46 +354,30 @@ void ZLIB_INTERNAL inflate_fast(z_stream *strm, unsigned long start) { from = out - dist; /* rest from output */ } } - while (len > 2) { - *out++ = *from++; - *out++ = *from++; - *out++ = *from++; - len -= 3; - } - if (len) { - *out++ = *from++; - if (len > 1) - *out++ = *from++; - } + + out = chunk_copy(out, from, (int) (out - from), len); #endif } else { #ifdef INFFAST_CHUNKSIZE - /* Whole reference is in range of current output. No - range checks are necessary because we start with room - for at least 258 bytes of output, so unroll and roundoff - operations can write beyond `out+len` so long as they - stay within 258 bytes of `out`. - */ - out = chunkunroll(out, &dist, &len); - out = chunkcopy(out, out - dist, len); -#else - from = out - dist; /* copy direct from output */ - if (dist == 1) { - memset (out, *from, len); - out += len; + if (dist == 1 && len >= sizeof(uint64_t)) { + out = byte_memset(out, len); } else { - 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++; - } + /* Whole reference is in range of current output. No + range checks are necessary because we start with room + for at least 258 bytes of output, so unroll and roundoff + operations can write beyond `out+len` so long as they + stay within 258 bytes of `out`. + */ + out = chunkunroll(out, &dist, &len); + out = chunkcopy(out, out - dist, len); } +#else + if (len < sizeof(uint64_t)) + out = set_bytes(out, out - dist, dist, len); + else if (dist == 1) + out = byte_memset(out, len); + else + out = chunk_memset(out, out - dist, dist, len); #endif } } else if ((op & 64) == 0) { /* 2nd level distance code */ |