summaryrefslogtreecommitdiff
path: root/README.STREAMS
diff options
context:
space:
mode:
authorWez Furlong <wez@php.net>2002-03-16 13:48:57 +0000
committerWez Furlong <wez@php.net>2002-03-16 13:48:57 +0000
commit30647934a477f876992c3390ce483bb55a3eee51 (patch)
treef6b85a5d08e90028538485c8a0addadd0f0a62c2 /README.STREAMS
parentd4e63bc5bf1dacce00f317bc2b3b759f6f6138d7 (diff)
downloadphp-git-30647934a477f876992c3390ce483bb55a3eee51.tar.gz
Tweak the API to be more consistent.
Update docs.
Diffstat (limited to 'README.STREAMS')
-rw-r--r--README.STREAMS179
1 files changed, 124 insertions, 55 deletions
diff --git a/README.STREAMS b/README.STREAMS
index 2ae89b7a51..e5a3cca35a 100644
--- a/README.STREAMS
+++ b/README.STREAMS
@@ -4,9 +4,6 @@ $Id$
Please send comments to: Wez Furlong <wez@thebrainroom.com>
-Note: this doc is preliminary and is intended to give the reader an idea of
-how streams work and should be used.
-
Why Streams?
============
You may have noticed a shed-load of issock parameters flying around the PHP
@@ -26,7 +23,7 @@ The main functions are:
PHPAPI size_t php_stream_read(php_stream * stream, char * buf, size_t count);
PHPAPI size_t php_stream_write(php_stream * stream, const char * buf, size_t
- count);
+ count);
PHPAPI int php_stream_eof(php_stream * stream);
PHPAPI int php_stream_getc(php_stream * stream);
PHPAPI char *php_stream_gets(php_stream * stream, char *buf, size_t maxlen);
@@ -40,16 +37,77 @@ names: fread, fwrite, feof, fgetc, fgets, fclose, fflush, fseek, ftell.
Opening Streams
===============
-Ultimately, I aim to implement an fopen_wrapper-like call to do this with
-minimum fuss.
-Currently, mostly for testing purposes, you can use php_stream_fopen to open a
-stream on a regular file.
+In most cases, you should use this API:
+
+PHPAPI php_stream *php_stream_open_wrapper(char *path, char *mode,
+ int options, char **opened_path TSRMLS_DC);
+
+Where:
+ path is the file or resource to open.
+ mode is the stdio compatible mode eg: "wb", "rb" etc.
+ options is a combination of the following values:
+ IGNORE_PATH (default) - don't use include path to search for the file
+ USE_PATH - use include path to search for the file
+ IGNORE_URL - do not use plugin wrappers
+ REPORT_ERRORS - show errors in a standard format if something
+ goes wrong.
+ opened_path is used to return the path of the actual file opened.
+
+If you need to open a specific stream, or convert standard resources into
+streams there are a range of functions to do this defined in php_streams.h.
+A brief list of the most commonly used functions:
+
+PHPAPI php_stream *php_stream_fopen_from_file(FILE *file, const char *mode);
+ Convert a FILE * into a stream.
-PHPAPI php_stream * php_stream_fopen(const char * filename, const char *
- mode);
+PHPAPI php_stream *php_stream_fopen_tmpfile(void);
+ Open a FILE * with tmpfile() and convert into a stream.
-This call behaves just like fopen(), except it returns a stream instead of a
-FILE *
+PHPAPI php_stream *php_stream_fopen_temporary_file(const char *dir,
+ const char *pfx, char **opened_path TSRMLS_DC);
+ Generate a temporary file name and open it.
+
+There are some network enabled relatives in php_network.h:
+
+PHPAPI php_stream *php_stream_sock_open_from_socket(int socket, int persistent);
+ Convert a socket into a stream.
+
+PHPAPI php_stream *php_stream_sock_open_host(const char *host, unsigned short port,
+ int socktype, int timeout, int persistent);
+ Open a connection to a host and return a stream.
+
+PHPAPI php_stream *php_stream_sock_open_unix(const char *path, int persistent,
+ struct timeval *timeout);
+ Open a UNIX domain socket.
+
+
+Stream Utilities
+================
+
+If you need to copy some data from one stream to another, you will be please
+to know that the streams API provides a standard way to do this:
+
+PHPAPI size_t php_stream_copy_to_stream(php_stream *src,
+ php_stream *dest, size_t maxlen);
+
+If you want to copy all remaining data from the src stream, pass
+PHP_STREAM_COPY_ALL as the maxlen parameter, otherwise maxlen indicates the
+number of bytes to copy.
+This function will try to use mmap where available to make the copying more
+efficient.
+
+If you want to read the contents of a stream into an allocated memory buffer,
+you should use:
+
+PHPAPI size_t php_stream_copy_to_mem(php_stream *src, char **buf,
+ size_t maxlen, int persistent);
+
+This function will set buf to the address of the buffer that it allocated,
+which will be maxlen bytes in length, or will be the entire length of the
+data remaining on the stream if you set maxlen to PHP_STREAM_COPY_ALL.
+The buffer is allocated using pemalloc(); you need to call pefree() to
+release the memory when you are done.
+As with copy_to_stream, this function will try use mmap where it can.
Casting Streams
===============
@@ -59,14 +117,14 @@ You need to "cast" the stream into a FILE*, and this is how you do it:
FILE * fp;
php_stream * stream; /* already opened */
-if (php_stream_cast(stream, PHP_STREAM_AS_STDIO, &fp, 1) == FAILURE) {
- RETURN_FALSE;
+if (php_stream_cast(stream, PHP_STREAM_AS_STDIO, (void*)&fp, REPORT_ERRORS) == FAILURE) {
+ RETURN_FALSE;
}
The prototype is:
PHPAPI int php_stream_cast(php_stream * stream, int castas, void ** ret, int
- show_err);
+ show_err);
The show_err parameter, if non-zero, will cause the function to display an
appropriate error message of type E_WARNING if the cast fails.
@@ -83,8 +141,14 @@ if you mix ANSI stdio calls on the FILE* with php stream calls on the stream.
If your system has the fopencookie function, php streams can synthesize a
FILE* on top of any stream, which is useful for SSL sockets, memory based
streams, data base streams etc. etc.
-NOTE: There might be situations where this is not desireable, and we need to
-provide a flag to inform the casting routine of this.
+
+In situations where this is not desireable, you should query the stream
+to see if it naturally supports FILE *. You can use this code snippet
+for this purpose:
+
+ if (php_stream_is(stream, PHP_STREAM_IS_STDIO)) {
+ /* can safely cast to FILE* with no adverse side effects */
+ }
You can use:
@@ -93,10 +157,15 @@ PHPAPI int php_stream_can_cast(php_stream * stream, int castas)
to find out if a stream can be cast, without actually performing the cast, so
to check if a stream is a socket you might use:
-if (php_stream_can_cast(stream, PHP_STREAM_AS_SOCKETD) == SUCCESS) {
- /* it's a socket */
+if (php_stream_can_cast(stream, PHP_STREAM_AS_SOCKETD) == SUCCESS) {
+ /* it can be a socket */
}
+Please note the difference between php_stream_is and php_stream_can_cast;
+stream_is tells you if the stream is a particular type of stream, whereas
+can_cast tells you if the stream can be forced into the form you request.
+The format doesn't change anything, while the later *might* change some
+state in the stream.
Stream Internals
================
@@ -121,17 +190,17 @@ As an example, the php_stream_fopen() function looks like this:
PHPAPI php_stream * php_stream_fopen(const char * filename, const char * mode)
{
- FILE * fp = fopen(filename, mode);
- php_stream * ret;
-
- if (fp) {
- ret = php_stream_alloc(&php_stream_stdio_ops, fp, 0, 0, mode);
- if (ret)
- return ret;
-
- fclose(fp);
- }
- return NULL;
+ FILE * fp = fopen(filename, mode);
+ php_stream * ret;
+
+ if (fp) {
+ ret = php_stream_alloc(&php_stream_stdio_ops, fp, 0, 0, mode);
+ if (ret)
+ return ret;
+
+ fclose(fp);
+ }
+ return NULL;
}
php_stream_stdio_ops is a php_stream_ops structure that can be used to handle
@@ -143,7 +212,7 @@ to be passed back to fopen_wrapper (or it's yet to be implemented successor).
The prototype for php_stream_alloc is this:
PHPAPI php_stream * php_stream_alloc(php_stream_ops * ops, void * abstract,
- size_t bufsize, int persistent, const char * mode)
+ size_t bufsize, int persistent, const char * mode)
ops is a pointer to the implementation,
abstract holds implementation specific data that is relevant to this instance
@@ -176,9 +245,9 @@ appropriately), and use the abstract pointer to refer to it.
For structured state you might have this:
-struct my_state {
- MYSQL conn;
- MYSQL_RES * result;
+struct my_state {
+ MYSQL conn;
+ MYSQL_RES * result;
};
struct my_state * state = pemalloc(sizeof(struct my_state), persistent);
@@ -201,32 +270,32 @@ For example, for reading from this wierd mysql stream:
static size_t php_mysqlop_read(php_stream * stream, char * buf, size_t count)
{
- struct my_state * state = (struct my_state*)stream->abstract;
-
- if (buf == NULL && count == 0) {
- /* in this special case, php_streams is asking if we have reached the
- * end of file */
- if (... at end of file ...)
- return EOF;
- else
- return 0;
- }
-
- /* pull out some data from the stream and put it in buf */
- ... mysql_fetch_row(state->result) ...
- /* we could do something strange, like format the data as XML here,
- and place that in the buf, but that brings in some complexities,
- such as coping with a buffer size too small to hold the data,
- so I won't even go in to how to do that here */
+ struct my_state * state = (struct my_state*)stream->abstract;
+
+ if (buf == NULL && count == 0) {
+ /* in this special case, php_streams is asking if we have reached the
+ * end of file */
+ if (... at end of file ...)
+ return EOF;
+ else
+ return 0;
+ }
+
+ /* pull out some data from the stream and put it in buf */
+ ... mysql_fetch_row(state->result) ...
+ /* we could do something strange, like format the data as XML here,
+ and place that in the buf, but that brings in some complexities,
+ such as coping with a buffer size too small to hold the data,
+ so I won't even go in to how to do that here */
}
Implement the other operations - remember that write, read, close and flush
are all mandatory. The rest are optional. Declare your stream ops struct:
php_stream_ops my_ops = {
- php_mysqlop_write, php_mysqlop_read, php_mysqlop_close,
- php_mysqlop_flush, NULL, NULL, NULL,
- "Strange mySQL example"
+ php_mysqlop_write, php_mysqlop_read, php_mysqlop_close,
+ php_mysqlop_flush, NULL, NULL, NULL,
+ "Strange mySQL example"
}
Thats it!
@@ -240,4 +309,4 @@ connection and then use pefree to dispose of the struct you allocated.
You may read the stream->persistent field to determine if your struct was
allocated in persistent mode or not.
-vim:tw=78
+vim:tw=78:et