cii-text-analysis/vendor/amphp/parser/lib/Parser.php
Jéremy Munsch f68d2ac333
premier poc
2026-02-11 08:24:04 +01:00

131 lines
4.3 KiB
PHP

<?php
namespace Amp\Parser;
class Parser {
/** @var \Generator */
private $generator;
/** @var string */
private $buffer = '';
/** @var int|string|null */
private $delimiter;
/**
* @param \Generator $generator
*
* @throws InvalidDelimiterError If the generator yields an invalid delimiter.
* @throws \Throwable If the generator throws.
*/
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 InvalidDelimiterError(
$generator,
\sprintf(
"Invalid value yielded: 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;
}
/**
* @return bool True if the parser can still receive more data to parse, false if it has ended and calling push
* will throw an exception.
*/
final public function isValid(): bool {
return $this->generator !== null;
}
/**
* Adds data to the internal buffer and tries to continue parsing.
*
* @param string $data Data to append to the internal buffer.
*
* @throws InvalidDelimiterError If the generator yields an invalid delimiter.
* @throws \Error If parsing has already been cancelled.
* @throws \Throwable If the generator throws.
*/
final public function push(string $data) {
if ($this->generator === null) {
throw new \Error("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 = "";
}
$this->delimiter = $this->generator->send($send);
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 InvalidDelimiterError(
$this->generator,
\sprintf(
"Invalid value yielded: 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;
}
}
}
}