Skip to content

Commit 9569809

Browse files
committed
Improve speed of gzprintf() in transparent mode.
1 parent 8a979f6 commit 9569809

File tree

4 files changed

+70
-51
lines changed

4 files changed

+70
-51
lines changed

gzguts.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ typedef struct {
170170
char *path; /* path or fd for error messages */
171171
unsigned size; /* buffer size, zero if not allocated yet */
172172
unsigned want; /* requested buffer size, default is GZBUFSIZE */
173-
unsigned char *in; /* input buffer */
173+
unsigned char *in; /* input buffer (double-sized when writing) */
174174
unsigned char *out; /* output buffer (double-sized when reading) */
175175
int direct; /* 0 if processing gzip, 1 if transparent */
176176
/* just for reading */

gzlib.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,8 @@ int ZEXPORT gzbuffer(file, size)
331331
return -1;
332332

333333
/* check and set requested size */
334+
if ((size << 1) < size)
335+
return -1; /* need to be able to double it */
334336
if (size < 2)
335337
size = 2; /* need two bytes to check magic header */
336338
state->want = size;

gzwrite.c

Lines changed: 64 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ local int gz_init(state)
1818
int ret;
1919
z_streamp strm = &(state->strm);
2020

21-
/* allocate input buffer */
22-
state->in = (unsigned char *)malloc(state->want);
21+
/* allocate input buffer (double size for gzprintf) */
22+
state->in = (unsigned char *)malloc(state->want << 1);
2323
if (state->in == NULL) {
2424
gz_error(state, Z_MEM_ERROR, "out of memory");
2525
return -1;
@@ -309,7 +309,8 @@ int ZEXPORT gzputs(file, str)
309309
/* -- see zlib.h -- */
310310
int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va)
311311
{
312-
int size, len;
312+
unsigned len, left;
313+
char *next;
313314
gz_statep state;
314315
z_streamp strm;
315316

@@ -334,39 +335,47 @@ int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va)
334335
return 0;
335336
}
336337

337-
/* consume whatever's left in the input buffer */
338-
if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
339-
return 0;
340-
341-
/* do the printf() into the input buffer, put length in len */
342-
size = (int)(state->size);
343-
state->in[size - 1] = 0;
338+
/* do the printf() into the input buffer, put length in len -- the input
339+
buffer is double-sized just for this function, so there is guaranteed to
340+
be state->size bytes available after the current contents */
341+
if (strm->avail_in == 0)
342+
strm->next_in = state->in;
343+
next = (char *)(strm->next_in + strm->avail_in);
344+
next[state->size - 1] = 0;
344345
#ifdef NO_vsnprintf
345346
# ifdef HAS_vsprintf_void
346-
(void)vsprintf((char *)(state->in), format, va);
347-
for (len = 0; len < size; len++)
348-
if (state->in[len] == 0) break;
347+
(void)vsprintf(next, format, va);
348+
for (len = 0; len < state->size; len++)
349+
if (next[len] == 0) break;
349350
# else
350-
len = vsprintf((char *)(state->in), format, va);
351+
len = vsprintf(next, format, va);
351352
# endif
352353
#else
353354
# ifdef HAS_vsnprintf_void
354-
(void)vsnprintf((char *)(state->in), size, format, va);
355-
len = strlen((char *)(state->in));
355+
(void)vsnprintf(next, state->size, format, va);
356+
len = strlen(next);
356357
# else
357-
len = vsnprintf((char *)(state->in), size, format, va);
358+
len = vsnprintf(next, state->size, format, va);
358359
# endif
359360
#endif
360361

361362
/* 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)
363364
return 0;
364365

365-
/* update buffer and position, defer compression until needed */
366-
strm->avail_in = (unsigned)len;
367-
strm->next_in = state->in;
366+
/* update buffer and position, compress first half if past that */
367+
strm->avail_in += len;
368368
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;
370379
}
371380

372381
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,
390399
int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
391400
a11, a12, a13, a14, a15, a16, a17, a18, a19, a20;
392401
{
393-
int size, len;
402+
unsigned len, left;
403+
char *next;
394404
gz_statep state;
395405
z_streamp strm;
396406

@@ -419,44 +429,52 @@ int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
419429
return 0;
420430
}
421431

422-
/* consume whatever's left in the input buffer */
423-
if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
424-
return 0;
425-
426-
/* do the printf() into the input buffer, put length in len */
427-
size = (int)(state->size);
428-
state->in[size - 1] = 0;
432+
/* do the printf() into the input buffer, put length in len -- the input
433+
buffer is double-sized just for this function, so there is guaranteed to
434+
be state->size bytes available after the current contents */
435+
if (strm->avail_in == 0)
436+
strm->next_in = state->in;
437+
next = (char *)(strm->next_in + strm->avail_in);
438+
next[state->size - 1] = 0;
429439
#ifdef NO_snprintf
430440
# ifdef HAS_sprintf_void
431-
sprintf((char *)(state->in), format, a1, a2, a3, a4, a5, a6, a7, a8,
432-
a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
441+
sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12,
442+
a13, a14, a15, a16, a17, a18, a19, a20);
433443
for (len = 0; len < size; len++)
434-
if (state->in[len] == 0) break;
444+
if (next[len] == 0)
445+
break;
435446
# else
436-
len = sprintf((char *)(state->in), format, a1, a2, a3, a4, a5, a6, a7, a8,
437-
a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
447+
len = sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11,
448+
a12, a13, a14, a15, a16, a17, a18, a19, a20);
438449
# endif
439450
#else
440451
# ifdef HAS_snprintf_void
441-
snprintf((char *)(state->in), size, format, a1, a2, a3, a4, a5, a6, a7, a8,
442-
a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
443-
len = strlen((char *)(state->in));
452+
snprintf(next, state->size, format, a1, a2, a3, a4, a5, a6, a7, a8, a9,
453+
a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
454+
len = strlen(next);
444455
# else
445-
len = snprintf((char *)(state->in), size, format, a1, a2, a3, a4, a5, a6,
446-
a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18,
447-
a19, a20);
456+
len = snprintf(next, state->size, format, a1, a2, a3, a4, a5, a6, a7, a8,
457+
a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
448458
# endif
449459
#endif
450460

451461
/* 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)
453463
return 0;
454464

455-
/* update buffer and position, defer compression until needed */
456-
strm->avail_in = (unsigned)len;
457-
strm->next_in = state->in;
465+
/* update buffer and position, compress first half if past that */
466+
strm->avail_in += len;
458467
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;
460478
}
461479

462480
#endif

zlib.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1291,10 +1291,9 @@ ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size));
12911291
default buffer size is 8192 bytes. This function must be called after
12921292
gzopen() or gzdopen(), and before any other calls that read or write the
12931293
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
1295-
writing, or one of the specified size and the other twice that size when
1296-
reading. A larger buffer size of, for example, 64K or 128K bytes will
1297-
noticeably increase the speed of decompression (reading).
1294+
write. Three times that size in buffer space is allocated. A larger buffer
1295+
size of, for example, 64K or 128K bytes will noticeably increase the speed
1296+
of decompression (reading).
12981297
12991298
The new buffer size also affects the maximum length for gzprintf().
13001299

0 commit comments

Comments
 (0)