Skip to content
70 changes: 69 additions & 1 deletion src/PHPCR/Util/CND/Reader/BufferReader.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,62 @@

/**
* @author Daniel Barsotti <daniel.barsotti@liip.ch>
* @author Nikola Petkanski <nikola@petkanski.com>
*/
class BufferReader implements ReaderInterface
{
/**
* @var string
*/
protected $eofMarker;

/**
* @var string
*/
protected $eolMarker;

/**
* @var string
*/
protected $buffer;

/**
* @var int
*/
protected $startPos;

/**
* @var int
*/
protected $forwardPos;

/**
* @var int
*/
protected $curLine;

/**
* @var int
*/
protected $curCol;

/**
* @var int
*/
protected $nextCurLine;

/**
* @var int
*/
protected $nextCurCol;

/**
* @param string $buffer
*/
public function __construct($buffer)
{
$this->eofMarker = chr(1);
$this->eolMarker = PHP_EOL;
$this->buffer = $buffer . $this->eofMarker;

$this->reset();
Expand All @@ -40,11 +74,22 @@ public function reset()
$this->nextCurLine = $this->nextCurCol = 1;
}

/**
* @return string
*/
public function getEofMarker()
{
return $this->eofMarker;
}

/**
* @return string
*/
public function getEolMarker()
{
return $this->eolMarker;
}

/**
* @return int
*/
Expand Down Expand Up @@ -75,6 +120,9 @@ public function currentChar()
return substr($this->buffer, $this->forwardPos, 1);
}

/**
* @return bool
*/
public function isEof()
{
return $this->currentChar() === $this->getEofMarker()
Expand All @@ -83,6 +131,24 @@ public function isEof()
|| $this->forwardPos > strlen($this->buffer);
}

/**
* @return bool
*/
public function isEol()
{
$current = $this->current();
$eolMarkerLength = strlen($this->getEolMarker());

// look ahead as far as the length of the EOL marker
$lookAhead = substr($this->buffer, $this->startPos, $this->forwardPos - $this->startPos + ($eolMarkerLength - 1));
$marker = $this->getEolMarker();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i don't think we need a field and getter for the eol, rather use the PHP_EOL directly below. end-of-line is handled by php for us, i think that is good enough.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the issue is that PHP_EOL is different depending on which OS you are running the code.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah ok, you wanted the test to test both. then lets just have a member variable but not use a getter method each time.

and lets have the constructor accept an optional $eolMarker that defaults to PHP_EOL. it could be useful for somebody in edge cases.


$result = preg_match('#'. preg_quote($marker) .'$#', $current) === 1;
$result = $result || preg_match('#'. preg_quote($marker) .'$#', $lookAhead) === 1;

return $result;
}

/**
* Advance the forward position and return the literal delimited by start and end position
* @return string
Expand All @@ -94,7 +160,9 @@ public function forward()
$this->nextCurCol++;
}

if ($this->current() === PHP_EOL) {
if ($this->isEol()) {
$eolMarkerLength = strlen($this->getEolMarker());
$this->forwardPos += ($eolMarkerLength - 1); // we already incremented with one
$this->nextCurLine++;
$this->nextCurCol = 1;
}
Expand Down
27 changes: 19 additions & 8 deletions src/PHPCR/Util/CND/Reader/FileReader.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,35 @@

/**
* @author Daniel Barsotti <daniel.barsotti@liip.ch>
* @author Nikola Petkanski <nikola@petkanski.com>
*/
class FileReader extends BufferReader
{
protected $fileName;
/**
* @var string
*/
protected $filePath;

public function __construct($fileName)
/**
* @param string $path
* @throws \InvalidArgumentException
*/
public function __construct($path)
{
if (!file_exists($fileName)) {
throw new \InvalidArgumentException(sprintf("Invalid file '%s'", $fileName));
if (!file_exists($path)) {
throw new \InvalidArgumentException(sprintf("Invalid file '%s'", $path));
}

$this->fileName = $fileName;
$this->path = $path;

parent::__construct(file_get_contents($fileName));
parent::__construct(file_get_contents($path));
}

public function getFileName()
/**
* @return string
*/
public function getPath()
{
return $this->fileName;
return $this->path;
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getting the file location is not needed anywhere. i suggest we simply drop the getter method. $fileName was good enough for me, but if you have a strong opinion then lets just rename it to $path.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, it's a path to the file and not it's name. $path sounds good.

15 changes: 14 additions & 1 deletion src/PHPCR/Util/CND/Reader/ReaderInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,30 @@
interface ReaderInterface
{
/**
* @return bool
* @return string
*/
public function getEofMarker();

/**
* @return string
*/
public function getEolMarker();

/**
* @return string with just one character
*/
public function currentChar();

/**
* @return bool
*/
public function isEof();

/**
* @return bool
*/
public function isEol();

/**
* @return int
*/
Expand Down
29 changes: 19 additions & 10 deletions src/PHPCR/Util/CND/Scanner/GenericScanner.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
* the token generation to your needs.
*
* @author Daniel Barsotti <daniel.barsotti@liip.ch>
* @author Nikola Petkanski <nikola@petkanski.com>
*/
class GenericScanner extends AbstractScanner
{
Expand Down Expand Up @@ -83,21 +84,31 @@ protected function consumeSpaces(ReaderInterface $reader)
*/
protected function consumeNewLine(ReaderInterface $reader)
{
if ($reader->currentChar() === PHP_EOL) {
$current = '';
while (strlen($current) < strlen($reader->getEolMarker())) {
$current = $reader->forward();
}

$token = new GenericToken(GenericToken::TK_NEWLINE, PHP_EOL);
if ($reader->isEol()) {
$token = new GenericToken(GenericToken::TK_NEWLINE, $reader->getEolMarker());
$this->addToken($reader, $token);


while ($reader->forward() === PHP_EOL) {
while ($reader->isEol()) {
$reader->consume();
$reader->forward();

$current = '';
while (strlen($current) < strlen($reader->getEolMarker())) {
$current = $reader->forward();
}
}

$reader->rewind();

return true;
}

$reader->rewind();

return false;
}

Expand All @@ -116,7 +127,7 @@ protected function consumeString(ReaderInterface $reader)
$char = $reader->forwardChar();
while ($char !== $curDelimiter) {

if ($char === PHP_EOL) {
if ($reader->isEol()) {
throw new ScannerException($reader, "Newline detected in string");
}

Expand Down Expand Up @@ -226,10 +237,8 @@ protected function consumeLineComments(ReaderInterface $reader)

if ($reader->current() === $delimiter) {

// consume to end of line
$char = $reader->currentChar();
while (!$reader->isEof() && $char !== PHP_EOL) {
$char = $reader->forwardChar();
while (!$reader->isEof() && !$reader->isEol()) {
$reader->forward();
}
$token = new GenericToken(GenericToken::TK_COMMENT, $reader->consume());
$this->addToken($reader, $token);
Expand Down
18 changes: 18 additions & 0 deletions tests/PHPCR/Tests/Util/CND/Fixtures/files/WindowsTestFile.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

namespace Test\Foobar;

class TestClass
{
/**
* Block comment
*/
public function testMethod($testParam)
{
// Line comment
$string = 'This is a "Test // string"';
return "Test string";
}

// String in "comment"
}
3 changes: 3 additions & 0 deletions tests/PHPCR/Tests/Util/CND/Fixtures/files/WindowsTestFile.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
This is a test file...

...containing dummy content.
33 changes: 29 additions & 4 deletions tests/PHPCR/Tests/Util/CND/Reader/BufferReaderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,38 @@

class BufferReaderTest extends \PHPUnit_Framework_TestCase
{
public function test__construct()
public function testWindowsLineEndings()
{
$buffer = "Some random\nstring";
$this->doTestReader("\r\n");
}

public function testUnixLineEndings()
{
$this->doTestReader("\n");
}

/**
* @param string $eolMarker
*/
protected function doTestReader($eolMarker)
{
$buffer = "Some random{$eolMarker}string";
$reader = new BufferReader($buffer);

$this->assertInstanceOf('\PHPCR\Util\CND\Reader\BufferReader', $reader);
$this->assertAttributeEquals($buffer . $reader->getEofMarker(), 'buffer', $reader);
$this->assertAttributeEquals(0, 'startPos', $reader);
$this->assertAttributeEquals(0, 'forwardPos', $reader);

// test whether the current EOL marker is correctly set
$this->assertAttributeEquals(PHP_EOL, 'eolMarker', $reader);

// swap the EOL marker with the one for the current platform being tested
$reflection = new \ReflectionObject($reader);
$property = $reflection->getProperty('eolMarker');
$property->setAccessible(true);
$property->setValue($reader, $eolMarker);

$this->assertEquals(1, $reader->getCurrentLine());
$this->assertEquals(1, $reader->getCurrentColumn());

Expand Down Expand Up @@ -55,8 +77,11 @@ public function test__construct()

$this->assertEquals(12, $reader->getCurrentColumn());

$this->assertEquals(PHP_EOL, $reader->forward());
$this->assertEquals(PHP_EOL, $reader->consume());
$this->assertFalse($reader->isEol());
$this->assertEquals($eolMarker, $reader->forward());
$this->assertTrue($reader->isEol());

$this->assertEquals($eolMarker, $reader->consume());

$this->assertEquals(2, $reader->getCurrentLine());
$this->assertEquals(1, $reader->getCurrentColumn());
Expand Down
Loading