On 19/04/02, "Andrei Zmievski" <[EMAIL PROTECTED]> wrote: > Take a look at this document: > http://primates.ximian.com/~miguel/monikers.html > Monikers seem to be similar to what you are describing. Maybe there are > some ideas to be gleaned from there.
Monikers are a very powerful system. The problem is that you get to the more powerful stringified monikers, it starts getting hard to parse, both by human eyes and by PHP code :-/ I did already have the following thoughts/notions about where I'd like the streams stuff to go, but I also don't want to make it too complex because I don't think PHP needs it to be that complicated. Stream Filters ============== At the moment, it is possible to "stack" wrappers together like this: fopen("compress.zlib://http://server.com/pricelist.gz", "r"); While that is useful, it's not all that readable. It actually looks like it is a garbage URL :-) I'm definitely planning on some mechanism for stacking dynamically: <?php $fp = fopen("file.txt", "r"); stream_stack_push("decode.base64", $fp); // this reads base 64 encoded data from $fp, decodes the encoding // and buffers it in the base64 filter. // It then returns a line of that buffer. $data = fgets($fp, 1024); // this removes the top-most filter from the stack stream_stack_pop($fp); // which means that this is now returning the raw data from the // file again. $data = fgets($fp, 1024); ?> The nice thing about this is that a range of encodings/decodings can be applied/removed based on the data that has just been read from the file. I think this sort of thing might be useful for things like templating processors: <?php $fp = fopen("data.xml", "r"); stream_stack_push("xslt:style.xsl?param1=value1¶m2=value2", $fp); stream_stack_push("compress.zlib", $fp); stream_stack_push("crypt.des", $fp); // this reads the result of applying an XSLT transform // (setting parameters param1 and param2) to data.xml, // and gzipping the ouput, and then encrypting it with DES $data = fread($fp, 4096); // now send the result somewhere over the internet. ?> It is useful to be able to specify that as a single URL parameter; gnome concatenates things with the '#' sign - I also think that specifying an array would also be useful, because it could be built dynamically: <?php // Gnome style $fp = fopen("data.xml#xslt:style.xsl#compress.zlib#crypt.des"), "r"); $data = fread($fp, 4096); // Array style $fp = fopen(array("data.xml", "xslt:style.xsl", "compress.zlib", "crypt.des"), "r"); $data = fread($fp, 4096); ?> I'm still not sure if I like using '#' as a separator for filters, but can't think of another character that isn't likely to force a lot of otherwise unneccessary URL encoding, or make it too cumbersome. Stream Interfaces ================= I was thinking that it could be useful for streams to offer interfaces for operations that can be carried out on similar types of stream. Right now in CVS we have network streams, file streams, memory streams and user-space streams. If you want to change the chunk-size for a network stream, you need to check if it is a network stream using code like this: if (php_stream_is(stream, PHP_STREAM_IS_SOCKET)) { ... use socket-stream functions here ... // this is a real function that assumes that stream->abstract // points to a php_netstream_data_t. php_stream_sock_set_chunk_size(stream, newsize); } That's works OK now, but what if a user-space stream uses an underlying network stream? If we had some kind of simple interface mechanism, we could write code like this instead, and be future compatible: if (php_stream_has(stream, PHP_STREAM_IFACE_SOCKET)) { ... use socket-stream functions here ... // would probably still use a macro with the same name as above, // but would implement the call in this way. // no assumptions are made about the streams internal data stream->sock_iface->set_chunk_size(stream, newsize); } The interfaces in streams would be very basic: we could have a bitfield where each bit corresponds to a pre-defined interface, and indicates that a particular pointer in the stream structure is valid and points to a "method table" (just like the stream_ops structure, but with different methods). With just a little bit more code, we can implement a system where extensions can register and query stream interfaces at runtime without risking a collision with interfaces from other extensions. At the moment I can think of 3 basic interfaces: the standard file/stream interface (that we have currently), an interface with network functions (set chunk size, blocking/non-blocking, timeouts), and an interface for streams that can expose their contents as a memory buffer - this would be implemented by the memory streams as well as by plain file streams (using mmap or equivalent). Where do we go from here? ========================= I really like both of these concepts; something like Dericks crypto extension could be implemented using filters rather than streams, and that would make them more versatile - just push them onto an existing stream and you won't need to think harder than that. Interfaces would be useful for cross-extension interoperation. In fact, it might be better to implement them as a lightweight layer that could be used for any non-stream resources, if the extension author desired. This would allow domxml XML resources to interoperate with other XML based extensions (as Stig mentioned recently), provided that we define a sensible set of operations that are likely to be required. Sterlings XSLT extension could benefit here too: ext/xslt would define the actual PHP user-land functions that call into xslt objects from different back-ends. The actual back-end that gets used could be decided at run-time (dynamic loading), rather than compile time. Right, I think I've go on for long enough now... all comments are welcome... --Wez. -- PHP Development Mailing List <http://www.php.net/> To unsubscribe, visit: http://www.php.net/unsub.php