diff options
| author | Mark Adler <madler@alumni.caltech.edu> | 2015-07-05 18:14:53 -0700 |
|---|---|---|
| committer | Mark Adler <madler@alumni.caltech.edu> | 2015-07-05 18:14:53 -0700 |
| commit | 95698093f023852ca4365df307c19a1d7cfa3687 (patch) | |
| tree | 743b907c5449f617343e8bec546eabbb650df0a8 | |
| parent | 8a979f6c7986574e37316148cd8ca440c3bc08a3 (diff) | |
| download | zlib-95698093f023852ca4365df307c19a1d7cfa3687.tar.gz zlib-95698093f023852ca4365df307c19a1d7cfa3687.tar.bz2 zlib-95698093f023852ca4365df307c19a1d7cfa3687.zip | |
Improve speed of gzprintf() in transparent mode.
| -rw-r--r-- | gzguts.h | 2 | ||||
| -rw-r--r-- | gzlib.c | 2 | ||||
| -rw-r--r-- | gzwrite.c | 110 | ||||
| -rw-r--r-- | zlib.h | 7 |
4 files changed, 70 insertions, 51 deletions
| @@ -170,7 +170,7 @@ typedef struct { | |||
| 170 | char *path; /* path or fd for error messages */ | 170 | char *path; /* path or fd for error messages */ |
| 171 | unsigned size; /* buffer size, zero if not allocated yet */ | 171 | unsigned size; /* buffer size, zero if not allocated yet */ |
| 172 | unsigned want; /* requested buffer size, default is GZBUFSIZE */ | 172 | unsigned want; /* requested buffer size, default is GZBUFSIZE */ |
| 173 | unsigned char *in; /* input buffer */ | 173 | unsigned char *in; /* input buffer (double-sized when writing) */ |
| 174 | unsigned char *out; /* output buffer (double-sized when reading) */ | 174 | unsigned char *out; /* output buffer (double-sized when reading) */ |
| 175 | int direct; /* 0 if processing gzip, 1 if transparent */ | 175 | int direct; /* 0 if processing gzip, 1 if transparent */ |
| 176 | /* just for reading */ | 176 | /* just for reading */ |
| @@ -331,6 +331,8 @@ int ZEXPORT gzbuffer(file, size) | |||
| 331 | return -1; | 331 | return -1; |
| 332 | 332 | ||
| 333 | /* check and set requested size */ | 333 | /* check and set requested size */ |
| 334 | if ((size << 1) < size) | ||
| 335 | return -1; /* need to be able to double it */ | ||
| 334 | if (size < 2) | 336 | if (size < 2) |
| 335 | size = 2; /* need two bytes to check magic header */ | 337 | size = 2; /* need two bytes to check magic header */ |
| 336 | state->want = size; | 338 | state->want = size; |
| @@ -18,8 +18,8 @@ local int gz_init(state) | |||
| 18 | int ret; | 18 | int ret; |
| 19 | z_streamp strm = &(state->strm); | 19 | z_streamp strm = &(state->strm); |
| 20 | 20 | ||
| 21 | /* allocate input buffer */ | 21 | /* allocate input buffer (double size for gzprintf) */ |
| 22 | state->in = (unsigned char *)malloc(state->want); | 22 | state->in = (unsigned char *)malloc(state->want << 1); |
| 23 | if (state->in == NULL) { | 23 | if (state->in == NULL) { |
| 24 | gz_error(state, Z_MEM_ERROR, "out of memory"); | 24 | gz_error(state, Z_MEM_ERROR, "out of memory"); |
| 25 | return -1; | 25 | return -1; |
| @@ -309,7 +309,8 @@ int ZEXPORT gzputs(file, str) | |||
| 309 | /* -- see zlib.h -- */ | 309 | /* -- see zlib.h -- */ |
| 310 | int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va) | 310 | int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va) |
| 311 | { | 311 | { |
| 312 | int size, len; | 312 | unsigned len, left; |
| 313 | char *next; | ||
| 313 | gz_statep state; | 314 | gz_statep state; |
| 314 | z_streamp strm; | 315 | z_streamp strm; |
| 315 | 316 | ||
| @@ -334,39 +335,47 @@ int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va) | |||
| 334 | return 0; | 335 | return 0; |
| 335 | } | 336 | } |
| 336 | 337 | ||
| 337 | /* consume whatever's left in the input buffer */ | 338 | /* do the printf() into the input buffer, put length in len -- the input |
| 338 | if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) | 339 | buffer is double-sized just for this function, so there is guaranteed to |
| 339 | return 0; | 340 | be state->size bytes available after the current contents */ |
| 340 | 341 | if (strm->avail_in == 0) | |
| 341 | /* do the printf() into the input buffer, put length in len */ | 342 | strm->next_in = state->in; |
| 342 | size = (int)(state->size); | 343 | next = (char *)(strm->next_in + strm->avail_in); |
| 343 | state->in[size - 1] = 0; | 344 | next[state->size - 1] = 0; |
| 344 | #ifdef NO_vsnprintf | 345 | #ifdef NO_vsnprintf |
| 345 | # ifdef HAS_vsprintf_void | 346 | # ifdef HAS_vsprintf_void |
| 346 | (void)vsprintf((char *)(state->in), format, va); | 347 | (void)vsprintf(next, format, va); |
| 347 | for (len = 0; len < size; len++) | 348 | for (len = 0; len < state->size; len++) |
| 348 | if (state->in[len] == 0) break; | 349 | if (next[len] == 0) break; |
| 349 | # else | 350 | # else |
| 350 | len = vsprintf((char *)(state->in), format, va); | 351 | len = vsprintf(next, format, va); |
| 351 | # endif | 352 | # endif |
| 352 | #else | 353 | #else |
| 353 | # ifdef HAS_vsnprintf_void | 354 | # ifdef HAS_vsnprintf_void |
| 354 | (void)vsnprintf((char *)(state->in), size, format, va); | 355 | (void)vsnprintf(next, state->size, format, va); |
| 355 | len = strlen((char *)(state->in)); | 356 | len = strlen(next); |
| 356 | # else | 357 | # else |
| 357 | len = vsnprintf((char *)(state->in), size, format, va); | 358 | len = vsnprintf(next, state->size, format, va); |
| 358 | # endif | 359 | # endif |
| 359 | #endif | 360 | #endif |
| 360 | 361 | ||
| 361 | /* check that printf() results fit in buffer */ | 362 | /* check that printf() results fit in buffer */ |
| 362 | if (len <= 0 || len >= (int)size || state->in[size - 1] != 0) | 363 | if (len == 0 || len >= state->size || next[state->size - 1] != 0) |
| 363 | return 0; | 364 | return 0; |
| 364 | 365 | ||
| 365 | /* update buffer and position, defer compression until needed */ | 366 | /* update buffer and position, compress first half if past that */ |
| 366 | strm->avail_in = (unsigned)len; | 367 | strm->avail_in += len; |
| 367 | strm->next_in = state->in; | ||
| 368 | state->x.pos += len; | 368 | state->x.pos += len; |
| 369 | return len; | 369 | if (strm->avail_in >= state->size) { |
| 370 | left = strm->avail_in - state->size; | ||
| 371 | strm->avail_in = state->size; | ||
| 372 | if (gz_comp(state, Z_NO_FLUSH) == -1) | ||
| 373 | return 0; | ||
| 374 | memcpy(state->in, state->in + state->size, left); | ||
| 375 | strm->next_in = state->in; | ||
| 376 | strm->avail_in = left; | ||
| 377 | } | ||
| 378 | return (int)len; | ||
| 370 | } | 379 | } |
| 371 | 380 | ||
| 372 | int ZEXPORTVA gzprintf(gzFile file, const char *format, ...) | 381 | int ZEXPORTVA gzprintf(gzFile file, const char *format, ...) |
| @@ -390,7 +399,8 @@ int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, | |||
| 390 | int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, | 399 | int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, |
| 391 | a11, a12, a13, a14, a15, a16, a17, a18, a19, a20; | 400 | a11, a12, a13, a14, a15, a16, a17, a18, a19, a20; |
| 392 | { | 401 | { |
| 393 | int size, len; | 402 | unsigned len, left; |
| 403 | char *next; | ||
| 394 | gz_statep state; | 404 | gz_statep state; |
| 395 | z_streamp strm; | 405 | z_streamp strm; |
| 396 | 406 | ||
| @@ -419,44 +429,52 @@ int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, | |||
| 419 | return 0; | 429 | return 0; |
| 420 | } | 430 | } |
| 421 | 431 | ||
| 422 | /* consume whatever's left in the input buffer */ | 432 | /* do the printf() into the input buffer, put length in len -- the input |
| 423 | if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) | 433 | buffer is double-sized just for this function, so there is guaranteed to |
| 424 | return 0; | 434 | be state->size bytes available after the current contents */ |
| 425 | 435 | if (strm->avail_in == 0) | |
| 426 | /* do the printf() into the input buffer, put length in len */ | 436 | strm->next_in = state->in; |
| 427 | size = (int)(state->size); | 437 | next = (char *)(strm->next_in + strm->avail_in); |
| 428 | state->in[size - 1] = 0; | 438 | next[state->size - 1] = 0; |
| 429 | #ifdef NO_snprintf | 439 | #ifdef NO_snprintf |
| 430 | # ifdef HAS_sprintf_void | 440 | # ifdef HAS_sprintf_void |
| 431 | sprintf((char *)(state->in), format, a1, a2, a3, a4, a5, a6, a7, a8, | 441 | sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, |
| 432 | a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); | 442 | a13, a14, a15, a16, a17, a18, a19, a20); |
| 433 | for (len = 0; len < size; len++) | 443 | for (len = 0; len < size; len++) |
| 434 | if (state->in[len] == 0) break; | 444 | if (next[len] == 0) |
| 445 | break; | ||
| 435 | # else | 446 | # else |
| 436 | len = sprintf((char *)(state->in), format, a1, a2, a3, a4, a5, a6, a7, a8, | 447 | len = sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, |
| 437 | a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); | 448 | a12, a13, a14, a15, a16, a17, a18, a19, a20); |
| 438 | # endif | 449 | # endif |
| 439 | #else | 450 | #else |
| 440 | # ifdef HAS_snprintf_void | 451 | # ifdef HAS_snprintf_void |
| 441 | snprintf((char *)(state->in), size, format, a1, a2, a3, a4, a5, a6, a7, a8, | 452 | snprintf(next, state->size, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, |
| 442 | a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); | 453 | a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); |
| 443 | len = strlen((char *)(state->in)); | 454 | len = strlen(next); |
| 444 | # else | 455 | # else |
| 445 | len = snprintf((char *)(state->in), size, format, a1, a2, a3, a4, a5, a6, | 456 | len = snprintf(next, state->size, format, a1, a2, a3, a4, a5, a6, a7, a8, |
| 446 | a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, | 457 | a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); |
| 447 | a19, a20); | ||
| 448 | # endif | 458 | # endif |
| 449 | #endif | 459 | #endif |
| 450 | 460 | ||
| 451 | /* check that printf() results fit in buffer */ | 461 | /* check that printf() results fit in buffer */ |
| 452 | if (len <= 0 || len >= (int)size || state->in[size - 1] != 0) | 462 | if (len == 0 || len >= state->size || next[state->size - 1] != 0) |
| 453 | return 0; | 463 | return 0; |
| 454 | 464 | ||
| 455 | /* update buffer and position, defer compression until needed */ | 465 | /* update buffer and position, compress first half if past that */ |
| 456 | strm->avail_in = (unsigned)len; | 466 | strm->avail_in += len; |
| 457 | strm->next_in = state->in; | ||
| 458 | state->x.pos += len; | 467 | state->x.pos += len; |
| 459 | return len; | 468 | if (strm->avail_in >= state->size) { |
| 469 | left = strm->avail_in - state->size; | ||
| 470 | strm->avail_in = state->size; | ||
| 471 | if (gz_comp(state, Z_NO_FLUSH) == -1) | ||
| 472 | return 0; | ||
| 473 | memcpy(state->in, state->in + state->size, left); | ||
| 474 | strm->next_in = state->in; | ||
| 475 | strm->avail_in = left; | ||
| 476 | } | ||
| 477 | return (int)len; | ||
| 460 | } | 478 | } |
| 461 | 479 | ||
| 462 | #endif | 480 | #endif |
| @@ -1291,10 +1291,9 @@ ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size)); | |||
| 1291 | default buffer size is 8192 bytes. This function must be called after | 1291 | default buffer size is 8192 bytes. This function must be called after |
| 1292 | gzopen() or gzdopen(), and before any other calls that read or write the | 1292 | gzopen() or gzdopen(), and before any other calls that read or write the |
| 1293 | file. The buffer memory allocation is always deferred to the first read or | 1293 | file. The buffer memory allocation is always deferred to the first read or |
| 1294 | write. Two buffers are allocated, either both of the specified size when | 1294 | write. Three times that size in buffer space is allocated. A larger buffer |
| 1295 | writing, or one of the specified size and the other twice that size when | 1295 | size of, for example, 64K or 128K bytes will noticeably increase the speed |
| 1296 | reading. A larger buffer size of, for example, 64K or 128K bytes will | 1296 | of decompression (reading). |
| 1297 | noticeably increase the speed of decompression (reading). | ||
| 1298 | 1297 | ||
| 1299 | The new buffer size also affects the maximum length for gzprintf(). | 1298 | The new buffer size also affects the maximum length for gzprintf(). |
| 1300 | 1299 | ||
