From a4e4521ee1303b756a8f96c18cdf4729327b687d Mon Sep 17 00:00:00 2001 From: Mark Adler Date: Fri, 21 Feb 2025 14:22:16 -0800 Subject: Have gz_skip() update how far it got for later continuation. This also simplifies seek processing in general. --- gzguts.h | 1 - gzlib.c | 18 ++++++++--------- gzread.c | 36 ++++++++++++++-------------------- gzwrite.c | 67 ++++++++++++++++++++++----------------------------------------- 4 files changed, 46 insertions(+), 76 deletions(-) diff --git a/gzguts.h b/gzguts.h index 71dea740..69c77eb9 100644 --- a/gzguts.h +++ b/gzguts.h @@ -193,7 +193,6 @@ typedef struct { int reset; /* true if a reset is pending after a Z_FINISH */ /* seek request */ z_off64_t skip; /* amount to skip (already rewound if backwards) */ - int seek; /* true if seek request pending */ /* error information */ int err; /* error code */ char *msg; /* error message */ diff --git a/gzlib.c b/gzlib.c index baa3e79d..2f9cdd4e 100644 --- a/gzlib.c +++ b/gzlib.c @@ -75,7 +75,7 @@ local void gz_reset(gz_statep state) { } else /* for writing ... */ state->reset = 0; /* no deflateReset pending */ - state->seek = 0; /* no seek request pending */ + state->skip = 0; /* no seek request pending */ gz_error(state, Z_OK, NULL); /* clear error */ state->x.pos = 0; /* no uncompressed data yet */ state->strm.avail_in = 0; /* no input data yet */ @@ -362,9 +362,10 @@ z_off64_t ZEXPORT gzseek64(gzFile file, z_off64_t offset, int whence) { /* normalize offset to a SEEK_CUR specification */ if (whence == SEEK_SET) offset -= state->x.pos; - else if (state->seek) - offset += state->skip; - state->seek = 0; + else { + offset += state->past ? 0 : state->skip; + state->skip = 0; + } /* if within raw area while reading, just go there */ if (state->mode == GZ_READ && state->how == COPY && @@ -375,7 +376,7 @@ z_off64_t ZEXPORT gzseek64(gzFile file, z_off64_t offset, int whence) { state->x.have = 0; state->eof = 0; state->past = 0; - state->seek = 0; + state->skip = 0; gz_error(state, Z_OK, NULL); state->strm.avail_in = 0; state->x.pos += offset; @@ -404,10 +405,7 @@ z_off64_t ZEXPORT gzseek64(gzFile file, z_off64_t offset, int whence) { } /* request skip (if not zero) */ - if (offset) { - state->seek = 1; - state->skip = offset; - } + state->skip = offset; return state->x.pos + offset; } @@ -431,7 +429,7 @@ z_off64_t ZEXPORT gztell64(gzFile file) { return -1; /* return position */ - return state->x.pos + (state->seek ? state->skip : 0); + return state->x.pos + (state->past ? 0 : state->skip); } /* -- see zlib.h -- */ diff --git a/gzread.c b/gzread.c index d2ab6b17..5edecbfc 100644 --- a/gzread.c +++ b/gzread.c @@ -234,20 +234,22 @@ local int gz_fetch(gz_statep state) { return 0; } -/* Skip len uncompressed bytes of output. Return -1 on error, 0 on success. */ -local int gz_skip(gz_statep state, z_off64_t len) { +/* Skip state->skip (> 0) uncompressed bytes of output. Return -1 on error, 0 + on success. */ +local int gz_skip(gz_statep state) { unsigned n; /* skip over len bytes or reach end-of-file, whichever comes first */ - while (len) + do { /* skip over whatever is in output buffer */ if (state->x.have) { - n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > len ? - (unsigned)len : state->x.have; + n = GT_OFF(state->x.have) || + (z_off64_t)state->x.have > state->skip ? + (unsigned)state->skip : state->x.have; state->x.have -= n; state->x.next += n; state->x.pos += n; - len -= n; + state->skip -= n; } /* output buffer empty -- return if we're at the end of the input */ @@ -260,6 +262,7 @@ local int gz_skip(gz_statep state, z_off64_t len) { if (gz_fetch(state) == -1) return -1; } + } while (state->skip); return 0; } @@ -276,11 +279,8 @@ local z_size_t gz_read(gz_statep state, voidp buf, z_size_t len) { return 0; /* process a skip request */ - if (state->seek) { - state->seek = 0; - if (gz_skip(state, state->skip) == -1) - return 0; - } + if (state->skip && gz_skip(state) == -1) + return 0; /* get len bytes to buf, or less than len if at the end */ got = 0; @@ -456,11 +456,8 @@ int ZEXPORT gzungetc(int c, gzFile file) { return -1; /* process a skip request */ - if (state->seek) { - state->seek = 0; - if (gz_skip(state, state->skip) == -1) - return -1; - } + if (state->skip && gz_skip(state) == -1) + return -1; /* can't push EOF */ if (c < 0) @@ -516,11 +513,8 @@ char * ZEXPORT gzgets(gzFile file, char *buf, int len) { return NULL; /* process a skip request */ - if (state->seek) { - state->seek = 0; - if (gz_skip(state, state->skip) == -1) - return NULL; - } + if (state->skip && gz_skip(state) == -1) + return NULL; /* copy output bytes up to new line or len - 1, whichever comes first -- append a terminating zero to the string (we don't check for a zero in diff --git a/gzwrite.c b/gzwrite.c index 435b4621..ef9ffee5 100644 --- a/gzwrite.c +++ b/gzwrite.c @@ -138,9 +138,9 @@ local int gz_comp(gz_statep state, int flush) { return 0; } -/* Compress len zeros to output. Return -1 on a write error or memory - allocation failure by gz_comp(), or 0 on success. */ -local int gz_zero(gz_statep state, z_off64_t len) { +/* Compress state->skip (> 0) zeros to output. Return -1 on a write error or + memory allocation failure by gz_comp(), or 0 on success. */ +local int gz_zero(gz_statep state) { int first; unsigned n; z_streamp strm = &(state->strm); @@ -149,11 +149,11 @@ local int gz_zero(gz_statep state, z_off64_t len) { if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) return -1; - /* compress len zeros (len guaranteed > 0) */ + /* compress state->skip zeros */ first = 1; - while (len) { - n = GT_OFF(state->size) || (z_off64_t)state->size > len ? - (unsigned)len : state->size; + do { + n = GT_OFF(state->size) || (z_off64_t)state->size > state->skip ? + (unsigned)state->skip : state->size; if (first) { memset(state->in, 0, n); first = 0; @@ -163,8 +163,8 @@ local int gz_zero(gz_statep state, z_off64_t len) { state->x.pos += n; if (gz_comp(state, Z_NO_FLUSH) == -1) return -1; - len -= n; - } + state->skip -= n; + } while (state->skip); return 0; } @@ -182,11 +182,8 @@ local z_size_t gz_write(gz_statep state, voidpc buf, z_size_t len) { return 0; /* check for seek request */ - if (state->seek) { - state->seek = 0; - if (gz_zero(state, state->skip) == -1) - return 0; - } + if (state->skip && gz_zero(state) == -1) + return 0; /* for small len, copy to input buffer, otherwise compress directly */ if (len < state->size) { @@ -301,11 +298,8 @@ int ZEXPORT gzputc(gzFile file, int c) { return -1; /* check for seek request */ - if (state->seek) { - state->seek = 0; - if (gz_zero(state, state->skip) == -1) - return -1; - } + if (state->skip && gz_zero(state) == -1) + return -1; /* try writing to input buffer for speed (state->size == 0 if buffer not initialized) */ @@ -378,11 +372,8 @@ int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va) { return state->err; /* check for seek request */ - if (state->seek) { - state->seek = 0; - if (gz_zero(state, state->skip) == -1) - return state->err; - } + if (state->skip && gz_zero(state) == -1) + return state->err; /* do the printf() into the input buffer, put length in len -- the input buffer is double-sized just for this function, so there is guaranteed to @@ -468,11 +459,8 @@ int ZEXPORTVA gzprintf(gzFile file, const char *format, int a1, int a2, int a3, return state->error; /* check for seek request */ - if (state->seek) { - state->seek = 0; - if (gz_zero(state, state->skip) == -1) - return state->error; - } + if (state->skip && gz_zero(state) == -1) + return state->error; /* do the printf() into the input buffer, put length in len -- the input buffer is double-sized just for this function, so there is guaranteed to @@ -542,11 +530,8 @@ int ZEXPORT gzflush(gzFile file, int flush) { return Z_STREAM_ERROR; /* check for seek request */ - if (state->seek) { - state->seek = 0; - if (gz_zero(state, state->skip) == -1) - return state->err; - } + if (state->skip && gz_zero(state) == -1) + return state->err; /* compress remaining data with requested flush */ (void)gz_comp(state, flush); @@ -573,11 +558,8 @@ int ZEXPORT gzsetparams(gzFile file, int level, int strategy) { return Z_OK; /* check for seek request */ - if (state->seek) { - state->seek = 0; - if (gz_zero(state, state->skip) == -1) - return state->err; - } + if (state->skip && gz_zero(state) == -1) + return state->err; /* change compression parameters for subsequent input */ if (state->size) { @@ -606,11 +588,8 @@ int ZEXPORT gzclose_w(gzFile file) { return Z_STREAM_ERROR; /* check for seek request */ - if (state->seek) { - state->seek = 0; - if (gz_zero(state, state->skip) == -1) - ret = state->err; - } + if (state->skip && gz_zero(state) == -1) + ret = state->err; /* flush, free memory, and close file */ if (gz_comp(state, Z_FINISH) == -1) -- cgit v1.2.3-55-g6feb