Skip to content

Instantly share code, notes, and snippets.

@SEUH
Last active April 8, 2022 19:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save SEUH/39e7ceef6a52dd14405c470713880157 to your computer and use it in GitHub Desktop.
Save SEUH/39e7ceef6a52dd14405c470713880157 to your computer and use it in GitHub Desktop.
[WIP] Reverse SplFileObject
<?php
class ReverseSplFileObject
{
private SplFileObject $file;
private int $readPointer;
/**
* @var int|mixed
*/
private int $cacheSize;
private int $lineCount;
private array $buffer;
private int $bufferSize;
private int $bufferPointer;
private bool $reachedStartOfFile = false;
public function __construct($filePath, $cacheSize = 100)
{
$this->file = new SplFileObject($filePath);
$this->cacheSize = $cacheSize;
// Broken
// $spl->fseek(0, SEEK_END);
$this->file->seek($this->file->getSize());
// SplFileObject has always 1 line
$this->lineCount = $this->file->key() + 1;
$this->readPointer = $this->lineCount;
}
public function current()
{
if (empty($this->buffer)) {
$this->readToBuffer();
}
return $this->buffer[$this->bufferPointer];
}
public function prev()
{
if ($this->sof()) {
return false;
}
if (empty($this->buffer)) {
$this->readToBuffer();
}
$this->bufferPointer++;
if ($this->bufferPointer >= $this->bufferSize) {
// If already read from first line, then SOF is reached. Force bufferPointer
// to be last entry of buffer.
if ($this->readPointer === 0) {
$this->reachedStartOfFile = true;
$this->bufferPointer = $this->bufferSize - 1;
return false;
}
$this->readToBuffer();
}
return true;
}
private function readToBuffer()
{
$start = max($this->readPointer - $this->cacheSize, 0);
$amount = $start === 0 ? $this->readPointer : $this->cacheSize;
$iter = new \LimitIterator($this->file, $start, $amount);
$this->buffer = array_reverse(iterator_to_array($iter));
$this->bufferSize = $amount;
$this->readPointer = $start;
$this->bufferPointer = 0;
}
public function sof()
{
return $this->reachedStartOfFile;
}
public function eof()
{
return $this->file->eof();
}
public function lineCount()
{
return $this->lineCount;
}
}
<?php
$file = new ReverseSplFileObject('test.log');
do {
echo $file->current() . "\n";
} while ($file->prev());
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment