Skip to content

Commit

Permalink
update to use immutable read file package
Browse files Browse the repository at this point in the history
  • Loading branch information
mallardduck committed Dec 22, 2020
1 parent 1b32450 commit 6b16e5b
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 40 deletions.
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@
"require": {
"php": "^7.4 || ^8.0",
"ext-mbstring": "*",
"cypresslab/php-curry": "^0.5.0"
"cypresslab/php-curry": "^0.5.0",
"mallardduck/immutable-read-file": "^0.5.2"
},
"require-dev": {
"ext-json": "*",
Expand Down
74 changes: 35 additions & 39 deletions src/TextFileStream.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace Verraes\Parsica;

use InvalidArgumentException;
use MallardDuck\ImmutableReadFile\ImmutableFile;
use Verraes\Parsica\Internal\EndOfStream;
use Verraes\Parsica\Internal\Position;
use Verraes\Parsica\Internal\TakeResult;
Expand All @@ -16,9 +17,8 @@ final class TextFileStream implements Stream
private string $filePath;
/**
* @psalm-allow-private-mutation
* @var resource
*/
private $fileHandle;
private ImmutableFile $fileHandle;
private Position $position;

public static function createFromPosition(Position $position): self
Expand All @@ -28,22 +28,15 @@ public static function createFromPosition(Position $position): self

public function __construct(string $filePath, ?Position $position = null)
{
/**
* @psalm-suppress ImpureFunctionCall
*/
if (!is_file($filePath)) {
throw new InvalidArgumentException("The file path for the text-file is not a valid file.");
}
$this->filePath = $filePath;
$this->fileHandle = fopen($this->filePath, 'rb');
$this->position = $position ?? Position::initial($this->filePath);
if (true !== is_null($position)) {
fseek($this->fileHandle, $this->position->bytePosition());
}
}

public function __destruct()
{
if (is_resource($this->fileHandle)) {
fclose($this->fileHandle);
}
$this->fileHandle = ImmutableFile::fromFilePathWithPosition($this->filePath, $this->position->bytePosition());
}

/**
Expand All @@ -56,26 +49,17 @@ private function guardEndOfStream(): void
}
}

private function safeRead(?int $n = null): string
{
if (is_null($n)) {
$tokenChunk = fgetc($this->fileHandle);
} else {
$tokenChunk = fread($this->fileHandle, $n);
}
rewind($this->fileHandle);
fseek($this->fileHandle, $this->position->bytePosition());
return !$tokenChunk ? '' : $tokenChunk;
}

/**
* @inheritDoc
*/
public function take1(): TakeResult
{
$this->guardEndOfStream();

$token = $this->safeRead();
/**
* @psalm-suppress ImpureMethodCall
*/
$token = $this->fileHandle->fgetc();
$position = $this->position->advance($token);

return new TakeResult(
Expand All @@ -95,7 +79,10 @@ public function takeN(int $n): TakeResult

$this->guardEndOfStream();

$chunk = $this->safeRead($n);
/**
* @psalm-suppress ImpureMethodCall
*/
$chunk = $this->fileHandle->fread($n);
$position = $this->position->advance($chunk);

return new TakeResult(
Expand All @@ -113,22 +100,31 @@ public function takeWhile(callable $predicate): TakeResult
return new TakeResult("", $this);
}

$remaining = $this->fileHandle;
/**
* @psalm-suppress ImpureMethodCall
*/
$nextToken = $this->fileHandle->fgetc();
$chunk = ""; // Init the result buffer
$nextToken = fgetc($this->fileHandle);
while ($predicate($nextToken)) {
$chunk .= $nextToken;
if (!feof($this->fileHandle)) {
$nextToken = fgetc($this->fileHandle);
/**
* @psalm-suppress ImpureMethodCall
*/
$remaining = $remaining->advanceBytePosition();
if (!$remaining->feof()) {
/**
* @psalm-suppress ImpureMethodCall
*/
$nextToken = $remaining->fgetc();
} else {
break;
}
}
$position = $this->position->advance($chunk);
$this->safeRead();

return new TakeResult(
$chunk,
self::createFromPosition($position)
self::createFromPosition($this->position->advance($chunk))
);
}

Expand All @@ -137,22 +133,22 @@ public function takeWhile(callable $predicate): TakeResult
*/
public function __toString(): string
{
if (0 === ($size = filesize($this->filePath))) {
/**
* @psalm-suppress ImpureMethodCall
*/
if (0 === $this->fileHandle->getFileSize()) {
return "<EMPTYFILE>";
}

fseek($this->fileHandle, $this->position->bytePosition());
$stringData = fread($this->fileHandle, $size);
fseek($this->fileHandle, $this->position->bytePosition());
return $stringData;
return (string) $this->fileHandle;
}

/**
* @inheritDoc
*/
public function isEOF(): bool
{
return feof($this->fileHandle);
return $this->fileHandle->feof();
}

/**
Expand Down

0 comments on commit 6b16e5b

Please sign in to comment.