pokemon-showdown-client/lib/css-sanitizer/Wikimedia/CSS/Parser/StringDataSource.php

92 lines
2.3 KiB
PHP

<?php
/**
* @file
* @license https://opensource.org/licenses/Apache-2.0 Apache-2.0
*/
namespace Wikimedia\CSS\Parser;
/**
* Read data for the CSS parser
*/
class StringDataSource implements DataSource {
/** @var string */
protected $string;
/** @var int */
protected $len = 0, $pos = 0;
/** @var string[] */
protected $putBack = [];
/**
* @param string $string Input string. Must be valid UTF-8 with no BOM.
*/
public function __construct( $string ) {
static $newPHP;
$this->string = (string)$string;
$this->len = strlen( $this->string );
// HHVM 3.4 and older come with an outdated version of libmbfl that
// incorrectly allows values above U+10FFFF, so we have to check
// for them separately. (This issue also exists in PHP 5.3 and
// older, which are no longer supported.)
// @codeCoverageIgnoreStart
if ( $newPHP === null ) {
$newPHP = !mb_check_encoding( "\xf4\x90\x80\x80", 'UTF-8' );
}
// @codeCoverageIgnoreEnd
if ( !mb_check_encoding( $this->string, 'UTF-8' ) ||
!$newPHP && preg_match( "/\xf4[\x90-\xbf]|[\xf5-\xff]/S", $this->string ) !== 0
) {
throw new \InvalidArgumentException( '$string is not valid UTF-8' );
}
}
public function readCharacter() {
if ( $this->putBack ) {
return array_pop( $this->putBack );
}
if ( $this->pos >= $this->len ) {
return self::EOF;
}
// We already checked that the string is valid UTF-8 in the
// constructor, so we can do a quick binary "get next character" here.
$p = $this->pos;
$c = $this->string[$p];
$cc = ord( $this->string[$p] );
if ( $cc <= 0x7f ) {
$this->pos += 1;
return $c;
} elseif ( ( $cc & 0xe0 ) === 0xc0 ) {
$this->pos += 2;
return substr( $this->string, $p, 2 );
} elseif ( ( $cc & 0xf0 ) === 0xe0 ) {
$this->pos += 3;
return substr( $this->string, $p, 3 );
} elseif ( ( $cc & 0xf8 ) === 0xf0 ) {
$this->pos += 4;
return substr( $this->string, $p, 4 );
} else {
// WTF? Should never get here because it should have failed
// validation in the constructor.
// @codeCoverageIgnoreStart
throw new \UnexpectedValueException(
sprintf( 'Unexpected byte %02X in string at position %d.', $cc, $this->pos )
);
// @codeCoverageIgnoreEnd
}
}
public function putBackCharacter( $char ) {
if ( $char !== self::EOF ) {
$this->putBack[] = $char;
}
}
}