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&param2=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

Reply via email to