summaryrefslogtreecommitdiff
path: root/main
diff options
context:
space:
mode:
authorArnaud Le Blanc <lbarnaud@php.net>2008-11-15 12:52:13 +0000
committerArnaud Le Blanc <lbarnaud@php.net>2008-11-15 12:52:13 +0000
commitc6e1b8bc6767a20a8a5d31df170d912a33a89494 (patch)
treeb100067e4e1a29fac8e06d614bf7eca3d389ecda /main
parentdd9e9f26e2e30175de7f750e143bdebc3daca008 (diff)
downloadphp-git-c6e1b8bc6767a20a8a5d31df170d912a33a89494.tar.gz
MFH: Added stream_cast() and stream_set_options() to user-space stream
wrappers, allowing stream_select(), stream_set_blocking(), stream_set_timeout() and stream_set_write_buffer() to work with user-space stream wrappers. Will document.
Diffstat (limited to 'main')
-rw-r--r--main/streams/userspace.c179
1 files changed, 177 insertions, 2 deletions
diff --git a/main/streams/userspace.c b/main/streams/userspace.c
index fbd03f1d56..327544c032 100644
--- a/main/streams/userspace.c
+++ b/main/streams/userspace.c
@@ -82,6 +82,19 @@ PHP_MINIT_FUNCTION(user_streams)
REGISTER_LONG_CONSTANT("STREAM_MKDIR_RECURSIVE", PHP_STREAM_MKDIR_RECURSIVE, CONST_CS|CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("STREAM_IS_URL", PHP_STREAM_IS_URL, CONST_CS|CONST_PERSISTENT);
+
+ REGISTER_LONG_CONSTANT("STREAM_OPTION_BLOCKING", PHP_STREAM_OPTION_BLOCKING, CONST_CS|CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("STREAM_OPTION_READ_TIMEOUT", PHP_STREAM_OPTION_READ_TIMEOUT, CONST_CS|CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("STREAM_OPTION_READ_BUFFER", PHP_STREAM_OPTION_READ_BUFFER, CONST_CS|CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("STREAM_OPTION_WRITE_BUFFER", PHP_STREAM_OPTION_WRITE_BUFFER, CONST_CS|CONST_PERSISTENT);
+
+ REGISTER_LONG_CONSTANT("STREAM_BUFFER_NONE", PHP_STREAM_BUFFER_NONE, CONST_CS|CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("STREAM_BUFFER_LINE", PHP_STREAM_BUFFER_LINE, CONST_CS|CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("STREAM_BUFFER_FULL", PHP_STREAM_BUFFER_FULL, CONST_CS|CONST_PERSISTENT);
+
+ REGISTER_LONG_CONSTANT("STREAM_CAST_AS_STREAM", PHP_STREAM_AS_STDIO, CONST_CS|CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("STREAM_CAST_FOR_SELECT", PHP_STREAM_AS_FD_FOR_SELECT, CONST_CS|CONST_PERSISTENT);
+
return SUCCESS;
}
@@ -111,6 +124,8 @@ typedef struct _php_userstream_data php_userstream_data_t;
#define USERSTREAM_DIR_REWIND "dir_rewinddir"
#define USERSTREAM_DIR_CLOSE "dir_closedir"
#define USERSTREAM_LOCK "stream_lock"
+#define USERSTREAM_CAST "stream_cast"
+#define USERSTREAM_SET_OPTION "stream_set_option"
/* {{{ class should have methods like these:
@@ -160,6 +175,33 @@ typedef struct _php_userstream_data php_userstream_data_t;
return array( just like that returned by fstat() );
}
+ function stream_cast($castas)
+ {
+ if ($castas == STREAM_CAST_FOR_SELECT) {
+ return $this->underlying_stream;
+ }
+ return false;
+ }
+
+ function stream_set_option($option, $arg1, $arg2)
+ {
+ switch($option) {
+ case STREAM_OPTION_BLOCKING:
+ $blocking = $arg1;
+ ...
+ case STREAM_OPTION_READ_TIMEOUT:
+ $sec = $arg1;
+ $usec = $arg2;
+ ...
+ case STREAM_OPTION_WRITE_BUFFER:
+ $mode = $arg1;
+ $size = $arg2;
+ ...
+ default:
+ return false;
+ }
+ }
+
function url_stat(string $url, int $flags)
{
return array( just like that returned by stat() );
@@ -882,7 +924,7 @@ static int php_userstreamop_set_option(php_stream *stream, int option, int value
php_userstream_data_t *us = (php_userstream_data_t *)stream->abstract;
int ret = -1;
zval *zvalue = NULL;
- zval **args[1];
+ zval **args[3];
switch (option) {
case PHP_STREAM_OPTION_CHECK_LIVENESS:
@@ -925,6 +967,75 @@ static int php_userstreamop_set_option(php_stream *stream, int option, int value
}
break;
+
+ case PHP_STREAM_OPTION_READ_BUFFER:
+ case PHP_STREAM_OPTION_WRITE_BUFFER:
+ case PHP_STREAM_OPTION_READ_TIMEOUT:
+ case PHP_STREAM_OPTION_BLOCKING: {
+ zval *zoption = NULL;
+ zval *zptrparam = NULL;
+
+ ZVAL_STRINGL(&func_name, USERSTREAM_SET_OPTION, sizeof(USERSTREAM_SET_OPTION)-1, 0);
+
+ ALLOC_INIT_ZVAL(zoption);
+ ZVAL_LONG(zoption, option);
+
+ ALLOC_INIT_ZVAL(zvalue);
+ ALLOC_INIT_ZVAL(zptrparam);
+
+ args[0] = &zoption;
+ args[1] = &zvalue;
+ args[2] = &zptrparam;
+
+ switch(option) {
+ case PHP_STREAM_OPTION_READ_BUFFER:
+ case PHP_STREAM_OPTION_WRITE_BUFFER:
+ ZVAL_LONG(zvalue, value);
+ if (ptrparam) {
+ ZVAL_LONG(zptrparam, *(long *)ptrparam);
+ } else {
+ ZVAL_LONG(zptrparam, BUFSIZ);
+ }
+ break;
+ case PHP_STREAM_OPTION_READ_TIMEOUT: {
+ struct timeval tv = *(struct timeval*)ptrparam;
+ ZVAL_LONG(zvalue, tv.tv_sec);
+ ZVAL_LONG(zptrparam, tv.tv_usec);
+ break;
+ }
+ case PHP_STREAM_OPTION_BLOCKING:
+ ZVAL_LONG(zvalue, value);
+ break;
+ default:
+ break;
+ }
+
+ call_result = call_user_function_ex(NULL,
+ &us->object,
+ &func_name,
+ &retval,
+ 3, args, 0, NULL TSRMLS_CC);
+
+ do {
+ if (call_result == FAILURE) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s::" USERSTREAM_SET_OPTION " is not implemented!",
+ us->wrapper->classname);
+ break;
+ }
+ if (retval && zend_is_true(retval)) {
+ ret = PHP_STREAM_OPTION_RETURN_OK;
+ }
+ } while (0);
+
+ if (zoption) {
+ zval_ptr_dtor(&zoption);
+ }
+ if (zptrparam) {
+ zval_ptr_dtor(&zptrparam);
+ }
+
+ break;
+ }
}
/* clean up */
@@ -1331,12 +1442,76 @@ static int php_userstreamop_rewinddir(php_stream *stream, off_t offset, int when
}
+static int php_userstreamop_cast(php_stream *stream, int castas, void **retptr TSRMLS_DC)
+{
+ php_userstream_data_t *us = (php_userstream_data_t *)stream->abstract;
+ zval func_name;
+ zval *retval = NULL;
+ zval *zcastas = NULL;
+ zval **args[1];
+ php_stream * intstream = NULL;
+ int call_result;
+ int ret = FAILURE;
+
+ ZVAL_STRINGL(&func_name, USERSTREAM_CAST, sizeof(USERSTREAM_CAST)-1, 0);
+
+ ALLOC_INIT_ZVAL(zcastas);
+ switch(castas) {
+ case PHP_STREAM_AS_FD_FOR_SELECT:
+ ZVAL_LONG(zcastas, PHP_STREAM_AS_FD_FOR_SELECT);
+ break;
+ default:
+ ZVAL_LONG(zcastas, PHP_STREAM_AS_STDIO);
+ break;
+ }
+ args[0] = &zcastas;
+
+ call_result = call_user_function_ex(NULL,
+ &us->object,
+ &func_name,
+ &retval,
+ 1, args, 0, NULL TSRMLS_CC);
+
+ do {
+ if (call_result == FAILURE) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s::" USERSTREAM_CAST " is not implemented!",
+ us->wrapper->classname);
+ break;
+ }
+ if (retval == NULL || !zend_is_true(retval)) {
+ break;
+ }
+ php_stream_from_zval_no_verify(intstream, &retval);
+ if (!intstream) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s::" USERSTREAM_CAST " must return a stream resource",
+ us->wrapper->classname);
+ break;
+ }
+ if (intstream == stream) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s::" USERSTREAM_CAST " must not return itself",
+ us->wrapper->classname);
+ intstream = NULL;
+ break;
+ }
+ ret = php_stream_cast(intstream, castas, retptr, 1);
+ } while (0);
+
+ if (retval) {
+ zval_ptr_dtor(&retval);
+ }
+ if (zcastas) {
+ zval_ptr_dtor(&zcastas);
+ }
+
+ return ret;
+}
+
php_stream_ops php_stream_userspace_ops = {
php_userstreamop_write, php_userstreamop_read,
php_userstreamop_close, php_userstreamop_flush,
"user-space",
php_userstreamop_seek,
- NULL, /* cast */
+ php_userstreamop_cast,
php_userstreamop_stat,
php_userstreamop_set_option,
};