Compile a single source character definition into a plain UTF-8 character.

Handles the two formats from the possible character definitions:
- U+xxxx : Unicode value in hexadecimal
- xx: Ascii value in hexadecimal

@param string $char

@return string
768630
protected function compileCharacter($char)
    {
        switch (true) {
            case preg_match('(^U\\+[0-9a-fA-F]{4}$)', $char):
                return $this->converter->toUTF8Character(hexdec(substr($char, 2)));

            case preg_match('(^[0-9a-fA-F]{2}$)', $char):
                return chr(hexdec($char));

            default:
                throw new RuntimeException("Invalid character definition: $char");
        }
    }
893841
public static function isLetterOrDigit($char)
    {
        $pattern = self::getLetterOrDigitPattern();

        return is_scalar($char) && (bool)preg_match($pattern, $char);
    }
1294427
function _Char_toCode(char)
{
	var code = char.charCodeAt(0);
	if (0xD800 <= code && code <= 0xDBFF)
	{
		return (code - 0xD800) * 0x400 + char.charCodeAt(1) - 0xDC00 + 0x10000
	}
	return code;
}
961952
private static function getExtendedVersion($char) {
        $o = ord($char);
        if ($o === 0) {
            return '%U';
        } elseif ($o >= 1 && $o <= 26) {
            return '$' . chr($o + 64);
        } elseif (($o >= 33 && $o <= 44) || $o === 47 || $o === 48) {
            return '/' . chr($o + 32);
        } elseif ($o >= 97 && $o <= 122) {
            return '+' . chr($o - 32);
        } elseif ($o >= 27 && $o <= 31) {
            return '%' . chr($o + 38);
        } elseif ($o >= 59 && $o <= 63) {
            return '%' . chr($o + 11);
        } elseif ($o >= 91 && $o <= 95) {
            return '%' . chr($o - 16);
        } elseif ($o >= 123 && $o <= 127) {
            return '%' . chr($o - 43);
        } elseif ($o === 64) {
            return '%V';
        } elseif ($o === 96) {
            return '%W';
        } elseif ($o > 127) {
            return false;
        } else {
            return $char;
        }
    }
431454
public static function toBinaryString(string $character) : string
    {
        $result = null;
        $length = strlen($character); // Note: We want the raw length, not the mb length.

        for ($i = 0; $i < $length; ++$i) {
            $result .= sprintf('%08b', ord($character[$i]));
        }

        return $result;
    }
626850
public static function getCharDirection($char)
    {
        $c = Strings::ord($char);

        if (!(0x5be <= $c && 0x10b7f >= $c)) {
            return static::LTR;
        }

        if (0x85e >= $c) {
            if (0x5be === $c ||
                0x5c0 === $c ||
                0x5c3 === $c ||
                0x5c6 === $c ||
                (0x5d0 <= $c && 0x5ea >= $c) ||
                (0x5f0 <= $c && 0x5f4 >= $c) ||
                0x608 === $c ||
                0x60b === $c ||
                0x60d === $c ||
                0x61b === $c ||
                (0x61e <= $c && 0x64a >= $c) ||
                (0x66d <= $c && 0x66f >= $c) ||
                (0x671 <= $c && 0x6d5 >= $c) ||
                (0x6e5 <= $c && 0x6e6 >= $c) ||
                (0x6ee <= $c && 0x6ef >= $c) ||
                (0x6fa <= $c && 0x70d >= $c) ||
                0x710 === $c ||
                (0x712 <= $c && 0x72f >= $c) ||
                (0x74d <= $c && 0x7a5 >= $c) ||
                0x7b1 === $c ||
                (0x7c0 <= $c && 0x7ea >= $c) ||
                (0x7f4 <= $c && 0x7f5 >= $c) ||
                0x7fa === $c ||
                (0x800 <= $c && 0x815 >= $c) ||
                0x81a === $c ||
                0x824 === $c ||
                0x828 === $c ||
                (0x830 <= $c && 0x83e >= $c) ||
                (0x840 <= $c && 0x858 >= $c) ||
                0x85e === $c) {
                return static::RTL;
            }
        } elseif (0x200f === $c) {
            return static::RTL;
        } elseif (0xfb1d <= $c) {
            if (0xfb1d === $c ||
                (0xfb1f <= $c && 0xfb28 >= $c) ||
                (0xfb2a <= $c && 0xfb36 >= $c) ||
                (0xfb38 <= $c && 0xfb3c >= $c) ||
                0xfb3e === $c ||
                (0xfb40 <= $c && 0xfb41 >= $c) ||
                (0xfb43 <= $c && 0xfb44 >= $c) ||
                (0xfb46 <= $c && 0xfbc1 >= $c) ||
                (0xfbd3 <= $c && 0xfd3d >= $c) ||
                (0xfd50 <= $c && 0xfd8f >= $c) ||
                (0xfd92 <= $c && 0xfdc7 >= $c) ||
                (0xfdf0 <= $c && 0xfdfc >= $c) ||
                (0xfe70 <= $c && 0xfe74 >= $c) ||
                (0xfe76 <= $c && 0xfefc >= $c) ||
                (0x10800 <= $c && 0x10805 >= $c) ||
                0x10808 === $c ||
                (0x1080a <= $c && 0x10835 >= $c) ||
                (0x10837 <= $c && 0x10838 >= $c) ||
                0x1083c === $c ||
                (0x1083f <= $c && 0x10855 >= $c) ||
                (0x10857 <= $c && 0x1085f >= $c) ||
                (0x10900 <= $c && 0x1091b >= $c) ||
                (0x10920 <= $c && 0x10939 >= $c) ||
                0x1093f === $c ||
                0x10a00 === $c ||
                (0x10a10 <= $c && 0x10a13 >= $c) ||
                (0x10a15 <= $c && 0x10a17 >= $c) ||
                (0x10a19 <= $c && 0x10a33 >= $c) ||
                (0x10a40 <= $c && 0x10a47 >= $c) ||
                (0x10a50 <= $c && 0x10a58 >= $c) ||
                (0x10a60 <= $c && 0x10a7f >= $c) ||
                (0x10b00 <= $c && 0x10b35 >= $c) ||
                (0x10b40 <= $c && 0x10b55 >= $c) ||
                (0x10b58 <= $c && 0x10b72 >= $c) ||
                (0x10b78 <= $c && 0x10b7f >= $c)) {
                return static::RTL;
            }
        }

        return static::LTR;
    }
493567
public static function charCount($char): int
    {
        self::handleIncomingChar($char);
        $stringChar = (string) $char;

        return mb_ord($stringChar, mb_detect_encoding($stringChar)) > 0xFFFF ? 2 : 1;
    }
653734
static function convertStringToUnicode( $str )
    {
        $unicodeValues = array();
        $strLen = strlen( $str );
        for ( $offset = 0; $offset < $strLen; )
        {
            $charLen = 1;
            $unicodeValue = eZUTF8Codec::fromUTF8( $str, $offset, $charLen );
            if ( $unicodeValue !== false )
                $unicodeValues[] = $unicodeValue;
            $offset += $charLen;
        }
        return $unicodeValues;
    }
476638
private static function toUtf8($string) {

        if(static :: getEncoding() === 'utf-8') {
            $result = $string;
        }
        else {
            $result = static :: convert($string, static :: getEncoding(), 'UTF-8');
        }

        if(false === static :: isUtf8($result)) {
            return trigger_error(sprintf('String to be escaped was not valid UTF-8 or could not be converted'), E_USER_ERROR);
        }

        return $result;
    }
455816
public static function ord($char)
	{
		if (! ReflectionTypeHint::isValid()) return false;
		if (is_null($char)) return $char;

		static $cache = array();
		if (array_key_exists($char, $cache)) return $cache[$char]; #speed improve

		switch (strlen($char))
		{
			case 1 : return $cache[$char] = ord($char);
			case 2 : return $cache[$char] = (ord($char{1}) & 63) |
											((ord($char{0}) & 31) << 6);
			case 3 : return $cache[$char] = (ord($char{2}) & 63) |
											((ord($char{1}) & 63) << 6) |
											((ord($char{0}) & 15) << 12);
			case 4 : return $cache[$char] = (ord($char{3}) & 63) |
											((ord($char{2}) & 63) << 6) |
											((ord($char{1}) & 63) << 12) |
											((ord($char{0}) & 7)  << 18);
			default :
				trigger_error('Character 0x' . bin2hex($char) . ' is not UTF-8!', E_USER_WARNING);
				return false;
		}
	}
1193086
protected function _utf8ToHex($string) {
		$length = strlen($string);
		$return = '';
		for ($i = 0; $i < $length; ++$i) {
			$ord = ord($string{$i});
			switch (true) {
				case $ord == 0x08:
					$return .= '\b';
					break;
				case $ord == 0x09:
					$return .= '\t';
					break;
				case $ord == 0x0A:
					$return .= '\n';
					break;
				case $ord == 0x0C:
					$return .= '\f';
					break;
				case $ord == 0x0D:
					$return .= '\r';
					break;
				case $ord == 0x22:
				case $ord == 0x2F:
				case $ord == 0x5C:
					$return .= '\\' . $string{$i};
					break;
				case (($ord >= 0x20) && ($ord <= 0x7F)):
					$return .= $string{$i};
					break;
				case (($ord & 0xE0) == 0xC0):
					if ($i + 1 >= $length) {
						$i += 1;
						$return .= '?';
						break;
					}
					$charbits = $string{$i} . $string{$i + 1};
					$char = static::utf8($charbits);
					$return .= sprintf('\u%04s', dechex($char[0]));
					$i += 1;
					break;
				case (($ord & 0xF0) == 0xE0):
					if ($i + 2 >= $length) {
						$i += 2;
						$return .= '?';
						break;
					}
					$charbits = $string{$i} . $string{$i + 1} . $string{$i + 2};
					$char = static::utf8($charbits);
					$return .= sprintf('\u%04s', dechex($char[0]));
					$i += 2;
					break;
				case (($ord & 0xF8) == 0xF0):
					if ($i + 3 >= $length) {
						$i += 3;
						$return .= '?';
						break;
					}
					$charbits = $string{$i} . $string{$i + 1} . $string{$i + 2} . $string{$i + 3};
					$char = static::utf8($charbits);
					$return .= sprintf('\u%04s', dechex($char[0]));
					$i += 3;
					break;
				case (($ord & 0xFC) == 0xF8):
					if ($i + 4 >= $length) {
						$i += 4;
						$return .= '?';
						break;
					}
					$charbits = $string{$i} . $string{$i + 1} . $string{$i + 2} . $string{$i + 3} . $string{$i + 4};
					$char = static::utf8($charbits);
					$return .= sprintf('\u%04s', dechex($char[0]));
					$i += 4;
					break;
				case (($ord & 0xFE) == 0xFC):
					if ($i + 5 >= $length) {
						$i += 5;
						$return .= '?';
						break;
					}
					$charbits = $string{$i} . $string{$i + 1} . $string{$i + 2} . $string{$i + 3} . $string{$i + 4} . $string{$i + 5};
					$char = static::utf8($charbits);
					$return .= sprintf('\u%04s', dechex($char[0]));
					$i += 5;
					break;
			}
		}
		return $return;
	}
265394
public function escapeCharacterClass($char)
	{
		return (isset($this->inCharacterClass[$char])) ? $this->inCharacterClass[$char] : $char;
	}
723442
public function escapeLiteral($char)
	{
		return (isset($this->inLiteral[$char])) ? $this->inLiteral[$char] : $char;
	}
381525
protected function toUtf8($string)
    {
        if ($this->getEncoding() === 'utf-8') {
            $result = $string;
        } else {
            $result = $this->convertEncoding($string, 'UTF-8', $this->getEncoding());
        }

        return $result;
    }
432502
private function convertToUTF8($string)
    {
        $encoding = mb_detect_encoding($string, mb_detect_order(), false);

        if ($encoding == "UTF-8") {
            $string = mb_convert_encoding($string, 'UTF-8', 'UTF-8');
        }

        $out = iconv(mb_detect_encoding($string, mb_detect_order(), false), "UTF-8//IGNORE", $string);
        return $out;
    }
994282
private static function utf8_to_unicode( &$str )
    {
        $unicode = array();
        $values = array();
        $looking_for = 1;

        for ($i = 0; $i < strlen( $str ); $i++ ) {
            $this_value = ord( $str[ $i ] );
            if ( $this_value < 128 ) $unicode[] = $this_value;
            else {
                if ( count( $values ) == 0 ) $looking_for = ( $this_value < 224 ) ? 2 : 3;
                $values[] = $this_value;
                if ( count( $values ) == $looking_for ) {
                    $number = ( $looking_for == 3 ) ?
                        ( ( $values[0] % 16 ) * 4096 ) + ( ( $values[1] % 64 ) * 64 ) + ( $values[2] % 64 ):
                        ( ( $values[0] % 32 ) * 64 ) + ( $values[1] % 64 );
                    $unicode[] = $number;
                    $values = array();
                    $looking_for = 1;
                }
            }
        }
        return $unicode;
    }
248899
public function base64Decode($char)
    {
        if (! array_key_exists($char, $this->charToIntMap)) {
            throw new \Exception(sprintf('Invalid base 64 digit "%s" given.', $char));
        }

        return $this->charToIntMap[$char];
    }