From 4d8607d7d783cb97d5fcc0c819467c9b95a7d1c7 Mon Sep 17 00:00:00 2001 From: macbre Date: Wed, 29 Nov 2023 19:34:15 +0000 Subject: [PATCH 1/3] JsonlParser: improve truncating the file when poping and pushing items --- src/JsonlParser.php | 5 +++-- tests/JsonParserTest.php | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/src/JsonlParser.php b/src/JsonlParser.php index 3303f0a..720bb41 100644 --- a/src/JsonlParser.php +++ b/src/JsonlParser.php @@ -65,9 +65,10 @@ public function pop(): null|array|string $buffer = strrev($buffer); - // truncate the stream and remove the trailing newline + // truncate the stream + // remove the trailing newline if the stream is now empty $pos = ftell($this->stream); - ftruncate($this->stream, $pos < 1 ? 0 : $pos-1); + ftruncate($this->stream, $pos <= strlen(self::LINES_SEPARATOR) ? 0 : $pos); return json_decode($buffer, associative: true); } diff --git a/tests/JsonParserTest.php b/tests/JsonParserTest.php index f17b0dd..54be400 100644 --- a/tests/JsonParserTest.php +++ b/tests/JsonParserTest.php @@ -126,4 +126,43 @@ public function testPushItemsToFile(): void fclose($stream); // this removes the file } + + public function testFileSyncing(): void + { + $tmpFilename = tempnam(directory: sys_get_temp_dir(), prefix: 'jsonld'); + $stream = fopen($tmpFilename, 'a+t'); + + // TODO: introduce a helper JsonlParser::fromFile() + $parser = new JsonlParser($stream); + $this->assertCount(0, $parser); + $parser->push(self::ITEM_ONE); + $parser->push(self::ITEM_TWO); + $this->assertCount(2, $parser); + + // now get one and push the next item + $this->assertSame(self::ITEM_TWO, $parser->pop()); + $this->assertStringEqualsFile( + expectedFile: $tmpFilename, + actualString: json_encode(self::ITEM_ONE) . JsonlParser::LINES_SEPARATOR + ); + $this->assertCount(1, $parser); + $parser->push(self::ITEM); + $this->assertStringEqualsFile( + expectedFile: $tmpFilename, + actualString: json_encode(self::ITEM_ONE) . JsonlParser::LINES_SEPARATOR . json_encode(self::ITEM) . JsonlParser::LINES_SEPARATOR + ); + $this->assertCount(2, $parser); + + // now, empty the file + $parser->pop(); + $parser->pop(); + $this->assertCount(0, $parser); + $this->assertStringEqualsFile( + expectedFile: $tmpFilename, + actualString: '' + ); + + fclose($stream); + unlink($tmpFilename); + } } From ec766354aa4f875810040b07a5bd3d77624f68f5 Mon Sep 17 00:00:00 2001 From: macbre Date: Wed, 29 Nov 2023 19:36:23 +0000 Subject: [PATCH 2/3] Add JsonlParser::empty() helper --- src/JsonlParser.php | 8 ++++++++ tests/JsonParserTest.php | 4 ++++ 2 files changed, 12 insertions(+) diff --git a/src/JsonlParser.php b/src/JsonlParser.php index 720bb41..0403f4f 100644 --- a/src/JsonlParser.php +++ b/src/JsonlParser.php @@ -104,4 +104,12 @@ public function count(): int return $count; } + + /** + * Checks if there are no items in the stream. + */ + public function empty(): bool + { + return count($this) === 0; + } } diff --git a/tests/JsonParserTest.php b/tests/JsonParserTest.php index 54be400..18dba0c 100644 --- a/tests/JsonParserTest.php +++ b/tests/JsonParserTest.php @@ -135,9 +135,12 @@ public function testFileSyncing(): void // TODO: introduce a helper JsonlParser::fromFile() $parser = new JsonlParser($stream); $this->assertCount(0, $parser); + $this->assertTrue($parser->empty()); + $parser->push(self::ITEM_ONE); $parser->push(self::ITEM_TWO); $this->assertCount(2, $parser); + $this->assertFalse($parser->empty()); // now get one and push the next item $this->assertSame(self::ITEM_TWO, $parser->pop()); @@ -157,6 +160,7 @@ public function testFileSyncing(): void $parser->pop(); $parser->pop(); $this->assertCount(0, $parser); + $this->assertTrue($parser->empty()); $this->assertStringEqualsFile( expectedFile: $tmpFilename, actualString: '' From c6ba82df3c69dccf6db3f7f061fa1d644adbfd93 Mon Sep 17 00:00:00 2001 From: macbre Date: Wed, 29 Nov 2023 19:38:46 +0000 Subject: [PATCH 3/3] Introduce the JsonlParser::fromFile() helper --- src/JsonlParser.php | 9 +++++++++ tests/JsonParserTest.php | 7 ++----- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/JsonlParser.php b/src/JsonlParser.php index 0403f4f..a58bf6d 100644 --- a/src/JsonlParser.php +++ b/src/JsonlParser.php @@ -13,6 +13,15 @@ public function __construct(protected $stream) { } + /** + * Initialize the parser from the given file. + */ + public static function fromFile(string $filename, string $mode = 'a+t'): self + { + $stream = fopen($filename, $mode); + return new self($stream); + } + public function push(array|string $item): void { $encoded = json_encode($item); diff --git a/tests/JsonParserTest.php b/tests/JsonParserTest.php index 18dba0c..8708666 100644 --- a/tests/JsonParserTest.php +++ b/tests/JsonParserTest.php @@ -127,13 +127,11 @@ public function testPushItemsToFile(): void fclose($stream); // this removes the file } - public function testFileSyncing(): void + public function testFromFile(): void { $tmpFilename = tempnam(directory: sys_get_temp_dir(), prefix: 'jsonld'); - $stream = fopen($tmpFilename, 'a+t'); - // TODO: introduce a helper JsonlParser::fromFile() - $parser = new JsonlParser($stream); + $parser = JsonlParser::fromFile($tmpFilename); $this->assertCount(0, $parser); $this->assertTrue($parser->empty()); @@ -166,7 +164,6 @@ public function testFileSyncing(): void actualString: '' ); - fclose($stream); unlink($tmpFilename); } }