diff options
author | Wez Furlong <wez@php.net> | 2002-03-16 13:48:57 +0000 |
---|---|---|
committer | Wez Furlong <wez@php.net> | 2002-03-16 13:48:57 +0000 |
commit | 30647934a477f876992c3390ce483bb55a3eee51 (patch) | |
tree | f6b85a5d08e90028538485c8a0addadd0f0a62c2 /README.STREAMS | |
parent | d4e63bc5bf1dacce00f317bc2b3b759f6f6138d7 (diff) | |
download | php-git-30647934a477f876992c3390ce483bb55a3eee51.tar.gz |
Tweak the API to be more consistent.
Update docs.
Diffstat (limited to 'README.STREAMS')
-rw-r--r-- | README.STREAMS | 179 |
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 |