summaryrefslogtreecommitdiff
path: root/inffast.c
diff options
context:
space:
mode:
Diffstat (limited to 'inffast.c')
-rw-r--r--inffast.c83
1 files changed, 37 insertions, 46 deletions
diff --git a/inffast.c b/inffast.c
index 1e60b23..32bb4f3 100644
--- a/inffast.c
+++ b/inffast.c
@@ -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 */