mirror of
https://github.com/danog/byte-stream.git
synced 2024-11-30 04:19:23 +01:00
Remove Parser
Moved to a separate repository at amphp/parser.
This commit is contained in:
parent
6eb83c1218
commit
7a8d6d5f1f
@ -75,7 +75,3 @@ This package offers some basic implementations, other libraries might provide ev
|
||||
|
||||
* [`ResourceOutputStream`](./resource-streams.md)
|
||||
* [`ZlibOutputStream`](./compression-streams.md)
|
||||
|
||||
## Parser
|
||||
|
||||
* [`Parser`](./parser.md)
|
||||
|
@ -1,5 +0,0 @@
|
||||
---
|
||||
title: Parser
|
||||
permalink: /parser
|
||||
---
|
||||
TBD.
|
@ -1,42 +0,0 @@
|
||||
<?php
|
||||
|
||||
require __DIR__ . "/../vendor/autoload.php";
|
||||
|
||||
use Amp\ByteStream\Parser;
|
||||
use Amp\Loop;
|
||||
|
||||
Loop::run(function () {
|
||||
// Defines a generator that yields integers (number of bytes to read), strings (delimiter to search for), or
|
||||
// null (read any amount of bytes).
|
||||
$generator = function (callable $printer): \Generator {
|
||||
while (true) {
|
||||
$buffer = yield "\n"; // Reads until a new-line character is found.
|
||||
$printer($buffer); // Use the received data.
|
||||
}
|
||||
};
|
||||
|
||||
// The user of Parser is responsible for creating the Generator object, allowing anything to be passed into the
|
||||
// generator that may be required.
|
||||
$parser = new Parser($generator(function (string $parsedData) {
|
||||
static $i = 0;
|
||||
printf("[%d] %s\n", $i++, $parsedData);
|
||||
}));
|
||||
|
||||
$parser->write("This\nis\n");
|
||||
|
||||
Loop::delay(1000, function () use ($parser) {
|
||||
$parser->write("an\nexample\nof\n");
|
||||
});
|
||||
|
||||
Loop::delay(2000, function () use ($parser) {
|
||||
$parser->write("a\nsimple\n");
|
||||
});
|
||||
|
||||
Loop::delay(3000, function () use ($parser) {
|
||||
$parser->write("incremental\nstream\nparser\n");
|
||||
});
|
||||
|
||||
Loop::delay(4000, function () use ($parser) {
|
||||
$parser->end(); // Marks the end of data.
|
||||
});
|
||||
});
|
119
lib/Parser.php
119
lib/Parser.php
@ -1,119 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Amp\ByteStream;
|
||||
|
||||
use Amp\InvalidYieldError;
|
||||
|
||||
class Parser {
|
||||
/** @var \Generator */
|
||||
private $generator;
|
||||
|
||||
/** @var string */
|
||||
private $buffer = '';
|
||||
|
||||
/** @var int|string|null */
|
||||
private $delimiter;
|
||||
|
||||
/**
|
||||
* @param \Generator $generator
|
||||
*
|
||||
* @throws \Amp\InvalidYieldError If the generator yields an invalid value.
|
||||
*/
|
||||
public function __construct(\Generator $generator) {
|
||||
$this->generator = $generator;
|
||||
|
||||
$this->delimiter = $this->generator->current();
|
||||
|
||||
if (!$this->generator->valid()) {
|
||||
$this->generator = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if ($this->delimiter !== null
|
||||
&& (!\is_int($this->delimiter) || $this->delimiter <= 0)
|
||||
&& (!\is_string($this->delimiter) || !\strlen($this->delimiter))
|
||||
) {
|
||||
throw new InvalidYieldError(
|
||||
$generator,
|
||||
\sprintf(
|
||||
"Unexpected yield; Expected NULL, an int greater than 0, or a non-empty string; %s given",
|
||||
\is_object($this->delimiter) ? \sprintf("instance of %s", \get_class($this->delimiter)) : \gettype($this->delimiter)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancels the generator parser and returns any remaining data in the internal buffer. Writing data after calling
|
||||
* this method will result in an error.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
final public function cancel(): string {
|
||||
$this->generator = null;
|
||||
return $this->buffer;
|
||||
}
|
||||
|
||||
final public function push(string $data) {
|
||||
if ($this->generator === null) {
|
||||
throw new StreamException("The parser is no longer writable");
|
||||
}
|
||||
|
||||
$this->buffer .= $data;
|
||||
$end = false;
|
||||
|
||||
try {
|
||||
while ($this->buffer !== "") {
|
||||
if (\is_int($this->delimiter)) {
|
||||
if (\strlen($this->buffer) < $this->delimiter) {
|
||||
break; // Too few bytes in buffer.
|
||||
}
|
||||
|
||||
$send = \substr($this->buffer, 0, $this->delimiter);
|
||||
$this->buffer = \substr($this->buffer, $this->delimiter);
|
||||
} elseif (\is_string($this->delimiter)) {
|
||||
if (($position = \strpos($this->buffer, $this->delimiter)) === false) {
|
||||
break;
|
||||
}
|
||||
|
||||
$send = \substr($this->buffer, 0, $position);
|
||||
$this->buffer = \substr($this->buffer, $position + \strlen($this->delimiter));
|
||||
} else {
|
||||
$send = $this->buffer;
|
||||
$this->buffer = "";
|
||||
}
|
||||
|
||||
try {
|
||||
$this->delimiter = $this->generator->send($send);
|
||||
} catch (\Exception $exception) { // Wrap Exception instances into a StreamException.
|
||||
throw new StreamException("The generator parser threw an exception", 0, $exception);
|
||||
}
|
||||
|
||||
if (!$this->generator->valid()) {
|
||||
$end = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if ($this->delimiter !== null
|
||||
&& (!\is_int($this->delimiter) || $this->delimiter <= 0)
|
||||
&& (!\is_string($this->delimiter) || !\strlen($this->delimiter))
|
||||
) {
|
||||
throw new InvalidYieldError(
|
||||
$this->generator,
|
||||
\sprintf(
|
||||
"Unexpected yield; Expected NULL, an int greater than 0, or a non-empty string; %s given",
|
||||
\is_object($this->delimiter) ? \sprintf("instance of %s", \get_class($this->delimiter)) : \gettype($this->delimiter)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
} catch (\Throwable $exception) {
|
||||
$end = true;
|
||||
throw $exception;
|
||||
} finally {
|
||||
if ($end) {
|
||||
$this->generator = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Amp\ByteStream\Test;
|
||||
|
||||
use Amp\ByteStream\Parser;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class ParserTest extends TestCase {
|
||||
public function testIntDelimiter() {
|
||||
$parser = new Parser((function () use (&$value) {
|
||||
$value = yield 6;
|
||||
})());
|
||||
|
||||
$parser->push("foobarfoo\r\n");
|
||||
|
||||
$this->assertSame("foobar", $value);
|
||||
}
|
||||
|
||||
public function testStringDelimiter() {
|
||||
$parser = new Parser((function () use (&$value1, &$value2) {
|
||||
$value1 = yield "bar";
|
||||
$value2 = yield "\r\n";
|
||||
})());
|
||||
|
||||
$parser->push("foobarbaz\r\n");
|
||||
|
||||
$this->assertSame("foo", $value1);
|
||||
$this->assertSame("baz", $value2);
|
||||
}
|
||||
|
||||
public function testUndelimited() {
|
||||
$parser = new Parser((function () use (&$value) {
|
||||
$value = yield;
|
||||
})());
|
||||
|
||||
$parser->push("foobarbaz\r\n");
|
||||
|
||||
$this->assertSame("foobarbaz\r\n", $value);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user