summaryrefslogtreecommitdiff
path: root/main
diff options
context:
space:
mode:
authorSara Golemon <pollita@php.net>2004-09-14 03:48:17 +0000
committerSara Golemon <pollita@php.net>2004-09-14 03:48:17 +0000
commit34550382d89597552df369fe1d6318d32b5929cb (patch)
tree1e788daee0de5c28b2e81d6d23e851df346ecc4e /main
parent41c4fd66d96856cab3c39542486941e748706830 (diff)
downloadphp-git-34550382d89597552df369fe1d6318d32b5929cb.tar.gz
Added stream_filter_remove() to cancel a stream filter.
Register filters as resources when instantiated by stream_filter_(ap|pre)pend(). Export php_stream_filter_flush() internal function to wind buffered data out of a particular filter until consumed by a later filter or sent to stream->readbuffer or stream->ops->write()
Diffstat (limited to 'main')
-rwxr-xr-xmain/php_streams.h1
-rw-r--r--main/streams/filter.c82
-rw-r--r--main/streams/php_stream_filter_api.h2
-rwxr-xr-xmain/streams/streams.c9
4 files changed, 94 insertions, 0 deletions
diff --git a/main/php_streams.h b/main/php_streams.h
index 290ec14e32..1c9802f93a 100755
--- a/main/php_streams.h
+++ b/main/php_streams.h
@@ -30,6 +30,7 @@
BEGIN_EXTERN_C()
PHPAPI int php_file_le_stream(void);
PHPAPI int php_file_le_pstream(void);
+PHPAPI int php_file_le_stream_filter(void);
END_EXTERN_C()
/* {{{ Streams memory debugging stuff */
diff --git a/main/streams/filter.c b/main/streams/filter.c
index da61c714fa..37ab4c14d5 100644
--- a/main/streams/filter.c
+++ b/main/streams/filter.c
@@ -405,6 +405,88 @@ PHPAPI void _php_stream_filter_append(php_stream_filter_chain *chain, php_stream
}
+PHPAPI int _php_stream_filter_flush(php_stream_filter *filter, int finish TSRMLS_DC)
+{
+ php_stream_bucket_brigade brig_a = { NULL, NULL }, brig_b = { NULL, NULL }, *inp = &brig_a, *outp = &brig_b, *brig_temp;
+ php_stream_bucket *bucket;
+ php_stream_filter_chain *chain;
+ php_stream_filter *current;
+ php_stream *stream;
+ size_t flushed_size = 0;
+ long flags = (finish ? PSFS_FLAG_FLUSH_CLOSE : PSFS_FLAG_FLUSH_INC);
+
+ if (!filter->chain || !filter->chain->stream) {
+ /* Filter is not attached to a chain, or chain is somehow not part of a stream */
+ return FAILURE;
+ }
+
+ chain = filter->chain;
+ stream = chain->stream;
+
+ for(current = filter; current; current = current->next) {
+ php_stream_filter_status_t status;
+
+ status = filter->fops->filter(stream, filter, inp, outp, NULL, flags TSRMLS_CC);
+ if (status == PSFS_FEED_ME) {
+ /* We've flushed the data far enough */
+ return SUCCESS;
+ }
+ if (status == PSFS_ERR_FATAL) {
+ return FAILURE;
+ }
+ /* Otherwise we have data available to PASS_ON
+ Swap the brigades and continue */
+ brig_temp = inp;
+ inp = outp;
+ outp = brig_temp;
+ outp->head = NULL;
+ outp->tail = NULL;
+
+ flags = PSFS_FLAG_NORMAL;
+ }
+
+ /* Last filter returned data via PSFS_PASS_ON
+ Do something with it */
+
+ for(bucket = inp->head; bucket; bucket = bucket->next) {
+ flushed_size += bucket->buflen;
+ }
+
+ if (flushed_size == 0) {
+ /* Unlikely, but possible */
+ return SUCCESS;
+ }
+
+ if (chain == &(stream->readfilters)) {
+ /* Dump any newly flushed data to the read buffer */
+ if (stream->readpos > 0) {
+ /* Back the buffer up */
+ memcpy(stream->readbuf, stream->readbuf + stream->readpos, stream->writepos - stream->readpos);
+ stream->readpos = 0;
+ stream->writepos -= stream->readpos;
+ }
+ if (flushed_size > (stream->readbuflen - stream->writepos)) {
+ /* Grow the buffer */
+ stream->readbuf = perealloc(stream->readbuf, stream->writepos + flushed_size + stream->chunk_size, stream->is_persistent);
+ }
+ while ((bucket = inp->head)) {
+ memcpy(stream->readbuf + stream->writepos, bucket->buf, bucket->buflen);
+ stream->writepos += bucket->buflen;
+ php_stream_bucket_unlink(bucket TSRMLS_CC);
+ php_stream_bucket_delref(bucket TSRMLS_CC);
+ }
+ } else if (chain == &(stream->writefilters)) {
+ /* Send flushed data to the stream */
+ while ((bucket = inp->head)) {
+ stream->ops->write(stream, bucket->buf, bucket->buflen TSRMLS_CC);
+ php_stream_bucket_unlink(bucket TSRMLS_CC);
+ php_stream_bucket_delref(bucket TSRMLS_CC);
+ }
+ }
+
+ return SUCCESS;
+}
+
PHPAPI php_stream_filter *php_stream_filter_remove(php_stream_filter *filter, int call_dtor TSRMLS_DC)
{
if (filter->prev) {
diff --git a/main/streams/php_stream_filter_api.h b/main/streams/php_stream_filter_api.h
index 733d1c5221..6ee8192923 100644
--- a/main/streams/php_stream_filter_api.h
+++ b/main/streams/php_stream_filter_api.h
@@ -123,6 +123,7 @@ struct _php_stream_filter {
BEGIN_EXTERN_C()
PHPAPI void _php_stream_filter_prepend(php_stream_filter_chain *chain, php_stream_filter *filter TSRMLS_DC);
PHPAPI void _php_stream_filter_append(php_stream_filter_chain *chain, php_stream_filter *filter TSRMLS_DC);
+PHPAPI int _php_stream_filter_flush(php_stream_filter *filter, int finish TSRMLS_DC);
PHPAPI php_stream_filter *php_stream_filter_remove(php_stream_filter *filter, int call_dtor TSRMLS_DC);
PHPAPI void php_stream_filter_free(php_stream_filter *filter TSRMLS_DC);
PHPAPI php_stream_filter *_php_stream_filter_alloc(php_stream_filter_ops *fops, void *abstract, int persistent STREAMS_DC TSRMLS_DC);
@@ -131,6 +132,7 @@ END_EXTERN_C()
#define php_stream_filter_alloc_rel(fops, thisptr, persistent) _php_stream_filter_alloc((fops), (thisptr), (persistent) STREAMS_REL_CC TSRMLS_CC)
#define php_stream_filter_prepend(chain, filter) _php_stream_filter_prepend((chain), (filter) TSRMLS_CC)
#define php_stream_filter_append(chain, filter) _php_stream_filter_append((chain), (filter) TSRMLS_CC)
+#define php_stream_filter_flush(filter, finish) _php_stream_filter_flush((filter), (finish) TSRMLS_CC)
#define php_stream_is_filtered(stream) ((stream)->readfilters.head || (stream)->writefilters.head)
diff --git a/main/streams/streams.c b/main/streams/streams.c
index bb2b137c32..6242afcf82 100755
--- a/main/streams/streams.c
+++ b/main/streams/streams.c
@@ -38,6 +38,7 @@
static HashTable url_stream_wrappers_hash;
static int le_stream = FAILURE; /* true global */
static int le_pstream = FAILURE; /* true global */
+static int le_stream_filter = FAILURE; /* true global */
PHPAPI int php_file_le_stream(void)
{
@@ -49,6 +50,11 @@ PHPAPI int php_file_le_pstream(void)
return le_pstream;
}
+PHPAPI int php_file_le_stream_filter(void)
+{
+ return le_stream_filter;
+}
+
PHPAPI HashTable *_php_stream_get_url_stream_wrappers_hash(TSRMLS_D)
{
return (FG(stream_wrappers) ? FG(stream_wrappers) : &url_stream_wrappers_hash);
@@ -1370,6 +1376,9 @@ int php_init_stream_wrappers(int module_number TSRMLS_DC)
le_stream = zend_register_list_destructors_ex(stream_resource_regular_dtor, NULL, "stream", module_number);
le_pstream = zend_register_list_destructors_ex(NULL, stream_resource_persistent_dtor, "persistent stream", module_number);
+ /* Filters are cleaned up by the streams they're attached to */
+ le_stream_filter = zend_register_list_destructors_ex(NULL, NULL, "stream filter", module_number);
+
return (
zend_hash_init(&url_stream_wrappers_hash, 0, NULL, NULL, 1) == SUCCESS
&&