iliaa Sun Jun 5 14:04:21 2005 EDT Modified files: /php-src/ext/bz2 bz2.c Log: Fixed bug #33070 (Improved performance of bzdecompress() by several orders of magnitude). http://cvs.php.net/diff.php/php-src/ext/bz2/bz2.c?r1=1.9&r2=1.10&ty=u Index: php-src/ext/bz2/bz2.c diff -u php-src/ext/bz2/bz2.c:1.9 php-src/ext/bz2/bz2.c:1.10 --- php-src/ext/bz2/bz2.c:1.9 Sat Mar 19 08:56:00 2005 +++ php-src/ext/bz2/bz2.c Sun Jun 5 14:04:20 2005 @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: bz2.c,v 1.9 2005/03/19 13:56:00 tony2001 Exp $ */ +/* $Id: bz2.c,v 1.10 2005/06/05 18:04:20 iliaa Exp $ */ #ifdef HAVE_CONFIG_H #include "config.h" @@ -40,9 +40,6 @@ #define PHP_BZ_ERRSTR 1 #define PHP_BZ_ERRBOTH 2 -/* Blocksize of the decompression buffer */ -#define PHP_BZ_DECOMPRESS_SIZE 4096 - function_entry bz2_functions[] = { PHP_FE(bzopen, NULL) PHP_FE(bzread, NULL) @@ -441,56 +438,49 @@ Decompresses BZip2 compressed data */ PHP_FUNCTION(bzdecompress) { - zval **source, /* Source data to decompress */ - **zsmall; /* (Optional) user specified small */ - char *dest; /* Destination buffer, initially allocated */ - int error, /* Error container */ - iter = 1, /* Iteration count for the compression loop */ - size, /* Current size to realloc the dest buffer to */ - dest_len = PHP_BZ_DECOMPRESS_SIZE, /* Size of the destination length */ - small = 0, /* The actual small */ - argc = ZEND_NUM_ARGS(); /* Argument count */ - - if (argc < 1 || argc > 2 || zend_get_parameters_ex(argc, &source, &zsmall) == FAILURE) { - WRONG_PARAM_COUNT; + char *source, *dest; + int source_len, error; + long small = 0; + unsigned int size = 0; + bz_stream bzs; + + if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &source, &source_len, &small)) { + RETURN_FALSE; } - convert_to_string_ex(source); - - /* optional small argument handling */ - if (argc > 1) { - convert_to_long_ex(zsmall); - small = Z_LVAL_PP(zsmall); + bzs.bzalloc = NULL; + bzs.bzfree = NULL; + + if (BZ2_bzDecompressInit(&bzs, 0, small) != BZ_OK) { + RETURN_FALSE; } - /* Depending on the size of the source buffer, either allocate - the length of the source buffer or the a default decompression - size */ - dest = emalloc(PHP_BZ_DECOMPRESS_SIZE > Z_STRLEN_PP(source) ? PHP_BZ_DECOMPRESS_SIZE : Z_STRLEN_PP(source)); - - /* (de)Compression Loop */ - do { - /* Handle the (re)allocation of the buffer */ - size = dest_len * iter; - if (iter > 1) { - dest = erealloc(dest, size); - } - ++iter; + bzs.next_in = source; + bzs.avail_in = source_len; - /* Perform the decompression */ - error = BZ2_bzBuffToBuffDecompress(dest, &size, Z_STRVAL_PP(source), Z_STRLEN_PP(source), small, 0); - } while (error == BZ_OUTBUFF_FULL); - - if (error != BZ_OK) { - efree(dest); - RETURN_LONG(error); - } else { - /* we might have allocated a little to much, so erealloc the buffer - down to size, before returning it */ + /* in most cases bz2 offers at least 2:1 compression, so we use that as our base */ + bzs.avail_out = source_len * 2; + bzs.next_out = dest = emalloc(bzs.avail_out + 1); + + while ((error = BZ2_bzDecompress(&bzs)) == BZ_OK && bzs.avail_in > 0) { + /* compression is better then 2:1, need to allocate more memory */ + bzs.avail_out = source_len; + size = (bzs.total_out_hi32 << 32) + bzs.total_out_lo32; + dest = erealloc(dest, size + bzs.avail_out + 1); + bzs.next_out = dest + size; + } + + if (error == BZ_STREAM_END || error == BZ_OK) { + size = (bzs.total_out_hi32 << 32) + bzs.total_out_lo32; dest = erealloc(dest, size + 1); - dest[size] = 0; - RETURN_STRINGL(dest, size, 0); + dest[size] = '\0'; + RETVAL_STRINGL(dest, size, 0); + } else { /* real error */ + efree(dest); + RETVAL_LONG(error); } + + BZ2_bzDecompressEnd(&bzs); } /* }}} */
-- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php