2026-01-09 07:13:59 +00:00

95 lines
2.9 KiB
PHP

<?php
declare(strict_types=1);
namespace PrinsFrank\PdfParser\Document\Generic\Parsing;
use PrinsFrank\PdfParser\Exception\InvalidArgumentException;
/** @internal */
class RollingCharBuffer {
/** @var int<1, max> $length */
private int $length;
/** @var int<0, max> */
private int $currentIndex = 0;
/**
* Rolling buffer, where the modulo of the index is used. Fe: when writing 'a', 'b', 'c', 'd', 'e', 'f' to a buffer of length 3:
* ['a']
* ['a', 'b']
* ['a', 'b', 'c']
* ['d', 'b', 'c']
* ['d', 'e', 'c']
* ['d', 'e', 'f']
*
* @var array<int<0, max>, string>
*/
private array $buffer = [];
/** @phpstan-assert int<1, max> $length */
public function __construct(int $length) {
if ($length < 1) {
throw new InvalidArgumentException(sprintf('A negative or zero buffer length doesn\'t make sense, %d provided', $length));
}
$this->length = $length;
}
public function next(string $char): self {
$this->currentIndex++;
$this->buffer[$this->currentIndex % $this->length] = $char;
return $this;
}
/** @throws InvalidArgumentException */
public function getPreviousCharacter(int $nAgo = 1): ?string {
if ($nAgo >= $this->length) {
throw new InvalidArgumentException('Buffer length of "' . $this->length . '" configured, but character "-' . $nAgo . '" requested');
}
return $this->buffer[($this->currentIndex - $nAgo) % $this->length] ?? null;
}
/**
* @phpstan-assert non-empty-string $string
*
* @throws InvalidArgumentException
*/
public function seenString(string $string): bool {
$strlen = strlen($string);
if ($strlen === 0) {
throw new InvalidArgumentException('Cannot assert if non empty string has been encountered');
}
if ($strlen > $this->length) {
throw new InvalidArgumentException(sprintf('Buffer length of %d configured, but value with length %d requested', $this->length, strlen($string)));
}
foreach (str_split($string) as $index => $char) {
$previousChar = $this->getPreviousCharacter($strlen - $index - 1);
if ($previousChar !== $char) {
return false;
}
}
return true;
}
/** @throws InvalidArgumentException */
public function seenReverseString(string $string): bool {
if (strlen($string) > $this->length) {
throw new InvalidArgumentException(sprintf('Buffer length of %d configured, but enum with length %d requested', $this->length, strlen($string)));
}
foreach (str_split($string) as $index => $char) {
$previousChar = $this->getPreviousCharacter($index);
if ($previousChar !== $char) {
return false;
}
}
return true;
}
}