';
protected $slash = " />\r\n\t";
protected $attr = ' >';
/**
* Content constructor.
*
* @param string $content
*/
public function __construct(string $content = '')
{
$this->content = $content;
$this->size = strlen($content);
$this->pos = 0;
}
/**
* Returns the current position of the content.
*
* @return int
*/
public function getPosition(): int
{
return $this->pos;
}
/**
* Gets the current character we are at.
*
* @param int $char
* @return string
*/
public function char(int $char = null): string
{
$pos = $this->pos;
if ( ! is_null($char)) {
$pos = $char;
}
if ( ! isset($this->content[$pos])) {
return '';
}
return $this->content[$pos];
}
/**
* Moves the current position forward.
*
* @param int $count
* @return Content
* @chainable
*/
public function fastForward(int $count): Content
{
$this->pos += $count;
return $this;
}
/**
* Moves the current position backward.
*
* @param int $count
* @return Content
* @chainable
*/
public function rewind(int $count): Content
{
$this->pos -= $count;
if ($this->pos < 0) {
$this->pos = 0;
}
return $this;
}
/**
* Copy the content until we find the given string.
*
* @param string $string
* @param bool $char
* @param bool $escape
* @return string
*/
public function copyUntil(string $string, bool $char = false, bool $escape = false): string
{
if ($this->pos >= $this->size) {
// nothing left
return '';
}
if ($escape) {
$position = $this->pos;
$found = false;
while ( ! $found) {
$position = strpos($this->content, $string, $position);
if ($position === false) {
// reached the end
$found = true;
continue;
}
if ($this->char($position - 1) == '\\') {
// this character is escaped
++$position;
continue;
}
$found = true;
}
} elseif ($char) {
$position = strcspn($this->content, $string, $this->pos);
$position += $this->pos;
} else {
$position = strpos($this->content, $string, $this->pos);
}
if ($position === false) {
// could not find character, just return the remaining of the content
$return = substr($this->content, $this->pos, $this->size - $this->pos);
$this->pos = $this->size;
return $return;
}
if ($position == $this->pos) {
// we are at the right place
return '';
}
$return = substr($this->content, $this->pos, $position - $this->pos);
// set the new position
$this->pos = $position;
return $return;
}
/**
* Copies the content until the string is found and return it
* unless the 'unless' is found in the substring.
*
* @param string $string
* @param string $unless
* @return string
*/
public function copyUntilUnless(string $string, string $unless)
{
$lastPos = $this->pos;
$this->fastForward(1);
$foundString = $this->copyUntil($string, true, true);
$position = strcspn($foundString, $unless);
if ($position == strlen($foundString)) {
return $string.$foundString;
}
// rewind changes and return nothing
$this->pos = $lastPos;
return '';
}
/**
* Copies the content until it reaches the token string.,
*
* @param string $token
* @param bool $char
* @param bool $escape
* @return string
* @uses $this->copyUntil()
*/
public function copyByToken(string $token, bool $char = false, bool $escape = false)
{
$string = $this->$token;
return $this->copyUntil($string, $char, $escape);
}
/**
* Skip a given set of characters.
*
* @param string $string
* @param bool $copy
* @return Content|string
*/
public function skip(string $string, bool $copy = false)
{
$len = strspn($this->content, $string, $this->pos);
// make it chainable if they don't want a copy
$return = $this;
if ($copy) {
$return = substr($this->content, $this->pos, $len);
}
// update the position
$this->pos += $len;
return $return;
}
/**
* Skip a given token of pre-defined characters.
*
* @param string $token
* @param bool $copy
* @return Content|string
* @uses $this->skip()
*/
public function skipByToken(string $token, bool $copy = false)
{
$string = $this->$token;
return $this->skip($string, $copy);
}
}