95 lines
2.9 KiB
PHP
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;
|
|
}
|
|
}
|