summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Adler <madler@alumni.caltech.edu>2011-09-26 22:50:28 -0700
committerMark Adler <madler@alumni.caltech.edu>2011-09-26 22:50:28 -0700
commitacfc85772a811f4c0efec835a3087b53f83f6079 (patch)
treefda6596291da38d9d3c8eaf5c521413b2b32fcd8
parent8e0d212910a42b3f856bbaebed970e8ddc081ca3 (diff)
downloadzlib-acfc85772a811f4c0efec835a3087b53f83f6079.tar.gz
zlib-acfc85772a811f4c0efec835a3087b53f83f6079.tar.bz2
zlib-acfc85772a811f4c0efec835a3087b53f83f6079.zip
Change gzgetc() to a macro for speed (~40% speedup in testing).
-rw-r--r--gzguts.h8
-rw-r--r--gzlib.c38
-rw-r--r--gzread.c119
-rw-r--r--gzwrite.c20
-rw-r--r--zlib.h25
5 files changed, 119 insertions, 91 deletions
diff --git a/gzguts.h b/gzguts.h
index 63b0c3f..ab3313a 100644
--- a/gzguts.h
+++ b/gzguts.h
@@ -84,18 +84,20 @@
84 84
85/* internal gzip file state data structure */ 85/* internal gzip file state data structure */
86typedef struct { 86typedef struct {
87 /* exposed contents for gzgetc() macro */
88 struct gzFile_s x; /* "x" for exposed */
89 /* x.have: number of bytes available at x.next */
90 /* x.next: next output data to deliver or write */
91 /* x.pos: current position in uncompressed data */
87 /* used for both reading and writing */ 92 /* used for both reading and writing */
88 int mode; /* see gzip modes above */ 93 int mode; /* see gzip modes above */
89 int fd; /* file descriptor */ 94 int fd; /* file descriptor */
90 char *path; /* path or fd for error messages */ 95 char *path; /* path or fd for error messages */
91 z_off64_t pos; /* current position in uncompressed data */
92 unsigned size; /* buffer size, zero if not allocated yet */ 96 unsigned size; /* buffer size, zero if not allocated yet */
93 unsigned want; /* requested buffer size, default is GZBUFSIZE */ 97 unsigned want; /* requested buffer size, default is GZBUFSIZE */
94 unsigned char *in; /* input buffer */ 98 unsigned char *in; /* input buffer */
95 unsigned char *out; /* output buffer (double-sized when reading) */ 99 unsigned char *out; /* output buffer (double-sized when reading) */
96 unsigned char *next; /* next output data to deliver or write */
97 /* just for reading */ 100 /* just for reading */
98 unsigned have; /* amount of output data unused at next */
99 int eof; /* true if end of input file reached */ 101 int eof; /* true if end of input file reached */
100 z_off64_t start; /* where the gzip data started, for rewinding */ 102 z_off64_t start; /* where the gzip data started, for rewinding */
101 int how; /* 0: get header, 1: copy, 2: decompress */ 103 int how; /* 0: get header, 1: copy, 2: decompress */
diff --git a/gzlib.c b/gzlib.c
index b26b0c2..61da8fd 100644
--- a/gzlib.c
+++ b/gzlib.c
@@ -71,15 +71,15 @@ char ZLIB_INTERNAL *gz_strwinerror (error)
71local void gz_reset(state) 71local void gz_reset(state)
72 gz_statep state; 72 gz_statep state;
73{ 73{
74 state->x.have = 0; /* no output data available */
74 if (state->mode == GZ_READ) { /* for reading ... */ 75 if (state->mode == GZ_READ) { /* for reading ... */
75 state->have = 0; /* no output data available */
76 state->eof = 0; /* not at end of file */ 76 state->eof = 0; /* not at end of file */
77 state->how = LOOK; /* look for gzip header */ 77 state->how = LOOK; /* look for gzip header */
78 state->direct = 1; /* default for empty file */ 78 state->direct = 1; /* default for empty file */
79 } 79 }
80 state->seek = 0; /* no seek request pending */ 80 state->seek = 0; /* no seek request pending */
81 gz_error(state, Z_OK, NULL); /* clear error */ 81 gz_error(state, Z_OK, NULL); /* clear error */
82 state->pos = 0; /* no uncompressed data yet */ 82 state->x.pos = 0; /* no uncompressed data yet */
83 state->strm.avail_in = 0; /* no input data yet */ 83 state->strm.avail_in = 0; /* no input data yet */
84} 84}
85 85
@@ -303,31 +303,31 @@ z_off64_t ZEXPORT gzseek64(file, offset, whence)
303 303
304 /* normalize offset to a SEEK_CUR specification */ 304 /* normalize offset to a SEEK_CUR specification */
305 if (whence == SEEK_SET) 305 if (whence == SEEK_SET)
306 offset -= state->pos; 306 offset -= state->x.pos;
307 else if (state->seek) 307 else if (state->seek)
308 offset += state->skip; 308 offset += state->skip;
309 state->seek = 0; 309 state->seek = 0;
310 310
311 /* if within raw area while reading, just go there */ 311 /* if within raw area while reading, just go there */
312 if (state->mode == GZ_READ && state->how == COPY && 312 if (state->mode == GZ_READ && state->how == COPY &&
313 state->pos + offset >= 0) { 313 state->x.pos + offset >= 0) {
314 ret = LSEEK(state->fd, offset - state->have, SEEK_CUR); 314 ret = LSEEK(state->fd, offset - state->x.have, SEEK_CUR);
315 if (ret == -1) 315 if (ret == -1)
316 return -1; 316 return -1;
317 state->have = 0; 317 state->x.have = 0;
318 state->eof = 0; 318 state->eof = 0;
319 state->seek = 0; 319 state->seek = 0;
320 gz_error(state, Z_OK, NULL); 320 gz_error(state, Z_OK, NULL);
321 state->strm.avail_in = 0; 321 state->strm.avail_in = 0;
322 state->pos += offset; 322 state->x.pos += offset;
323 return state->pos; 323 return state->x.pos;
324 } 324 }
325 325
326 /* calculate skip amount, rewinding if needed for back seek when reading */ 326 /* calculate skip amount, rewinding if needed for back seek when reading */
327 if (offset < 0) { 327 if (offset < 0) {
328 if (state->mode != GZ_READ) /* writing -- can't go backwards */ 328 if (state->mode != GZ_READ) /* writing -- can't go backwards */
329 return -1; 329 return -1;
330 offset += state->pos; 330 offset += state->x.pos;
331 if (offset < 0) /* before start of file! */ 331 if (offset < 0) /* before start of file! */
332 return -1; 332 return -1;
333 if (gzrewind(file) == -1) /* rewind, then skip to offset */ 333 if (gzrewind(file) == -1) /* rewind, then skip to offset */
@@ -336,11 +336,11 @@ z_off64_t ZEXPORT gzseek64(file, offset, whence)
336 336
337 /* if reading, skip what's in output buffer (one less gzgetc() check) */ 337 /* if reading, skip what's in output buffer (one less gzgetc() check) */
338 if (state->mode == GZ_READ) { 338 if (state->mode == GZ_READ) {
339 n = GT_OFF(state->have) || (z_off64_t)state->have > offset ? 339 n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > offset ?
340 (unsigned)offset : state->have; 340 (unsigned)offset : state->x.have;
341 state->have -= n; 341 state->x.have -= n;
342 state->next += n; 342 state->x.next += n;
343 state->pos += n; 343 state->x.pos += n;
344 offset -= n; 344 offset -= n;
345 } 345 }
346 346
@@ -349,7 +349,7 @@ z_off64_t ZEXPORT gzseek64(file, offset, whence)
349 state->seek = 1; 349 state->seek = 1;
350 state->skip = offset; 350 state->skip = offset;
351 } 351 }
352 return state->pos + offset; 352 return state->x.pos + offset;
353} 353}
354 354
355/* -- see zlib.h -- */ 355/* -- see zlib.h -- */
@@ -378,7 +378,7 @@ z_off64_t ZEXPORT gztell64(file)
378 return -1; 378 return -1;
379 379
380 /* return position */ 380 /* return position */
381 return state->pos + (state->seek ? state->skip : 0); 381 return state->x.pos + (state->seek ? state->skip : 0);
382} 382}
383 383
384/* -- see zlib.h -- */ 384/* -- see zlib.h -- */
@@ -439,7 +439,7 @@ int ZEXPORT gzeof(file)
439 439
440 /* return end-of-file state */ 440 /* return end-of-file state */
441 return state->mode == GZ_READ ? 441 return state->mode == GZ_READ ?
442 (state->eof && state->strm.avail_in == 0 && state->have == 0) : 0; 442 (state->eof && state->strm.avail_in == 0 && state->x.have == 0) : 0;
443} 443}
444 444
445/* -- see zlib.h -- */ 445/* -- see zlib.h -- */
@@ -499,6 +499,10 @@ void ZLIB_INTERNAL gz_error(state, err, msg)
499 state->msg = NULL; 499 state->msg = NULL;
500 } 500 }
501 501
502 /* if fatal, set state->x.have to 0 so that the gzgetc() macro fails */
503 if (err != Z_OK && err != Z_BUF_ERROR)
504 state->x.have = 0;
505
502 /* set error code, and if no message, then done */ 506 /* set error code, and if no message, then done */
503 state->err = err; 507 state->err = err;
504 if (msg == NULL) 508 if (msg == NULL)
diff --git a/gzread.c b/gzread.c
index a41e5d9..22eb627 100644
--- a/gzread.c
+++ b/gzread.c
@@ -68,7 +68,7 @@ local int gz_avail(state)
68 return 0; 68 return 0;
69} 69}
70 70
71/* Look for gzip header, set up for inflate or copy. state->have must be zero. 71/* Look for gzip header, set up for inflate or copy. state->x.have must be 0.
72 If this is the first time in, allocate required memory. state->how will be 72 If this is the first time in, allocate required memory. state->how will be
73 left unchanged if there is no more input data available, will be set to COPY 73 left unchanged if there is no more input data available, will be set to COPY
74 if there is no gzip header and direct copying will be performed, or it will 74 if there is no gzip header and direct copying will be performed, or it will
@@ -140,17 +140,17 @@ local int gz_look(state)
140 if (state->direct == 0) { 140 if (state->direct == 0) {
141 strm->avail_in = 0; 141 strm->avail_in = 0;
142 state->eof = 1; 142 state->eof = 1;
143 state->have = 0; 143 state->x.have = 0;
144 return 0; 144 return 0;
145 } 145 }
146 146
147 /* doing raw i/o, copy any leftover input to output -- this assumes that 147 /* doing raw i/o, copy any leftover input to output -- this assumes that
148 the output buffer is larger than the input buffer, which also assures 148 the output buffer is larger than the input buffer, which also assures
149 space for gzungetc() */ 149 space for gzungetc() */
150 state->next = state->out; 150 state->x.next = state->out;
151 if (strm->avail_in) { 151 if (strm->avail_in) {
152 memcpy(state->next, strm->next_in, strm->avail_in); 152 memcpy(state->x.next, strm->next_in, strm->avail_in);
153 state->have = strm->avail_in; 153 state->x.have = strm->avail_in;
154 strm->avail_in = 0; 154 strm->avail_in = 0;
155 } 155 }
156 state->how = COPY; 156 state->how = COPY;
@@ -159,10 +159,10 @@ local int gz_look(state)
159} 159}
160 160
161/* Decompress from input to the provided next_out and avail_out in the state. 161/* Decompress from input to the provided next_out and avail_out in the state.
162 state->have and state->next are set to point to the just decompressed data, 162 On return, state->x.have and state->x.next point to the just decompressed
163 If the gzip stream completes, state->how is reset to LOOK to look for the 163 data. If the gzip stream completes, state->how is reset to LOOK to look for
164 next gzip stream or raw data, once state->have is depleted. Returns 0 on 164 the next gzip stream or raw data, once state->x.have is depleted. Returns 0
165 success, -1 on failure. */ 165 on success, -1 on failure. */
166local int gz_decomp(state) 166local int gz_decomp(state)
167 gz_statep state; 167 gz_statep state;
168{ 168{
@@ -200,8 +200,8 @@ local int gz_decomp(state)
200 } while (strm->avail_out && ret != Z_STREAM_END); 200 } while (strm->avail_out && ret != Z_STREAM_END);
201 201
202 /* update available output */ 202 /* update available output */
203 state->have = had - strm->avail_out; 203 state->x.have = had - strm->avail_out;
204 state->next = strm->next_out - state->have; 204 state->x.next = strm->next_out - state->x.have;
205 205
206 /* if the gzip stream completed successfully, look for another */ 206 /* if the gzip stream completed successfully, look for another */
207 if (ret == Z_STREAM_END) 207 if (ret == Z_STREAM_END)
@@ -211,7 +211,7 @@ local int gz_decomp(state)
211 return 0; 211 return 0;
212} 212}
213 213
214/* Fetch data and put it in the output buffer. Assumes that state->have == 0. 214/* Fetch data and put it in the output buffer. Assumes state->x.have is 0.
215 Data is either copied from the input file or decompressed from the input 215 Data is either copied from the input file or decompressed from the input
216 file depending on state->how. If state->how is LOOK, then a gzip header is 216 file depending on state->how. If state->how is LOOK, then a gzip header is
217 looked for to determine whether to copy or decompress. Returns -1 on error, 217 looked for to determine whether to copy or decompress. Returns -1 on error,
@@ -231,10 +231,10 @@ local int gz_fetch(state)
231 return 0; 231 return 0;
232 break; 232 break;
233 case COPY: /* -> COPY */ 233 case COPY: /* -> COPY */
234 if (gz_load(state, state->out, state->size << 1, &(state->have)) 234 if (gz_load(state, state->out, state->size << 1, &(state->x.have))
235 == -1) 235 == -1)
236 return -1; 236 return -1;
237 state->next = state->out; 237 state->x.next = state->out;
238 return 0; 238 return 0;
239 case GZIP: /* -> GZIP or LOOK (if end of gzip stream) */ 239 case GZIP: /* -> GZIP or LOOK (if end of gzip stream) */
240 strm->avail_out = state->size << 1; 240 strm->avail_out = state->size << 1;
@@ -242,7 +242,7 @@ local int gz_fetch(state)
242 if (gz_decomp(state) == -1) 242 if (gz_decomp(state) == -1)
243 return -1; 243 return -1;
244 } 244 }
245 } while (state->have == 0); 245 } while (state->x.have == 0);
246 return 0; 246 return 0;
247} 247}
248 248
@@ -256,12 +256,12 @@ local int gz_skip(state, len)
256 /* skip over len bytes or reach end-of-file, whichever comes first */ 256 /* skip over len bytes or reach end-of-file, whichever comes first */
257 while (len) 257 while (len)
258 /* skip over whatever is in output buffer */ 258 /* skip over whatever is in output buffer */
259 if (state->have) { 259 if (state->x.have) {
260 n = GT_OFF(state->have) || (z_off64_t)state->have > len ? 260 n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > len ?
261 (unsigned)len : state->have; 261 (unsigned)len : state->x.have;
262 state->have -= n; 262 state->x.have -= n;
263 state->next += n; 263 state->x.next += n;
264 state->pos += n; 264 state->x.pos += n;
265 len -= n; 265 len -= n;
266 } 266 }
267 267
@@ -321,11 +321,11 @@ int ZEXPORT gzread(file, buf, len)
321 got = 0; 321 got = 0;
322 do { 322 do {
323 /* first just try copying data from the output buffer */ 323 /* first just try copying data from the output buffer */
324 if (state->have) { 324 if (state->x.have) {
325 n = state->have > len ? len : state->have; 325 n = state->x.have > len ? len : state->x.have;
326 memcpy(buf, state->next, n); 326 memcpy(buf, state->x.next, n);
327 state->next += n; 327 state->x.next += n;
328 state->have -= n; 328 state->x.have -= n;
329 } 329 }
330 330
331 /* output buffer empty -- return if we're at the end of the input */ 331 /* output buffer empty -- return if we're at the end of the input */
@@ -355,15 +355,15 @@ int ZEXPORT gzread(file, buf, len)
355 strm->next_out = buf; 355 strm->next_out = buf;
356 if (gz_decomp(state) == -1) 356 if (gz_decomp(state) == -1)
357 return -1; 357 return -1;
358 n = state->have; 358 n = state->x.have;
359 state->have = 0; 359 state->x.have = 0;
360 } 360 }
361 361
362 /* update progress */ 362 /* update progress */
363 len -= n; 363 len -= n;
364 buf = (char *)buf + n; 364 buf = (char *)buf + n;
365 got += n; 365 got += n;
366 state->pos += n; 366 state->x.pos += n;
367 } while (len); 367 } while (len);
368 368
369 /* return number of bytes read into user buffer (will fit in int) */ 369 /* return number of bytes read into user buffer (will fit in int) */
@@ -371,7 +371,7 @@ int ZEXPORT gzread(file, buf, len)
371} 371}
372 372
373/* -- see zlib.h -- */ 373/* -- see zlib.h -- */
374int ZEXPORT gzgetc(file) 374int ZEXPORT gzgetc_(file)
375 gzFile file; 375 gzFile file;
376{ 376{
377 int ret; 377 int ret;
@@ -388,11 +388,14 @@ int ZEXPORT gzgetc(file)
388 (state->err != Z_OK && state->err != Z_BUF_ERROR)) 388 (state->err != Z_OK && state->err != Z_BUF_ERROR))
389 return -1; 389 return -1;
390 390
391 /* try output buffer (no need to check for skip request) */ 391 /* try output buffer (no need to check for skip request) -- while
392 if (state->have) { 392 this check really isn't required since the gzgetc() macro has
393 state->have--; 393 already determined that x.have is zero, we leave it in for
394 state->pos++; 394 completeness. */
395 return *(state->next)++; 395 if (state->x.have) {
396 state->x.have--;
397 state->x.pos++;
398 return *(state->x.next)++;
396 } 399 }
397 400
398 /* nothing there -- try gzread() */ 401 /* nothing there -- try gzread() */
@@ -429,32 +432,32 @@ int ZEXPORT gzungetc(c, file)
429 return -1; 432 return -1;
430 433
431 /* if output buffer empty, put byte at end (allows more pushing) */ 434 /* if output buffer empty, put byte at end (allows more pushing) */
432 if (state->have == 0) { 435 if (state->x.have == 0) {
433 state->have = 1; 436 state->x.have = 1;
434 state->next = state->out + (state->size << 1) - 1; 437 state->x.next = state->out + (state->size << 1) - 1;
435 state->next[0] = c; 438 state->x.next[0] = c;
436 state->pos--; 439 state->x.pos--;
437 return c; 440 return c;
438 } 441 }
439 442
440 /* if no room, give up (must have already done a gzungetc()) */ 443 /* if no room, give up (must have already done a gzungetc()) */
441 if (state->have == (state->size << 1)) { 444 if (state->x.have == (state->size << 1)) {
442 gz_error(state, Z_BUF_ERROR, "out of room to push characters"); 445 gz_error(state, Z_BUF_ERROR, "out of room to push characters");
443 return -1; 446 return -1;
444 } 447 }
445 448
446 /* slide output data if needed and insert byte before existing data */ 449 /* slide output data if needed and insert byte before existing data */
447 if (state->next == state->out) { 450 if (state->x.next == state->out) {
448 unsigned char *src = state->out + state->have; 451 unsigned char *src = state->out + state->x.have;
449 unsigned char *dest = state->out + (state->size << 1); 452 unsigned char *dest = state->out + (state->size << 1);
450 while (src > state->out) 453 while (src > state->out)
451 *--dest = *--src; 454 *--dest = *--src;
452 state->next = dest; 455 state->x.next = dest;
453 } 456 }
454 state->have++; 457 state->x.have++;
455 state->next--; 458 state->x.next--;
456 state->next[0] = c; 459 state->x.next[0] = c;
457 state->pos--; 460 state->x.pos--;
458 return c; 461 return c;
459} 462}
460 463
@@ -493,25 +496,25 @@ char * ZEXPORT gzgets(file, buf, len)
493 left = (unsigned)len - 1; 496 left = (unsigned)len - 1;
494 if (left) do { 497 if (left) do {
495 /* assure that something is in the output buffer */ 498 /* assure that something is in the output buffer */
496 if (state->have == 0 && gz_fetch(state) == -1) 499 if (state->x.have == 0 && gz_fetch(state) == -1)
497 return NULL; /* error */ 500 return NULL; /* error */
498 if (state->have == 0) { /* end of file */ 501 if (state->x.have == 0) { /* end of file */
499 if (buf == str) /* got bupkus */ 502 if (buf == str) /* got bupkus */
500 return NULL; 503 return NULL;
501 break; /* got something -- return it */ 504 break; /* got something -- return it */
502 } 505 }
503 506
504 /* look for end-of-line in current output buffer */ 507 /* look for end-of-line in current output buffer */
505 n = state->have > left ? left : state->have; 508 n = state->x.have > left ? left : state->x.have;
506 eol = memchr(state->next, '\n', n); 509 eol = memchr(state->x.next, '\n', n);
507 if (eol != NULL) 510 if (eol != NULL)
508 n = (unsigned)(eol - state->next) + 1; 511 n = (unsigned)(eol - state->x.next) + 1;
509 512
510 /* copy through end-of-line, or remainder if not found */ 513 /* copy through end-of-line, or remainder if not found */
511 memcpy(buf, state->next, n); 514 memcpy(buf, state->x.next, n);
512 state->have -= n; 515 state->x.have -= n;
513 state->next += n; 516 state->x.next += n;
514 state->pos += n; 517 state->x.pos += n;
515 left -= n; 518 left -= n;
516 buf += n; 519 buf += n;
517 } while (left && eol == NULL); 520 } while (left && eol == NULL);
@@ -538,7 +541,7 @@ int ZEXPORT gzdirect(file)
538 541
539 /* if the state is not known, but we can find out, then do so (this is 542 /* if the state is not known, but we can find out, then do so (this is
540 mainly for right after a gzopen() or gzdopen()) */ 543 mainly for right after a gzopen() or gzdopen()) */
541 if (state->how == LOOK && state->have == 0) 544 if (state->how == LOOK && state->x.have == 0)
542 (void)gz_look(state); 545 (void)gz_look(state);
543 546
544 /* return 1 if reading direct, 0 if decompressing a gzip stream */ 547 /* return 1 if reading direct, 0 if decompressing a gzip stream */
diff --git a/gzwrite.c b/gzwrite.c
index 0ea2994..d08f309 100644
--- a/gzwrite.c
+++ b/gzwrite.c
@@ -48,7 +48,7 @@ local int gz_init(state)
48 /* initialize write buffer */ 48 /* initialize write buffer */
49 strm->avail_out = state->size; 49 strm->avail_out = state->size;
50 strm->next_out = state->out; 50 strm->next_out = state->out;
51 state->next = strm->next_out; 51 state->x.next = strm->next_out;
52 return 0; 52 return 0;
53} 53}
54 54
@@ -75,8 +75,8 @@ local int gz_comp(state, flush)
75 doing Z_FINISH then don't write until we get to Z_STREAM_END */ 75 doing Z_FINISH then don't write until we get to Z_STREAM_END */
76 if (strm->avail_out == 0 || (flush != Z_NO_FLUSH && 76 if (strm->avail_out == 0 || (flush != Z_NO_FLUSH &&
77 (flush != Z_FINISH || ret == Z_STREAM_END))) { 77 (flush != Z_FINISH || ret == Z_STREAM_END))) {
78 have = (unsigned)(strm->next_out - state->next); 78 have = (unsigned)(strm->next_out - state->x.next);
79 if (have && ((got = write(state->fd, state->next, have)) < 0 || 79 if (have && ((got = write(state->fd, state->x.next, have)) < 0 ||
80 (unsigned)got != have)) { 80 (unsigned)got != have)) {
81 gz_error(state, Z_ERRNO, zstrerror()); 81 gz_error(state, Z_ERRNO, zstrerror());
82 return -1; 82 return -1;
@@ -85,7 +85,7 @@ local int gz_comp(state, flush)
85 strm->avail_out = state->size; 85 strm->avail_out = state->size;
86 strm->next_out = state->out; 86 strm->next_out = state->out;
87 } 87 }
88 state->next = strm->next_out; 88 state->x.next = strm->next_out;
89 } 89 }
90 90
91 /* compress */ 91 /* compress */
@@ -131,7 +131,7 @@ local int gz_zero(state, len)
131 } 131 }
132 strm->avail_in = n; 132 strm->avail_in = n;
133 strm->next_in = state->in; 133 strm->next_in = state->in;
134 state->pos += n; 134 state->x.pos += n;
135 if (gz_comp(state, Z_NO_FLUSH) == -1) 135 if (gz_comp(state, Z_NO_FLUSH) == -1)
136 return -1; 136 return -1;
137 len -= n; 137 len -= n;
@@ -193,7 +193,7 @@ int ZEXPORT gzwrite(file, buf, len)
193 n = len; 193 n = len;
194 memcpy(strm->next_in + strm->avail_in, buf, n); 194 memcpy(strm->next_in + strm->avail_in, buf, n);
195 strm->avail_in += n; 195 strm->avail_in += n;
196 state->pos += n; 196 state->x.pos += n;
197 buf = (char *)buf + n; 197 buf = (char *)buf + n;
198 len -= n; 198 len -= n;
199 if (len && gz_comp(state, Z_NO_FLUSH) == -1) 199 if (len && gz_comp(state, Z_NO_FLUSH) == -1)
@@ -208,7 +208,7 @@ int ZEXPORT gzwrite(file, buf, len)
208 /* directly compress user buffer to file */ 208 /* directly compress user buffer to file */
209 strm->avail_in = len; 209 strm->avail_in = len;
210 strm->next_in = (voidp)buf; 210 strm->next_in = (voidp)buf;
211 state->pos += len; 211 state->x.pos += len;
212 if (gz_comp(state, Z_NO_FLUSH) == -1) 212 if (gz_comp(state, Z_NO_FLUSH) == -1)
213 return 0; 213 return 0;
214 } 214 }
@@ -249,7 +249,7 @@ int ZEXPORT gzputc(file, c)
249 if (strm->avail_in == 0) 249 if (strm->avail_in == 0)
250 strm->next_in = state->in; 250 strm->next_in = state->in;
251 strm->next_in[strm->avail_in++] = c; 251 strm->next_in[strm->avail_in++] = c;
252 state->pos++; 252 state->x.pos++;
253 return c; 253 return c;
254 } 254 }
255 255
@@ -342,7 +342,7 @@ int ZEXPORTVA gzprintf (gzFile file, const char *format, ...)
342 /* update buffer and position, defer compression until needed */ 342 /* update buffer and position, defer compression until needed */
343 strm->avail_in = (unsigned)len; 343 strm->avail_in = (unsigned)len;
344 strm->next_in = state->in; 344 strm->next_in = state->in;
345 state->pos += len; 345 state->x.pos += len;
346 return len; 346 return len;
347} 347}
348 348
@@ -420,7 +420,7 @@ int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
420 /* update buffer and position, defer compression until needed */ 420 /* update buffer and position, defer compression until needed */
421 strm->avail_in = (unsigned)len; 421 strm->avail_in = (unsigned)len;
422 strm->next_in = state->in; 422 strm->next_in = state->in;
423 state->pos += len; 423 state->x.pos += len;
424 return len; 424 return len;
425} 425}
426 426
diff --git a/zlib.h b/zlib.h
index 4c505b9..d358a62 100644
--- a/zlib.h
+++ b/zlib.h
@@ -1186,7 +1186,7 @@ ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen,
1186 wrapper, documented in RFC 1952, wrapped around a deflate stream. 1186 wrapper, documented in RFC 1952, wrapped around a deflate stream.
1187*/ 1187*/
1188 1188
1189typedef voidp gzFile; /* opaque gzip file descriptor */ 1189typedef struct gzFile_s *gzFile; /* semi-opaque gzip file descriptor */
1190 1190
1191/* 1191/*
1192ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); 1192ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode));
@@ -1322,10 +1322,13 @@ ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c));
1322 returns the value that was written, or -1 in case of error. 1322 returns the value that was written, or -1 in case of error.
1323*/ 1323*/
1324 1324
1325ZEXTERN int ZEXPORT gzgetc OF((gzFile file));
1326/* 1325/*
1326ZEXTERN int ZEXPORT gzgetc OF((gzFile file));
1327 Reads one byte from the compressed file. gzgetc returns this byte or -1 1327 Reads one byte from the compressed file. gzgetc returns this byte or -1
1328 in case of end of file or error. 1328 in case of end of file or error. This is implemented as a macro for speed.
1329 As such, it does not do all of the checking the other functions do. I.e.
1330 it does not check to see if file is NULL, nor whether the structure file
1331 points to has been clobbered or not.
1329*/ 1332*/
1330 1333
1331ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); 1334ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file));
@@ -1583,6 +1586,22 @@ ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits,
1583 inflateBackInit_((strm), (windowBits), (window), \ 1586 inflateBackInit_((strm), (windowBits), (window), \
1584 ZLIB_VERSION, (int)sizeof(z_stream)) 1587 ZLIB_VERSION, (int)sizeof(z_stream))
1585 1588
1589/* gzgetc() macro and its supporting function and exposed data structure. Note
1590 * that the real internal state is much larger than the exposed structure.
1591 * This abbreviated structure exposes just enough for the gzgetc() macro. The
1592 * user should not mess with these exposed elements, since their names or
1593 * behavior could change in the future, perhaps even capriciously. They can
1594 * only be used by the gzgetc() macro. You have been warned.
1595 */
1596struct gzFile_s {
1597 unsigned have;
1598 unsigned char *next;
1599 z_off64_t pos;
1600};
1601ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file));
1602#define gzgetc(g) \
1603 ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : gzgetc_(g))
1604
1586/* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or 1605/* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or
1587 * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if 1606 * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if
1588 * both are true, the application gets the *64 functions, and the regular 1607 * both are true, the application gets the *64 functions, and the regular