26
26
*/
27
27
class Parser {
28
28
29
- private $ sText ;
29
+ private $ aText ;
30
30
private $ iCurrentPosition ;
31
31
private $ oParserSettings ;
32
32
private $ sCharset ;
33
33
private $ iLength ;
34
- private $ peekCache = null ;
35
34
private $ blockRules ;
36
35
private $ aSizeUnits ;
37
36
38
37
public function __construct ($ sText , Settings $ oParserSettings = null ) {
39
- $ this ->sText = $ sText ;
40
38
$ this ->iCurrentPosition = 0 ;
41
39
if ($ oParserSettings === null ) {
42
40
$ oParserSettings = Settings::create ();
43
41
}
44
42
$ 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
+ }
45
48
$ this ->blockRules = explode ('/ ' , AtRule::BLOCK_RULES );
46
49
47
50
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) {
56
59
57
60
public function setCharset ($ sCharset ) {
58
61
$ this ->sCharset = $ sCharset ;
59
- $ this ->iLength = $ this -> strlen ($ this ->sText );
62
+ $ this ->iLength = count ($ this ->aText );
60
63
}
61
64
62
65
public function getCharset () {
@@ -284,9 +287,8 @@ private function parseRuleSet($oRuleSet) {
284
287
try {
285
288
$ sConsume = $ this ->consumeUntil (array ("\n" , "; " , '} ' ), true );
286
289
// 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 ), '} ' )) {
288
291
--$ this ->iCurrentPosition ;
289
- $ this ->peekCache = null ;
290
292
} else {
291
293
$ this ->consumeWhiteSpace ();
292
294
while ($ this ->comes ('; ' )) {
@@ -469,8 +471,8 @@ private function parseURLValue() {
469
471
}
470
472
471
473
/**
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
+ */
474
476
private function identifierIs ($ sIdentifier , $ sMatch ) {
475
477
return (strcasecmp ($ sIdentifier , $ sMatch ) === 0 )
476
478
?: preg_match ("/^(- \\w+-)? $ sMatch$/i " , $ sIdentifier ) === 1 ;
@@ -484,38 +486,28 @@ private function comes($sString, $bCaseInsensitive = false) {
484
486
}
485
487
486
488
private function peek ($ iLength = 1 , $ iOffset = 0 ) {
487
- if (($ peek = (!$ iOffset && ($ iLength === 1 ))) &&
488
- !is_null ($ this ->peekCache )) {
489
- return $ this ->peekCache ;
490
- }
491
489
$ iOffset += $ this ->iCurrentPosition ;
492
490
if ($ iOffset >= $ this ->iLength ) {
493
491
return '' ;
494
492
}
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 );
500
494
return $ out ;
501
495
}
502
496
503
497
private function consume ($ mValue = 1 ) {
504
498
if (is_string ($ mValue )) {
505
499
$ 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 )) {
507
501
throw new UnexpectedTokenException ($ mValue , $ this ->peek (max ($ iLength , 5 )));
508
502
}
509
503
$ this ->iCurrentPosition += $ this ->strlen ($ mValue );
510
- $ this ->peekCache = null ;
511
504
return $ mValue ;
512
505
} else {
513
506
if ($ this ->iCurrentPosition + $ mValue > $ this ->iLength ) {
514
507
throw new UnexpectedTokenException ($ mValue , $ this ->peek (5 ), 'count ' );
515
508
}
516
- $ sResult = $ this ->substr ($ this ->sText , $ this -> iCurrentPosition , $ mValue );
509
+ $ sResult = $ this ->substr ($ this ->iCurrentPosition , $ mValue );
517
510
$ this ->iCurrentPosition += $ mValue ;
518
- $ this ->peekCache = null ;
519
511
return $ sResult ;
520
512
}
521
513
}
@@ -587,15 +579,23 @@ private function consumeUntil($aEnd, $bIncludeEnd = false, $consumeEnd = false)
587
579
}
588
580
589
581
private function inputLeft () {
590
- return $ this ->substr ($ this ->sText , $ this -> iCurrentPosition , -1 );
582
+ return $ this ->substr ($ this ->iCurrentPosition , -1 );
591
583
}
592
584
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 ;
598
591
}
592
+ $ out = '' ;
593
+ while ($ iLength > 0 ) {
594
+ $ out .= $ this ->aText [$ iStart ];
595
+ $ iStart ++;
596
+ $ iLength --;
597
+ }
598
+ return $ out ;
599
599
}
600
600
601
601
private function strlen ($ sString ) {
0 commit comments