From 1014a9adbf2f32684865b052bab803581d416875 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 29 Oct 2010 19:01:58 +0200 Subject: decompress_bunzip2: relieve register pressure in hot function read_bunzip function old new delta unpack_bz2_stream 318 329 +11 read_bunzip 268 262 -6 Signed-off-by: Denys Vlasenko --- archival/libunarchive/decompress_bunzip2.c | 20 +++++++++++++------- include/unarchive.h | 2 ++ 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/archival/libunarchive/decompress_bunzip2.c b/archival/libunarchive/decompress_bunzip2.c index 8d7746a79..00ec47c75 100644 --- a/archival/libunarchive/decompress_bunzip2.c +++ b/archival/libunarchive/decompress_bunzip2.c @@ -488,18 +488,21 @@ static int get_next_block(bunzip_data *bd) data are written to outbuf. Return value is number of bytes written or error (all errors are negative numbers). If out_fd!=-1, outbuf and len are ignored, data is written to out_fd and return is RETVAL_OK or error. + + NB: read_bunzip returns < 0 on error, or the number of *unfilled* bytes + in outbuf. IOW: on EOF returns len ("all bytes are not filled"), not 0. + (Why? This allows to get rid of one local variable) */ int FAST_FUNC read_bunzip(bunzip_data *bd, char *outbuf, int len) { const uint32_t *dbuf; - int pos, current, previous, out_count; + int pos, current, previous; uint32_t CRC; /* If we already have error/end indicator, return it */ if (bd->writeCount < 0) return bd->writeCount; - out_count = 0; dbuf = bd->dbuf; /* Register-cached state (hopefully): */ @@ -520,7 +523,7 @@ int FAST_FUNC read_bunzip(bunzip_data *bd, char *outbuf, int len) for (;;) { /* If the output buffer is full, save cached state and return */ - if (out_count >= len) { + if (--len < 0) { /* Unlikely branch. * Use of "goto" instead of keeping code here * helps compiler to realize this. */ @@ -528,7 +531,7 @@ int FAST_FUNC read_bunzip(bunzip_data *bd, char *outbuf, int len) } /* Write next byte into output buffer, updating CRC */ - outbuf[out_count++] = current; + *outbuf++ = current; CRC = (CRC << 8) ^ bd->crc32Table[(CRC >> 24) ^ current]; /* Loop now if we're outputting multiple copies of this byte */ @@ -587,7 +590,7 @@ int FAST_FUNC read_bunzip(bunzip_data *bd, char *outbuf, int len) int r = get_next_block(bd); if (r) { /* error/end */ bd->writeCount = r; - return (r != RETVAL_LAST_BLOCK) ? r : out_count; + return (r != RETVAL_LAST_BLOCK) ? r : len; } } @@ -604,7 +607,7 @@ int FAST_FUNC read_bunzip(bunzip_data *bd, char *outbuf, int len) bd->writeCopies++; - return out_count; + return 0; } /* Allocate the structure, read file header. If in_fd==-1, inbuf must contain @@ -698,7 +701,10 @@ unpack_bz2_stream(int src_fd, int dst_fd) if (i == 0) { while (1) { /* "Produce some output bytes" loop */ i = read_bunzip(bd, outbuf, IOBUF_SIZE); - if (i <= 0) + if (i < 0) /* error? */ + break; + i = IOBUF_SIZE - i; /* number of bytes produced */ + if (i == 0) /* EOF? */ break; if (i != full_write(dst_fd, outbuf, i)) { bb_error_msg("short write"); diff --git a/include/unarchive.h b/include/unarchive.h index 11d8c77a0..ba6d323e0 100644 --- a/include/unarchive.h +++ b/include/unarchive.h @@ -194,6 +194,8 @@ extern const llist_t *find_list_entry2(const llist_t *list, const char *filename /* A bit of bunzip2 internals are exposed for compressed help support: */ typedef struct bunzip_data bunzip_data; int start_bunzip(bunzip_data **bdp, int in_fd, const void *inbuf, int len) FAST_FUNC; +/* NB: read_bunzip returns < 0 on error, or the number of *unfilled* bytes + * in outbuf. IOW: on EOF returns len ("all bytes are not filled"), not 0: */ int read_bunzip(bunzip_data *bd, char *outbuf, int len) FAST_FUNC; void dealloc_bunzip(bunzip_data *bd) FAST_FUNC; -- cgit v1.2.3