@@ -31,6 +31,7 @@ class Parser {
3131 private $ oParserSettings ;
3232 private $ sCharset ;
3333 private $ iLength ;
34+ private $ peekCache = null ;
3435
3536 public function __construct ($ sText , Settings $ oParserSettings = null ) {
3637 $ this ->sText = $ sText ;
@@ -268,6 +269,7 @@ private function parseRuleSet($oRuleSet) {
268269 // We need to “unfind” the matches to the end of the ruleSet as this will be matched later
269270 if ($ this ->streql ($ this ->substr ($ sConsume , $ this ->strlen ($ sConsume )-1 , 1 ), '} ' )) {
270271 --$ this ->iCurrentPosition ;
272+ $ this ->peekCache = null ;
271273 } else {
272274 $ this ->consumeWhiteSpace ();
273275 while ($ this ->comes ('; ' )) {
@@ -446,7 +448,7 @@ private function parseURLValue() {
446448 }
447449 return $ oResult ;
448450 }
449-
451+
450452 /**
451453 * 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.
452454 */
@@ -468,12 +470,25 @@ private function peek($iLength = 1, $iOffset = 0) {
468470 if (is_string ($ iOffset )) {
469471 $ iOffset = $ this ->strlen ($ iOffset );
470472 }
471- $ iOffset = $ this ->iCurrentPosition + $ iOffset ;
473+ if (($ peek = (!$ iOffset && ($ iLength == 1 ))) &&
474+ !is_null ($ this ->peekCache )) {
475+ return $ this ->peekCache ;
476+ }
477+ if (!is_null ($ this ->peekCache ) &&
478+ $ iLength == 1 &&
479+ $ iOffset = 0 ) {
480+ return $ this ->peekCache ;
481+ }
482+ $ iOffset += $ this ->iCurrentPosition ;
472483 if ($ iOffset >= $ this ->iLength ) {
473484 return '' ;
474485 }
475486 $ iLength = min ($ iLength , $ this ->iLength -$ iOffset );
476- return $ this ->substr ($ this ->sText , $ iOffset , $ iLength );
487+ $ out = $ this ->substr ($ this ->sText , $ iOffset , $ iLength );
488+ if ($ peek ) {
489+ $ this ->peekCache = $ out ;
490+ }
491+ return $ out ;
477492 }
478493
479494 private function consume ($ mValue = 1 ) {
@@ -483,13 +498,15 @@ private function consume($mValue = 1) {
483498 throw new UnexpectedTokenException ($ mValue , $ this ->peek (max ($ iLength , 5 )));
484499 }
485500 $ this ->iCurrentPosition += $ this ->strlen ($ mValue );
501+ $ this ->peekCache = null ;
486502 return $ mValue ;
487503 } else {
488504 if ($ this ->iCurrentPosition + $ mValue > $ this ->iLength ) {
489505 throw new UnexpectedTokenException ($ mValue , $ this ->peek (5 ), 'count ' );
490506 }
491507 $ sResult = $ this ->substr ($ this ->sText , $ this ->iCurrentPosition , $ mValue );
492508 $ this ->iCurrentPosition += $ mValue ;
509+ $ this ->peekCache = null ;
493510 return $ sResult ;
494511 }
495512 }
0 commit comments