Skip to content

Commit 3f4c774

Browse files
committed
Merge pull request #98 from ossinkine/performance-issue
Increase performance up to 15000%
2 parents 003e4fb + c5a44a9 commit 3f4c774

File tree

1 file changed

+27
-27
lines changed

1 file changed

+27
-27
lines changed

lib/Sabberworm/CSS/Parser.php

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -26,22 +26,25 @@
2626
*/
2727
class Parser {
2828

29-
private $sText;
29+
private $aText;
3030
private $iCurrentPosition;
3131
private $oParserSettings;
3232
private $sCharset;
3333
private $iLength;
34-
private $peekCache = null;
3534
private $blockRules;
3635
private $aSizeUnits;
3736

3837
public function __construct($sText, Settings $oParserSettings = null) {
39-
$this->sText = $sText;
4038
$this->iCurrentPosition = 0;
4139
if ($oParserSettings === null) {
4240
$oParserSettings = Settings::create();
4341
}
4442
$this->oParserSettings = $oParserSettings;
43+
if ($this->oParserSettings->bMultibyteSupport) {
44+
$this->aText = preg_split('//u', $sText, null, PREG_SPLIT_NO_EMPTY);
45+
} else {
46+
$this->aText = str_split($sText);
47+
}
4548
$this->blockRules = explode('/', AtRule::BLOCK_RULES);
4649

4750
foreach (explode('/', Size::ABSOLUTE_SIZE_UNITS.'/'.Size::RELATIVE_SIZE_UNITS.'/'.Size::NON_SIZE_UNITS) as $val) {
@@ -56,7 +59,7 @@ public function __construct($sText, Settings $oParserSettings = null) {
5659

5760
public function setCharset($sCharset) {
5861
$this->sCharset = $sCharset;
59-
$this->iLength = $this->strlen($this->sText);
62+
$this->iLength = count($this->aText);
6063
}
6164

6265
public function getCharset() {
@@ -284,9 +287,8 @@ private function parseRuleSet($oRuleSet) {
284287
try {
285288
$sConsume = $this->consumeUntil(array("\n", ";", '}'), true);
286289
// We need to “unfind” the matches to the end of the ruleSet as this will be matched later
287-
if($this->streql($this->substr($sConsume, $this->strlen($sConsume)-1, 1), '}')) {
290+
if($this->streql(substr($sConsume, -1), '}')) {
288291
--$this->iCurrentPosition;
289-
$this->peekCache = null;
290292
} else {
291293
$this->consumeWhiteSpace();
292294
while ($this->comes(';')) {
@@ -469,8 +471,8 @@ private function parseURLValue() {
469471
}
470472

471473
/**
472-
* Tests an identifier for a given value. Since identifiers are all keywords, they can be vendor-prefixed. We need to check for these versions too.
473-
*/
474+
* Tests an identifier for a given value. Since identifiers are all keywords, they can be vendor-prefixed. We need to check for these versions too.
475+
*/
474476
private function identifierIs($sIdentifier, $sMatch) {
475477
return (strcasecmp($sIdentifier, $sMatch) === 0)
476478
?: preg_match("/^(-\\w+-)?$sMatch$/i", $sIdentifier) === 1;
@@ -484,38 +486,28 @@ private function comes($sString, $bCaseInsensitive = false) {
484486
}
485487

486488
private function peek($iLength = 1, $iOffset = 0) {
487-
if (($peek = (!$iOffset && ($iLength === 1))) &&
488-
!is_null($this->peekCache)) {
489-
return $this->peekCache;
490-
}
491489
$iOffset += $this->iCurrentPosition;
492490
if ($iOffset >= $this->iLength) {
493491
return '';
494492
}
495-
$iLength = min($iLength, $this->iLength-$iOffset);
496-
$out = $this->substr($this->sText, $iOffset, $iLength);
497-
if ($peek) {
498-
$this->peekCache = $out;
499-
}
493+
$out = $this->substr($iOffset, $iLength);
500494
return $out;
501495
}
502496

503497
private function consume($mValue = 1) {
504498
if (is_string($mValue)) {
505499
$iLength = $this->strlen($mValue);
506-
if (!$this->streql($this->substr($this->sText, $this->iCurrentPosition, $iLength), $mValue)) {
500+
if (!$this->streql($this->substr($this->iCurrentPosition, $iLength), $mValue)) {
507501
throw new UnexpectedTokenException($mValue, $this->peek(max($iLength, 5)));
508502
}
509503
$this->iCurrentPosition += $this->strlen($mValue);
510-
$this->peekCache = null;
511504
return $mValue;
512505
} else {
513506
if ($this->iCurrentPosition + $mValue > $this->iLength) {
514507
throw new UnexpectedTokenException($mValue, $this->peek(5), 'count');
515508
}
516-
$sResult = $this->substr($this->sText, $this->iCurrentPosition, $mValue);
509+
$sResult = $this->substr($this->iCurrentPosition, $mValue);
517510
$this->iCurrentPosition += $mValue;
518-
$this->peekCache = null;
519511
return $sResult;
520512
}
521513
}
@@ -587,15 +579,23 @@ private function consumeUntil($aEnd, $bIncludeEnd = false, $consumeEnd = false)
587579
}
588580

589581
private function inputLeft() {
590-
return $this->substr($this->sText, $this->iCurrentPosition, -1);
582+
return $this->substr($this->iCurrentPosition, -1);
591583
}
592584

593-
private function substr($sString, $iStart, $iLength) {
594-
if ($this->oParserSettings->bMultibyteSupport) {
595-
return mb_substr($sString, $iStart, $iLength, $this->sCharset);
596-
} else {
597-
return substr($sString, $iStart, $iLength);
585+
private function substr($iStart, $iLength) {
586+
if ($iLength < 0) {
587+
$iLength = $this->iLength - $iStart + $iLength;
588+
}
589+
if ($iStart + $iLength > $this->iLength) {
590+
$iLength = $this->iLength - $iStart;
598591
}
592+
$out = '';
593+
while ($iLength > 0) {
594+
$out .= $this->aText[$iStart];
595+
$iStart++;
596+
$iLength--;
597+
}
598+
return $out;
599599
}
600600

601601
private function strlen($sString) {

0 commit comments

Comments
 (0)