charm/streams

Various utilities to work with streams and resources in PHP.

1.0.0 2021-07-16 14:32 UTC

This package is auto-updated.

Last update: 2024-12-14 21:36:23 UTC


README

Create readable and writable resource streams. This library uses php stream wrappers to create programmed stream resources.

Readable stream

/**
 * @var resource
 */
$bottlesOfBeer = Charm\Streams\GeneratorStreams::fromGenerator(function() {
    // Yield READ_ONLY, WRITE_ONLY or READ_WRITE mode before
    yield Charm\Streams\GeneratorStreams::READ_ONLY;

    $numberBottles = 99;
    while ($numberBottles > 1) {
        yield $numberBottles . " bottles of beer on the wall<br>\n";
        yield echo $numberBottles . " bottles of beer<br>\n";
        yield "If you take one down<br>\n";
        yield "And pass it around<br>\n";
        $numberBottles = $numberBottles - 1;
        yield "There'll be " . $numberBottles . " bottles of beer on the wall.<br><br>\n";
    }
    yield "Just " . $numberBottles . " bottle of beer on the wall<br>\n";
    yield "Just " . $numberBottles . " bottle of beer<br>\n";
    yield "If you take it down<br>\n";
    yield "And pass it around<br>\n";
    yield "There'll be no more bottles of beer on the wall.<br><br>\n";
});


while (!feof($bottlesOfBeer)) {
    $line = fgets($bottlesOfBeer);
    echo $line;
}

Writable stream

/**
 * @var resource
 */
$log = Charm\Streams\GeneratorStreams::fromGenerator(function() {
    yield Charm\Streams\GeneratorStreams::WRITE_ONLY;

    while (false !== ($data = yield)) {
        echo "Received: ".trim($data)."\n";
    }
});

fwrite($log, "This goes to the log somehow");
fclose($log);

Seekable stream

/**
 * @var resource
 */
$seekableReadStream = Charm\Streams\GeneratorStreams::fromGenerator(function() {
    yield Charm\Streams\GeneratorStreams::READ_ONLY | Charm\Streams\GeneratorStreams::SEEKABLE;

    $offset = 0;
    $data = 'This is some data for a seekable stream';

    // Bucket is passed back and forth and carries messages and strings
    $bucket = null;

    while (false !== ($bucket = yield $bucket) {

        switch (gettype($bucket)) {
            case 'null' :
                // Emit a chunk and update offset
                $bucket = substr($data, $offset, 4);
                $offset += 4;
                break;

            case 'int' : 
                if ($bucket >= 0) {
                    // Update offset
                    $offset = $bucket;
                    $bucket = null;
                    break;
                }
            default :
                // negative integers (they are reserved instructions) and strings are ignored
                $bucket = null;
                break;
        }
    }
});

FIFO stream
-----------

/**

  • @var resource */ $fifo = Charm\Streams\GeneratorStreams::fromGenerator(function() { yield Charm\Streams\GeneratorStreams::READ_WRITE;

    $bucket = null while (false !== ($bucket = yield $bucket)) {

     switch (gettype($bucket)) {
         case 'null' :
             // null means we have nothing, so we'll just yield it
         case 'string' :
             // bucket contains the data we are supposed to serve
             break;
         case 'int' :
             if ($bucket >= 0) {
                 // We don't support seeking
                 $bucket = null;
                 break;
             }
         default :
             $bucket = null;
             break;           
     }
    

    } });

echo fread($fifo, 4096); // '' - empty string returned fwrite($fifo, 'String is no longer empty'); echo fread($fifo, 4096); // 'String is no longer empty'

feof($fifo); // true, unless fclose($fifo) is called