优化跳过性能
This commit is contained in:
parent
4c4be41f8b
commit
89470252e7
@ -47,22 +47,18 @@ abstract class ReaderInterface
|
|||||||
*/
|
*/
|
||||||
abstract public function moveToNextToken(): bool;
|
abstract public function moveToNextToken(): bool;
|
||||||
|
|
||||||
/**
|
abstract protected function getBetween(int $start = 0, int $end = 0): string;
|
||||||
* 跳过当前行
|
|
||||||
* @return bool
|
|
||||||
* @author Jerry Yan <792602257@qq.com>
|
|
||||||
* @date 2020/12/17 15:43
|
|
||||||
*/
|
|
||||||
abstract public function skipCurrentLine(): bool;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 从当前位置跳到结束位置
|
* 从当前位置跳到结束位置
|
||||||
* @param string $end
|
* @param string[] $chars
|
||||||
* @return bool
|
* @param int|null $startAt
|
||||||
|
* @param string $matched
|
||||||
|
* @return int|null
|
||||||
* @author Jerry Yan <792602257@qq.com>
|
* @author Jerry Yan <792602257@qq.com>
|
||||||
* @date 2020/12/17 15:43
|
* @date 2020/12/17 15:43
|
||||||
*/
|
*/
|
||||||
abstract public function skipUntil(string $end = "*/"): bool;
|
abstract public function findNextChars(array $chars, int $startAt = null, string &$matched = ""): ?int;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 重置读取器
|
* 重置读取器
|
||||||
@ -113,15 +109,84 @@ abstract class ReaderInterface
|
|||||||
return $this->currentToken;
|
return $this->currentToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function moveCursorToNextChar(): void
|
/**
|
||||||
|
* 跳过当前行
|
||||||
|
* @return bool
|
||||||
|
* @author Jerry Yan <792602257@qq.com>
|
||||||
|
* @date 2020/12/17 15:43
|
||||||
|
*/
|
||||||
|
public function skipCurrentLine(): bool
|
||||||
{
|
{
|
||||||
$this->currentPosition++;
|
$_ = $this->moveCursorToNextLine();
|
||||||
|
if ($_ === false) return false;
|
||||||
|
return $this->moveToNextToken();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function moveCursorToNextLine(int $chars = 1): void
|
/**
|
||||||
|
* 移动Cursor至下一字符
|
||||||
|
* @param int $charLength
|
||||||
|
* @author Jerry Yan <792602257@qq.com>
|
||||||
|
* @date 2020/12/19 15:05
|
||||||
|
*/
|
||||||
|
protected function moveCursorToNextChar(int $charLength = 1): void
|
||||||
{
|
{
|
||||||
$this->currentPosition += $chars;
|
$this->currentPosition += $charLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 移动Cursor至下一行
|
||||||
|
* @param int|null $newPos 下一行位置,不提供则手动检测
|
||||||
|
* @return bool
|
||||||
|
* @author Jerry Yan <792602257@qq.com>
|
||||||
|
* @date 2020/12/19 15:05
|
||||||
|
*/
|
||||||
|
protected function moveCursorToNextLine(int $newPos = null): bool
|
||||||
|
{
|
||||||
|
if ($newPos === null) {
|
||||||
|
$curPos = $this->currentPosition;
|
||||||
|
$newPos = $this->findNextChars(["\r\n", "\r", "\n"], $curPos);
|
||||||
|
if ($newPos === null) return false;
|
||||||
|
$this->nextPosition = $newPos;
|
||||||
|
}
|
||||||
|
$this->moveCursorToNextChar($newPos - $this->currentPosition);
|
||||||
$this->currentLineDelta = $this->currentPosition;
|
$this->currentLineDelta = $this->currentPosition;
|
||||||
$this->currentLine++;
|
$this->currentLine++;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cursor向后移动多少字符
|
||||||
|
* @param int $length 字符长度
|
||||||
|
* @return bool 是否成功
|
||||||
|
* @author Jerry Yan <792602257@qq.com>
|
||||||
|
* @date 2020/12/19 15:13
|
||||||
|
*/
|
||||||
|
protected function moveCursorAfter(int $length): bool
|
||||||
|
{
|
||||||
|
$lastLinePos = $pos = $this->currentPosition;
|
||||||
|
$end = $pos + $length;
|
||||||
|
while ($pos < $end) {
|
||||||
|
$pos = $this->findNextChars(["\r\n", "\r", "\n"], $pos);
|
||||||
|
if ($pos === null || $pos > $end) break;
|
||||||
|
$this->moveCursorToNextLine($pos);
|
||||||
|
$lastLinePos = $pos;
|
||||||
|
}
|
||||||
|
$this->moveCursorToNextChar($end - $lastLinePos);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 移动到新的位置
|
||||||
|
* @param int $newPos
|
||||||
|
* @return bool
|
||||||
|
* @author Jerry Yan <792602257@qq.com>
|
||||||
|
* @date 2020/12/19 15:14
|
||||||
|
*/
|
||||||
|
protected function moveCursorTo(int $newPos): bool
|
||||||
|
{
|
||||||
|
// TODO: Forward Or Backward
|
||||||
|
$this->moveCursorAfter($newPos - $this->currentPosition);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -112,33 +112,24 @@ class StringReader extends ReaderInterface
|
|||||||
/**
|
/**
|
||||||
* @inheritDoc
|
* @inheritDoc
|
||||||
*/
|
*/
|
||||||
public function skipCurrentLine(): bool
|
public function findNextChars(array $chars, int $startAt = null, string &$matched = ""): ?int
|
||||||
{
|
{
|
||||||
$curPos = $this->currentPosition;
|
if (empty($chars)) return null;
|
||||||
while ($curChar = $this->getNextChar($curPos)) {
|
if ($startAt === null) $startAt = $this->currentPosition;
|
||||||
$curPos++;
|
/** @var array<string, int> $result */
|
||||||
switch ($curChar) {
|
$result = [];
|
||||||
case "\r":
|
foreach ($chars as $char) {
|
||||||
if ($this->getNextChar($curPos) === "\n") {
|
$_ = mb_strpos($this->string, $char, $startAt);
|
||||||
// CRLF换行
|
if ($_ !== false) $result[$char] = $_;
|
||||||
$curPos++;
|
|
||||||
}
|
}
|
||||||
break 2;
|
if (empty($result)) return null;
|
||||||
case "\n":
|
asort($result);
|
||||||
break 2;
|
$matched = array_keys($result)[0];
|
||||||
}
|
return $result[$matched] + mb_strlen($matched);
|
||||||
}
|
|
||||||
$this->nextPosition = $curPos;
|
|
||||||
$this->moveCursorToNextLine($curPos - $this->currentPosition);
|
|
||||||
return $this->moveToNextToken();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
protected function getBetween(int $start = 0, int $end = 0): string
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
public function skipUntil(string $end = "*/"): bool
|
|
||||||
{
|
{
|
||||||
// TODO: Implement skipUntil() method.
|
return mb_substr($this->string, $start, $end - $start);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -29,13 +29,13 @@ class StringReaderTest extends TestCase
|
|||||||
'moveToNextLines' => [],
|
'moveToNextLines' => [],
|
||||||
];
|
];
|
||||||
$this->thingsWithCrLf = [
|
$this->thingsWithCrLf = [
|
||||||
'original' => " 中文 \r\n\r 这是 \r Is \n\n 一个 新的 TOken",
|
'original' => " 中文 \r\n\r 这是 \r Is A \n\n 一个 新的 TOken",
|
||||||
'tokens' => ["中文", "这是", "Is", "一个", "新的", "TOken"],
|
'tokens' => ["中文", "这是", "Is", "A", "一个", "新的", "TOken"],
|
||||||
'nextTokens' => ["这是", "Is", "一个", "新的", "TOken", ""],
|
'nextTokens' => ["这是", "Is", "A", "一个", "新的", "TOken", ""],
|
||||||
'positions' => [1, 8, 13, 19, 22, 25],
|
'positions' => [1, 8, 13, 16, 21, 24, 27],
|
||||||
'lines' => [1, 3, 4, 6, 6, 6],
|
'lines' => [1, 3, 4, 4, 6, 6, 6],
|
||||||
'linePositions' => [1, 1, 1, 1, 4, 7],
|
'linePositions' => [1, 1, 1, 4, 1, 4, 7],
|
||||||
'moveToNextLines' => [1, 2, 3],
|
'moveToNextLines' => [1, 2, 4],
|
||||||
];
|
];
|
||||||
$this->reader = new StringReader($this->things['original']);
|
$this->reader = new StringReader($this->things['original']);
|
||||||
$this->readerWithCrLf = new StringReader($this->thingsWithCrLf['original']);
|
$this->readerWithCrLf = new StringReader($this->thingsWithCrLf['original']);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user