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