]> granicus.if.org Git - php/commitdiff
Implement stream_select() which works just like socket_select, but only on
authorWez Furlong <wez@php.net>
Fri, 27 Sep 2002 23:42:38 +0000 (23:42 +0000)
committerWez Furlong <wez@php.net>
Fri, 27 Sep 2002 23:42:38 +0000 (23:42 +0000)
streams.
@ - Added stream_select() which works like socket_select but only works on
@   streams returned by fopen(), fsockopen() and pfsockopen(). (Wez)

ext/standard/basic_functions.c
ext/standard/file.c
ext/standard/file.h

index 999e9f2de2eb0242535d433fd8b20d9cc6851eab..765b9300e171f0f96e7a142e3aa1c279239f1151 100644 (file)
@@ -99,6 +99,9 @@ static unsigned char second_and_third_args_force_ref[] = { 3, BYREF_NONE, BYREF_
 static unsigned char second_args_force_ref[] = { 2, BYREF_NONE, BYREF_FORCE };
 static unsigned char third_and_fourth_args_force_ref[] = { 4, BYREF_NONE, BYREF_NONE, BYREF_FORCE, BYREF_FORCE };
 static unsigned char third_and_rest_force_ref[] = { 3, BYREF_NONE, BYREF_NONE, BYREF_FORCE_REST };
+static unsigned char first_through_third_args_force_ref[] =
+{3, BYREF_FORCE, BYREF_FORCE, BYREF_FORCE};
+
 
 typedef struct _php_shutdown_function_entry {
        zval **arguments;
@@ -617,6 +620,7 @@ function_entry basic_functions[] = {
        PHP_STATIC_FE("tmpfile",                php_if_tmpfile,                                                 NULL)
        PHP_FE(file,                                                                                                                    NULL)
        PHP_FE(file_get_contents,                                                                                               NULL)
+       PHP_FE(stream_select,                                     first_through_third_args_force_ref)
        PHP_FE(stream_context_create,                                                                                   NULL)
        PHP_FE(stream_context_set_params,                                                                               NULL)
        PHP_FE(stream_context_set_option,                                                                               NULL)
@@ -628,11 +632,9 @@ function_entry basic_functions[] = {
        PHP_FE(get_meta_tags,                                                                                                   NULL)
        PHP_FE(set_file_buffer,                                                                                                 NULL)
 
-       /* set_socket_blocking() is deprecated,
-          use socket_set_blocking() instead 
-       */
        PHP_FE(set_socket_blocking,                                                                                             NULL)
-       PHP_FE(socket_set_blocking,                                                                                             NULL)
+       PHP_FE(stream_set_blocking,                                                                                             NULL)
+       PHP_FALIAS(socket_set_blocking, stream_set_blocking,                                    NULL)
 
        PHP_FE(file_get_meta_data,                                                                                              NULL)
        PHP_FE(file_register_wrapper,                                                                                   NULL)
index 38497a4a71e6245337ef7a9410a4eb4972a02ce5..419cab56dd19166d5dd652327eaaef3179eafd6a 100644 (file)
@@ -639,6 +639,130 @@ PHP_FUNCTION(file_get_meta_data)
 }
 /* }}} */
 
+static int stream_array_to_fd_set(zval *stream_array, fd_set *fds, int *max_fd TSRMLS_DC)
+{
+       zval **elem;
+       php_stream *stream;
+       int this_fd;
+
+       if (Z_TYPE_P(stream_array) != IS_ARRAY)
+               return 0;
+
+       for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(stream_array));
+                zend_hash_get_current_data(Z_ARRVAL_P(stream_array), (void **) &elem) == SUCCESS;
+                zend_hash_move_forward(Z_ARRVAL_P(stream_array))) {
+
+               php_stream_from_zval_no_verify(stream, elem);
+               if (stream == NULL)
+                       continue;
+
+               /* get the fd */
+               if (SUCCESS == php_stream_cast(stream, PHP_STREAM_AS_FD, (void*)&this_fd, 1)) {
+                       FD_SET(this_fd, fds);
+                       if (this_fd > *max_fd) {
+                               *max_fd = this_fd;
+                       }
+               }
+       }
+
+       return 1;
+
+}
+
+static int stream_array_from_fd_set(zval *stream_array, fd_set *fds TSRMLS_DC)
+{
+       zval **elem, **dest_elem;
+       php_stream *stream;
+       HashTable *new_hash;
+       int this_fd;
+
+       if (Z_TYPE_P(stream_array) != IS_ARRAY)
+               return 0;
+
+       ALLOC_HASHTABLE(new_hash);
+       zend_hash_init(new_hash, 0, NULL, ZVAL_PTR_DTOR, 0);
+       
+       for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(stream_array));
+                zend_hash_get_current_data(Z_ARRVAL_P(stream_array), (void **) &elem) == SUCCESS;
+                zend_hash_move_forward(Z_ARRVAL_P(stream_array))) {
+
+               php_stream_from_zval_no_verify(stream, elem);
+               if (stream == NULL)
+                       continue;
+
+               /* get the fd */
+               if (SUCCESS == php_stream_cast(stream, PHP_STREAM_AS_FD, (void*)&this_fd, 1)) {
+                       if (FD_ISSET(this_fd, fds)) {
+                               zend_hash_next_index_insert(new_hash, (void *)elem, sizeof(zval *), (void **)&dest_elem);
+                               if (dest_elem)
+                                       zval_add_ref(dest_elem);
+                       }
+               }
+       }
+
+       /* destroy old array and add new one */
+       zend_hash_destroy(Z_ARRVAL_P(stream_array));
+       efree(Z_ARRVAL_P(stream_array));
+
+       zend_hash_internal_pointer_reset(new_hash);
+       Z_ARRVAL_P(stream_array) = new_hash;
+       
+       return 1;
+
+}
+
+
+/* {{{ proto int stream_select(array &read_streams, array &write_streams, array &except_streams, int tv_sec[, int tv_usec])
+   Runs the select() system call on the sets of streams with a timeout specified by tv_sec and tv_usec */
+PHP_FUNCTION(stream_select)
+{
+       zval                    *r_array, *w_array, *e_array, *sec;
+       struct timeval  tv;
+       struct timeval *tv_p = NULL;
+       fd_set                  rfds, wfds, efds;
+       int                             max_fd = 0;
+       int                             retval, sets = 0, usec = 0;
+
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a!a!a!z!|l", &r_array, &w_array, &e_array, &sec, &usec) == FAILURE)
+               return;
+
+       FD_ZERO(&rfds);
+       FD_ZERO(&wfds);
+       FD_ZERO(&efds);
+
+       if (r_array != NULL) sets += stream_array_to_fd_set(r_array, &rfds, &max_fd TSRMLS_CC);
+       if (w_array != NULL) sets += stream_array_to_fd_set(w_array, &wfds, &max_fd TSRMLS_CC);
+       if (e_array != NULL) sets += stream_array_to_fd_set(e_array, &efds, &max_fd TSRMLS_CC);
+
+       if (!sets) {
+               php_error_docref(NULL TSRMLS_CC, E_WARNING, "No stream arrays were passed");
+               RETURN_FALSE;
+       }
+
+       /* If seconds is not set to null, build the timeval, else we wait indefinitely */
+       if (sec != NULL) {
+               convert_to_long_ex(&sec);
+               tv.tv_sec = Z_LVAL_P(sec);
+               tv.tv_usec = usec;
+               tv_p = &tv;
+       }
+
+       retval = select(max_fd+1, &rfds, &wfds, &efds, tv_p);
+
+       if (retval == -1) {
+               php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to select [%d]: %s",
+                               errno, strerror(errno));
+               RETURN_FALSE;
+       }
+
+       if (r_array != NULL) stream_array_from_fd_set(r_array, &rfds TSRMLS_CC);
+       if (w_array != NULL) stream_array_from_fd_set(w_array, &wfds TSRMLS_CC);
+       if (e_array != NULL) stream_array_from_fd_set(e_array, &efds TSRMLS_CC);
+
+       RETURN_LONG(retval);
+}
+
+
 /* {{{ stream_context related functions */
 static void user_space_stream_notifier(php_stream_context *context, int notifycode, int severity,
                char *xmsg, int xcode, size_t bytes_sofar, size_t bytes_max, void * ptr TSRMLS_DC)
@@ -846,6 +970,7 @@ PHP_FUNCTION(stream_context_create)
 }
 /* }}} */
 
+/* {{{ streams filter functions */
 static void apply_filter_to_stream(int append, INTERNAL_FUNCTION_PARAMETERS)
 {
        zval *zstream;
@@ -888,6 +1013,7 @@ PHP_FUNCTION(stream_filter_append)
        apply_filter_to_stream(1, INTERNAL_FUNCTION_PARAM_PASSTHRU);
 }
 /* }}} */
+/* }}} */
 
 /* {{{ proto resource fopen(string filename, string mode [, bool use_include_path [, resource context]])
    Open a file or a URL and return a file pointer */
@@ -1045,9 +1171,9 @@ PHPAPI PHP_FUNCTION(feof)
 }
 /* }}} */
 
-/* {{{ proto bool socket_set_blocking(resource socket, int mode)
+/* {{{ proto bool stream_set_blocking(resource socket, int mode)
    Set blocking/non-blocking mode on a socket or stream */
-PHP_FUNCTION(socket_set_blocking)
+PHP_FUNCTION(stream_set_blocking)
 {
        zval **arg1, **arg2;
        int block;
@@ -1073,8 +1199,8 @@ PHP_FUNCTION(socket_set_blocking)
    Set blocking/non-blocking mode on a socket */
 PHP_FUNCTION(set_socket_blocking)
 {
-       php_error_docref(NULL TSRMLS_CC, E_NOTICE, "This function is deprecated, use socket_set_blocking() instead");
-       PHP_FN(socket_set_blocking)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
+       php_error_docref(NULL TSRMLS_CC, E_NOTICE, "This function is deprecated, use stream_set_blocking() instead");
+       PHP_FN(stream_set_blocking)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
 }
 /* }}} */
 
index 4e5eba55dd9b81aed3a2bf238094307d01bd1077..d8eb1aa301cb4629978ba0cfdf967f0885e71f42 100644 (file)
@@ -55,7 +55,8 @@ PHP_FUNCTION(copy);
 PHP_FUNCTION(file);
 PHP_FUNCTION(file_get_contents);
 PHP_FUNCTION(set_socket_blocking); /* deprecated */
-PHP_FUNCTION(socket_set_blocking);
+PHP_FUNCTION(stream_set_blocking);
+PHP_FUNCTION(stream_select);
 PHP_FUNCTION(socket_set_timeout);
 PHP_FUNCTION(set_file_buffer);
 PHP_FUNCTION(get_meta_tags);