moriyoshi Tue Feb 18 18:22:49 2003 EDT Modified files: /php4/ext/standard filters.c Log: Revived convert filter codes
Index: php4/ext/standard/filters.c diff -u php4/ext/standard/filters.c:1.24 php4/ext/standard/filters.c:1.25 --- php4/ext/standard/filters.c:1.24 Mon Feb 17 20:22:21 2003 +++ php4/ext/standard/filters.c Tue Feb 18 18:22:49 2003 @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: filters.c,v 1.24 2003/02/18 01:22:21 wez Exp $ */ +/* $Id: filters.c,v 1.25 2003/02/18 23:22:49 moriyoshi Exp $ */ #include "php.h" #include "php_globals.h" @@ -1016,14 +1016,9 @@ /* }}} */ typedef struct _php_convert_filter { - php_conv *write_cd; - php_conv *read_cd; + php_conv *cd; int persistent; char *filtername; - - /* ring buffer for read operation */ - char read_buf[4096]; - size_t read_buf_left; } php_convert_filter; #define PHP_CONV_BASE64_ENCODE 1 @@ -1303,40 +1298,22 @@ #undef GET_BOOL_PROP static int php_convert_filter_ctor(php_convert_filter *inst, - int write_conv_mode, HashTable *write_conv_opts, - int read_conv_mode, HashTable *read_conv_opts, + int conv_mode, HashTable *conv_opts, const char *filtername, int persistent) { - php_conv *write_cd = NULL; - php_conv *read_cd = NULL; - inst->persistent = persistent; - inst->filtername = pestrdup(filtername, persistent); - if ((write_cd = php_conv_open(write_conv_mode, write_conv_opts, persistent)) == NULL) { - goto out_failure; - } - - if ((read_cd = php_conv_open(read_conv_mode, read_conv_opts, persistent)) == NULL) { + if ((inst->cd = php_conv_open(conv_mode, conv_opts, persistent)) == NULL) { goto out_failure; } - inst->write_cd = write_cd; - inst->read_cd = read_cd; - - inst->read_buf_left = 0; - return SUCCESS; out_failure: - if (write_cd != NULL) { - php_conv_dtor(write_cd); - pefree(write_cd, persistent); - } - if (read_cd != NULL) { - php_conv_dtor(read_cd); - pefree(read_cd, persistent); + if (inst->cd != NULL) { + php_conv_dtor(inst->cd); + pefree(inst->cd, persistent); } if (inst->filtername != NULL) { pefree(inst->filtername, persistent); @@ -1346,14 +1323,9 @@ static void php_convert_filter_dtor(php_convert_filter *inst) { - if (inst->write_cd != NULL) { - php_conv_dtor(inst->write_cd); - pefree(inst->write_cd, inst->persistent); - } - - if (inst->read_cd != NULL) { - php_conv_dtor(inst->read_cd); - pefree(inst->read_cd, inst->persistent); + if (inst->cd != NULL) { + php_conv_dtor(inst->cd); + pefree(inst->cd, inst->persistent); } if (inst->filtername != NULL) { @@ -1370,183 +1342,162 @@ int flags TSRMLS_DC) { - php_stream_bucket *bucket; + php_stream_bucket *bucket, *new_bucket; size_t consumed = 0; php_conv_err_t err; php_convert_filter *inst = (php_convert_filter *)thisfilter->abstract; + char *out_buf; + size_t out_buf_size; + char *pd; + size_t ocnt; + + if (buckets_in->head == NULL && buckets_in->tail == NULL) { + /* flush operation */ + + out_buf_size = 64; + out_buf = pemalloc(out_buf_size, inst->persistent); + ocnt = out_buf_size; + pd = out_buf; - while (thisfilter->buffer.head || buckets_in->head) { - /* take head off buffer first, then input brigade */ - bucket = thisfilter->buffer.head ? thisfilter->buffer.head : buckets_in->head; - php_stream_bucket_unlink(bucket TSRMLS_CC); - -#if 0 - err = php_conv_convert(inst->write_cd, ... ) - - /* update consumed by the number of bytes just used */ - - /* give output bucket to next in chain */ - php_stream_bucket_append(buckets_out, bucket TSRMLS_CC); - - if (only used part of buffer) { - bucket *left, *right; - php_stream_buffer_split(bucket, &left, &right, used_len TSRMLS_CC); - php_stream_buffer_delref(left); /* delete the part we consumed */ - php_stream_buffer_append(&filter->buffer, right TSRMLS_CC); - break; - } -#endif - } - - if (bytes_consumed) { - *bytes_consumed = consumed; - } - - return PSFS_PASS_ON; -} - - - - -#if 0 -static size_t strfilter_convert_write(php_stream *stream, php_stream_filter *thisfilter, - const char *buf, size_t count TSRMLS_DC) -{ - php_convert_filter *inst = (php_convert_filter *)thisfilter->abstract; - - if (inst->write_cd != NULL) { - char bucket_buf[2048]; - size_t out_left, in_left; - const char *in_p; - char *out_p; - - in_p = buf; - in_left = count; - out_p = bucket_buf; - out_left = sizeof(bucket_buf); + /* trying hard to reduce the number of buckets to hand to the + * next filter */ - while (in_left > 0) { - php_conv_err_t err; + for (;;) { + err = php_conv_convert(inst->cd, NULL, NULL, &pd, &ocnt); - err = php_conv_convert(inst->write_cd, &in_p, &in_left, &out_p, &out_left); switch (err) { - case PHP_CONV_ERR_TOO_BIG: - php_stream_filter_write_next(stream, thisfilter, bucket_buf, sizeof(bucket_buf) - out_left); - out_p = bucket_buf; - out_left = sizeof(bucket_buf); - break; - case PHP_CONV_ERR_UNKNOWN: php_error_docref(NULL TSRMLS_CC, E_WARNING, "stream filter (%s): unknown error", inst->filtername, err); - return 0; + return PSFS_ERR_FATAL; case PHP_CONV_ERR_INVALID_SEQ: php_error_docref(NULL TSRMLS_CC, E_WARNING, "stream filter (%s): invalid base64 sequence", inst->filtername, err); - return 0; - - case PHP_CONV_ERR_UNEXPECTED_EOS: + return PSFS_ERR_FATAL; + + case PHP_CONV_ERR_UNEXPECTED_EOS: php_error_docref(NULL TSRMLS_CC, E_WARNING, "stream filter (%s): unexpected end of stream", inst->filtername, err); - return 0; + return PSFS_ERR_FATAL; default: break; } - } - php_stream_filter_write_next(stream, thisfilter, bucket_buf, sizeof(bucket_buf) - out_left); - return (size_t)(count - in_left); - } - return php_stream_filter_write_next(stream, thisfilter, buf, count); -} - -static size_t strfilter_convert_read(php_stream *stream, php_stream_filter *thisfilter, - char *buf, size_t count TSRMLS_DC) -{ - php_convert_filter *inst = (php_convert_filter *)thisfilter->abstract; - size_t retval; - if (inst->read_cd != NULL) { - php_conv_err_t err = PHP_CONV_ERR_SUCCESS; - size_t out_left; - const char *in_p; - char *out_p; - - in_p = inst->read_buf + (sizeof(inst->read_buf) - inst->read_buf_left); - out_p = buf; - out_left = count; - - while (out_left > 0 && err != PHP_CONV_ERR_TOO_BIG) { - if (inst->read_buf_left == 0) { - inst->read_buf_left = php_stream_filter_read_next(stream, thisfilter, inst->read_buf, sizeof(inst->read_buf)); - in_p = inst->read_buf; - } - if (inst->read_buf_left == 0) { - /* reached end of stream */ - err = php_conv_convert(inst->read_cd, NULL, NULL, &out_p, &out_left); - if (err == PHP_CONV_ERR_SUCCESS) { - break; - } + if (err != PHP_CONV_ERR_TOO_BIG) { + break; } else { - err = php_conv_convert(inst->read_cd, &in_p, &(inst->read_buf_left), &out_p, &out_left); - } + char *new_out_buf; + size_t new_out_buf_size; - switch (err) { - case PHP_CONV_ERR_UNKNOWN: - php_error_docref(NULL TSRMLS_CC, E_WARNING, "stream filter (%s): unknown error", inst->filtername, err); - return 0; + new_out_buf_size = out_buf_size << 1; - case PHP_CONV_ERR_INVALID_SEQ: - php_error_docref(NULL TSRMLS_CC, E_WARNING, "stream filter (%s): invalid base64 sequence", inst->filtername, err); - return 0; + if (new_out_buf_size < out_buf_size) { + /* whoa! no bigger buckets are sold +anywhere... */ + new_bucket = php_stream_bucket_new(stream, +out_buf, (out_buf_size - ocnt), 1, inst->persistent TSRMLS_CC); - case PHP_CONV_ERR_UNEXPECTED_EOS: - php_error_docref(NULL TSRMLS_CC, E_WARNING, "stream filter (%s): unexpected end of stream", inst->filtername, err); - return 0; + php_stream_bucket_append(buckets_out, +new_bucket TSRMLS_CC); - default: - break; + out_buf_size = bucket->buflen; + out_buf = pemalloc(out_buf_size, +inst->persistent); + ocnt = out_buf_size; + pd = out_buf; + } else { + new_out_buf = perealloc(out_buf, +new_out_buf_size, inst->persistent); + pd = new_out_buf + (pd - out_buf); + ocnt += (new_out_buf_size - out_buf_size); + out_buf = new_out_buf; + out_buf_size = new_out_buf_size; + } } } - retval = (size_t)(count - out_left); + /* give output bucket to next in chain */ + if (out_buf_size - ocnt > 0) { + new_bucket = php_stream_bucket_new(stream, out_buf, +(out_buf_size - ocnt), 1, inst->persistent TSRMLS_CC); + php_stream_bucket_append(buckets_out, new_bucket TSRMLS_CC); + } } else { - retval = php_stream_filter_read_next(stream, thisfilter, buf, count); - } - return retval; -} + while (buckets_in->head != NULL) { + const char *ps; + size_t icnt; + + bucket = buckets_in->head; + + php_stream_bucket_unlink(bucket TSRMLS_CC); + icnt = bucket->buflen; + ps = bucket->buf; + + out_buf_size = bucket->buflen; + out_buf = pemalloc(out_buf_size, inst->persistent); + ocnt = out_buf_size; + pd = out_buf; + + /* trying hard to reduce the number of buckets to hand to the + * next filter */ + + while (icnt > 0) { + err = php_conv_convert(inst->cd, &ps, &icnt, &pd, +&ocnt); + + switch (err) { + case PHP_CONV_ERR_UNKNOWN: + php_error_docref(NULL TSRMLS_CC, +E_WARNING, "stream filter (%s): unknown error", inst->filtername, err); + return PSFS_ERR_FATAL; + + case PHP_CONV_ERR_INVALID_SEQ: + php_error_docref(NULL TSRMLS_CC, +E_WARNING, "stream filter (%s): invalid base64 sequence", inst->filtername, err); + return PSFS_ERR_FATAL; + + case PHP_CONV_ERR_UNEXPECTED_EOS: + php_error_docref(NULL TSRMLS_CC, +E_WARNING, "stream filter (%s): unexpected end of stream", inst->filtername, err); + return PSFS_ERR_FATAL; -static int strfilter_convert_flush(php_stream *stream, php_stream_filter *thisfilter, int closing TSRMLS_DC) -{ - if (closing) { - php_convert_filter *inst = (php_convert_filter *)thisfilter->abstract; + default: + break; + } - if (inst->write_cd != NULL) { - php_conv_err_t err; - char bucket_buf[1024]; - char *out_p; - size_t out_left; - - out_p = bucket_buf; - out_left = sizeof(bucket_buf); - - for (;;) { - err = php_conv_convert(inst->write_cd, NULL, NULL, &out_p, &out_left); - if (err == PHP_CONV_ERR_SUCCESS) { - break; - } else if (err == PHP_CONV_ERR_TOO_BIG) { - php_stream_filter_write_next(stream, thisfilter, bucket_buf, sizeof(bucket_buf) - out_left); - out_p = bucket_buf; - out_left = sizeof(bucket_buf); - } else { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "stream filter (%s): unknown error", inst->filtername); - return 0; + if (err == PHP_CONV_ERR_TOO_BIG) { + char *new_out_buf; + size_t new_out_buf_size; + + new_out_buf_size = out_buf_size << 1; + + if (new_out_buf_size < out_buf_size) { + /* whoa! no bigger buckets are sold +anywhere... */ + new_bucket = +php_stream_bucket_new(stream, out_buf, (out_buf_size - ocnt), 1, inst->persistent +TSRMLS_CC); + + php_stream_bucket_append(buckets_out, +new_bucket TSRMLS_CC); + + out_buf_size = bucket->buflen; + out_buf = pemalloc(out_buf_size, +inst->persistent); + ocnt = out_buf_size; + pd = out_buf; + } else { + new_out_buf = perealloc(out_buf, +new_out_buf_size, inst->persistent); + pd = new_out_buf + (pd - out_buf); + ocnt += (new_out_buf_size - +out_buf_size); + out_buf = new_out_buf; + out_buf_size = new_out_buf_size; + } } } - php_stream_filter_write_next(stream, thisfilter, bucket_buf, sizeof(bucket_buf) - out_left); + /* update consumed by the number of bytes just used */ + consumed = bucket->buflen - icnt; + + /* give output bucket to next in chain */ + if (out_buf_size - ocnt > 0) { + new_bucket = php_stream_bucket_new(stream, out_buf, +(out_buf_size - ocnt), 1, inst->persistent TSRMLS_CC); + php_stream_bucket_append(buckets_out, new_bucket +TSRMLS_CC); + } + + php_stream_bucket_delref(bucket TSRMLS_CC); } } - return php_stream_filter_flush_next(stream, thisfilter, closing); + + if (bytes_consumed) { + *bytes_consumed = consumed; + } + + return PSFS_PASS_ON; } -#endif static void strfilter_convert_dtor(php_stream_filter *thisfilter TSRMLS_DC) { @@ -1753,8 +1704,8 @@ php_convert_filter *inst; php_stream_filter *retval = NULL; char *dot; - zval *options = NULL, **tmp_zval_pp; - HashTable *write_conv_opts, *read_conv_opts; + zval *options = NULL; + int conv_mode; if ((dot = strchr(filtername, '.')) == NULL) { return NULL; @@ -1770,79 +1721,23 @@ } } - write_conv_opts = read_conv_opts = NULL; - if (strcasecmp(dot, "base64-encode") == 0) { - if (options != NULL && - zend_hash_find(Z_ARRVAL_P(options), "base64-encode", sizeof("base64-encode"), (void **)&tmp_zval_pp) == SUCCESS && - Z_TYPE_PP(tmp_zval_pp) == IS_ARRAY) { - write_conv_opts = Z_ARRVAL_PP(tmp_zval_pp); - } - if (options != NULL && - zend_hash_find(Z_ARRVAL_P(options), "base64-decode", sizeof("base64-decode"), (void **)&tmp_zval_pp) == SUCCESS && - Z_TYPE_PP(tmp_zval_pp) == IS_ARRAY) { - read_conv_opts = Z_ARRVAL_PP(tmp_zval_pp); - } - if (php_convert_filter_ctor(inst, - PHP_CONV_BASE64_ENCODE, write_conv_opts, - PHP_CONV_BASE64_DECODE, read_conv_opts, - filtername, persistent) != SUCCESS) { - goto out; - } - retval = php_stream_filter_alloc(&strfilter_convert_ops, inst, persistent); + conv_mode = PHP_CONV_BASE64_ENCODE; } else if (strcasecmp(dot, "base64-decode") == 0) { - if (options != NULL && - zend_hash_find(Z_ARRVAL_P(options), "base64-decode", sizeof("base64-decode"), (void **)&tmp_zval_pp) == SUCCESS && - Z_TYPE_PP(tmp_zval_pp) == IS_ARRAY) { - write_conv_opts = Z_ARRVAL_PP(tmp_zval_pp); - } - if (options != NULL && - zend_hash_find(Z_ARRVAL_P(options), "base64-encode", sizeof("base64-encode"), (void **)&tmp_zval_pp) == SUCCESS && - Z_TYPE_PP(tmp_zval_pp) == IS_ARRAY) { - read_conv_opts = Z_ARRVAL_PP(tmp_zval_pp); - } - if (php_convert_filter_ctor(inst, - PHP_CONV_BASE64_DECODE, write_conv_opts, - PHP_CONV_BASE64_ENCODE, read_conv_opts, - filtername, persistent) != SUCCESS) { - goto out; - } - retval = php_stream_filter_alloc(&strfilter_convert_ops, inst, persistent); + conv_mode = PHP_CONV_BASE64_DECODE; } else if (strcasecmp(dot, "quoted-printable-encode") == 0) { - if (options != NULL && - zend_hash_find(Z_ARRVAL_P(options), "quoted-printable-encode", sizeof("quoted-printable-encode"), (void **)&tmp_zval_pp) == SUCCESS && - Z_TYPE_PP(tmp_zval_pp) == IS_ARRAY) { - write_conv_opts = Z_ARRVAL_PP(tmp_zval_pp); - } - if (options != NULL && zend_hash_find(Z_ARRVAL_P(options), "quoted-printable-decode", sizeof("quoted-printable-decode"), (void **)&tmp_zval_pp) == SUCCESS) { - read_conv_opts = Z_ARRVAL_PP(tmp_zval_pp); - } - if (php_convert_filter_ctor(inst, - PHP_CONV_QPRINT_ENCODE, write_conv_opts, - PHP_CONV_QPRINT_DECODE, read_conv_opts, - filtername, persistent) != SUCCESS) { - goto out; - } - retval = php_stream_filter_alloc(&strfilter_convert_ops, inst, persistent); + conv_mode = PHP_CONV_QPRINT_ENCODE; } else if (strcasecmp(dot, "quoted-printable-decode") == 0) { - if (options != NULL && - zend_hash_find(Z_ARRVAL_P(options), "quoted-printable-decode", sizeof("quoted-printable-decode"), (void **)&tmp_zval_pp) == SUCCESS && - Z_TYPE_PP(tmp_zval_pp) == IS_ARRAY) { - write_conv_opts = Z_ARRVAL_PP(tmp_zval_pp); - } - if (options != NULL && - zend_hash_find(Z_ARRVAL_P(options), "quoted-printable-encode", sizeof("quoted-printable-encode"), (void **)&tmp_zval_pp) == SUCCESS && - Z_TYPE_PP(tmp_zval_pp) == IS_ARRAY) { - read_conv_opts = Z_ARRVAL_PP(tmp_zval_pp); - } - if (php_convert_filter_ctor(inst, - PHP_CONV_QPRINT_DECODE, write_conv_opts, - PHP_CONV_QPRINT_ENCODE, read_conv_opts, - filtername, persistent) != SUCCESS) { - goto out; - } - retval = php_stream_filter_alloc(&strfilter_convert_ops, inst, persistent); + conv_mode = PHP_CONV_QPRINT_DECODE; } + + if (php_convert_filter_ctor(inst, conv_mode, + (options != NULL ? Z_ARRVAL_P(options) : NULL), + filtername, persistent) != SUCCESS) { + goto out; + } + + retval = php_stream_filter_alloc(&strfilter_convert_ops, inst, persistent); out: if (retval == NULL) { pefree(inst, persistent);
-- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php