Файловый менеджер - Редактировать - /home/tuudkjt/globeasy/wp-includes/ID3/string.tar
Назад
LazyString.php 0000777 00000011543 15251261610 0007375 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Rvx\Symfony\Component\String; /** * A string whose value is computed lazily by a callback. * * @author Nicolas Grekas <p@tchwork.com> */ class LazyString implements \Stringable, \JsonSerializable { private $value; /** * @param callable|array $callback A callable or a [Closure, method] lazy-callable * * @return static */ public static function fromCallable($callback, ...$arguments) : self { if (!\is_callable($callback) && !(\is_array($callback) && isset($callback[0]) && $callback[0] instanceof \Closure && 2 >= \count($callback))) { throw new \TypeError(\sprintf('Argument 1 passed to "%s()" must be a callable or a [Closure, method] lazy-callable, "%s" given.', __METHOD__, \get_debug_type($callback))); } $lazyString = new static(); $lazyString->value = static function () use(&$callback, &$arguments, &$value) : string { if (null !== $arguments) { if (!\is_callable($callback)) { $callback[0] = $callback[0](); $callback[1] = $callback[1] ?? '__invoke'; } $value = $callback(...$arguments); $callback = self::getPrettyName($callback); $arguments = null; } return $value ?? ''; }; return $lazyString; } /** * @param string|int|float|bool|\Stringable $value * * @return static */ public static function fromStringable($value) : self { if (!self::isStringable($value)) { throw new \TypeError(\sprintf('Argument 1 passed to "%s()" must be a scalar or a stringable object, "%s" given.', __METHOD__, \get_debug_type($value))); } if (\is_object($value)) { return static::fromCallable([$value, '__toString']); } $lazyString = new static(); $lazyString->value = (string) $value; return $lazyString; } /** * Tells whether the provided value can be cast to string. */ public static final function isStringable($value) : bool { return \is_string($value) || $value instanceof self || (\is_object($value) ? \method_exists($value, '__toString') : \is_scalar($value)); } /** * Casts scalars and stringable objects to strings. * * @param object|string|int|float|bool $value * * @throws \TypeError When the provided value is not stringable */ public static final function resolve($value) : string { return $value; } /** * @return string */ public function __toString() { if (\is_string($this->value)) { return $this->value; } try { return $this->value = ($this->value)(); } catch (\Throwable $e) { if (\TypeError::class === \get_class($e) && __FILE__ === $e->getFile()) { $type = \explode(', ', $e->getMessage()); $type = \substr(\array_pop($type), 0, -\strlen(' returned')); $r = new \ReflectionFunction($this->value); $callback = $r->getStaticVariables()['callback']; $e = new \TypeError(\sprintf('Return value of %s() passed to %s::fromCallable() must be of the type string, %s returned.', $callback, static::class, $type)); } if (\PHP_VERSION_ID < 70400) { // leverage the ErrorHandler component with graceful fallback when it's not available return \trigger_error($e, \E_USER_ERROR); } throw $e; } } public function __sleep() : array { $this->__toString(); return ['value']; } public function jsonSerialize() : string { return $this->__toString(); } private function __construct() { } private static function getPrettyName(callable $callback) : string { if (\is_string($callback)) { return $callback; } if (\is_array($callback)) { $class = \is_object($callback[0]) ? \get_debug_type($callback[0]) : $callback[0]; $method = $callback[1]; } elseif ($callback instanceof \Closure) { $r = new \ReflectionFunction($callback); if (\str_contains($r->name, '{closure') || !($class = \PHP_VERSION_ID >= 80111 ? $r->getClosureCalledClass() : $r->getClosureScopeClass())) { return $r->name; } $class = $class->name; $method = $r->name; } else { $class = \get_debug_type($callback); $method = '__invoke'; } return $class . '::' . $method; } } LICENSE 0000777 00000023675 15251261610 0005574 0 ustar 00 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS CodePointString.php 0000777 00000017604 15251261610 0010346 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Rvx\Symfony\Component\String; use Rvx\Symfony\Component\String\Exception\ExceptionInterface; use Rvx\Symfony\Component\String\Exception\InvalidArgumentException; /** * Represents a string of Unicode code points encoded as UTF-8. * * @author Nicolas Grekas <p@tchwork.com> * @author Hugo Hamon <hugohamon@neuf.fr> * * @throws ExceptionInterface */ class CodePointString extends AbstractUnicodeString { public function __construct(string $string = '') { if ('' !== $string && !\preg_match('//u', $string)) { throw new InvalidArgumentException('Invalid UTF-8 string.'); } $this->string = $string; } public function append(string ...$suffix) : AbstractString { $str = clone $this; $str->string .= 1 >= \count($suffix) ? $suffix[0] ?? '' : \implode('', $suffix); if (!\preg_match('//u', $str->string)) { throw new InvalidArgumentException('Invalid UTF-8 string.'); } return $str; } public function chunk(int $length = 1) : array { if (1 > $length) { throw new InvalidArgumentException('The chunk length must be greater than zero.'); } if ('' === $this->string) { return []; } $rx = '/('; while (65535 < $length) { $rx .= '.{65535}'; $length -= 65535; } $rx .= '.{' . $length . '})/us'; $str = clone $this; $chunks = []; foreach (\preg_split($rx, $this->string, -1, \PREG_SPLIT_DELIM_CAPTURE | \PREG_SPLIT_NO_EMPTY) as $chunk) { $str->string = $chunk; $chunks[] = clone $str; } return $chunks; } public function codePointsAt(int $offset) : array { $str = $offset ? $this->slice($offset, 1) : $this; return '' === $str->string ? [] : [\mb_ord($str->string, 'UTF-8')]; } public function endsWith($suffix) : bool { if ($suffix instanceof AbstractString) { $suffix = $suffix->string; } elseif (\is_array($suffix) || $suffix instanceof \Traversable) { return parent::endsWith($suffix); } else { $suffix = (string) $suffix; } if ('' === $suffix || !\preg_match('//u', $suffix)) { return \false; } if ($this->ignoreCase) { return \preg_match('{' . \preg_quote($suffix) . '$}iuD', $this->string); } return \strlen($this->string) >= \strlen($suffix) && 0 === \substr_compare($this->string, $suffix, -\strlen($suffix)); } public function equalsTo($string) : bool { if ($string instanceof AbstractString) { $string = $string->string; } elseif (\is_array($string) || $string instanceof \Traversable) { return parent::equalsTo($string); } else { $string = (string) $string; } if ('' !== $string && $this->ignoreCase) { return \strlen($string) === \strlen($this->string) && 0 === \mb_stripos($this->string, $string, 0, 'UTF-8'); } return $string === $this->string; } public function indexOf($needle, int $offset = 0) : ?int { if ($needle instanceof AbstractString) { $needle = $needle->string; } elseif (\is_array($needle) || $needle instanceof \Traversable) { return parent::indexOf($needle, $offset); } else { $needle = (string) $needle; } if ('' === $needle) { return null; } $i = $this->ignoreCase ? \mb_stripos($this->string, $needle, $offset, 'UTF-8') : \mb_strpos($this->string, $needle, $offset, 'UTF-8'); return \false === $i ? null : $i; } public function indexOfLast($needle, int $offset = 0) : ?int { if ($needle instanceof AbstractString) { $needle = $needle->string; } elseif (\is_array($needle) || $needle instanceof \Traversable) { return parent::indexOfLast($needle, $offset); } else { $needle = (string) $needle; } if ('' === $needle) { return null; } $i = $this->ignoreCase ? \mb_strripos($this->string, $needle, $offset, 'UTF-8') : \mb_strrpos($this->string, $needle, $offset, 'UTF-8'); return \false === $i ? null : $i; } public function length() : int { return \mb_strlen($this->string, 'UTF-8'); } public function prepend(string ...$prefix) : AbstractString { $str = clone $this; $str->string = (1 >= \count($prefix) ? $prefix[0] ?? '' : \implode('', $prefix)) . $this->string; if (!\preg_match('//u', $str->string)) { throw new InvalidArgumentException('Invalid UTF-8 string.'); } return $str; } public function replace(string $from, string $to) : AbstractString { $str = clone $this; if ('' === $from || !\preg_match('//u', $from)) { return $str; } if ('' !== $to && !\preg_match('//u', $to)) { throw new InvalidArgumentException('Invalid UTF-8 string.'); } if ($this->ignoreCase) { $str->string = \implode($to, \preg_split('{' . \preg_quote($from) . '}iuD', $this->string)); } else { $str->string = \str_replace($from, $to, $this->string); } return $str; } public function slice(int $start = 0, ?int $length = null) : AbstractString { $str = clone $this; $str->string = \mb_substr($this->string, $start, $length, 'UTF-8'); return $str; } public function splice(string $replacement, int $start = 0, ?int $length = null) : AbstractString { if (!\preg_match('//u', $replacement)) { throw new InvalidArgumentException('Invalid UTF-8 string.'); } $str = clone $this; $start = $start ? \strlen(\mb_substr($this->string, 0, $start, 'UTF-8')) : 0; $length = $length ? \strlen(\mb_substr($this->string, $start, $length, 'UTF-8')) : $length; $str->string = \substr_replace($this->string, $replacement, $start, $length ?? \PHP_INT_MAX); return $str; } public function split(string $delimiter, ?int $limit = null, ?int $flags = null) : array { if (1 > ($limit = $limit ?? \PHP_INT_MAX)) { throw new InvalidArgumentException('Split limit must be a positive integer.'); } if ('' === $delimiter) { throw new InvalidArgumentException('Split delimiter is empty.'); } if (null !== $flags) { return parent::split($delimiter . 'u', $limit, $flags); } if (!\preg_match('//u', $delimiter)) { throw new InvalidArgumentException('Split delimiter is not a valid UTF-8 string.'); } $str = clone $this; $chunks = $this->ignoreCase ? \preg_split('{' . \preg_quote($delimiter) . '}iuD', $this->string, $limit) : \explode($delimiter, $this->string, $limit); foreach ($chunks as &$chunk) { $str->string = $chunk; $chunk = clone $str; } return $chunks; } public function startsWith($prefix) : bool { if ($prefix instanceof AbstractString) { $prefix = $prefix->string; } elseif (\is_array($prefix) || $prefix instanceof \Traversable) { return parent::startsWith($prefix); } else { $prefix = (string) $prefix; } if ('' === $prefix || !\preg_match('//u', $prefix)) { return \false; } if ($this->ignoreCase) { return 0 === \mb_stripos($this->string, $prefix, 0, 'UTF-8'); } return 0 === \strncmp($this->string, $prefix, \strlen($prefix)); } } UnicodeString.php 0000777 00000031243 15251261610 0010043 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Rvx\Symfony\Component\String; use Rvx\Symfony\Component\String\Exception\ExceptionInterface; use Rvx\Symfony\Component\String\Exception\InvalidArgumentException; /** * Represents a string of Unicode grapheme clusters encoded as UTF-8. * * A letter followed by combining characters (accents typically) form what Unicode defines * as a grapheme cluster: a character as humans mean it in written texts. This class knows * about the concept and won't split a letter apart from its combining accents. It also * ensures all string comparisons happen on their canonically-composed representation, * ignoring e.g. the order in which accents are listed when a letter has many of them. * * @see https://unicode.org/reports/tr15/ * * @author Nicolas Grekas <p@tchwork.com> * @author Hugo Hamon <hugohamon@neuf.fr> * * @throws ExceptionInterface */ class UnicodeString extends AbstractUnicodeString { public function __construct(string $string = '') { $this->string = \normalizer_is_normalized($string) ? $string : \normalizer_normalize($string); if (\false === $this->string) { throw new InvalidArgumentException('Invalid UTF-8 string.'); } } public function append(string ...$suffix) : AbstractString { $str = clone $this; $str->string = $this->string . (1 >= \count($suffix) ? $suffix[0] ?? '' : \implode('', $suffix)); \normalizer_is_normalized($str->string) ?: ($str->string = \normalizer_normalize($str->string)); if (\false === $str->string) { throw new InvalidArgumentException('Invalid UTF-8 string.'); } return $str; } public function chunk(int $length = 1) : array { if (1 > $length) { throw new InvalidArgumentException('The chunk length must be greater than zero.'); } if ('' === $this->string) { return []; } $rx = '/('; while (65535 < $length) { $rx .= '\\X{65535}'; $length -= 65535; } $rx .= '\\X{' . $length . '})/u'; $str = clone $this; $chunks = []; foreach (\preg_split($rx, $this->string, -1, \PREG_SPLIT_DELIM_CAPTURE | \PREG_SPLIT_NO_EMPTY) as $chunk) { $str->string = $chunk; $chunks[] = clone $str; } return $chunks; } public function endsWith($suffix) : bool { if ($suffix instanceof AbstractString) { $suffix = $suffix->string; } elseif (\is_array($suffix) || $suffix instanceof \Traversable) { return parent::endsWith($suffix); } else { $suffix = (string) $suffix; } $form = null === $this->ignoreCase ? \Normalizer::NFD : \Normalizer::NFC; \normalizer_is_normalized($suffix, $form) ?: ($suffix = \normalizer_normalize($suffix, $form)); if ('' === $suffix || \false === $suffix) { return \false; } if ($this->ignoreCase) { return 0 === \mb_stripos(\grapheme_extract($this->string, \strlen($suffix), \GRAPHEME_EXTR_MAXBYTES, \strlen($this->string) - \strlen($suffix)), $suffix, 0, 'UTF-8'); } return $suffix === \grapheme_extract($this->string, \strlen($suffix), \GRAPHEME_EXTR_MAXBYTES, \strlen($this->string) - \strlen($suffix)); } public function equalsTo($string) : bool { if ($string instanceof AbstractString) { $string = $string->string; } elseif (\is_array($string) || $string instanceof \Traversable) { return parent::equalsTo($string); } else { $string = (string) $string; } $form = null === $this->ignoreCase ? \Normalizer::NFD : \Normalizer::NFC; \normalizer_is_normalized($string, $form) ?: ($string = \normalizer_normalize($string, $form)); if ('' !== $string && \false !== $string && $this->ignoreCase) { return \strlen($string) === \strlen($this->string) && 0 === \mb_stripos($this->string, $string, 0, 'UTF-8'); } return $string === $this->string; } public function indexOf($needle, int $offset = 0) : ?int { if ($needle instanceof AbstractString) { $needle = $needle->string; } elseif (\is_array($needle) || $needle instanceof \Traversable) { return parent::indexOf($needle, $offset); } else { $needle = (string) $needle; } $form = null === $this->ignoreCase ? \Normalizer::NFD : \Normalizer::NFC; \normalizer_is_normalized($needle, $form) ?: ($needle = \normalizer_normalize($needle, $form)); if ('' === $needle || \false === $needle) { return null; } try { $i = $this->ignoreCase ? \grapheme_stripos($this->string, $needle, $offset) : \grapheme_strpos($this->string, $needle, $offset); } catch (\ValueError $e) { return null; } return \false === $i ? null : $i; } public function indexOfLast($needle, int $offset = 0) : ?int { if ($needle instanceof AbstractString) { $needle = $needle->string; } elseif (\is_array($needle) || $needle instanceof \Traversable) { return parent::indexOfLast($needle, $offset); } else { $needle = (string) $needle; } $form = null === $this->ignoreCase ? \Normalizer::NFD : \Normalizer::NFC; \normalizer_is_normalized($needle, $form) ?: ($needle = \normalizer_normalize($needle, $form)); if ('' === $needle || \false === $needle) { return null; } $string = $this->string; if (0 > $offset) { // workaround https://bugs.php.net/74264 if (0 > ($offset += \grapheme_strlen($needle))) { $string = \grapheme_substr($string, 0, $offset); } $offset = 0; } $i = $this->ignoreCase ? \grapheme_strripos($string, $needle, $offset) : \grapheme_strrpos($string, $needle, $offset); return \false === $i ? null : $i; } public function join(array $strings, ?string $lastGlue = null) : AbstractString { $str = parent::join($strings, $lastGlue); \normalizer_is_normalized($str->string) ?: ($str->string = \normalizer_normalize($str->string)); return $str; } public function length() : int { return \grapheme_strlen($this->string); } /** * @return static */ public function normalize(int $form = self::NFC) : parent { $str = clone $this; if (\in_array($form, [self::NFC, self::NFKC], \true)) { \normalizer_is_normalized($str->string, $form) ?: ($str->string = \normalizer_normalize($str->string, $form)); } elseif (!\in_array($form, [self::NFD, self::NFKD], \true)) { throw new InvalidArgumentException('Unsupported normalization form.'); } elseif (!\normalizer_is_normalized($str->string, $form)) { $str->string = \normalizer_normalize($str->string, $form); $str->ignoreCase = null; } return $str; } public function prepend(string ...$prefix) : AbstractString { $str = clone $this; $str->string = (1 >= \count($prefix) ? $prefix[0] ?? '' : \implode('', $prefix)) . $this->string; \normalizer_is_normalized($str->string) ?: ($str->string = \normalizer_normalize($str->string)); if (\false === $str->string) { throw new InvalidArgumentException('Invalid UTF-8 string.'); } return $str; } public function replace(string $from, string $to) : AbstractString { $str = clone $this; \normalizer_is_normalized($from) ?: ($from = \normalizer_normalize($from)); if ('' !== $from && \false !== $from) { $tail = $str->string; $result = ''; $indexOf = $this->ignoreCase ? 'grapheme_stripos' : 'grapheme_strpos'; while ('' !== $tail && \false !== ($i = $indexOf($tail, $from))) { $slice = \grapheme_substr($tail, 0, $i); $result .= $slice . $to; $tail = \substr($tail, \strlen($slice) + \strlen($from)); } $str->string = $result . $tail; \normalizer_is_normalized($str->string) ?: ($str->string = \normalizer_normalize($str->string)); if (\false === $str->string) { throw new InvalidArgumentException('Invalid UTF-8 string.'); } } return $str; } public function replaceMatches(string $fromRegexp, $to) : AbstractString { $str = parent::replaceMatches($fromRegexp, $to); \normalizer_is_normalized($str->string) ?: ($str->string = \normalizer_normalize($str->string)); return $str; } public function slice(int $start = 0, ?int $length = null) : AbstractString { $str = clone $this; if (\PHP_VERSION_ID < 80000 && 0 > $start && \grapheme_strlen($this->string) < -$start) { $start = 0; } $str->string = (string) \grapheme_substr($this->string, $start, $length ?? 2147483647); return $str; } public function splice(string $replacement, int $start = 0, ?int $length = null) : AbstractString { $str = clone $this; if (\PHP_VERSION_ID < 80000 && 0 > $start && \grapheme_strlen($this->string) < -$start) { $start = 0; } $start = $start ? \strlen(\grapheme_substr($this->string, 0, $start)) : 0; $length = $length ? \strlen(\grapheme_substr($this->string, $start, $length ?? 2147483647)) : $length; $str->string = \substr_replace($this->string, $replacement, $start, $length ?? 2147483647); \normalizer_is_normalized($str->string) ?: ($str->string = \normalizer_normalize($str->string)); if (\false === $str->string) { throw new InvalidArgumentException('Invalid UTF-8 string.'); } return $str; } public function split(string $delimiter, ?int $limit = null, ?int $flags = null) : array { if (1 > ($limit = $limit ?? 2147483647)) { throw new InvalidArgumentException('Split limit must be a positive integer.'); } if ('' === $delimiter) { throw new InvalidArgumentException('Split delimiter is empty.'); } if (null !== $flags) { return parent::split($delimiter . 'u', $limit, $flags); } \normalizer_is_normalized($delimiter) ?: ($delimiter = \normalizer_normalize($delimiter)); if (\false === $delimiter) { throw new InvalidArgumentException('Split delimiter is not a valid UTF-8 string.'); } $str = clone $this; $tail = $this->string; $chunks = []; $indexOf = $this->ignoreCase ? 'grapheme_stripos' : 'grapheme_strpos'; while (1 < $limit && \false !== ($i = $indexOf($tail, $delimiter))) { $str->string = \grapheme_substr($tail, 0, $i); $chunks[] = clone $str; $tail = \substr($tail, \strlen($str->string) + \strlen($delimiter)); --$limit; } $str->string = $tail; $chunks[] = clone $str; return $chunks; } public function startsWith($prefix) : bool { if ($prefix instanceof AbstractString) { $prefix = $prefix->string; } elseif (\is_array($prefix) || $prefix instanceof \Traversable) { return parent::startsWith($prefix); } else { $prefix = (string) $prefix; } $form = null === $this->ignoreCase ? \Normalizer::NFD : \Normalizer::NFC; \normalizer_is_normalized($prefix, $form) ?: ($prefix = \normalizer_normalize($prefix, $form)); if ('' === $prefix || \false === $prefix) { return \false; } if ($this->ignoreCase) { return 0 === \mb_stripos(\grapheme_extract($this->string, \strlen($prefix), \GRAPHEME_EXTR_MAXBYTES), $prefix, 0, 'UTF-8'); } return $prefix === \grapheme_extract($this->string, \strlen($prefix), \GRAPHEME_EXTR_MAXBYTES); } public function __wakeup() { if (!\is_string($this->string)) { throw new \BadMethodCallException('Cannot unserialize ' . __CLASS__); } \normalizer_is_normalized($this->string) ?: ($this->string = \normalizer_normalize($this->string)); } public function __clone() { if (null === $this->ignoreCase) { \normalizer_is_normalized($this->string) ?: ($this->string = \normalizer_normalize($this->string)); } $this->ignoreCase = \false; } } Inflector/EnglishInflector.php 0000777 00000041374 15251261610 0012460 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Rvx\Symfony\Component\String\Inflector; final class EnglishInflector implements InflectorInterface { /** * Map English plural to singular suffixes. * * @see http://english-zone.com/spelling/plurals.html */ private const PLURAL_MAP = [ // First entry: plural suffix, reversed // Second entry: length of plural suffix // Third entry: Whether the suffix may succeed a vowel // Fourth entry: Whether the suffix may succeed a consonant // Fifth entry: singular suffix, normal // bacteria (bacterium) ['airetcab', 8, \true, \true, 'bacterium'], // corpora (corpus) ['aroproc', 7, \true, \true, 'corpus'], // criteria (criterion) ['airetirc', 8, \true, \true, 'criterion'], // curricula (curriculum) ['alucirruc', 9, \true, \true, 'curriculum'], // genera (genus) ['areneg', 6, \true, \true, 'genus'], // media (medium) ['aidem', 5, \true, \true, 'medium'], // memoranda (memorandum) ['adnaromem', 9, \true, \true, 'memorandum'], // phenomena (phenomenon) ['anemonehp', 9, \true, \true, 'phenomenon'], // strata (stratum) ['atarts', 6, \true, \true, 'stratum'], // nebulae (nebula) ['ea', 2, \true, \true, 'a'], // services (service) ['secivres', 8, \true, \true, 'service'], // mice (mouse), lice (louse) ['eci', 3, \false, \true, 'ouse'], // geese (goose) ['esee', 4, \false, \true, 'oose'], // fungi (fungus), alumni (alumnus), syllabi (syllabus), radii (radius) ['i', 1, \true, \true, 'us'], // men (man), women (woman) ['nem', 3, \true, \true, 'man'], // children (child) ['nerdlihc', 8, \true, \true, 'child'], // oxen (ox) ['nexo', 4, \false, \false, 'ox'], // indices (index), appendices (appendix), prices (price) ['seci', 4, \false, \true, ['ex', 'ix', 'ice']], // codes (code) ['sedoc', 5, \false, \true, 'code'], // selfies (selfie) ['seifles', 7, \true, \true, 'selfie'], // zombies (zombie) ['seibmoz', 7, \true, \true, 'zombie'], // movies (movie) ['seivom', 6, \true, \true, 'movie'], // names (name) ['seman', 5, \true, \false, 'name'], // conspectuses (conspectus), prospectuses (prospectus) ['sesutcep', 8, \true, \true, 'pectus'], // feet (foot) ['teef', 4, \true, \true, 'foot'], // geese (goose) ['eseeg', 5, \true, \true, 'goose'], // teeth (tooth) ['hteet', 5, \true, \true, 'tooth'], // news (news) ['swen', 4, \true, \true, 'news'], // series (series) ['seires', 6, \true, \true, 'series'], // babies (baby) ['sei', 3, \false, \true, 'y'], // accesses (access), addresses (address), kisses (kiss) ['sess', 4, \true, \false, 'ss'], // statuses (status) ['sesutats', 8, \true, \true, 'status'], // article (articles), ancle (ancles) ['sel', 3, \true, \true, 'le'], // analyses (analysis), ellipses (ellipsis), fungi (fungus), // neuroses (neurosis), theses (thesis), emphases (emphasis), // oases (oasis), crises (crisis), houses (house), bases (base), // atlases (atlas) ['ses', 3, \true, \true, ['s', 'se', 'sis']], // objectives (objective), alternative (alternatives) ['sevit', 5, \true, \true, 'tive'], // drives (drive) ['sevird', 6, \false, \true, 'drive'], // lives (life), wives (wife) ['sevi', 4, \false, \true, 'ife'], // moves (move) ['sevom', 5, \true, \true, 'move'], // hooves (hoof), dwarves (dwarf), elves (elf), leaves (leaf), caves (cave), staves (staff) ['sev', 3, \true, \true, ['f', 've', 'ff']], // axes (axis), axes (ax), axes (axe) ['sexa', 4, \false, \false, ['ax', 'axe', 'axis']], // indexes (index), matrixes (matrix) ['sex', 3, \true, \false, 'x'], // quizzes (quiz) ['sezz', 4, \true, \false, 'z'], // bureaus (bureau) ['suae', 4, \false, \true, 'eau'], // fees (fee), trees (tree), employees (employee) ['see', 3, \true, \true, 'ee'], // edges (edge) ['segd', 4, \true, \true, 'dge'], // roses (rose), garages (garage), cassettes (cassette), // waltzes (waltz), heroes (hero), bushes (bush), arches (arch), // shoes (shoe) ['se', 2, \true, \true, ['', 'e']], // status (status) ['sutats', 6, \true, \true, 'status'], // tags (tag) ['s', 1, \true, \true, ''], // chateaux (chateau) ['xuae', 4, \false, \true, 'eau'], // people (person) ['elpoep', 6, \true, \true, 'person'], ]; /** * Map English singular to plural suffixes. * * @see http://english-zone.com/spelling/plurals.html */ private const SINGULAR_MAP = [ // First entry: singular suffix, reversed // Second entry: length of singular suffix // Third entry: Whether the suffix may succeed a vowel // Fourth entry: Whether the suffix may succeed a consonant // Fifth entry: plural suffix, normal // axes (axis) ['sixa', 4, \false, \false, 'axes'], // criterion (criteria) ['airetirc', 8, \false, \false, 'criterion'], // nebulae (nebula) ['aluben', 6, \false, \false, 'nebulae'], // children (child) ['dlihc', 5, \true, \true, 'children'], // prices (price) ['eci', 3, \false, \true, 'ices'], // services (service) ['ecivres', 7, \true, \true, 'services'], // lives (life), wives (wife) ['efi', 3, \false, \true, 'ives'], // selfies (selfie) ['eifles', 6, \true, \true, 'selfies'], // movies (movie) ['eivom', 5, \true, \true, 'movies'], // lice (louse) ['esuol', 5, \false, \true, 'lice'], // mice (mouse) ['esuom', 5, \false, \true, 'mice'], // geese (goose) ['esoo', 4, \false, \true, 'eese'], // houses (house), bases (base) ['es', 2, \true, \true, 'ses'], // geese (goose) ['esoog', 5, \true, \true, 'geese'], // caves (cave) ['ev', 2, \true, \true, 'ves'], // drives (drive) ['evird', 5, \false, \true, 'drives'], // objectives (objective), alternative (alternatives) ['evit', 4, \true, \true, 'tives'], // moves (move) ['evom', 4, \true, \true, 'moves'], // staves (staff) ['ffats', 5, \true, \true, 'staves'], // hooves (hoof), dwarves (dwarf), elves (elf), leaves (leaf) ['ff', 2, \true, \true, 'ffs'], // hooves (hoof), dwarves (dwarf), elves (elf), leaves (leaf) ['f', 1, \true, \true, ['fs', 'ves']], // arches (arch) ['hc', 2, \true, \true, 'ches'], // bushes (bush) ['hs', 2, \true, \true, 'shes'], // teeth (tooth) ['htoot', 5, \true, \true, 'teeth'], // albums (album) ['mubla', 5, \true, \true, 'albums'], // bacteria (bacterium), curricula (curriculum), media (medium), memoranda (memorandum), phenomena (phenomenon), strata (stratum) ['mu', 2, \true, \true, 'a'], // men (man), women (woman) ['nam', 3, \true, \true, 'men'], // people (person) ['nosrep', 6, \true, \true, ['persons', 'people']], // criteria (criterion) ['noiretirc', 9, \true, \true, 'criteria'], // phenomena (phenomenon) ['nonemonehp', 10, \true, \true, 'phenomena'], // echoes (echo) ['ohce', 4, \true, \true, 'echoes'], // heroes (hero) ['oreh', 4, \true, \true, 'heroes'], // atlases (atlas) ['salta', 5, \true, \true, 'atlases'], // aliases (alias) ['saila', 5, \true, \true, 'aliases'], // irises (iris) ['siri', 4, \true, \true, 'irises'], // analyses (analysis), ellipses (ellipsis), neuroses (neurosis) // theses (thesis), emphases (emphasis), oases (oasis), // crises (crisis) ['sis', 3, \true, \true, 'ses'], // accesses (access), addresses (address), kisses (kiss) ['ss', 2, \true, \false, 'sses'], // syllabi (syllabus) ['suballys', 8, \true, \true, 'syllabi'], // buses (bus) ['sub', 3, \true, \true, 'buses'], // circuses (circus) ['suc', 3, \true, \true, 'cuses'], // hippocampi (hippocampus) ['supmacoppih', 11, \false, \false, 'hippocampi'], // campuses (campus) ['sup', 3, \true, \true, 'puses'], // status (status) ['sutats', 6, \true, \true, ['status', 'statuses']], // conspectuses (conspectus), prospectuses (prospectus) ['sutcep', 6, \true, \true, 'pectuses'], // fungi (fungus), alumni (alumnus), syllabi (syllabus), radii (radius) ['su', 2, \true, \true, 'i'], // news (news) ['swen', 4, \true, \true, 'news'], // feet (foot) ['toof', 4, \true, \true, 'feet'], // chateaux (chateau), bureaus (bureau) ['uae', 3, \false, \true, ['eaus', 'eaux']], // oxen (ox) ['xo', 2, \false, \false, 'oxen'], // hoaxes (hoax) ['xaoh', 4, \true, \false, 'hoaxes'], // indices (index) ['xedni', 5, \false, \true, ['indicies', 'indexes']], // fax (faxes, faxxes) ['xaf', 3, \true, \true, ['faxes', 'faxxes']], // boxes (box) ['xo', 2, \false, \true, 'oxes'], // indexes (index), matrixes (matrix), appendices (appendix) ['x', 1, \true, \false, ['ces', 'xes']], // babies (baby) ['y', 1, \false, \true, 'ies'], // quizzes (quiz) ['ziuq', 4, \true, \false, 'quizzes'], // waltzes (waltz) ['z', 1, \true, \true, 'zes'], ]; /** * A list of words which should not be inflected, reversed. */ private const UNINFLECTED = [ '', // data 'atad', // deer 'reed', // equipment 'tnempiuqe', // feedback 'kcabdeef', // fish 'hsif', // health 'htlaeh', // history 'yrotsih', // info 'ofni', // information 'noitamrofni', // money 'yenom', // moose 'esoom', // series 'seires', // sheep 'peehs', // species 'seiceps', // traffic 'ciffart', // aircraft 'tfarcria', // hardware 'erawdrah', ]; public function singularize(string $plural) : array { $pluralRev = \strrev($plural); $lowerPluralRev = \strtolower($pluralRev); $pluralLength = \strlen($lowerPluralRev); // Check if the word is one which is not inflected, return early if so if (\in_array($lowerPluralRev, self::UNINFLECTED, \true)) { return [$plural]; } // The outer loop iterates over the entries of the plural table // The inner loop $j iterates over the characters of the plural suffix // in the plural table to compare them with the characters of the actual // given plural suffix foreach (self::PLURAL_MAP as $map) { $suffix = $map[0]; $suffixLength = $map[1]; $j = 0; // Compare characters in the plural table and of the suffix of the // given plural one by one while ($suffix[$j] === $lowerPluralRev[$j]) { // Let $j point to the next character ++$j; // Successfully compared the last character // Add an entry with the singular suffix to the singular array if ($j === $suffixLength) { // Is there any character preceding the suffix in the plural string? if ($j < $pluralLength) { $nextIsVowel = \str_contains('aeiou', $lowerPluralRev[$j]); if (!$map[2] && $nextIsVowel) { // suffix may not succeed a vowel but next char is one break; } if (!$map[3] && !$nextIsVowel) { // suffix may not succeed a consonant but next char is one break; } } $newBase = \substr($plural, 0, $pluralLength - $suffixLength); $newSuffix = $map[4]; // Check whether the first character in the plural suffix // is uppercased. If yes, uppercase the first character in // the singular suffix too $firstUpper = \ctype_upper($pluralRev[$j - 1]); if (\is_array($newSuffix)) { $singulars = []; foreach ($newSuffix as $newSuffixEntry) { $singulars[] = $newBase . ($firstUpper ? \ucfirst($newSuffixEntry) : $newSuffixEntry); } return $singulars; } return [$newBase . ($firstUpper ? \ucfirst($newSuffix) : $newSuffix)]; } // Suffix is longer than word if ($j === $pluralLength) { break; } } } // Assume that plural and singular is identical return [$plural]; } public function pluralize(string $singular) : array { $singularRev = \strrev($singular); $lowerSingularRev = \strtolower($singularRev); $singularLength = \strlen($lowerSingularRev); // Check if the word is one which is not inflected, return early if so if (\in_array($lowerSingularRev, self::UNINFLECTED, \true)) { return [$singular]; } // The outer loop iterates over the entries of the singular table // The inner loop $j iterates over the characters of the singular suffix // in the singular table to compare them with the characters of the actual // given singular suffix foreach (self::SINGULAR_MAP as $map) { $suffix = $map[0]; $suffixLength = $map[1]; $j = 0; // Compare characters in the singular table and of the suffix of the // given plural one by one while ($suffix[$j] === $lowerSingularRev[$j]) { // Let $j point to the next character ++$j; // Successfully compared the last character // Add an entry with the plural suffix to the plural array if ($j === $suffixLength) { // Is there any character preceding the suffix in the plural string? if ($j < $singularLength) { $nextIsVowel = \str_contains('aeiou', $lowerSingularRev[$j]); if (!$map[2] && $nextIsVowel) { // suffix may not succeed a vowel but next char is one break; } if (!$map[3] && !$nextIsVowel) { // suffix may not succeed a consonant but next char is one break; } } $newBase = \substr($singular, 0, $singularLength - $suffixLength); $newSuffix = $map[4]; // Check whether the first character in the singular suffix // is uppercased. If yes, uppercase the first character in // the singular suffix too $firstUpper = \ctype_upper($singularRev[$j - 1]); if (\is_array($newSuffix)) { $plurals = []; foreach ($newSuffix as $newSuffixEntry) { $plurals[] = $newBase . ($firstUpper ? \ucfirst($newSuffixEntry) : $newSuffixEntry); } return $plurals; } return [$newBase . ($firstUpper ? \ucfirst($newSuffix) : $newSuffix)]; } // Suffix is longer than word if ($j === $singularLength) { break; } } } // Assume that plural is singular with a trailing `s` return [$singular . 's']; } } Inflector/FrenchInflector.php 0000777 00000013673 15251261610 0012275 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Rvx\Symfony\Component\String\Inflector; /** * French inflector. * * This class does only inflect nouns; not adjectives nor composed words like "soixante-dix". */ final class FrenchInflector implements InflectorInterface { /** * A list of all rules for pluralise. * * @see https://la-conjugaison.nouvelobs.com/regles/grammaire/le-pluriel-des-noms-121.php */ private const PLURALIZE_REGEXP = [ // First entry: regexp // Second entry: replacement // Words finishing with "s", "x" or "z" are invariables // Les mots finissant par "s", "x" ou "z" sont invariables ['/(s|x|z)$/i', '\\1'], // Words finishing with "eau" are pluralized with a "x" // Les mots finissant par "eau" prennent tous un "x" au pluriel ['/(eau)$/i', '\\1x'], // Words finishing with "au" are pluralized with a "x" excepted "landau" // Les mots finissant par "au" prennent un "x" au pluriel sauf "landau" ['/^(landau)$/i', '\\1s'], ['/(au)$/i', '\\1x'], // Words finishing with "eu" are pluralized with a "x" excepted "pneu", "bleu", "émeu" // Les mots finissant en "eu" prennent un "x" au pluriel sauf "pneu", "bleu", "émeu" ['/^(pneu|bleu|émeu)$/i', '\\1s'], ['/(eu)$/i', '\\1x'], // Words finishing with "al" are pluralized with a "aux" excepted // Les mots finissant en "al" se terminent en "aux" sauf ['/^(bal|carnaval|caracal|chacal|choral|corral|étal|festival|récital|val)$/i', '\\1s'], ['/al$/i', '\\1aux'], // Aspirail, bail, corail, émail, fermail, soupirail, travail, vantail et vitrail font leur pluriel en -aux ['/^(aspir|b|cor|ém|ferm|soupir|trav|vant|vitr)ail$/i', '\\1aux'], // Bijou, caillou, chou, genou, hibou, joujou et pou qui prennent un x au pluriel ['/^(bij|caill|ch|gen|hib|jouj|p)ou$/i', '\\1oux'], // Invariable words ['/^(cinquante|soixante|mille)$/i', '\\1'], // French titles ['/^(mon|ma)(sieur|dame|demoiselle|seigneur)$/', 'Rvx\\mes\\2s'], ['/^(Mon|Ma)(sieur|dame|demoiselle|seigneur)$/', 'Rvx\\Mes\\2s'], ]; /** * A list of all rules for singularize. */ private const SINGULARIZE_REGEXP = [ // First entry: regexp // Second entry: replacement // Aspirail, bail, corail, émail, fermail, soupirail, travail, vantail et vitrail font leur pluriel en -aux ['/((aspir|b|cor|ém|ferm|soupir|trav|vant|vitr))aux$/i', '\\1ail'], // Words finishing with "eau" are pluralized with a "x" // Les mots finissant par "eau" prennent tous un "x" au pluriel ['/(eau)x$/i', '\\1'], // Words finishing with "al" are pluralized with a "aux" expected // Les mots finissant en "al" se terminent en "aux" sauf ['/(amir|anim|arsen|boc|can|capit|capor|chev|crist|génér|hopit|hôpit|idé|journ|littor|loc|m|mét|minér|princip|radic|termin)aux$/i', '\\1al'], // Words finishing with "au" are pluralized with a "x" excepted "landau" // Les mots finissant par "au" prennent un "x" au pluriel sauf "landau" ['/(au)x$/i', '\\1'], // Words finishing with "eu" are pluralized with a "x" excepted "pneu", "bleu", "émeu" // Les mots finissant en "eu" prennent un "x" au pluriel sauf "pneu", "bleu", "émeu" ['/(eu)x$/i', '\\1'], // Words finishing with "ou" are pluralized with a "s" excepted bijou, caillou, chou, genou, hibou, joujou, pou // Les mots finissant par "ou" prennent un "s" sauf bijou, caillou, chou, genou, hibou, joujou, pou ['/(bij|caill|ch|gen|hib|jouj|p)oux$/i', '\\1ou'], // French titles ['/^mes(dame|demoiselle)s$/', 'Rvx\\ma\\1'], ['/^Mes(dame|demoiselle)s$/', 'Rvx\\Ma\\1'], ['/^mes(sieur|seigneur)s$/', 'Rvx\\mon\\1'], ['/^Mes(sieur|seigneur)s$/', 'Rvx\\Mon\\1'], // Default rule ['/s$/i', ''], ]; /** * A list of words which should not be inflected. * This list is only used by singularize. */ private const UNINFLECTED = '/^(abcès|accès|abus|albatros|anchois|anglais|autobus|bois|brebis|carquois|cas|chas|colis|concours|corps|cours|cyprès|décès|devis|discours|dos|embarras|engrais|entrelacs|excès|fils|fois|gâchis|gars|glas|héros|intrus|jars|jus|kermès|lacis|legs|lilas|marais|mars|matelas|mépris|mets|mois|mors|obus|os|palais|paradis|parcours|pardessus|pays|plusieurs|poids|pois|pouls|printemps|processus|progrès|puits|pus|rabais|radis|recors|recours|refus|relais|remords|remous|rictus|rhinocéros|repas|rubis|sans|sas|secours|sens|souris|succès|talus|tapis|tas|taudis|temps|tiers|univers|velours|verglas|vernis|virus)$/i'; /** * {@inheritdoc} */ public function singularize(string $plural) : array { if ($this->isInflectedWord($plural)) { return [$plural]; } foreach (self::SINGULARIZE_REGEXP as $rule) { [$regexp, $replace] = $rule; if (1 === \preg_match($regexp, $plural)) { return [\preg_replace($regexp, $replace, $plural)]; } } return [$plural]; } /** * {@inheritdoc} */ public function pluralize(string $singular) : array { if ($this->isInflectedWord($singular)) { return [$singular]; } foreach (self::PLURALIZE_REGEXP as $rule) { [$regexp, $replace] = $rule; if (1 === \preg_match($regexp, $singular)) { return [\preg_replace($regexp, $replace, $singular)]; } } return [$singular . 's']; } private function isInflectedWord(string $word) : bool { return 1 === \preg_match(self::UNINFLECTED, $word); } } Inflector/InflectorInterface.php 0000777 00000001507 15251261610 0012761 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Rvx\Symfony\Component\String\Inflector; interface InflectorInterface { /** * Returns the singular forms of a string. * * If the method can't determine the form with certainty, several possible singulars are returned. * * @return string[] */ public function singularize(string $plural) : array; /** * Returns the plural forms of a string. * * If the method can't determine the form with certainty, several possible plurals are returned. * * @return string[] */ public function pluralize(string $singular) : array; } AbstractUnicodeString.php 0000777 00000064421 15251261610 0011533 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Rvx\Symfony\Component\String; use Rvx\Symfony\Component\String\Exception\ExceptionInterface; use Rvx\Symfony\Component\String\Exception\InvalidArgumentException; use Rvx\Symfony\Component\String\Exception\RuntimeException; /** * Represents a string of abstract Unicode characters. * * Unicode defines 3 types of "characters" (bytes, code points and grapheme clusters). * This class is the abstract type to use as a type-hint when the logic you want to * implement is Unicode-aware but doesn't care about code points vs grapheme clusters. * * @author Nicolas Grekas <p@tchwork.com> * * @throws ExceptionInterface */ abstract class AbstractUnicodeString extends AbstractString { public const NFC = \Normalizer::NFC; public const NFD = \Normalizer::NFD; public const NFKC = \Normalizer::NFKC; public const NFKD = \Normalizer::NFKD; // all ASCII letters sorted by typical frequency of occurrence private const ASCII = " eiasntrolud][cmp'\ng|hv.fb,:=-q10C2*yx)(L9AS/P\"EjMIk3>5T<D4}B{8FwR67UGN;JzV#HOW_&!K?XQ%Y\\\tZ+~^\$@`\x00\x01\x02\x03\x04\x05\x06\x07\x08\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"; // the subset of folded case mappings that is not in lower case mappings private const FOLD_FROM = ['İ', 'µ', 'ſ', "ͅ", 'ς', 'ϐ', 'ϑ', 'ϕ', 'ϖ', 'ϰ', 'ϱ', 'ϵ', 'ẛ', "ι", 'ß', 'ʼn', 'ǰ', 'ΐ', 'ΰ', 'և', 'ẖ', 'ẗ', 'ẘ', 'ẙ', 'ẚ', 'ẞ', 'ὐ', 'ὒ', 'ὔ', 'ὖ', 'ᾀ', 'ᾁ', 'ᾂ', 'ᾃ', 'ᾄ', 'ᾅ', 'ᾆ', 'ᾇ', 'ᾈ', 'ᾉ', 'ᾊ', 'ᾋ', 'ᾌ', 'ᾍ', 'ᾎ', 'ᾏ', 'ᾐ', 'ᾑ', 'ᾒ', 'ᾓ', 'ᾔ', 'ᾕ', 'ᾖ', 'ᾗ', 'ᾘ', 'ᾙ', 'ᾚ', 'ᾛ', 'ᾜ', 'ᾝ', 'ᾞ', 'ᾟ', 'ᾠ', 'ᾡ', 'ᾢ', 'ᾣ', 'ᾤ', 'ᾥ', 'ᾦ', 'ᾧ', 'ᾨ', 'ᾩ', 'ᾪ', 'ᾫ', 'ᾬ', 'ᾭ', 'ᾮ', 'ᾯ', 'ᾲ', 'ᾳ', 'ᾴ', 'ᾶ', 'ᾷ', 'ᾼ', 'ῂ', 'ῃ', 'ῄ', 'ῆ', 'ῇ', 'ῌ', 'ῒ', 'ῖ', 'ῗ', 'ῢ', 'ῤ', 'ῦ', 'ῧ', 'ῲ', 'ῳ', 'ῴ', 'ῶ', 'ῷ', 'ῼ', 'ff', 'fi', 'fl', 'ffi', 'ffl', 'ſt', 'st', 'ﬓ', 'ﬔ', 'ﬕ', 'ﬖ', 'ﬗ']; private const FOLD_TO = ['i̇', 'μ', 's', 'ι', 'σ', 'β', 'θ', 'φ', 'π', 'κ', 'ρ', 'ε', 'ṡ', 'ι', 'ss', 'ʼn', 'ǰ', 'ΐ', 'ΰ', 'եւ', 'ẖ', 'ẗ', 'ẘ', 'ẙ', 'aʾ', 'ss', 'ὐ', 'ὒ', 'ὔ', 'ὖ', 'ἀι', 'ἁι', 'ἂι', 'ἃι', 'ἄι', 'ἅι', 'ἆι', 'ἇι', 'ἀι', 'ἁι', 'ἂι', 'ἃι', 'ἄι', 'ἅι', 'ἆι', 'ἇι', 'ἠι', 'ἡι', 'ἢι', 'ἣι', 'ἤι', 'ἥι', 'ἦι', 'ἧι', 'ἠι', 'ἡι', 'ἢι', 'ἣι', 'ἤι', 'ἥι', 'ἦι', 'ἧι', 'ὠι', 'ὡι', 'ὢι', 'ὣι', 'ὤι', 'ὥι', 'ὦι', 'ὧι', 'ὠι', 'ὡι', 'ὢι', 'ὣι', 'ὤι', 'ὥι', 'ὦι', 'ὧι', 'ὰι', 'αι', 'άι', 'ᾶ', 'ᾶι', 'αι', 'ὴι', 'ηι', 'ήι', 'ῆ', 'ῆι', 'ηι', 'ῒ', 'ῖ', 'ῗ', 'ῢ', 'ῤ', 'ῦ', 'ῧ', 'ὼι', 'ωι', 'ώι', 'ῶ', 'ῶι', 'ωι', 'ff', 'fi', 'fl', 'ffi', 'ffl', 'st', 'st', 'մն', 'մե', 'մի', 'վն', 'մխ']; // the subset of upper case mappings that map one code point to many code points private const UPPER_FROM = ['ß', 'ff', 'fi', 'fl', 'ffi', 'ffl', 'ſt', 'st', 'և', 'ﬓ', 'ﬔ', 'ﬕ', 'ﬖ', 'ﬗ', 'ʼn', 'ΐ', 'ΰ', 'ǰ', 'ẖ', 'ẗ', 'ẘ', 'ẙ', 'ẚ', 'ὐ', 'ὒ', 'ὔ', 'ὖ', 'ᾶ', 'ῆ', 'ῒ', 'ΐ', 'ῖ', 'ῗ', 'ῢ', 'ΰ', 'ῤ', 'ῦ', 'ῧ', 'ῶ']; private const UPPER_TO = ['SS', 'FF', 'FI', 'FL', 'FFI', 'FFL', 'ST', 'ST', 'ԵՒ', 'ՄՆ', 'ՄԵ', 'ՄԻ', 'ՎՆ', 'ՄԽ', 'ʼN', 'Ϊ́', 'Ϋ́', 'J̌', 'H̱', 'T̈', 'W̊', 'Y̊', 'Aʾ', 'Υ̓', 'Υ̓̀', 'Υ̓́', 'Υ̓͂', 'Α͂', 'Η͂', 'Ϊ̀', 'Ϊ́', 'Ι͂', 'Ϊ͂', 'Ϋ̀', 'Ϋ́', 'Ρ̓', 'Υ͂', 'Ϋ͂', 'Ω͂']; // the subset of https://github.com/unicode-org/cldr/blob/master/common/transforms/Latin-ASCII.xml that is not in NFKD private const TRANSLIT_FROM = ['Æ', 'Ð', 'Ø', 'Þ', 'ß', 'æ', 'ð', 'ø', 'þ', 'Đ', 'đ', 'Ħ', 'ħ', 'ı', 'ĸ', 'Ŀ', 'ŀ', 'Ł', 'ł', 'ʼn', 'Ŋ', 'ŋ', 'Œ', 'œ', 'Ŧ', 'ŧ', 'ƀ', 'Ɓ', 'Ƃ', 'ƃ', 'Ƈ', 'ƈ', 'Ɖ', 'Ɗ', 'Ƌ', 'ƌ', 'Ɛ', 'Ƒ', 'ƒ', 'Ɠ', 'ƕ', 'Ɩ', 'Ɨ', 'Ƙ', 'ƙ', 'ƚ', 'Ɲ', 'ƞ', 'Ƣ', 'ƣ', 'Ƥ', 'ƥ', 'ƫ', 'Ƭ', 'ƭ', 'Ʈ', 'Ʋ', 'Ƴ', 'ƴ', 'Ƶ', 'ƶ', 'DŽ', 'Dž', 'dž', 'Ǥ', 'ǥ', 'ȡ', 'Ȥ', 'ȥ', 'ȴ', 'ȵ', 'ȶ', 'ȷ', 'ȸ', 'ȹ', 'Ⱥ', 'Ȼ', 'ȼ', 'Ƚ', 'Ⱦ', 'ȿ', 'ɀ', 'Ƀ', 'Ʉ', 'Ɇ', 'ɇ', 'Ɉ', 'ɉ', 'Ɍ', 'ɍ', 'Ɏ', 'ɏ', 'ɓ', 'ɕ', 'ɖ', 'ɗ', 'ɛ', 'ɟ', 'ɠ', 'ɡ', 'ɢ', 'ɦ', 'ɧ', 'ɨ', 'ɪ', 'ɫ', 'ɬ', 'ɭ', 'ɱ', 'ɲ', 'ɳ', 'ɴ', 'ɶ', 'ɼ', 'ɽ', 'ɾ', 'ʀ', 'ʂ', 'ʈ', 'ʉ', 'ʋ', 'ʏ', 'ʐ', 'ʑ', 'ʙ', 'ʛ', 'ʜ', 'ʝ', 'ʟ', 'ʠ', 'ʣ', 'ʥ', 'ʦ', 'ʪ', 'ʫ', 'ᴀ', 'ᴁ', 'ᴃ', 'ᴄ', 'ᴅ', 'ᴆ', 'ᴇ', 'ᴊ', 'ᴋ', 'ᴌ', 'ᴍ', 'ᴏ', 'ᴘ', 'ᴛ', 'ᴜ', 'ᴠ', 'ᴡ', 'ᴢ', 'ᵫ', 'ᵬ', 'ᵭ', 'ᵮ', 'ᵯ', 'ᵰ', 'ᵱ', 'ᵲ', 'ᵳ', 'ᵴ', 'ᵵ', 'ᵶ', 'ᵺ', 'ᵻ', 'ᵽ', 'ᵾ', 'ᶀ', 'ᶁ', 'ᶂ', 'ᶃ', 'ᶄ', 'ᶅ', 'ᶆ', 'ᶇ', 'ᶈ', 'ᶉ', 'ᶊ', 'ᶌ', 'ᶍ', 'ᶎ', 'ᶏ', 'ᶑ', 'ᶒ', 'ᶓ', 'ᶖ', 'ᶙ', 'ẚ', 'ẜ', 'ẝ', 'ẞ', 'Ỻ', 'ỻ', 'Ỽ', 'ỽ', 'Ỿ', 'ỿ', '©', '®', '₠', '₢', '₣', '₤', '₧', '₺', '₹', 'ℌ', '℞', '㎧', '㎮', '㏆', '㏗', '㏞', '㏟', '¼', '½', '¾', '⅓', '⅔', '⅕', '⅖', '⅗', '⅘', '⅙', '⅚', '⅛', '⅜', '⅝', '⅞', '⅟', '〇', '‘', '’', '‚', '‛', '“', '”', '„', '‟', '′', '″', '〝', '〞', '«', '»', '‹', '›', '‐', '‑', '‒', '–', '—', '―', '︱', '︲', '﹘', '‖', '⁄', '⁅', '⁆', '⁎', '、', '。', '〈', '〉', '《', '》', '〔', '〕', '〘', '〙', '〚', '〛', '︑', '︒', '︹', '︺', '︽', '︾', '︿', '﹀', '﹑', '﹝', '﹞', '⦅', '⦆', '。', '、', '×', '÷', '−', '∕', '∖', '∣', '∥', '≪', '≫', '⦅', '⦆']; private const TRANSLIT_TO = ['AE', 'D', 'O', 'TH', 'ss', 'ae', 'd', 'o', 'th', 'D', 'd', 'H', 'h', 'i', 'q', 'L', 'l', 'L', 'l', '\'n', 'N', 'n', 'OE', 'oe', 'T', 't', 'b', 'B', 'B', 'b', 'C', 'c', 'D', 'D', 'D', 'd', 'E', 'F', 'f', 'G', 'hv', 'I', 'I', 'K', 'k', 'l', 'N', 'n', 'OI', 'oi', 'P', 'p', 't', 'T', 't', 'T', 'V', 'Y', 'y', 'Z', 'z', 'DZ', 'Dz', 'dz', 'G', 'g', 'd', 'Z', 'z', 'l', 'n', 't', 'j', 'db', 'qp', 'A', 'C', 'c', 'L', 'T', 's', 'z', 'B', 'U', 'E', 'e', 'J', 'j', 'R', 'r', 'Y', 'y', 'b', 'c', 'd', 'd', 'e', 'j', 'g', 'g', 'G', 'h', 'h', 'i', 'I', 'l', 'l', 'l', 'm', 'n', 'n', 'N', 'OE', 'r', 'r', 'r', 'R', 's', 't', 'u', 'v', 'Y', 'z', 'z', 'B', 'G', 'H', 'j', 'L', 'q', 'dz', 'dz', 'ts', 'ls', 'lz', 'A', 'AE', 'B', 'C', 'D', 'D', 'E', 'J', 'K', 'L', 'M', 'O', 'P', 'T', 'U', 'V', 'W', 'Z', 'ue', 'b', 'd', 'f', 'm', 'n', 'p', 'r', 'r', 's', 't', 'z', 'th', 'I', 'p', 'U', 'b', 'd', 'f', 'g', 'k', 'l', 'm', 'n', 'p', 'r', 's', 'v', 'x', 'z', 'a', 'd', 'e', 'e', 'i', 'u', 'a', 's', 's', 'SS', 'LL', 'll', 'V', 'v', 'Y', 'y', '(C)', '(R)', 'CE', 'Cr', 'Fr.', 'L.', 'Pts', 'TL', 'Rs', 'x', 'Rx', 'm/s', 'rad/s', 'C/kg', 'pH', 'V/m', 'A/m', ' 1/4', ' 1/2', ' 3/4', ' 1/3', ' 2/3', ' 1/5', ' 2/5', ' 3/5', ' 4/5', ' 1/6', ' 5/6', ' 1/8', ' 3/8', ' 5/8', ' 7/8', ' 1/', '0', '\'', '\'', ',', '\'', '"', '"', ',,', '"', '\'', '"', '"', '"', '<<', '>>', '<', '>', '-', '-', '-', '-', '-', '-', '-', '-', '-', '||', '/', '[', ']', '*', ',', '.', '<', '>', '<<', '>>', '[', ']', '[', ']', '[', ']', ',', '.', '[', ']', '<<', '>>', '<', '>', ',', '[', ']', '((', '))', '.', ',', '*', '/', '-', '/', '\\', '|', '||', '<<', '>>', '((', '))']; private static $transliterators = []; private static $tableZero; private static $tableWide; /** * @return static */ public static function fromCodePoints(int ...$codes) : self { $string = ''; foreach ($codes as $code) { if (0x80 > ($code %= 0x200000)) { $string .= \chr($code); } elseif (0x800 > $code) { $string .= \chr(0xc0 | $code >> 6) . \chr(0x80 | $code & 0x3f); } elseif (0x10000 > $code) { $string .= \chr(0xe0 | $code >> 12) . \chr(0x80 | $code >> 6 & 0x3f) . \chr(0x80 | $code & 0x3f); } else { $string .= \chr(0xf0 | $code >> 18) . \chr(0x80 | $code >> 12 & 0x3f) . \chr(0x80 | $code >> 6 & 0x3f) . \chr(0x80 | $code & 0x3f); } } return new static($string); } /** * Generic UTF-8 to ASCII transliteration. * * Install the intl extension for best results. * * @param string[]|\Transliterator[]|\Closure[] $rules See "*-Latin" rules from Transliterator::listIDs() */ public function ascii(array $rules = []) : self { $str = clone $this; $s = $str->string; $str->string = ''; \array_unshift($rules, 'nfd'); $rules[] = 'latin-ascii'; if (\function_exists('transliterator_transliterate')) { $rules[] = 'any-latin/bgn'; } $rules[] = 'nfkd'; $rules[] = '[:nonspacing mark:] remove'; while (\strlen($s) - 1 > ($i = \strspn($s, self::ASCII))) { if (0 < --$i) { $str->string .= \substr($s, 0, $i); $s = \substr($s, $i); } if (!($rule = \array_shift($rules))) { $rules = []; // An empty rule interrupts the next ones } if ($rule instanceof \Transliterator) { $s = $rule->transliterate($s); } elseif ($rule instanceof \Closure) { $s = $rule($s); } elseif ($rule) { if ('nfd' === ($rule = \strtolower($rule))) { \normalizer_is_normalized($s, self::NFD) ?: ($s = \normalizer_normalize($s, self::NFD)); } elseif ('nfkd' === $rule) { \normalizer_is_normalized($s, self::NFKD) ?: ($s = \normalizer_normalize($s, self::NFKD)); } elseif ('[:nonspacing mark:] remove' === $rule) { $s = \preg_replace('/\\p{Mn}++/u', '', $s); } elseif ('latin-ascii' === $rule) { $s = \str_replace(self::TRANSLIT_FROM, self::TRANSLIT_TO, $s); } elseif ('de-ascii' === $rule) { $s = \preg_replace("/([AUO])̈(?=\\p{Ll})/u", '$1e', $s); $s = \str_replace(["ä", "ö", "ü", "Ä", "Ö", "Ü"], ['ae', 'oe', 'ue', 'AE', 'OE', 'UE'], $s); } elseif (\function_exists('transliterator_transliterate')) { if (null === ($transliterator = self::$transliterators[$rule] ?? (self::$transliterators[$rule] = \Transliterator::create($rule)))) { if ('any-latin/bgn' === $rule) { $rule = 'any-latin'; $transliterator = self::$transliterators[$rule] ?? (self::$transliterators[$rule] = \Transliterator::create($rule)); } if (null === $transliterator) { throw new InvalidArgumentException(\sprintf('Unknown transliteration rule "%s".', $rule)); } self::$transliterators['any-latin/bgn'] = $transliterator; } $s = $transliterator->transliterate($s); } } elseif (!\function_exists('iconv')) { $s = \preg_replace('/[^\\x00-\\x7F]/u', '?', $s); } else { $s = @\preg_replace_callback('/[^\\x00-\\x7F]/u', static function ($c) { $c = (string) \iconv('UTF-8', 'ASCII//TRANSLIT', $c[0]); if ('' === $c && '' === \iconv('UTF-8', 'ASCII//TRANSLIT', '²')) { throw new \LogicException(\sprintf('"%s" requires a translit-able iconv implementation, try installing "gnu-libiconv" if you\'re using Alpine Linux.', static::class)); } return 1 < \strlen($c) ? \ltrim($c, '\'`"^~') : ('' !== $c ? $c : '?'); }, $s); } } $str->string .= $s; return $str; } public function camel() : parent { $str = clone $this; $str->string = \str_replace(' ', '', \preg_replace_callback('/\\b.(?!\\p{Lu})/u', static function ($m) use(&$i) { return 1 === ++$i ? 'İ' === $m[0] ? 'i̇' : \mb_strtolower($m[0], 'UTF-8') : \mb_convert_case($m[0], \MB_CASE_TITLE, 'UTF-8'); }, \preg_replace('/[^\\pL0-9]++/u', ' ', $this->string))); return $str; } /** * @return int[] */ public function codePointsAt(int $offset) : array { $str = $this->slice($offset, 1); if ('' === $str->string) { return []; } $codePoints = []; foreach (\preg_split('//u', $str->string, -1, \PREG_SPLIT_NO_EMPTY) as $c) { $codePoints[] = \mb_ord($c, 'UTF-8'); } return $codePoints; } public function folded(bool $compat = \true) : parent { $str = clone $this; if (!$compat || \PHP_VERSION_ID < 70300 || !\defined('Normalizer::NFKC_CF')) { $str->string = \normalizer_normalize($str->string, $compat ? \Normalizer::NFKC : \Normalizer::NFC); $str->string = \mb_strtolower(\str_replace(self::FOLD_FROM, self::FOLD_TO, $str->string), 'UTF-8'); } else { $str->string = \normalizer_normalize($str->string, \Normalizer::NFKC_CF); } return $str; } public function join(array $strings, ?string $lastGlue = null) : parent { $str = clone $this; $tail = null !== $lastGlue && 1 < \count($strings) ? $lastGlue . \array_pop($strings) : ''; $str->string = \implode($this->string, $strings) . $tail; if (!\preg_match('//u', $str->string)) { throw new InvalidArgumentException('Invalid UTF-8 string.'); } return $str; } public function lower() : parent { $str = clone $this; $str->string = \mb_strtolower(\str_replace('İ', 'i̇', $str->string), 'UTF-8'); return $str; } public function match(string $regexp, int $flags = 0, int $offset = 0) : array { $match = (\PREG_PATTERN_ORDER | \PREG_SET_ORDER) & $flags ? 'preg_match_all' : 'preg_match'; if ($this->ignoreCase) { $regexp .= 'i'; } \set_error_handler(static function ($t, $m) { throw new InvalidArgumentException($m); }); try { if (\false === $match($regexp . 'u', $this->string, $matches, $flags | \PREG_UNMATCHED_AS_NULL, $offset)) { $lastError = \preg_last_error(); foreach (\get_defined_constants(\true)['pcre'] as $k => $v) { if ($lastError === $v && '_ERROR' === \substr($k, -6)) { throw new RuntimeException('Matching failed with ' . $k . '.'); } } throw new RuntimeException('Matching failed with unknown error code.'); } } finally { \restore_error_handler(); } return $matches; } /** * @return static */ public function normalize(int $form = self::NFC) : self { if (!\in_array($form, [self::NFC, self::NFD, self::NFKC, self::NFKD])) { throw new InvalidArgumentException('Unsupported normalization form.'); } $str = clone $this; \normalizer_is_normalized($str->string, $form) ?: ($str->string = \normalizer_normalize($str->string, $form)); return $str; } public function padBoth(int $length, string $padStr = ' ') : parent { if ('' === $padStr || !\preg_match('//u', $padStr)) { throw new InvalidArgumentException('Invalid UTF-8 string.'); } $pad = clone $this; $pad->string = $padStr; return $this->pad($length, $pad, \STR_PAD_BOTH); } public function padEnd(int $length, string $padStr = ' ') : parent { if ('' === $padStr || !\preg_match('//u', $padStr)) { throw new InvalidArgumentException('Invalid UTF-8 string.'); } $pad = clone $this; $pad->string = $padStr; return $this->pad($length, $pad, \STR_PAD_RIGHT); } public function padStart(int $length, string $padStr = ' ') : parent { if ('' === $padStr || !\preg_match('//u', $padStr)) { throw new InvalidArgumentException('Invalid UTF-8 string.'); } $pad = clone $this; $pad->string = $padStr; return $this->pad($length, $pad, \STR_PAD_LEFT); } public function replaceMatches(string $fromRegexp, $to) : parent { if ($this->ignoreCase) { $fromRegexp .= 'i'; } if (\is_array($to) || $to instanceof \Closure) { if (!\is_callable($to)) { throw new \TypeError(\sprintf('Argument 2 passed to "%s::replaceMatches()" must be callable, array given.', static::class)); } $replace = 'preg_replace_callback'; $to = static function (array $m) use($to) : string { $to = $to($m); if ('' !== $to && (!\is_string($to) || !\preg_match('//u', $to))) { throw new InvalidArgumentException('Replace callback must return a valid UTF-8 string.'); } return $to; }; } elseif ('' !== $to && !\preg_match('//u', $to)) { throw new InvalidArgumentException('Invalid UTF-8 string.'); } else { $replace = 'preg_replace'; } \set_error_handler(static function ($t, $m) { throw new InvalidArgumentException($m); }); try { if (null === ($string = $replace($fromRegexp . 'u', $to, $this->string))) { $lastError = \preg_last_error(); foreach (\get_defined_constants(\true)['pcre'] as $k => $v) { if ($lastError === $v && '_ERROR' === \substr($k, -6)) { throw new RuntimeException('Matching failed with ' . $k . '.'); } } throw new RuntimeException('Matching failed with unknown error code.'); } } finally { \restore_error_handler(); } $str = clone $this; $str->string = $string; return $str; } public function reverse() : parent { $str = clone $this; $str->string = \implode('', \array_reverse(\preg_split('/(\\X)/u', $str->string, -1, \PREG_SPLIT_DELIM_CAPTURE | \PREG_SPLIT_NO_EMPTY))); return $str; } public function snake() : parent { $str = $this->camel(); $str->string = \mb_strtolower(\preg_replace(['/(\\p{Lu}+)(\\p{Lu}\\p{Ll})/u', '/([\\p{Ll}0-9])(\\p{Lu})/u'], 'Rvx\\1_\\2', $str->string), 'UTF-8'); return $str; } public function title(bool $allWords = \false) : parent { $str = clone $this; $limit = $allWords ? -1 : 1; $str->string = \preg_replace_callback('/\\b./u', static function (array $m) : string { return \mb_convert_case($m[0], \MB_CASE_TITLE, 'UTF-8'); }, $str->string, $limit); return $str; } public function trim(string $chars = " \t\n\r\x00\v\f ") : parent { if (" \t\n\r\x00\v\f " !== $chars && !\preg_match('//u', $chars)) { throw new InvalidArgumentException('Invalid UTF-8 chars.'); } $chars = \preg_quote($chars); $str = clone $this; $str->string = \preg_replace("{^[{$chars}]++|[{$chars}]++\$}uD", '', $str->string); return $str; } public function trimEnd(string $chars = " \t\n\r\x00\v\f ") : parent { if (" \t\n\r\x00\v\f " !== $chars && !\preg_match('//u', $chars)) { throw new InvalidArgumentException('Invalid UTF-8 chars.'); } $chars = \preg_quote($chars); $str = clone $this; $str->string = \preg_replace("{[{$chars}]++\$}uD", '', $str->string); return $str; } public function trimPrefix($prefix) : parent { if (!$this->ignoreCase) { return parent::trimPrefix($prefix); } $str = clone $this; if ($prefix instanceof \Traversable) { $prefix = \iterator_to_array($prefix, \false); } elseif ($prefix instanceof parent) { $prefix = $prefix->string; } $prefix = \implode('|', \array_map('preg_quote', (array) $prefix)); $str->string = \preg_replace("{^(?:{$prefix})}iuD", '', $this->string); return $str; } public function trimStart(string $chars = " \t\n\r\x00\v\f ") : parent { if (" \t\n\r\x00\v\f " !== $chars && !\preg_match('//u', $chars)) { throw new InvalidArgumentException('Invalid UTF-8 chars.'); } $chars = \preg_quote($chars); $str = clone $this; $str->string = \preg_replace("{^[{$chars}]++}uD", '', $str->string); return $str; } public function trimSuffix($suffix) : parent { if (!$this->ignoreCase) { return parent::trimSuffix($suffix); } $str = clone $this; if ($suffix instanceof \Traversable) { $suffix = \iterator_to_array($suffix, \false); } elseif ($suffix instanceof parent) { $suffix = $suffix->string; } $suffix = \implode('|', \array_map('preg_quote', (array) $suffix)); $str->string = \preg_replace("{(?:{$suffix})\$}iuD", '', $this->string); return $str; } public function upper() : parent { $str = clone $this; $str->string = \mb_strtoupper($str->string, 'UTF-8'); if (\PHP_VERSION_ID < 70300) { $str->string = \str_replace(self::UPPER_FROM, self::UPPER_TO, $str->string); } return $str; } public function width(bool $ignoreAnsiDecoration = \true) : int { $width = 0; $s = \str_replace(["\x00", "\x05", "\x07"], '', $this->string); if (\false !== \strpos($s, "\r")) { $s = \str_replace(["\r\n", "\r"], "\n", $s); } if (!$ignoreAnsiDecoration) { $s = \preg_replace('/[\\p{Cc}\\x7F]++/u', '', $s); } foreach (\explode("\n", $s) as $s) { if ($ignoreAnsiDecoration) { $s = \preg_replace('/(?:\\x1B(?: \\[ [\\x30-\\x3F]*+ [\\x20-\\x2F]*+ [\\x40-\\x7E] | [P\\]X^_] .*? \\x1B\\\\ | [\\x41-\\x7E] )|[\\p{Cc}\\x7F]++)/xu', '', $s); } $lineWidth = $this->wcswidth($s); if ($lineWidth > $width) { $width = $lineWidth; } } return $width; } /** * @return static */ private function pad(int $len, self $pad, int $type) : parent { $sLen = $this->length(); if ($len <= $sLen) { return clone $this; } $padLen = $pad->length(); $freeLen = $len - $sLen; $len = $freeLen % $padLen; switch ($type) { case \STR_PAD_RIGHT: return $this->append(\str_repeat($pad->string, \intdiv($freeLen, $padLen)) . ($len ? $pad->slice(0, $len) : '')); case \STR_PAD_LEFT: return $this->prepend(\str_repeat($pad->string, \intdiv($freeLen, $padLen)) . ($len ? $pad->slice(0, $len) : '')); case \STR_PAD_BOTH: $freeLen /= 2; $rightLen = \ceil($freeLen); $len = $rightLen % $padLen; $str = $this->append(\str_repeat($pad->string, \intdiv($rightLen, $padLen)) . ($len ? $pad->slice(0, $len) : '')); $leftLen = \floor($freeLen); $len = $leftLen % $padLen; return $str->prepend(\str_repeat($pad->string, \intdiv($leftLen, $padLen)) . ($len ? $pad->slice(0, $len) : '')); default: throw new InvalidArgumentException('Invalid padding type.'); } } /** * Based on https://github.com/jquast/wcwidth, a Python implementation of https://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c. */ private function wcswidth(string $string) : int { $width = 0; foreach (\preg_split('//u', $string, -1, \PREG_SPLIT_NO_EMPTY) as $c) { $codePoint = \mb_ord($c, 'UTF-8'); if (0 === $codePoint || 0x34f === $codePoint || 0x200b <= $codePoint && 0x200f >= $codePoint || 0x2028 === $codePoint || 0x2029 === $codePoint || 0x202a <= $codePoint && 0x202e >= $codePoint || 0x2060 <= $codePoint && 0x2063 >= $codePoint) { continue; } // Non printable characters if (32 > $codePoint || 0x7f <= $codePoint && 0xa0 > $codePoint) { return -1; } if (null === self::$tableZero) { self::$tableZero = (require __DIR__ . '/Resources/data/wcswidth_table_zero.php'); } if ($codePoint >= self::$tableZero[0][0] && $codePoint <= self::$tableZero[$ubound = \count(self::$tableZero) - 1][1]) { $lbound = 0; while ($ubound >= $lbound) { $mid = \floor(($lbound + $ubound) / 2); if ($codePoint > self::$tableZero[$mid][1]) { $lbound = $mid + 1; } elseif ($codePoint < self::$tableZero[$mid][0]) { $ubound = $mid - 1; } else { continue 2; } } } if (null === self::$tableWide) { self::$tableWide = (require __DIR__ . '/Resources/data/wcswidth_table_wide.php'); } if ($codePoint >= self::$tableWide[0][0] && $codePoint <= self::$tableWide[$ubound = \count(self::$tableWide) - 1][1]) { $lbound = 0; while ($ubound >= $lbound) { $mid = \floor(($lbound + $ubound) / 2); if ($codePoint > self::$tableWide[$mid][1]) { $lbound = $mid + 1; } elseif ($codePoint < self::$tableWide[$mid][0]) { $ubound = $mid - 1; } else { $width += 2; continue 2; } } } ++$width; } return $width; } } README.md 0000777 00000001053 15251261610 0006030 0 ustar 00 String Component ================ The String component provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way. Resources --------- * [Documentation](https://symfony.com/doc/current/components/string.html) * [Contributing](https://symfony.com/doc/current/contributing/index.html) * [Report issues](https://github.com/symfony/symfony/issues) and [send Pull Requests](https://github.com/symfony/symfony/pulls) in the [main Symfony repository](https://github.com/symfony/symfony) Slugger/SluggerInterface.php 0000777 00000001323 15251261610 0012123 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Rvx\Symfony\Component\String\Slugger; use Rvx\Symfony\Component\String\AbstractUnicodeString; /** * Creates a URL-friendly slug from a given string. * * @author Titouan Galopin <galopintitouan@gmail.com> */ interface SluggerInterface { /** * Creates a slug for the given string and locale, using appropriate transliteration when needed. */ public function slug(string $string, string $separator = '-', ?string $locale = null) : AbstractUnicodeString; } Slugger/AsciiSlugger.php 0000777 00000013367 15251261610 0011266 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Rvx\Symfony\Component\String\Slugger; use Rvx\Symfony\Component\String\AbstractUnicodeString; use Rvx\Symfony\Component\String\UnicodeString; use Rvx\Symfony\Contracts\Translation\LocaleAwareInterface; if (!\interface_exists(LocaleAwareInterface::class)) { throw new \LogicException('You cannot use the "Symfony\\Component\\String\\Slugger\\AsciiSlugger" as the "symfony/translation-contracts" package is not installed. Try running "composer require symfony/translation-contracts".'); } /** * @author Titouan Galopin <galopintitouan@gmail.com> */ class AsciiSlugger implements SluggerInterface, LocaleAwareInterface { private const LOCALE_TO_TRANSLITERATOR_ID = ['am' => 'Amharic-Latin', 'ar' => 'Arabic-Latin', 'az' => 'Azerbaijani-Latin', 'be' => 'Belarusian-Latin', 'bg' => 'Bulgarian-Latin', 'bn' => 'Bengali-Latin', 'de' => 'de-ASCII', 'el' => 'Greek-Latin', 'fa' => 'Persian-Latin', 'he' => 'Hebrew-Latin', 'hy' => 'Armenian-Latin', 'ka' => 'Georgian-Latin', 'kk' => 'Kazakh-Latin', 'ky' => 'Kirghiz-Latin', 'ko' => 'Korean-Latin', 'mk' => 'Macedonian-Latin', 'mn' => 'Mongolian-Latin', 'or' => 'Oriya-Latin', 'ps' => 'Pashto-Latin', 'ru' => 'Russian-Latin', 'sr' => 'Serbian-Latin', 'sr_Cyrl' => 'Serbian-Latin', 'th' => 'Thai-Latin', 'tk' => 'Turkmen-Latin', 'uk' => 'Ukrainian-Latin', 'uz' => 'Uzbek-Latin', 'zh' => 'Han-Latin']; private $defaultLocale; private $symbolsMap = ['en' => ['@' => 'at', '&' => 'and']]; /** * Cache of transliterators per locale. * * @var \Transliterator[] */ private $transliterators = []; /** * @param array|\Closure|null $symbolsMap */ public function __construct(?string $defaultLocale = null, $symbolsMap = null) { if (null !== $symbolsMap && !\is_array($symbolsMap) && !$symbolsMap instanceof \Closure) { throw new \TypeError(\sprintf('Argument 2 passed to "%s()" must be array, Closure or null, "%s" given.', __METHOD__, \gettype($symbolsMap))); } $this->defaultLocale = $defaultLocale; $this->symbolsMap = $symbolsMap ?? $this->symbolsMap; } /** * {@inheritdoc} */ public function setLocale($locale) { $this->defaultLocale = $locale; } /** * {@inheritdoc} */ public function getLocale() { return $this->defaultLocale; } /** * {@inheritdoc} */ public function slug(string $string, string $separator = '-', ?string $locale = null) : AbstractUnicodeString { $locale = $locale ?? $this->defaultLocale; $transliterator = []; if ($locale && ('de' === $locale || 0 === \strpos($locale, 'de_'))) { // Use the shortcut for German in UnicodeString::ascii() if possible (faster and no requirement on intl) $transliterator = ['de-ASCII']; } elseif (\function_exists('transliterator_transliterate') && $locale) { $transliterator = (array) $this->createTransliterator($locale); } if ($this->symbolsMap instanceof \Closure) { // If the symbols map is passed as a closure, there is no need to fallback to the parent locale // as the closure can just provide substitutions for all locales of interest. $symbolsMap = $this->symbolsMap; \array_unshift($transliterator, static function ($s) use($symbolsMap, $locale) { return $symbolsMap($s, $locale); }); } $unicodeString = (new UnicodeString($string))->ascii($transliterator); if (\is_array($this->symbolsMap)) { $map = null; if (isset($this->symbolsMap[$locale])) { $map = $this->symbolsMap[$locale]; } else { $parent = self::getParentLocale($locale); if ($parent && isset($this->symbolsMap[$parent])) { $map = $this->symbolsMap[$parent]; } } if ($map) { foreach ($map as $char => $replace) { $unicodeString = $unicodeString->replace($char, ' ' . $replace . ' '); } } } return $unicodeString->replaceMatches('/[^A-Za-z0-9]++/', $separator)->trim($separator); } private function createTransliterator(string $locale) : ?\Transliterator { if (\array_key_exists($locale, $this->transliterators)) { return $this->transliterators[$locale]; } // Exact locale supported, cache and return if ($id = self::LOCALE_TO_TRANSLITERATOR_ID[$locale] ?? null) { return $this->transliterators[$locale] = \Transliterator::create($id . '/BGN') ?? \Transliterator::create($id); } // Locale not supported and no parent, fallback to any-latin if (!($parent = self::getParentLocale($locale))) { return $this->transliterators[$locale] = null; } // Try to use the parent locale (ie. try "de" for "de_AT") and cache both locales if ($id = self::LOCALE_TO_TRANSLITERATOR_ID[$parent] ?? null) { $transliterator = \Transliterator::create($id . '/BGN') ?? \Transliterator::create($id); } return $this->transliterators[$locale] = $this->transliterators[$parent] = $transliterator ?? null; } private static function getParentLocale(?string $locale) : ?string { if (!$locale) { return null; } if (\false === ($str = \strrchr($locale, '_'))) { // no parent locale return null; } return \substr($locale, 0, -\strlen($str)); } } Exception/RuntimeException.php 0000777 00000000563 15251261610 0012527 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Rvx\Symfony\Component\String\Exception; class RuntimeException extends \RuntimeException implements ExceptionInterface { } Exception/InvalidArgumentException.php 0000777 00000000603 15251261610 0014170 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Rvx\Symfony\Component\String\Exception; class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface { } Exception/ExceptionInterface.php 0000777 00000000524 15251261610 0013001 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Rvx\Symfony\Component\String\Exception; interface ExceptionInterface extends \Throwable { } ByteString.php 0000777 00000036231 15251261610 0007362 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Rvx\Symfony\Component\String; use Rvx\Symfony\Component\String\Exception\ExceptionInterface; use Rvx\Symfony\Component\String\Exception\InvalidArgumentException; use Rvx\Symfony\Component\String\Exception\RuntimeException; /** * Represents a binary-safe string of bytes. * * @author Nicolas Grekas <p@tchwork.com> * @author Hugo Hamon <hugohamon@neuf.fr> * * @throws ExceptionInterface */ class ByteString extends AbstractString { private const ALPHABET_ALPHANUMERIC = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'; public function __construct(string $string = '') { $this->string = $string; } /* * The following method was derived from code of the Hack Standard Library (v4.40 - 2020-05-03) * * https://github.com/hhvm/hsl/blob/80a42c02f036f72a42f0415e80d6b847f4bf62d5/src/random/private.php#L16 * * Code subject to the MIT license (https://github.com/hhvm/hsl/blob/master/LICENSE). * * Copyright (c) 2004-2020, Facebook, Inc. (https://www.facebook.com/) */ public static function fromRandom(int $length = 16, ?string $alphabet = null) : self { if ($length <= 0) { throw new InvalidArgumentException(\sprintf('A strictly positive length is expected, "%d" given.', $length)); } $alphabet = $alphabet ?? self::ALPHABET_ALPHANUMERIC; $alphabetSize = \strlen($alphabet); $bits = (int) \ceil(\log($alphabetSize, 2.0)); if ($bits <= 0 || $bits > 56) { throw new InvalidArgumentException('The length of the alphabet must in the [2^1, 2^56] range.'); } $ret = ''; while ($length > 0) { $urandomLength = (int) \ceil(2 * $length * $bits / 8.0); $data = \random_bytes($urandomLength); $unpackedData = 0; $unpackedBits = 0; for ($i = 0; $i < $urandomLength && $length > 0; ++$i) { // Unpack 8 bits $unpackedData = $unpackedData << 8 | \ord($data[$i]); $unpackedBits += 8; // While we have enough bits to select a character from the alphabet, keep // consuming the random data for (; $unpackedBits >= $bits && $length > 0; $unpackedBits -= $bits) { $index = $unpackedData & (1 << $bits) - 1; $unpackedData >>= $bits; // Unfortunately, the alphabet size is not necessarily a power of two. // Worst case, it is 2^k + 1, which means we need (k+1) bits and we // have around a 50% chance of missing as k gets larger if ($index < $alphabetSize) { $ret .= $alphabet[$index]; --$length; } } } } return new static($ret); } public function bytesAt(int $offset) : array { $str = $this->string[$offset] ?? ''; return '' === $str ? [] : [\ord($str)]; } public function append(string ...$suffix) : parent { $str = clone $this; $str->string .= 1 >= \count($suffix) ? $suffix[0] ?? '' : \implode('', $suffix); return $str; } public function camel() : parent { $str = clone $this; $parts = \explode(' ', \trim(\ucwords(\preg_replace('/[^a-zA-Z0-9\\x7f-\\xff]++/', ' ', $this->string)))); $parts[0] = 1 !== \strlen($parts[0]) && \ctype_upper($parts[0]) ? $parts[0] : \lcfirst($parts[0]); $str->string = \implode('', $parts); return $str; } public function chunk(int $length = 1) : array { if (1 > $length) { throw new InvalidArgumentException('The chunk length must be greater than zero.'); } if ('' === $this->string) { return []; } $str = clone $this; $chunks = []; foreach (\str_split($this->string, $length) as $chunk) { $str->string = $chunk; $chunks[] = clone $str; } return $chunks; } public function endsWith($suffix) : bool { if ($suffix instanceof parent) { $suffix = $suffix->string; } elseif (\is_array($suffix) || $suffix instanceof \Traversable) { return parent::endsWith($suffix); } else { $suffix = (string) $suffix; } return '' !== $suffix && \strlen($this->string) >= \strlen($suffix) && 0 === \substr_compare($this->string, $suffix, -\strlen($suffix), null, $this->ignoreCase); } public function equalsTo($string) : bool { if ($string instanceof parent) { $string = $string->string; } elseif (\is_array($string) || $string instanceof \Traversable) { return parent::equalsTo($string); } else { $string = (string) $string; } if ('' !== $string && $this->ignoreCase) { return 0 === \strcasecmp($string, $this->string); } return $string === $this->string; } public function folded() : parent { $str = clone $this; $str->string = \strtolower($str->string); return $str; } public function indexOf($needle, int $offset = 0) : ?int { if ($needle instanceof parent) { $needle = $needle->string; } elseif (\is_array($needle) || $needle instanceof \Traversable) { return parent::indexOf($needle, $offset); } else { $needle = (string) $needle; } if ('' === $needle) { return null; } $i = $this->ignoreCase ? \stripos($this->string, $needle, $offset) : \strpos($this->string, $needle, $offset); return \false === $i ? null : $i; } public function indexOfLast($needle, int $offset = 0) : ?int { if ($needle instanceof parent) { $needle = $needle->string; } elseif (\is_array($needle) || $needle instanceof \Traversable) { return parent::indexOfLast($needle, $offset); } else { $needle = (string) $needle; } if ('' === $needle) { return null; } $i = $this->ignoreCase ? \strripos($this->string, $needle, $offset) : \strrpos($this->string, $needle, $offset); return \false === $i ? null : $i; } public function isUtf8() : bool { return '' === $this->string || \preg_match('//u', $this->string); } public function join(array $strings, ?string $lastGlue = null) : parent { $str = clone $this; $tail = null !== $lastGlue && 1 < \count($strings) ? $lastGlue . \array_pop($strings) : ''; $str->string = \implode($this->string, $strings) . $tail; return $str; } public function length() : int { return \strlen($this->string); } public function lower() : parent { $str = clone $this; $str->string = \strtolower($str->string); return $str; } public function match(string $regexp, int $flags = 0, int $offset = 0) : array { $match = (\PREG_PATTERN_ORDER | \PREG_SET_ORDER) & $flags ? 'preg_match_all' : 'preg_match'; if ($this->ignoreCase) { $regexp .= 'i'; } \set_error_handler(static function ($t, $m) { throw new InvalidArgumentException($m); }); try { if (\false === $match($regexp, $this->string, $matches, $flags | \PREG_UNMATCHED_AS_NULL, $offset)) { $lastError = \preg_last_error(); foreach (\get_defined_constants(\true)['pcre'] as $k => $v) { if ($lastError === $v && '_ERROR' === \substr($k, -6)) { throw new RuntimeException('Matching failed with ' . $k . '.'); } } throw new RuntimeException('Matching failed with unknown error code.'); } } finally { \restore_error_handler(); } return $matches; } public function padBoth(int $length, string $padStr = ' ') : parent { $str = clone $this; $str->string = \str_pad($this->string, $length, $padStr, \STR_PAD_BOTH); return $str; } public function padEnd(int $length, string $padStr = ' ') : parent { $str = clone $this; $str->string = \str_pad($this->string, $length, $padStr, \STR_PAD_RIGHT); return $str; } public function padStart(int $length, string $padStr = ' ') : parent { $str = clone $this; $str->string = \str_pad($this->string, $length, $padStr, \STR_PAD_LEFT); return $str; } public function prepend(string ...$prefix) : parent { $str = clone $this; $str->string = (1 >= \count($prefix) ? $prefix[0] ?? '' : \implode('', $prefix)) . $str->string; return $str; } public function replace(string $from, string $to) : parent { $str = clone $this; if ('' !== $from) { $str->string = $this->ignoreCase ? \str_ireplace($from, $to, $this->string) : \str_replace($from, $to, $this->string); } return $str; } public function replaceMatches(string $fromRegexp, $to) : parent { if ($this->ignoreCase) { $fromRegexp .= 'i'; } if (\is_array($to)) { if (!\is_callable($to)) { throw new \TypeError(\sprintf('Argument 2 passed to "%s::replaceMatches()" must be callable, array given.', static::class)); } $replace = 'preg_replace_callback'; } else { $replace = $to instanceof \Closure ? 'preg_replace_callback' : 'preg_replace'; } \set_error_handler(static function ($t, $m) { throw new InvalidArgumentException($m); }); try { if (null === ($string = $replace($fromRegexp, $to, $this->string))) { $lastError = \preg_last_error(); foreach (\get_defined_constants(\true)['pcre'] as $k => $v) { if ($lastError === $v && '_ERROR' === \substr($k, -6)) { throw new RuntimeException('Matching failed with ' . $k . '.'); } } throw new RuntimeException('Matching failed with unknown error code.'); } } finally { \restore_error_handler(); } $str = clone $this; $str->string = $string; return $str; } public function reverse() : parent { $str = clone $this; $str->string = \strrev($str->string); return $str; } public function slice(int $start = 0, ?int $length = null) : parent { $str = clone $this; $str->string = (string) \substr($this->string, $start, $length ?? \PHP_INT_MAX); return $str; } public function snake() : parent { $str = $this->camel(); $str->string = \strtolower(\preg_replace(['/([A-Z]+)([A-Z][a-z])/', '/([a-z\\d])([A-Z])/'], 'Rvx\\1_\\2', $str->string)); return $str; } public function splice(string $replacement, int $start = 0, ?int $length = null) : parent { $str = clone $this; $str->string = \substr_replace($this->string, $replacement, $start, $length ?? \PHP_INT_MAX); return $str; } public function split(string $delimiter, ?int $limit = null, ?int $flags = null) : array { if (1 > ($limit = $limit ?? \PHP_INT_MAX)) { throw new InvalidArgumentException('Split limit must be a positive integer.'); } if ('' === $delimiter) { throw new InvalidArgumentException('Split delimiter is empty.'); } if (null !== $flags) { return parent::split($delimiter, $limit, $flags); } $str = clone $this; $chunks = $this->ignoreCase ? \preg_split('{' . \preg_quote($delimiter) . '}iD', $this->string, $limit) : \explode($delimiter, $this->string, $limit); foreach ($chunks as &$chunk) { $str->string = $chunk; $chunk = clone $str; } return $chunks; } public function startsWith($prefix) : bool { if ($prefix instanceof parent) { $prefix = $prefix->string; } elseif (!\is_string($prefix)) { return parent::startsWith($prefix); } return '' !== $prefix && 0 === ($this->ignoreCase ? \strncasecmp($this->string, $prefix, \strlen($prefix)) : \strncmp($this->string, $prefix, \strlen($prefix))); } public function title(bool $allWords = \false) : parent { $str = clone $this; $str->string = $allWords ? \ucwords($str->string) : \ucfirst($str->string); return $str; } public function toUnicodeString(?string $fromEncoding = null) : UnicodeString { return new UnicodeString($this->toCodePointString($fromEncoding)->string); } public function toCodePointString(?string $fromEncoding = null) : CodePointString { $u = new CodePointString(); if (\in_array($fromEncoding, [null, 'utf8', 'utf-8', 'UTF8', 'UTF-8'], \true) && \preg_match('//u', $this->string)) { $u->string = $this->string; return $u; } \set_error_handler(static function ($t, $m) { throw new InvalidArgumentException($m); }); try { try { $validEncoding = \false !== \mb_detect_encoding($this->string, $fromEncoding ?? 'Windows-1252', \true); } catch (InvalidArgumentException $e) { if (!\function_exists('iconv')) { throw $e; } $u->string = \iconv($fromEncoding ?? 'Windows-1252', 'UTF-8', $this->string); return $u; } } finally { \restore_error_handler(); } if (!$validEncoding) { throw new InvalidArgumentException(\sprintf('Invalid "%s" string.', $fromEncoding ?? 'Windows-1252')); } $u->string = \mb_convert_encoding($this->string, 'UTF-8', $fromEncoding ?? 'Windows-1252'); return $u; } public function trim(string $chars = " \t\n\r\x00\v\f") : parent { $str = clone $this; $str->string = \trim($str->string, $chars); return $str; } public function trimEnd(string $chars = " \t\n\r\x00\v\f") : parent { $str = clone $this; $str->string = \rtrim($str->string, $chars); return $str; } public function trimStart(string $chars = " \t\n\r\x00\v\f") : parent { $str = clone $this; $str->string = \ltrim($str->string, $chars); return $str; } public function upper() : parent { $str = clone $this; $str->string = \strtoupper($str->string); return $str; } public function width(bool $ignoreAnsiDecoration = \true) : int { $string = \preg_match('//u', $this->string) ? $this->string : \preg_replace('/[\\x80-\\xFF]/', '?', $this->string); return (new CodePointString($string))->width($ignoreAnsiDecoration); } } AbstractString.php 0000777 00000047644 15251261610 0010234 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Rvx\Symfony\Component\String; use Rvx\Symfony\Component\String\Exception\ExceptionInterface; use Rvx\Symfony\Component\String\Exception\InvalidArgumentException; use Rvx\Symfony\Component\String\Exception\RuntimeException; /** * Represents a string of abstract characters. * * Unicode defines 3 types of "characters" (bytes, code points and grapheme clusters). * This class is the abstract type to use as a type-hint when the logic you want to * implement doesn't care about the exact variant it deals with. * * @author Nicolas Grekas <p@tchwork.com> * @author Hugo Hamon <hugohamon@neuf.fr> * * @throws ExceptionInterface */ abstract class AbstractString implements \Stringable, \JsonSerializable { public const PREG_PATTERN_ORDER = \PREG_PATTERN_ORDER; public const PREG_SET_ORDER = \PREG_SET_ORDER; public const PREG_OFFSET_CAPTURE = \PREG_OFFSET_CAPTURE; public const PREG_UNMATCHED_AS_NULL = \PREG_UNMATCHED_AS_NULL; public const PREG_SPLIT = 0; public const PREG_SPLIT_NO_EMPTY = \PREG_SPLIT_NO_EMPTY; public const PREG_SPLIT_DELIM_CAPTURE = \PREG_SPLIT_DELIM_CAPTURE; public const PREG_SPLIT_OFFSET_CAPTURE = \PREG_SPLIT_OFFSET_CAPTURE; protected $string = ''; protected $ignoreCase = \false; public abstract function __construct(string $string = ''); /** * Unwraps instances of AbstractString back to strings. * * @return string[]|array */ public static function unwrap(array $values) : array { foreach ($values as $k => $v) { if ($v instanceof self) { $values[$k] = $v->__toString(); } elseif (\is_array($v) && $values[$k] !== ($v = static::unwrap($v))) { $values[$k] = $v; } } return $values; } /** * Wraps (and normalizes) strings in instances of AbstractString. * * @return static[]|array */ public static function wrap(array $values) : array { $i = 0; $keys = null; foreach ($values as $k => $v) { if (\is_string($k) && '' !== $k && $k !== ($j = (string) new static($k))) { $keys = $keys ?? \array_keys($values); $keys[$i] = $j; } if (\is_string($v)) { $values[$k] = new static($v); } elseif (\is_array($v) && $values[$k] !== ($v = static::wrap($v))) { $values[$k] = $v; } ++$i; } return null !== $keys ? \array_combine($keys, $values) : $values; } /** * @param string|string[] $needle * * @return static */ public function after($needle, bool $includeNeedle = \false, int $offset = 0) : self { $str = clone $this; $i = \PHP_INT_MAX; foreach ((array) $needle as $n) { $n = (string) $n; $j = $this->indexOf($n, $offset); if (null !== $j && $j < $i) { $i = $j; $str->string = $n; } } if (\PHP_INT_MAX === $i) { return $str; } if (!$includeNeedle) { $i += $str->length(); } return $this->slice($i); } /** * @param string|string[] $needle * * @return static */ public function afterLast($needle, bool $includeNeedle = \false, int $offset = 0) : self { $str = clone $this; $i = null; foreach ((array) $needle as $n) { $n = (string) $n; $j = $this->indexOfLast($n, $offset); if (null !== $j && $j >= $i) { $i = $offset = $j; $str->string = $n; } } if (null === $i) { return $str; } if (!$includeNeedle) { $i += $str->length(); } return $this->slice($i); } /** * @return static */ public abstract function append(string ...$suffix) : self; /** * @param string|string[] $needle * * @return static */ public function before($needle, bool $includeNeedle = \false, int $offset = 0) : self { $str = clone $this; $i = \PHP_INT_MAX; foreach ((array) $needle as $n) { $n = (string) $n; $j = $this->indexOf($n, $offset); if (null !== $j && $j < $i) { $i = $j; $str->string = $n; } } if (\PHP_INT_MAX === $i) { return $str; } if ($includeNeedle) { $i += $str->length(); } return $this->slice(0, $i); } /** * @param string|string[] $needle * * @return static */ public function beforeLast($needle, bool $includeNeedle = \false, int $offset = 0) : self { $str = clone $this; $i = null; foreach ((array) $needle as $n) { $n = (string) $n; $j = $this->indexOfLast($n, $offset); if (null !== $j && $j >= $i) { $i = $offset = $j; $str->string = $n; } } if (null === $i) { return $str; } if ($includeNeedle) { $i += $str->length(); } return $this->slice(0, $i); } /** * @return int[] */ public function bytesAt(int $offset) : array { $str = $this->slice($offset, 1); return '' === $str->string ? [] : \array_values(\unpack('C*', $str->string)); } /** * @return static */ public abstract function camel() : self; /** * @return static[] */ public abstract function chunk(int $length = 1) : array; /** * @return static */ public function collapseWhitespace() : self { $str = clone $this; $str->string = \trim(\preg_replace("/(?:[ \n\r\t\f]{2,}+|[\n\r\t\f])/", ' ', $str->string), " \n\r\t\f"); return $str; } /** * @param string|string[] $needle */ public function containsAny($needle) : bool { return null !== $this->indexOf($needle); } /** * @param string|string[] $suffix */ public function endsWith($suffix) : bool { if (!\is_array($suffix) && !$suffix instanceof \Traversable) { throw new \TypeError(\sprintf('Method "%s()" must be overridden by class "%s" to deal with non-iterable values.', __FUNCTION__, static::class)); } foreach ($suffix as $s) { if ($this->endsWith((string) $s)) { return \true; } } return \false; } /** * @return static */ public function ensureEnd(string $suffix) : self { if (!$this->endsWith($suffix)) { return $this->append($suffix); } $suffix = \preg_quote($suffix); $regex = '{(' . $suffix . ')(?:' . $suffix . ')++$}D'; return $this->replaceMatches($regex . ($this->ignoreCase ? 'i' : ''), '$1'); } /** * @return static */ public function ensureStart(string $prefix) : self { $prefix = new static($prefix); if (!$this->startsWith($prefix)) { return $this->prepend($prefix); } $str = clone $this; $i = $prefixLen = $prefix->length(); while ($this->indexOf($prefix, $i) === $i) { $str = $str->slice($prefixLen); $i += $prefixLen; } return $str; } /** * @param string|string[] $string */ public function equalsTo($string) : bool { if (!\is_array($string) && !$string instanceof \Traversable) { throw new \TypeError(\sprintf('Method "%s()" must be overridden by class "%s" to deal with non-iterable values.', __FUNCTION__, static::class)); } foreach ($string as $s) { if ($this->equalsTo((string) $s)) { return \true; } } return \false; } /** * @return static */ public abstract function folded() : self; /** * @return static */ public function ignoreCase() : self { $str = clone $this; $str->ignoreCase = \true; return $str; } /** * @param string|string[] $needle */ public function indexOf($needle, int $offset = 0) : ?int { if (!\is_array($needle) && !$needle instanceof \Traversable) { throw new \TypeError(\sprintf('Method "%s()" must be overridden by class "%s" to deal with non-iterable values.', __FUNCTION__, static::class)); } $i = \PHP_INT_MAX; foreach ($needle as $n) { $j = $this->indexOf((string) $n, $offset); if (null !== $j && $j < $i) { $i = $j; } } return \PHP_INT_MAX === $i ? null : $i; } /** * @param string|string[] $needle */ public function indexOfLast($needle, int $offset = 0) : ?int { if (!\is_array($needle) && !$needle instanceof \Traversable) { throw new \TypeError(\sprintf('Method "%s()" must be overridden by class "%s" to deal with non-iterable values.', __FUNCTION__, static::class)); } $i = null; foreach ($needle as $n) { $j = $this->indexOfLast((string) $n, $offset); if (null !== $j && $j >= $i) { $i = $offset = $j; } } return $i; } public function isEmpty() : bool { return '' === $this->string; } /** * @return static */ public abstract function join(array $strings, ?string $lastGlue = null) : self; public function jsonSerialize() : string { return $this->string; } public abstract function length() : int; /** * @return static */ public abstract function lower() : self; /** * Matches the string using a regular expression. * * Pass PREG_PATTERN_ORDER or PREG_SET_ORDER as $flags to get all occurrences matching the regular expression. * * @return array All matches in a multi-dimensional array ordered according to flags */ public abstract function match(string $regexp, int $flags = 0, int $offset = 0) : array; /** * @return static */ public abstract function padBoth(int $length, string $padStr = ' ') : self; /** * @return static */ public abstract function padEnd(int $length, string $padStr = ' ') : self; /** * @return static */ public abstract function padStart(int $length, string $padStr = ' ') : self; /** * @return static */ public abstract function prepend(string ...$prefix) : self; /** * @return static */ public function repeat(int $multiplier) : self { if (0 > $multiplier) { throw new InvalidArgumentException(\sprintf('Multiplier must be positive, %d given.', $multiplier)); } $str = clone $this; $str->string = \str_repeat($str->string, $multiplier); return $str; } /** * @return static */ public abstract function replace(string $from, string $to) : self; /** * @param string|callable $to * * @return static */ public abstract function replaceMatches(string $fromRegexp, $to) : self; /** * @return static */ public abstract function reverse() : self; /** * @return static */ public abstract function slice(int $start = 0, ?int $length = null) : self; /** * @return static */ public abstract function snake() : self; /** * @return static */ public abstract function splice(string $replacement, int $start = 0, ?int $length = null) : self; /** * @return static[] */ public function split(string $delimiter, ?int $limit = null, ?int $flags = null) : array { if (null === $flags) { throw new \TypeError('Split behavior when $flags is null must be implemented by child classes.'); } if ($this->ignoreCase) { $delimiter .= 'i'; } \set_error_handler(static function ($t, $m) { throw new InvalidArgumentException($m); }); try { if (\false === ($chunks = \preg_split($delimiter, $this->string, $limit, $flags))) { $lastError = \preg_last_error(); foreach (\get_defined_constants(\true)['pcre'] as $k => $v) { if ($lastError === $v && '_ERROR' === \substr($k, -6)) { throw new RuntimeException('Splitting failed with ' . $k . '.'); } } throw new RuntimeException('Splitting failed with unknown error code.'); } } finally { \restore_error_handler(); } $str = clone $this; if (self::PREG_SPLIT_OFFSET_CAPTURE & $flags) { foreach ($chunks as &$chunk) { $str->string = $chunk[0]; $chunk[0] = clone $str; } } else { foreach ($chunks as &$chunk) { $str->string = $chunk; $chunk = clone $str; } } return $chunks; } /** * @param string|string[] $prefix */ public function startsWith($prefix) : bool { if (!\is_array($prefix) && !$prefix instanceof \Traversable) { throw new \TypeError(\sprintf('Method "%s()" must be overridden by class "%s" to deal with non-iterable values.', __FUNCTION__, static::class)); } foreach ($prefix as $prefix) { if ($this->startsWith((string) $prefix)) { return \true; } } return \false; } /** * @return static */ public abstract function title(bool $allWords = \false) : self; public function toByteString(?string $toEncoding = null) : ByteString { $b = new ByteString(); $toEncoding = \in_array($toEncoding, ['utf8', 'utf-8', 'UTF8'], \true) ? 'UTF-8' : $toEncoding; if (null === $toEncoding || $toEncoding === ($fromEncoding = $this instanceof AbstractUnicodeString || \preg_match('//u', $b->string) ? 'UTF-8' : 'Windows-1252')) { $b->string = $this->string; return $b; } \set_error_handler(static function ($t, $m) { throw new InvalidArgumentException($m); }); try { try { $b->string = \mb_convert_encoding($this->string, $toEncoding, 'UTF-8'); } catch (InvalidArgumentException|\ValueError $e) { if (!\function_exists('iconv')) { if ($e instanceof \ValueError) { throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e); } throw $e; } $b->string = \iconv('UTF-8', $toEncoding, $this->string); } } finally { \restore_error_handler(); } return $b; } public function toCodePointString() : CodePointString { return new CodePointString($this->string); } public function toString() : string { return $this->string; } public function toUnicodeString() : UnicodeString { return new UnicodeString($this->string); } /** * @return static */ public abstract function trim(string $chars = " \t\n\r\x00\v\f ") : self; /** * @return static */ public abstract function trimEnd(string $chars = " \t\n\r\x00\v\f ") : self; /** * @param string|string[] $prefix * * @return static */ public function trimPrefix($prefix) : self { if (\is_array($prefix) || $prefix instanceof \Traversable) { foreach ($prefix as $s) { $t = $this->trimPrefix($s); if ($t->string !== $this->string) { return $t; } } return clone $this; } $str = clone $this; if ($prefix instanceof self) { $prefix = $prefix->string; } else { $prefix = (string) $prefix; } if ('' !== $prefix && \strlen($this->string) >= \strlen($prefix) && 0 === \substr_compare($this->string, $prefix, 0, \strlen($prefix), $this->ignoreCase)) { $str->string = \substr($this->string, \strlen($prefix)); } return $str; } /** * @return static */ public abstract function trimStart(string $chars = " \t\n\r\x00\v\f ") : self; /** * @param string|string[] $suffix * * @return static */ public function trimSuffix($suffix) : self { if (\is_array($suffix) || $suffix instanceof \Traversable) { foreach ($suffix as $s) { $t = $this->trimSuffix($s); if ($t->string !== $this->string) { return $t; } } return clone $this; } $str = clone $this; if ($suffix instanceof self) { $suffix = $suffix->string; } else { $suffix = (string) $suffix; } if ('' !== $suffix && \strlen($this->string) >= \strlen($suffix) && 0 === \substr_compare($this->string, $suffix, -\strlen($suffix), null, $this->ignoreCase)) { $str->string = \substr($this->string, 0, -\strlen($suffix)); } return $str; } /** * @return static */ public function truncate(int $length, string $ellipsis = '', bool $cut = \true) : self { $stringLength = $this->length(); if ($stringLength <= $length) { return clone $this; } $ellipsisLength = '' !== $ellipsis ? (new static($ellipsis))->length() : 0; if ($length < $ellipsisLength) { $ellipsisLength = 0; } if (!$cut) { if (null === ($length = $this->indexOf([' ', "\r", "\n", "\t"], ($length ?: 1) - 1))) { return clone $this; } $length += $ellipsisLength; } $str = $this->slice(0, $length - $ellipsisLength); return $ellipsisLength ? $str->trimEnd()->append($ellipsis) : $str; } /** * @return static */ public abstract function upper() : self; /** * Returns the printable length on a terminal. */ public abstract function width(bool $ignoreAnsiDecoration = \true) : int; /** * @return static */ public function wordwrap(int $width = 75, string $break = "\n", bool $cut = \false) : self { $lines = '' !== $break ? $this->split($break) : [clone $this]; $chars = []; $mask = ''; if (1 === \count($lines) && '' === $lines[0]->string) { return $lines[0]; } foreach ($lines as $i => $line) { if ($i) { $chars[] = $break; $mask .= '#'; } foreach ($line->chunk() as $char) { $chars[] = $char->string; $mask .= ' ' === $char->string ? ' ' : '?'; } } $string = ''; $j = 0; $b = $i = -1; $mask = \wordwrap($mask, $width, '#', $cut); while (\false !== ($b = \strpos($mask, '#', $b + 1))) { for (++$i; $i < $b; ++$i) { $string .= $chars[$j]; unset($chars[$j++]); } if ($break === $chars[$j] || ' ' === $chars[$j]) { unset($chars[$j++]); } $string .= $break; } $str = clone $this; $str->string = $string . \implode('', $chars); return $str; } public function __sleep() : array { return ['string']; } public function __clone() { $this->ignoreCase = \false; } public function __toString() : string { return $this->string; } } composer.json 0000777 00000001742 15251261610 0007300 0 ustar 00 { "name": "opis/string", "description": "Multibyte strings as objects", "keywords": ["opis", "string", "utf-8", "multi-byte", "string manipulation"], "homepage": "https://opis.io/string", "license": "Apache-2.0", "authors": [ { "name": "Marius Sarca", "email": "marius.sarca@gmail.com" }, { "name": "Sorin Sarca", "email": "sarca_sorin@hotmail.com" } ], "require": { "php": "^7.4 || ^8.0", "ext-json": "*", "ext-iconv": "*" }, "require-dev": { "phpunit/phpunit": "^9.0" }, "autoload": { "psr-4": { "Opis\\String\\": "src/" } }, "autoload-dev": { "psr-4": { "Opis\\String\\Test\\": "tests/" } }, "scripts": { "tests": "./vendor/bin/phpunit --verbose --color" }, "extra": { "branch-alias": { "dev-master": "2.x-dev" } } } Resources/data/wcswidth_table_zero.php 0000777 00000013073 15251261610 0014214 0 ustar 00 <?php namespace Rvx; /* * This file has been auto-generated by the Symfony String Component for internal use. * * Unicode version: 16.0.0 * Date: 2024-09-11T08:21:22+00:00 */ return [[768, 879], [1155, 1159], [1160, 1161], [1425, 1469], [1471, 1471], [1473, 1474], [1476, 1477], [1479, 1479], [1552, 1562], [1611, 1631], [1648, 1648], [1750, 1756], [1759, 1764], [1767, 1768], [1770, 1773], [1809, 1809], [1840, 1866], [1958, 1968], [2027, 2035], [2045, 2045], [2070, 2073], [2075, 2083], [2085, 2087], [2089, 2093], [2137, 2139], [2199, 2207], [2250, 2273], [2275, 2306], [2362, 2362], [2364, 2364], [2369, 2376], [2381, 2381], [2385, 2391], [2402, 2403], [2433, 2433], [2492, 2492], [2497, 2500], [2509, 2509], [2530, 2531], [2558, 2558], [2561, 2562], [2620, 2620], [2625, 2626], [2631, 2632], [2635, 2637], [2641, 2641], [2672, 2673], [2677, 2677], [2689, 2690], [2748, 2748], [2753, 2757], [2759, 2760], [2765, 2765], [2786, 2787], [2810, 2815], [2817, 2817], [2876, 2876], [2879, 2879], [2881, 2884], [2893, 2893], [2901, 2902], [2914, 2915], [2946, 2946], [3008, 3008], [3021, 3021], [3072, 3072], [3076, 3076], [3132, 3132], [3134, 3136], [3142, 3144], [3146, 3149], [3157, 3158], [3170, 3171], [3201, 3201], [3260, 3260], [3263, 3263], [3270, 3270], [3276, 3277], [3298, 3299], [3328, 3329], [3387, 3388], [3393, 3396], [3405, 3405], [3426, 3427], [3457, 3457], [3530, 3530], [3538, 3540], [3542, 3542], [3633, 3633], [3636, 3642], [3655, 3662], [3761, 3761], [3764, 3772], [3784, 3790], [3864, 3865], [3893, 3893], [3895, 3895], [3897, 3897], [3953, 3966], [3968, 3972], [3974, 3975], [3981, 3991], [3993, 4028], [4038, 4038], [4141, 4144], [4146, 4151], [4153, 4154], [4157, 4158], [4184, 4185], [4190, 4192], [4209, 4212], [4226, 4226], [4229, 4230], [4237, 4237], [4253, 4253], [4957, 4959], [5906, 5908], [5938, 5939], [5970, 5971], [6002, 6003], [6068, 6069], [6071, 6077], [6086, 6086], [6089, 6099], [6109, 6109], [6155, 6157], [6159, 6159], [6277, 6278], [6313, 6313], [6432, 6434], [6439, 6440], [6450, 6450], [6457, 6459], [6679, 6680], [6683, 6683], [6742, 6742], [6744, 6750], [6752, 6752], [6754, 6754], [6757, 6764], [6771, 6780], [6783, 6783], [6832, 6845], [6846, 6846], [6847, 6862], [6912, 6915], [6964, 6964], [6966, 6970], [6972, 6972], [6978, 6978], [7019, 7027], [7040, 7041], [7074, 7077], [7080, 7081], [7083, 7085], [7142, 7142], [7144, 7145], [7149, 7149], [7151, 7153], [7212, 7219], [7222, 7223], [7376, 7378], [7380, 7392], [7394, 7400], [7405, 7405], [7412, 7412], [7416, 7417], [7616, 7679], [8400, 8412], [8413, 8416], [8417, 8417], [8418, 8420], [8421, 8432], [11503, 11505], [11647, 11647], [11744, 11775], [12330, 12333], [12441, 12442], [42607, 42607], [42608, 42610], [42612, 42621], [42654, 42655], [42736, 42737], [43010, 43010], [43014, 43014], [43019, 43019], [43045, 43046], [43052, 43052], [43204, 43205], [43232, 43249], [43263, 43263], [43302, 43309], [43335, 43345], [43392, 43394], [43443, 43443], [43446, 43449], [43452, 43453], [43493, 43493], [43561, 43566], [43569, 43570], [43573, 43574], [43587, 43587], [43596, 43596], [43644, 43644], [43696, 43696], [43698, 43700], [43703, 43704], [43710, 43711], [43713, 43713], [43756, 43757], [43766, 43766], [44005, 44005], [44008, 44008], [44013, 44013], [64286, 64286], [65024, 65039], [65056, 65071], [66045, 66045], [66272, 66272], [66422, 66426], [68097, 68099], [68101, 68102], [68108, 68111], [68152, 68154], [68159, 68159], [68325, 68326], [68900, 68903], [68969, 68973], [69291, 69292], [69372, 69375], [69446, 69456], [69506, 69509], [69633, 69633], [69688, 69702], [69744, 69744], [69747, 69748], [69759, 69761], [69811, 69814], [69817, 69818], [69826, 69826], [69888, 69890], [69927, 69931], [69933, 69940], [70003, 70003], [70016, 70017], [70070, 70078], [70089, 70092], [70095, 70095], [70191, 70193], [70196, 70196], [70198, 70199], [70206, 70206], [70209, 70209], [70367, 70367], [70371, 70378], [70400, 70401], [70459, 70460], [70464, 70464], [70502, 70508], [70512, 70516], [70587, 70592], [70606, 70606], [70608, 70608], [70610, 70610], [70625, 70626], [70712, 70719], [70722, 70724], [70726, 70726], [70750, 70750], [70835, 70840], [70842, 70842], [70847, 70848], [70850, 70851], [71090, 71093], [71100, 71101], [71103, 71104], [71132, 71133], [71219, 71226], [71229, 71229], [71231, 71232], [71339, 71339], [71341, 71341], [71344, 71349], [71351, 71351], [71453, 71453], [71455, 71455], [71458, 71461], [71463, 71467], [71727, 71735], [71737, 71738], [71995, 71996], [71998, 71998], [72003, 72003], [72148, 72151], [72154, 72155], [72160, 72160], [72193, 72202], [72243, 72248], [72251, 72254], [72263, 72263], [72273, 72278], [72281, 72283], [72330, 72342], [72344, 72345], [72752, 72758], [72760, 72765], [72767, 72767], [72850, 72871], [72874, 72880], [72882, 72883], [72885, 72886], [73009, 73014], [73018, 73018], [73020, 73021], [73023, 73029], [73031, 73031], [73104, 73105], [73109, 73109], [73111, 73111], [73459, 73460], [73472, 73473], [73526, 73530], [73536, 73536], [73538, 73538], [73562, 73562], [78912, 78912], [78919, 78933], [90398, 90409], [90413, 90415], [92912, 92916], [92976, 92982], [94031, 94031], [94095, 94098], [94180, 94180], [113821, 113822], [118528, 118573], [118576, 118598], [119143, 119145], [119163, 119170], [119173, 119179], [119210, 119213], [119362, 119364], [121344, 121398], [121403, 121452], [121461, 121461], [121476, 121476], [121499, 121503], [121505, 121519], [122880, 122886], [122888, 122904], [122907, 122913], [122915, 122916], [122918, 122922], [123023, 123023], [123184, 123190], [123566, 123566], [123628, 123631], [124140, 124143], [124398, 124399], [125136, 125142], [125252, 125258], [917760, 917999]]; Resources/data/wcswidth_table_wide.php 0000777 00000011540 15251261610 0014162 0 ustar 00 <?php namespace Rvx; /* * This file has been auto-generated by the Symfony String Component for internal use. * * Unicode version: 16.0.0 * Date: 2024-09-11T08:21:22+00:00 */ return [[4352, 4447], [8986, 8987], [9001, 9001], [9002, 9002], [9193, 9196], [9200, 9200], [9203, 9203], [9725, 9726], [9748, 9749], [9776, 9783], [9800, 9811], [9855, 9855], [9866, 9871], [9875, 9875], [9889, 9889], [9898, 9899], [9917, 9918], [9924, 9925], [9934, 9934], [9940, 9940], [9962, 9962], [9970, 9971], [9973, 9973], [9978, 9978], [9981, 9981], [9989, 9989], [9994, 9995], [10024, 10024], [10060, 10060], [10062, 10062], [10067, 10069], [10071, 10071], [10133, 10135], [10160, 10160], [10175, 10175], [11035, 11036], [11088, 11088], [11093, 11093], [11904, 11929], [11931, 12019], [12032, 12245], [12272, 12287], [12288, 12288], [12289, 12291], [12292, 12292], [12293, 12293], [12294, 12294], [12295, 12295], [12296, 12296], [12297, 12297], [12298, 12298], [12299, 12299], [12300, 12300], [12301, 12301], [12302, 12302], [12303, 12303], [12304, 12304], [12305, 12305], [12306, 12307], [12308, 12308], [12309, 12309], [12310, 12310], [12311, 12311], [12312, 12312], [12313, 12313], [12314, 12314], [12315, 12315], [12316, 12316], [12317, 12317], [12318, 12319], [12320, 12320], [12321, 12329], [12330, 12333], [12334, 12335], [12336, 12336], [12337, 12341], [12342, 12343], [12344, 12346], [12347, 12347], [12348, 12348], [12349, 12349], [12350, 12350], [12353, 12438], [12441, 12442], [12443, 12444], [12445, 12446], [12447, 12447], [12448, 12448], [12449, 12538], [12539, 12539], [12540, 12542], [12543, 12543], [12549, 12591], [12593, 12686], [12688, 12689], [12690, 12693], [12694, 12703], [12704, 12735], [12736, 12773], [12783, 12783], [12784, 12799], [12800, 12830], [12832, 12841], [12842, 12871], [12880, 12880], [12881, 12895], [12896, 12927], [12928, 12937], [12938, 12976], [12977, 12991], [12992, 13055], [13056, 13311], [13312, 19903], [19904, 19967], [19968, 40959], [40960, 40980], [40981, 40981], [40982, 42124], [42128, 42182], [43360, 43388], [44032, 55203], [63744, 64109], [64110, 64111], [64112, 64217], [64218, 64255], [65040, 65046], [65047, 65047], [65048, 65048], [65049, 65049], [65072, 65072], [65073, 65074], [65075, 65076], [65077, 65077], [65078, 65078], [65079, 65079], [65080, 65080], [65081, 65081], [65082, 65082], [65083, 65083], [65084, 65084], [65085, 65085], [65086, 65086], [65087, 65087], [65088, 65088], [65089, 65089], [65090, 65090], [65091, 65091], [65092, 65092], [65093, 65094], [65095, 65095], [65096, 65096], [65097, 65100], [65101, 65103], [65104, 65106], [65108, 65111], [65112, 65112], [65113, 65113], [65114, 65114], [65115, 65115], [65116, 65116], [65117, 65117], [65118, 65118], [65119, 65121], [65122, 65122], [65123, 65123], [65124, 65126], [65128, 65128], [65129, 65129], [65130, 65131], [65281, 65283], [65284, 65284], [65285, 65287], [65288, 65288], [65289, 65289], [65290, 65290], [65291, 65291], [65292, 65292], [65293, 65293], [65294, 65295], [65296, 65305], [65306, 65307], [65308, 65310], [65311, 65312], [65313, 65338], [65339, 65339], [65340, 65340], [65341, 65341], [65342, 65342], [65343, 65343], [65344, 65344], [65345, 65370], [65371, 65371], [65372, 65372], [65373, 65373], [65374, 65374], [65375, 65375], [65376, 65376], [65504, 65505], [65506, 65506], [65507, 65507], [65508, 65508], [65509, 65510], [94176, 94177], [94178, 94178], [94179, 94179], [94180, 94180], [94192, 94193], [94208, 100343], [100352, 101119], [101120, 101589], [101631, 101631], [101632, 101640], [110576, 110579], [110581, 110587], [110589, 110590], [110592, 110847], [110848, 110882], [110898, 110898], [110928, 110930], [110933, 110933], [110948, 110951], [110960, 111355], [119552, 119638], [119648, 119670], [126980, 126980], [127183, 127183], [127374, 127374], [127377, 127386], [127488, 127490], [127504, 127547], [127552, 127560], [127568, 127569], [127584, 127589], [127744, 127776], [127789, 127797], [127799, 127868], [127870, 127891], [127904, 127946], [127951, 127955], [127968, 127984], [127988, 127988], [127992, 127994], [127995, 127999], [128000, 128062], [128064, 128064], [128066, 128252], [128255, 128317], [128331, 128334], [128336, 128359], [128378, 128378], [128405, 128406], [128420, 128420], [128507, 128511], [128512, 128591], [128640, 128709], [128716, 128716], [128720, 128722], [128725, 128727], [128732, 128735], [128747, 128748], [128756, 128764], [128992, 129003], [129008, 129008], [129292, 129338], [129340, 129349], [129351, 129535], [129648, 129660], [129664, 129673], [129679, 129734], [129742, 129756], [129759, 129769], [129776, 129784], [131072, 173791], [173792, 173823], [173824, 177977], [177978, 177983], [177984, 178205], [178206, 178207], [178208, 183969], [183970, 183983], [183984, 191456], [191457, 191471], [191472, 192093], [192094, 194559], [194560, 195101], [195102, 195103], [195104, 196605], [196608, 201546], [201547, 201551], [201552, 205743], [205744, 262141]]; Resources/functions.php 0000777 00000001541 15251261610 0011246 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Rvx\Symfony\Component\String; if (!\function_exists(u::class)) { function u(?string $string = '') : UnicodeString { return new UnicodeString($string ?? ''); } } if (!\function_exists(b::class)) { function b(?string $string = '') : ByteString { return new ByteString($string ?? ''); } } if (!\function_exists(s::class)) { /** * @return UnicodeString|ByteString */ function s(?string $string = '') : AbstractString { $string = $string ?? ''; return \preg_match('//u', $string) ? new UnicodeString($string) : new ByteString($string); } } CHANGELOG.md 0000777 00000001504 15251261610 0006363 0 ustar 00 CHANGELOG ========= 5.4 --- * Add `trimSuffix()` and `trimPrefix()` methods 5.3 --- * Made `AsciiSlugger` fallback to parent locale's symbolsMap 5.2.0 ----- * added a `FrenchInflector` class 5.1.0 ----- * added the `AbstractString::reverse()` method * made `AbstractString::width()` follow POSIX.1-2001 * added `LazyString` which provides memoizing stringable objects * The component is not marked as `@experimental` anymore * added the `s()` helper method to get either an `UnicodeString` or `ByteString` instance, depending of the input string UTF-8 compliancy * added `$cut` parameter to `Symfony\Component\String\AbstractString::truncate()` * added `AbstractString::containsAny()` * allow passing a string of custom characters to `ByteString::fromRandom()` 5.0.0 ----- * added the component as experimental src/Exception/InvalidCodePointException.php 0000777 00000002450 15251721406 0015067 0 ustar 00 <?php /* =========================================================================== * Copyright 2020-2021 Zindex Software * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ============================================================================ */ namespace Opis\String\Exception; use Throwable; class InvalidCodePointException extends UnicodeException { /** * @var mixed */ protected $codePoint; /** * @param $codePoint * @param Throwable|null $previous */ public function __construct($codePoint, ?Throwable $previous = null) { parent::__construct("Invalid code point", 0, $previous); $this->codePoint = $codePoint; } /** * @return mixed */ public function codePoint() { return$this->codePoint; } } src/Exception/InvalidStringException.php 0000777 00000003077 15251721406 0014457 0 ustar 00 <?php /* =========================================================================== * Copyright 2020-2021 Zindex Software * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ============================================================================ */ namespace Opis\String\Exception; use Throwable; class InvalidStringException extends UnicodeException { /** * @var string */ protected string $string; /** * @var int */ protected int $offset; /** * @param string $string * @param int $offset * @param Throwable|null $previous */ public function __construct(string $string, int $offset = -1, ?Throwable $previous = null) { parent::__construct("Invalid UTF-8 string at offset {$offset}", 0, $previous); $this->string = $string; $this->offset = $offset; } /** * @return string */ public function string(): string { return $this->string; } /** * @return int */ public function offset(): int { return $this->offset; } } src/Exception/UnicodeException.php 0000777 00000001553 15251721406 0013265 0 ustar 00 <?php /* =========================================================================== * Copyright 2020-2021 Zindex Software * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ============================================================================ */ namespace Opis\String\Exception; use RuntimeException; class UnicodeException extends RuntimeException { } src/UnicodeString.php 0000777 00000127574 15251721406 0010653 0 ustar 00 <?php /* =========================================================================== * Copyright 2018-2021 Zindex Software * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ============================================================================ */ namespace Opis\String; use RuntimeException; use OutOfBoundsException; use Countable, ArrayAccess; use JsonSerializable; use Opis\String\Exception\{ UnicodeException, InvalidStringException, InvalidCodePointException }; class UnicodeString implements Countable, ArrayAccess, JsonSerializable { const KEEP_CASE = 0; const LOWER_CASE = 1; const UPPER_CASE = 2; const FOLD_CASE = 3; const ASCII_CONV = 4; /** * @var int[] */ private array $codes; /** * @var string[]|null */ private ?array $chars = null; private int $length; private ?string $str = null; private ?array $cache = null; /** * @var int[][] */ private static array $maps = []; /** * @param int[] $codes */ private function __construct(array $codes = []) { $this->codes = $codes; $this->length = count($codes); } /** * @return int[] */ public function codePoints(): array { return $this->codes; } /** * @return string[] */ public function chars(): array { if ($this->chars === null) { $this->chars = self::getCharsFromCodePoints($this->codes); } return $this->chars; } /** * @return int */ public function length(): int { return $this->length; } /** * @return bool */ public function isEmpty(): bool { return $this->length === 0; } /** * @param string|self|int[]|string[] $text * @param bool $ignoreCase * @return bool */ public function equals($text, bool $ignoreCase = false): bool { return $this->compareTo($text, $ignoreCase) === 0; } /** * @param string|self|int[]|string[] $text * @param bool $ignoreCase * @return int */ public function compareTo($text, bool $ignoreCase = false): int { $mode = $ignoreCase ? self::FOLD_CASE : self::KEEP_CASE; $text = self::resolveCodePoints($text, $mode); $length = count($text); if ($length !== $this->length) { return $this->length <=> $length; } return $this->getMappedCodes($mode) <=> $text; } /** * @param string|self|int[]|string[] $text * @param bool $ignoreCase * @return bool */ public function contains($text, bool $ignoreCase = false): bool { return $this->indexOf($text, 0, $ignoreCase) !== -1; } /** * @param string|self|int[]|string[] $text * @param bool $ignoreCase * @return bool */ public function startsWith($text, bool $ignoreCase = false): bool { $mode = $ignoreCase ? self::FOLD_CASE : self::KEEP_CASE; $text = self::resolveCodePoints($text, $mode); $len = count($text); if ($len === 0 || $len > $this->length) { return false; } return array_slice($this->getMappedCodes($mode), 0, $len) === $text; } /** * @param string|self|int[]|string[] $text * @param bool $ignoreCase * @return bool */ public function endsWith($text, bool $ignoreCase = false): bool { $mode = $ignoreCase ? self::FOLD_CASE : self::KEEP_CASE; $text = self::resolveCodePoints($text, $mode); if (empty($text)) { return false; } $codes = $this->getMappedCodes($mode); $offset = $this->length - count($text); if ($offset < 0) { return false; } return array_slice($codes, $offset) === $text; } /** * @param string|self|int[]|string[] $text * @param int $offset * @param bool $ignoreCase * @return int */ public function indexOf($text, int $offset = 0, bool $ignoreCase = false): int { if ($offset < 0) { $offset += $this->length; } if ($offset < 0 || $offset >= $this->length) { return -1; } $mode = $ignoreCase ? self::FOLD_CASE : self::KEEP_CASE; $text = self::resolveCodePoints($text, $mode); $len = count($text); if ($len === 0 || $offset + $len > $this->length) { return -1; } return $this->doIndexOf($this->getMappedCodes($mode), $text, $offset); } /** * @param string|self|int[]|string[] $text * @param int $offset * @param bool $ignoreCase * @return int */ public function lastIndexOf($text, int $offset = 0, bool $ignoreCase = false): int { if ($offset < 0) { $start = $this->length + $offset; if ($start < 0) { return -1; } $last = 0; } else { if ($offset >= $this->length) { return -1; } $start = $this->length - 1; $last = $offset; } $mode = $ignoreCase ? self::FOLD_CASE : self::KEEP_CASE; $text = self::resolveCodePoints($text, $mode); $len = count($text); if ($len === 0) { return -1; } if ($offset < 0) { if ($len > $this->length) { return -1; } $start = min($start, $this->length - $len); } elseif ($offset + $len > $this->length) { return -1; } $codes = $this->getMappedCodes($mode); for ($i = $start; $i >= $last; $i--) { $match = true; for ($j = 0; $j < $len; $j++) { if ($codes[$i + $j] !== $text[$j]) { $match = false; break; } } if ($match) { return $i; } } return -1; } /** * @param string|self|int[]|string[] $text * @param bool $ignoreCase * @param bool $allowPrefixOnly If true the result can contain only the prefix * @return $this */ public function ensurePrefix($text, bool $ignoreCase = false, bool $allowPrefixOnly = true): self { $text = self::resolveCodePoints($text); $len = count($text); if ($len === 0) { return clone $this; } if ($this->length === 0) { return new static($text); } if ($ignoreCase) { $prefix = self::getMappedCodePoints($text, self::FOLD_CASE); } else { $prefix = &$text; } if ($this->length === $len) { $part = $this->getMappedCodes($ignoreCase ? self::FOLD_CASE : self::KEEP_CASE); if ($allowPrefixOnly && $part === $prefix) { return clone $this; } // Remove last element to avoid double check array_pop($part); } elseif ($this->length < $len) { $part = $this->getMappedCodes($ignoreCase ? self::FOLD_CASE : self::KEEP_CASE); // Checks if this can be a suffix if ($allowPrefixOnly && (array_slice($prefix, 0, $this->length) === $part)) { $text = array_slice($text, $this->length); return new static(array_merge($this->codes, $text)); } } else { $part = array_slice($this->codes, 0, $len); if ($ignoreCase) { $part = self::getMappedCodePoints($part, self::FOLD_CASE); } if ($part === $prefix) { return clone $this; } // Remove last element to avoid double check array_pop($part); } $copy = $len; $part_len = count($part); while ($part_len) { if ($part === array_slice($prefix, -$part_len)) { $copy = $len - $part_len; break; } array_pop($part); $part_len--; } if ($copy === 0) { return clone $this; } if ($copy < $len) { $text = array_slice($text, 0, $copy); } return new static(array_merge($text, $this->codes)); } /** * @param string|self|int[]|string[] $text * @param bool $ignoreCase * @param bool $allowSuffixOnly If true the result can contain only the suffix * @return static */ public function ensureSuffix($text, bool $ignoreCase = false, bool $allowSuffixOnly = true): self { $text = self::resolveCodePoints($text); $len = count($text); if ($len === 0) { return clone $this; } if ($this->length === 0) { return new static($text); } if ($ignoreCase) { $suffix = self::getMappedCodePoints($text, self::FOLD_CASE); } else { $suffix = &$text; } if ($this->length === $len) { $part = $this->getMappedCodes($ignoreCase ? self::FOLD_CASE : self::KEEP_CASE); if ($allowSuffixOnly && $part === $suffix) { return clone $this; } // Remove first element to avoid double check array_shift($part); } elseif ($this->length < $len) { $part = $this->getMappedCodes($ignoreCase ? self::FOLD_CASE : self::KEEP_CASE); // Checks if this can be a prefix if ($allowSuffixOnly && (array_slice($suffix, -$this->length) === $part)) { $text = array_slice($text, 0, $len - $this->length); return new static(array_merge($text, $this->codes)); } } else { $part = array_slice($this->codes, -$len); if ($ignoreCase) { $part = self::getMappedCodePoints($part, self::FOLD_CASE); } if ($part === $suffix) { return clone $this; } // Remove first element to avoid double check array_shift($part); } $skip = 0; $part_len = count($part); while ($part_len) { if ($part === array_slice($suffix, 0, $part_len)) { $skip = $part_len; break; } array_shift($part); $part_len--; } if ($skip === $len) { return clone $this; } if ($skip) { array_splice($text, 0, $skip); } return new static(array_merge($this->codes, $text)); } /** * @param string|self|int[]|string[] $text * @param int $mode * @return static */ public function append($text, int $mode = self::KEEP_CASE): self { return new static(array_merge($this->codes, self::resolveCodePoints($text, $mode))); } /** * @param string|self|int[]|string[] $text * @param int $mode * @return static */ public function prepend($text, int $mode = self::KEEP_CASE): self { return new static(array_merge(self::resolveCodePoints($text, $mode), $this->codes)); } /** * @param string|self|int[]|string[] $text * @param int $offset * @param int $mode * @return static */ public function insert($text, int $offset, int $mode = self::KEEP_CASE): self { $codes = $this->codes; array_splice($codes, $offset, 0, self::resolveCodePoints($text, $mode)); return new static($codes); } /** * @param int $offset * @param int|null $length * @return static */ public function remove(int $offset, ?int $length = null): self { $codes = $this->codes; if ($length === null) { array_splice($codes, $offset); } else { array_splice($codes, $offset, $length); } return new static($codes); } /** * @param string|self|int[]|string[] $mask * @return static */ public function trim($mask = " \t\n\r\0\x0B"): self { return $this->doTrim($mask, true, true); } /** * @param string|self|int[]|string[] $mask * @return static */ public function trimLeft($mask = " \t\n\r\0\x0B"): self { return $this->doTrim($mask, true, false); } /** * @param string|self|int[]|string[] $mask * @return static */ public function trimRight($mask = " \t\n\r\0\x0B"): self { return $this->doTrim($mask, false, true); } /** * @return static */ public function reverse(): self { return new static(array_reverse($this->codes)); } /** * @param int $times * @return static */ public function repeat(int $times = 1): self { if ($times <= 1) { return clone $this; } $codes = []; while ($times--) { $codes = array_merge($codes, $this->codes); } return new static($codes); } /** * @param string|self|int[]|string[] $subject * @param string|self|int[]|string[] $replace * @param int $offset * @param bool $ignoreCase * @return static */ public function replace($subject, $replace, int $offset = 0, bool $ignoreCase = false): self { if ($offset < 0) { $offset += $this->length; } if ($offset < 0 || $offset >= $this->length) { return clone $this; } $mode = $ignoreCase ? self::FOLD_CASE : self::KEEP_CASE; $subject = self::resolveCodePoints($subject, $mode); $len = count($subject); if ($len === 0 || $offset + $len > $this->length) { return clone $this; } $offset = $this->doIndexOf($this->getMappedCodes($mode), $subject, $offset); if ($offset === -1) { return clone $this; } $codes = $this->codes; array_splice($codes, $offset, count($subject), self::resolveCodePoints($replace)); return new static($codes); } /** * @param string|self|int[]|string[] $subject * @param string|self|int[]|string[] $replace * @param bool $ignoreCase * @param int $offset * @return static */ public function replaceAll($subject, $replace, int $offset = 0, bool $ignoreCase = false): self { if ($offset < 0) { $offset += $this->length; } if ($offset < 0 || $offset >= $this->length) { return clone $this; } $mode = $ignoreCase ? self::FOLD_CASE : self::KEEP_CASE; $subject = self::resolveCodePoints($subject, $mode); $len = count($subject); if ($len === 0 || $offset + $len > $this->length) { return clone $this; } $replace = self::resolveCodePoints($replace); $codes = $this->getMappedCodes($mode); $copy = $this->codes; $fix = count($replace) - $len; $t = 0; while (($pos = $this->doIndexOf($codes, $subject, $offset)) >= 0) { array_splice($copy, $pos + $t * $fix, $len, $replace); $offset = $pos + $len; $t++; } return new static($copy); } /** * @param string|self|int[]|string[] $delimiter * @param bool $ignoreCase * @return array */ public function split($delimiter = '', bool $ignoreCase = false): array { $mode = $ignoreCase ? self::FOLD_CASE : self::KEEP_CASE; $delimiter = self::resolveCodePoints($delimiter, $mode); $len = count($delimiter); $ret = []; if ($len === 0) { foreach ($this->codes as $code) { $ret[] = new static([$code]); } } else { $codes = $this->getMappedCodes($mode); $offset = 0; while (($pos = $this->doIndexOf($codes, $delimiter, $offset)) >= 0) { $ret[] = new static(array_slice($this->codes, $offset, $pos - $offset)); $offset = $pos + $len; } $ret[] = new static(array_slice($this->codes, $offset)); } return $ret; } /** * @param int $start * @param int|null $length * @return static */ public function substring(int $start, ?int $length = null): self { return new static(array_slice($this->codes, $start, $length)); } /** * @param int $size If negative then pad left otherwise pad right * @param self|string|int $char A char or a code point * @return static */ public function pad(int $size, $char = 0x20): self { return new static(array_pad($this->codes, $size, self::resolveFirstCodePoint($char, 0x20))); } /** * @param int $size * @param self|string|int $char * @return static */ public function padLeft(int $size, $char = 0x20): self { if ($size > 0) { $size = -$size; } return $this->pad($size, $char); } /** * @param int $size * @param self|string|int $char * @return static */ public function padRight(int $size, $char = 0x20): self { if ($size < 0) { $size = -$size; } return $this->pad($size, $char); } /** * @return bool */ public function isLowerCase(): bool { return $this->isCase(self::LOWER_CASE); } /** * @return bool */ public function isUpperCase(): bool { return $this->isCase(self::UPPER_CASE); } /** * @return bool */ public function isAscii(): bool { $key = 'i' . self::ASCII_CONV; if (!isset($this->cache[$key])) { $ok = true; foreach ($this->codes as $code) { if ($code >= 0x80) { $ok = false; break; } } $this->cache[$key] = $ok; } return $this->cache[$key]; } /** * Convert all chars to lower case (where possible) * @return static */ public function toLower(): self { if ($this->cache['i' . self::LOWER_CASE] ?? false) { return clone $this; } return new static($this->getMappedCodes(self::LOWER_CASE)); } /** * Convert all chars to upper case (where possible) * @return static */ public function toUpper(): self { if ($this->cache['i' . self::UPPER_CASE] ?? false) { return clone $this; } return new static($this->getMappedCodes(self::UPPER_CASE)); } /** * Converts all chars to their ASCII equivalent (if any) * @return static */ public function toAscii(): self { if ($this->cache['i' . self::ASCII_CONV] ?? false) { return clone $this; } return new static($this->getMappedCodes(self::ASCII_CONV)); } /** * @param int $index * @return string */ public function charAt(int $index): string { // Allow negative index if ($index < 0 && $index + $this->length >= 0) { $index += $this->length; } if ($index < 0 || $index >= $this->length) { return ''; } return $this->chars()[$index]; } /** * @param int $index * @return int */ public function codePointAt(int $index): int { // Allow negative index if ($index < 0 && $index + $this->length >= 0) { $index += $this->length; } if ($index < 0 || $index >= $this->length) { return -1; } return $this->codes[$index]; } /** * @param int $offset * @return int */ public function __invoke(int $offset): int { if ($offset < 0) { if ($offset + $this->length < 0) { throw new OutOfBoundsException("Undefined offset: {$offset}"); } $offset += $this->length; } elseif ($offset >= $this->length) { throw new OutOfBoundsException("Undefined offset: {$offset}"); } return $this->codes[$offset]; } /** * @inheritDoc */ public function offsetExists($offset): bool { // Allow negative index if ($offset < 0) { $offset += $this->length; } return isset($this->codes[$offset]); } /** * @inheritDoc */ public function offsetGet($offset): string { if ($offset < 0) { if ($offset + $this->length < 0) { throw new OutOfBoundsException("Undefined offset: {$offset}"); } $offset += $this->length; } elseif ($offset >= $this->length) { throw new OutOfBoundsException("Undefined offset: {$offset}"); } return $this->chars()[$offset]; } /** * @inheritDoc */ #[\ReturnTypeWillChange] public function offsetSet($offset, $value) { // Allow negative index if ($offset < 0) { $offset += $this->length; } if (!isset($this->codes[$offset])) { return; } $value = self::resolveFirstCodePoint($value); if ($value === -1) { return; } if ($value === $this->codes[$offset]) { // Same value, nothing to do return; } $this->codes[$offset] = $value; // Clear cache $this->str = null; $this->cache = null; if ($this->chars) { $this->chars[$offset] = self::getCharFromCodePoint($value); } } /** * @inheritDoc */ #[\ReturnTypeWillChange] public function offsetUnset($offset) { throw new RuntimeException("Invalid operation"); } /** * @inheritDoc */ public function count(): int { return $this->length; } /** * @return string */ public function __toString(): string { if ($this->str === null) { $this->str = self::getStringFromCodePoints($this->codes); } return $this->str; } /** * @inheritDoc */ public function jsonSerialize(): string { return $this->__toString(); } public function __serialize(): array { return [ 'value' => $this->__toString(), ]; } public function __unserialize(array $data): void { $this->str = $data['value']; $this->codes = self::getCodePointsFromString($this->str); $this->length = count($this->codes); } /** * Creates an unicode string instance from raw string * @param string $string * @param string|null $encoding Defaults to UTF-8 * @param int $mode * @return static * @throws InvalidStringException */ public static function from(string $string, ?string $encoding = null, int $mode = self::KEEP_CASE): self { if ($encoding !== null && strcasecmp($encoding, 'UTF-8') !== 0) { if (false === $string = @iconv($encoding, 'UTF-8', $string)) { throw new UnicodeException("Could not convert string from '$encoding' encoding to UTF-8 encoding"); } } $instance = new static(self::getCodePointsFromString($string, $mode)); if ($mode === self::KEEP_CASE) { $instance->str = $string; } return $instance; } /** * Creates an unicode string instance from code points * @param int[] $codes * @param int $mode * @return static * @throws InvalidCodePointException */ public static function fromCodePoints(array $codes, int $mode = self::KEEP_CASE): self { $map = self::getMapByMode($mode); foreach ($codes as &$code) { if (!is_int($codes) || !self::isValidCodePoint($code)) { throw new InvalidCodePointException($code); } else { $code = $map[$code] ?? $code; } } return new static(array_values($codes)); } /** * Converts the code point to corresponding char * @param int $code * @return string The char or an empty string if code point is invalid */ public static function getCharFromCodePoint(int $code): string { if ($code < 0) { return ''; } if ($code < 0x80) { return chr($code); } if ($code < 0x800) { return chr(($code >> 6) + 0xC0) . chr(($code & 0x3F) + 0x80); } if ($code >= 0xD800 && $code <= 0xDFFF) { /* The definition of UTF-8 prohibits encoding character numbers between U+D800 and U+DFFF, which are reserved for use with the UTF-16 encoding form (as surrogate pairs) and do not directly represent characters. */ return ''; } if ($code <= 0xFFFF) { return chr(($code >> 12) + 0xE0) . chr((($code >> 6) & 0x3F) + 0x80) . chr(($code & 0x3F) + 0x80); } if ($code <= 0x10FFFF) { return chr(($code >> 18) + 0xF0) . chr((($code >> 12) & 0x3F) + 0x80) . chr((($code >> 6) & 0x3F) + 0x80) . chr(($code & 0x3F) + 0x80); } /* Restricted the range of characters to 0000-10FFFF (the UTF-16 accessible range). */ return ''; } /** * Convert a string to a code point array * @param string $str * @param int $mode * @return array * @throws InvalidStringException */ public static function getCodePointsFromString(string $str, int $mode = self::KEEP_CASE): array { // 0x00-0x7F // 0xC2-0xDF 0x80-0xBF // 0xE0-0xE0 0xA0-0xBF 0x80-0xBF // 0xE1-0xEC 0x80-0xBF 0x80-0xBF // 0xED-0xED 0x80-0x9F 0x80-0xBF // 0xEE-0xEF 0x80-0xBF 0x80-0xBF // 0xF0-0xF0 0x90-0xBF 0x80-0xBF 0x80-0xBF // 0xF1-0xF3 0x80-0xBF 0x80-0xBF 0x80-0xBF // 0xF4-0xF4 0x80-0x8F 0x80-0xBF 0x80-0xBF $codes = []; $length = strlen($str); $mode = self::getMapByMode($mode); $i = 0; while ($i < $length) { $ord0 = ord($str[$i++]); if ($ord0 < 0x80) { $codes[] = $mode[$ord0] ?? $ord0; continue; } if ($i === $length || $ord0 < 0xC2 || $ord0 > 0xF4) { throw new InvalidStringException($str, $i - 1); } $ord1 = ord($str[$i++]); if ($ord0 < 0xE0) { if ($ord1 < 0x80 || $ord1 >= 0xC0) { throw new InvalidStringException($str, $i - 1); } $ord1 = ($ord0 - 0xC0) * 64 + $ord1 - 0x80; $codes[] = $mode[$ord1] ?? $ord1; continue; } if ($i === $length) { throw new InvalidStringException($str, $i - 1); } $ord2 = ord($str[$i++]); if ($ord0 < 0xF0) { if ($ord0 === 0xE0) { if ($ord1 < 0xA0 || $ord1 >= 0xC0) { throw new InvalidStringException($str, $i - 2); } } elseif ($ord0 === 0xED) { if ($ord1 < 0x80 || $ord1 >= 0xA0) { throw new InvalidStringException($str, $i - 2); } } elseif ($ord1 < 0x80 || $ord1 >= 0xC0) { throw new InvalidStringException($str, $i - 2); } if ($ord2 < 0x80 || $ord2 >= 0xC0) { throw new InvalidStringException($str, $i - 1); } $ord2 = ($ord0 - 0xE0) * 0x1000 + ($ord1 - 0x80) * 64 + $ord2 - 0x80; $codes[] = $mode[$ord2] ?? $ord2; continue; } if ($i === $length) { throw new InvalidStringException($str, $i - 1); } $ord3 = ord($str[$i++]); if ($ord0 < 0xF5) { if ($ord0 === 0xF0) { if ($ord1 < 0x90 || $ord1 >= 0xC0) { throw new InvalidStringException($str, $i - 3); } } elseif ($ord0 === 0xF4) { if ($ord1 < 0x80 || $ord1 >= 0x90) { throw new InvalidStringException($str, $i - 3); } } elseif ($ord1 < 0x80 || $ord1 >= 0xC0) { throw new InvalidStringException($str, $i - 3); } if ($ord2 < 0x80 || $ord2 >= 0xC0) { throw new InvalidStringException($str, $i - 2); } if ($ord3 < 0x80 || $ord3 >= 0xC0) { throw new InvalidStringException($str, $i - 1); } $ord3 = ($ord0 - 0xF0) * 0x40000 + ($ord1 - 0x80) * 0x1000 + ($ord2 - 0x80) * 64 + $ord3 - 0x80; $codes[] = $mode[$ord3] ?? $ord3; continue; } throw new InvalidStringException($str, $i - 1); } return $codes; } /** * @param string $str * @return iterable * * The key represents the current char index * Value is a two element array * - first element is an integer representing the code point * - second element is an array of integers (length 1 to 4) representing bytes */ public static function walkString(string $str): iterable { $i = 0; $length = strlen($str); while ($i < $length) { $index = $i; $ord0 = ord($str[$i++]); if ($ord0 < 0x80) { yield $index => [ $ord0, [$ord0] ]; continue; } if ($i === $length || $ord0 < 0xC2 || $ord0 > 0xF4) { throw new InvalidStringException($str, $i - 1); } $ord1 = ord($str[$i++]); if ($ord0 < 0xE0) { if ($ord1 < 0x80 || $ord1 >= 0xC0) { throw new InvalidStringException($str, $i - 1); } yield $index => [ ($ord0 - 0xC0) * 64 + $ord1 - 0x80, [$ord0, $ord1] ]; continue; } if ($i === $length) { throw new InvalidStringException($str, $i - 1); } $ord2 = ord($str[$i++]); if ($ord0 < 0xF0) { if ($ord0 === 0xE0) { if ($ord1 < 0xA0 || $ord1 >= 0xC0) { throw new InvalidStringException($str, $i - 2); } } elseif ($ord0 === 0xED) { if ($ord1 < 0x80 || $ord1 >= 0xA0) { throw new InvalidStringException($str, $i - 2); } } elseif ($ord1 < 0x80 || $ord1 >= 0xC0) { throw new InvalidStringException($str, $i - 2); } if ($ord2 < 0x80 || $ord2 >= 0xC0) { throw new InvalidStringException($str, $i - 1); } yield $index => [ ($ord0 - 0xE0) * 0x1000 + ($ord1 - 0x80) * 64 + $ord2 - 0x80, [$ord0, $ord1, $ord2] ]; continue; } if ($i === $length) { throw new InvalidStringException($str, $i - 1); } $ord3 = ord($str[$i++]); if ($ord0 < 0xF5) { if ($ord0 === 0xF0) { if ($ord1 < 0x90 || $ord1 >= 0xC0) { throw new InvalidStringException($str, $i - 3); } } elseif ($ord0 === 0xF4) { if ($ord1 < 0x80 || $ord1 >= 0x90) { throw new InvalidStringException($str, $i - 3); } } elseif ($ord1 < 0x80 || $ord1 >= 0xC0) { throw new InvalidStringException($str, $i - 3); } if ($ord2 < 0x80 || $ord2 >= 0xC0) { throw new InvalidStringException($str, $i - 2); } if ($ord3 < 0x80 || $ord3 >= 0xC0) { throw new InvalidStringException($str, $i - 1); } yield $index => [ ($ord0 - 0xF0) * 0x40000 + ($ord1 - 0x80) * 0x1000 + ($ord2 - 0x80) * 64 + $ord3 - 0x80, [$ord0, $ord1, $ord2, $ord3] ]; continue; } throw new InvalidStringException($str, $i - 1); } } /** * Compute string length * @param string $str * @return int * @throws InvalidStringException */ public static function getStringLength(string $str): int { $count = 0; $length = strlen($str); $i = 0; while ($i < $length) { $ord0 = ord($str[$i++]); if ($ord0 < 0x80) { $count++; continue; } if ($i === $length || $ord0 < 0xC2 || $ord0 > 0xF4) { throw new InvalidStringException($str, $i - 1); } $ord1 = ord($str[$i++]); if ($ord0 < 0xE0) { if ($ord1 < 0x80 || $ord1 >= 0xC0) { throw new InvalidStringException($str, $i - 1); } // $ord1 = ($ord0 - 0xC0) * 64 + $ord1 - 0x80; $count++; continue; } if ($i === $length) { throw new InvalidStringException($str, $i - 1); } $ord2 = ord($str[$i++]); if ($ord0 < 0xF0) { if ($ord0 === 0xE0) { if ($ord1 < 0xA0 || $ord1 >= 0xC0) { throw new InvalidStringException($str, $i - 2); } } elseif ($ord0 === 0xED) { if ($ord1 < 0x80 || $ord1 >= 0xA0) { throw new InvalidStringException($str, $i - 2); } } elseif ($ord1 < 0x80 || $ord1 >= 0xC0) { throw new InvalidStringException($str, $i - 2); } if ($ord2 < 0x80 || $ord2 >= 0xC0) { throw new InvalidStringException($str, $i - 1); } // $ord2 = ($ord0 - 0xE0) * 0x1000 + ($ord1 - 0x80) * 64 + $ord2 - 0x80; $count++; continue; } if ($i === $length) { throw new InvalidStringException($str, $i - 1); } $ord3 = ord($str[$i++]); if ($ord0 < 0xF5) { if ($ord0 === 0xF0) { if ($ord1 < 0x90 || $ord1 >= 0xC0) { throw new InvalidStringException($str, $i - 3); } } elseif ($ord0 === 0xF4) { if ($ord1 < 0x80 || $ord1 >= 0x90) { throw new InvalidStringException($str, $i - 3); } } elseif ($ord1 < 0x80 || $ord1 >= 0xC0) { throw new InvalidStringException($str, $i - 3); } if ($ord2 < 0x80 || $ord2 >= 0xC0) { throw new InvalidStringException($str, $i - 2); } if ($ord3 < 0x80 || $ord3 >= 0xC0) { throw new InvalidStringException($str, $i - 1); } // $ord3 = ($ord0 - 0xF0) * 0x40000 + ($ord1 - 0x80) * 0x1000 + ($ord2 - 0x80) * 64 + $ord3 - 0x80; $count++; continue; } throw new InvalidStringException($str, $i - 1); } return $count; } /** * Converts each code point to a char * @param array $codes * @param int $mode * @return array * @throws InvalidCodePointException */ public static function getCharsFromCodePoints(array $codes, int $mode = self::KEEP_CASE): array { $mode = self::getMapByMode($mode); foreach ($codes as &$code) { $char = self::getCharFromCodePoint($mode[$code] ?? $code); if ($char === '') { throw new InvalidCodePointException($code); } else { $code = $char; } } return $codes; } /** * @param string $str * @param int $mode * @return string[] */ public static function getCharsFromString(string $str, int $mode = self::KEEP_CASE): array { return self::getCharsFromCodePoints(self::getCodePointsFromString($str), $mode); } /** * Converts all code points to chars and returns the string * Invalid code points are ignored * @param array $codes * @param int $mode * @return string */ public static function getStringFromCodePoints(array $codes, int $mode = self::KEEP_CASE): string { $str = ''; $mode = self::getMapByMode($mode); foreach ($codes as $code) { if (isset($mode[$code])) { $code = $mode[$code]; } if ($code < 0x80) { $str .= chr($code); continue; } if ($code < 0x800) { $str .= chr(($code >> 6) + 0xC0) . chr(($code & 0x3F) + 0x80); continue; } if ($code >= 0xD800 && $code <= 0xDFFF) { continue; } if ($code <= 0xFFFF) { $str .= chr(($code >> 12) + 0xE0) . chr((($code >> 6) & 0x3F) + 0x80) . chr(($code & 0x3F) + 0x80); continue; } if ($code <= 0x10FFFF) { $str .= chr(($code >> 18) + 0xF0) . chr((($code >> 12) & 0x3F) + 0x80) . chr((($code >> 6) & 0x3F) + 0x80) . chr(($code & 0x3F) + 0x80); } } return $str; } /** * @param array $codes * @param int $mode * @return array */ public static function getMappedCodePoints(array $codes, int $mode): array { if ($mode === self::KEEP_CASE) { return $codes; } $mode = self::getMapByMode($mode); if (empty($mode)) { return $codes; } foreach ($codes as &$code) { $code = $mode[$code] ?? $code; } return $codes; } /** * Checks if a code point is valid * @param int $code * @return bool */ public static function isValidCodePoint(int $code): bool { if ($code < 0 || $code > 0x10FFFF) { return false; } return $code < 0xD800 || $code > 0xDFFF; } /** * @param int $mode * @return int[] */ private function getMappedCodes(int $mode): array { if ($mode === self::KEEP_CASE || ($this->cache['i' . $mode] ?? false)) { return $this->codes; } $key = 'm' . $mode; if (!isset($this->cache[$key])) { $this->cache[$key] = self::getMappedCodePoints($this->codes, $mode); } return $this->cache[$key]; } /** * @param int $mode * @return bool */ private function isCase(int $mode): bool { $key = 'i' . $mode; if (!isset($this->cache[$key])) { $list = self::getMapByMode($mode); foreach ($this->codes as $code) { if (isset($list[$code])) { return $this->cache[$key] = false; } } return $this->cache[$key] = true; } return $this->cache[$key]; } /** * @param int[] $codes * @param int[] $text * @param int $offset * @return int */ private function doIndexOf(array $codes, array $text, int $offset = 0): int { $len = count($text); for ($i = $offset, $last = count($codes) - $len; $i <= $last; $i++) { $match = true; for ($j = 0; $j < $len; $j++) { if ($codes[$i + $j] !== $text[$j]) { $match = false; break; } } if ($match) { return $i; } } return -1; } /** * @param string|self|int[]|string[] $mask * @param bool $left * @param bool $right * @return static */ private function doTrim($mask, bool $left, bool $right): self { if ($this->length === 0) { return clone $this; } $mask = self::resolveCodePoints($mask); if (empty($mask)) { return clone $this; } $codes = $this->codes; if ($left) { while (in_array($codes[0], $mask, true)) { array_shift($codes); if (empty($codes)) { return new static(); } } } if ($right) { $last = count($codes) - 1; while (in_array($codes[$last], $mask, true)) { array_pop($codes); if (--$last < 0) { return new static(); } } } return new static($codes); } /** * @param string|self|int[]|string[] $text * @param int $mode * @return array */ private static function resolveCodePoints($text, int $mode = self::KEEP_CASE): array { if ($text instanceof self) { return $text->getMappedCodes($mode); } if (is_string($text)) { return self::getCodePointsFromString($text, $mode); } if ($text && is_array($text) && is_int($text[0])) { // assume code point array return self::getMappedCodePoints($text, $mode); } return []; } /** * @param self|string|int|string[]|int[] $text * @param int $invalid * @return int */ private static function resolveFirstCodePoint($text, int $invalid = -1): int { if ($text instanceof self) { return $text->length === 0 ? $invalid : $text->codes[0]; } if (is_array($text)) { if (empty($text)) { return $invalid; } $text = reset($text); } if (is_string($text)) { if (isset($text[4])) { $text = substr($text, 0, 4); } return self::getCodePointsFromString($text)[0] ?? $invalid; } if (is_int($text)) { return self::isValidCodePoint($text) ? $text : $invalid; } return $invalid; } /** * @param int $mode * @return int[] */ private static function getMapByMode(int $mode): array { if (isset(self::$maps[$mode])) { return self::$maps[$mode]; } switch ($mode) { case self::LOWER_CASE: $file = 'lower'; break; case self::UPPER_CASE: $file = 'upper'; break; case self::ASCII_CONV: $file = 'ascii'; break; case self::FOLD_CASE: $file = 'fold'; break; default: return []; } /** @noinspection PhpIncludeInspection */ return self::$maps[$mode] = include(__DIR__ . "/../res/{$file}.php"); } } res/upper.php 0000777 00000060255 15251721406 0007223 0 ustar 00 <?php return [ 0x61 => 0x41, 0x62 => 0x42, 0x63 => 0x43, 0x64 => 0x44, 0x65 => 0x45, 0x66 => 0x46, 0x67 => 0x47, 0x68 => 0x48, 0x69 => 0x49, 0x6A => 0x4A, 0x6B => 0x4B, 0x6C => 0x4C, 0x6D => 0x4D, 0x6E => 0x4E, 0x6F => 0x4F, 0x70 => 0x50, 0x71 => 0x51, 0x72 => 0x52, 0x73 => 0x53, 0x74 => 0x54, 0x75 => 0x55, 0x76 => 0x56, 0x77 => 0x57, 0x78 => 0x58, 0x79 => 0x59, 0x7A => 0x5A, 0xB5 => 0x39C, 0xE0 => 0xC0, 0xE1 => 0xC1, 0xE2 => 0xC2, 0xE3 => 0xC3, 0xE4 => 0xC4, 0xE5 => 0xC5, 0xE6 => 0xC6, 0xE7 => 0xC7, 0xE8 => 0xC8, 0xE9 => 0xC9, 0xEA => 0xCA, 0xEB => 0xCB, 0xEC => 0xCC, 0xED => 0xCD, 0xEE => 0xCE, 0xEF => 0xCF, 0xF0 => 0xD0, 0xF1 => 0xD1, 0xF2 => 0xD2, 0xF3 => 0xD3, 0xF4 => 0xD4, 0xF5 => 0xD5, 0xF6 => 0xD6, 0xF8 => 0xD8, 0xF9 => 0xD9, 0xFA => 0xDA, 0xFB => 0xDB, 0xFC => 0xDC, 0xFD => 0xDD, 0xFE => 0xDE, 0xFF => 0x178, 0x101 => 0x100, 0x103 => 0x102, 0x105 => 0x104, 0x107 => 0x106, 0x109 => 0x108, 0x10B => 0x10A, 0x10D => 0x10C, 0x10F => 0x10E, 0x111 => 0x110, 0x113 => 0x112, 0x115 => 0x114, 0x117 => 0x116, 0x119 => 0x118, 0x11B => 0x11A, 0x11D => 0x11C, 0x11F => 0x11E, 0x121 => 0x120, 0x123 => 0x122, 0x125 => 0x124, 0x127 => 0x126, 0x129 => 0x128, 0x12B => 0x12A, 0x12D => 0x12C, 0x12F => 0x12E, 0x131 => 0x49, 0x133 => 0x132, 0x135 => 0x134, 0x137 => 0x136, 0x13A => 0x139, 0x13C => 0x13B, 0x13E => 0x13D, 0x140 => 0x13F, 0x142 => 0x141, 0x144 => 0x143, 0x146 => 0x145, 0x148 => 0x147, 0x14B => 0x14A, 0x14D => 0x14C, 0x14F => 0x14E, 0x151 => 0x150, 0x153 => 0x152, 0x155 => 0x154, 0x157 => 0x156, 0x159 => 0x158, 0x15B => 0x15A, 0x15D => 0x15C, 0x15F => 0x15E, 0x161 => 0x160, 0x163 => 0x162, 0x165 => 0x164, 0x167 => 0x166, 0x169 => 0x168, 0x16B => 0x16A, 0x16D => 0x16C, 0x16F => 0x16E, 0x171 => 0x170, 0x173 => 0x172, 0x175 => 0x174, 0x177 => 0x176, 0x17A => 0x179, 0x17C => 0x17B, 0x17E => 0x17D, 0x17F => 0x53, 0x180 => 0x243, 0x183 => 0x182, 0x185 => 0x184, 0x188 => 0x187, 0x18C => 0x18B, 0x192 => 0x191, 0x195 => 0x1F6, 0x199 => 0x198, 0x19A => 0x23D, 0x19E => 0x220, 0x1A1 => 0x1A0, 0x1A3 => 0x1A2, 0x1A5 => 0x1A4, 0x1A8 => 0x1A7, 0x1AD => 0x1AC, 0x1B0 => 0x1AF, 0x1B4 => 0x1B3, 0x1B6 => 0x1B5, 0x1B9 => 0x1B8, 0x1BD => 0x1BC, 0x1BF => 0x1F7, 0x1C5 => 0x1C4, 0x1C6 => 0x1C4, 0x1C8 => 0x1C7, 0x1C9 => 0x1C7, 0x1CB => 0x1CA, 0x1CC => 0x1CA, 0x1CE => 0x1CD, 0x1D0 => 0x1CF, 0x1D2 => 0x1D1, 0x1D4 => 0x1D3, 0x1D6 => 0x1D5, 0x1D8 => 0x1D7, 0x1DA => 0x1D9, 0x1DC => 0x1DB, 0x1DD => 0x18E, 0x1DF => 0x1DE, 0x1E1 => 0x1E0, 0x1E3 => 0x1E2, 0x1E5 => 0x1E4, 0x1E7 => 0x1E6, 0x1E9 => 0x1E8, 0x1EB => 0x1EA, 0x1ED => 0x1EC, 0x1EF => 0x1EE, 0x1F2 => 0x1F1, 0x1F3 => 0x1F1, 0x1F5 => 0x1F4, 0x1F9 => 0x1F8, 0x1FB => 0x1FA, 0x1FD => 0x1FC, 0x1FF => 0x1FE, 0x201 => 0x200, 0x203 => 0x202, 0x205 => 0x204, 0x207 => 0x206, 0x209 => 0x208, 0x20B => 0x20A, 0x20D => 0x20C, 0x20F => 0x20E, 0x211 => 0x210, 0x213 => 0x212, 0x215 => 0x214, 0x217 => 0x216, 0x219 => 0x218, 0x21B => 0x21A, 0x21D => 0x21C, 0x21F => 0x21E, 0x223 => 0x222, 0x225 => 0x224, 0x227 => 0x226, 0x229 => 0x228, 0x22B => 0x22A, 0x22D => 0x22C, 0x22F => 0x22E, 0x231 => 0x230, 0x233 => 0x232, 0x23C => 0x23B, 0x23F => 0x2C7E, 0x240 => 0x2C7F, 0x242 => 0x241, 0x247 => 0x246, 0x249 => 0x248, 0x24B => 0x24A, 0x24D => 0x24C, 0x24F => 0x24E, 0x250 => 0x2C6F, 0x251 => 0x2C6D, 0x252 => 0x2C70, 0x253 => 0x181, 0x254 => 0x186, 0x256 => 0x189, 0x257 => 0x18A, 0x259 => 0x18F, 0x25B => 0x190, 0x25C => 0xA7AB, 0x260 => 0x193, 0x261 => 0xA7AC, 0x263 => 0x194, 0x265 => 0xA78D, 0x266 => 0xA7AA, 0x268 => 0x197, 0x269 => 0x196, 0x26A => 0xA7AE, 0x26B => 0x2C62, 0x26C => 0xA7AD, 0x26F => 0x19C, 0x271 => 0x2C6E, 0x272 => 0x19D, 0x275 => 0x19F, 0x27D => 0x2C64, 0x280 => 0x1A6, 0x282 => 0xA7C5, 0x283 => 0x1A9, 0x287 => 0xA7B1, 0x288 => 0x1AE, 0x289 => 0x244, 0x28A => 0x1B1, 0x28B => 0x1B2, 0x28C => 0x245, 0x292 => 0x1B7, 0x29D => 0xA7B2, 0x29E => 0xA7B0, 0x345 => 0x399, 0x371 => 0x370, 0x373 => 0x372, 0x377 => 0x376, 0x37B => 0x3FD, 0x37C => 0x3FE, 0x37D => 0x3FF, 0x3AC => 0x386, 0x3AD => 0x388, 0x3AE => 0x389, 0x3AF => 0x38A, 0x3B1 => 0x391, 0x3B2 => 0x392, 0x3B3 => 0x393, 0x3B4 => 0x394, 0x3B5 => 0x395, 0x3B6 => 0x396, 0x3B7 => 0x397, 0x3B8 => 0x398, 0x3B9 => 0x399, 0x3BA => 0x39A, 0x3BB => 0x39B, 0x3BC => 0x39C, 0x3BD => 0x39D, 0x3BE => 0x39E, 0x3BF => 0x39F, 0x3C0 => 0x3A0, 0x3C1 => 0x3A1, 0x3C2 => 0x3A3, 0x3C3 => 0x3A3, 0x3C4 => 0x3A4, 0x3C5 => 0x3A5, 0x3C6 => 0x3A6, 0x3C7 => 0x3A7, 0x3C8 => 0x3A8, 0x3C9 => 0x3A9, 0x3CA => 0x3AA, 0x3CB => 0x3AB, 0x3CC => 0x38C, 0x3CD => 0x38E, 0x3CE => 0x38F, 0x3D0 => 0x392, 0x3D1 => 0x398, 0x3D5 => 0x3A6, 0x3D6 => 0x3A0, 0x3D7 => 0x3CF, 0x3D9 => 0x3D8, 0x3DB => 0x3DA, 0x3DD => 0x3DC, 0x3DF => 0x3DE, 0x3E1 => 0x3E0, 0x3E3 => 0x3E2, 0x3E5 => 0x3E4, 0x3E7 => 0x3E6, 0x3E9 => 0x3E8, 0x3EB => 0x3EA, 0x3ED => 0x3EC, 0x3EF => 0x3EE, 0x3F0 => 0x39A, 0x3F1 => 0x3A1, 0x3F2 => 0x3F9, 0x3F3 => 0x37F, 0x3F5 => 0x395, 0x3F8 => 0x3F7, 0x3FB => 0x3FA, 0x430 => 0x410, 0x431 => 0x411, 0x432 => 0x412, 0x433 => 0x413, 0x434 => 0x414, 0x435 => 0x415, 0x436 => 0x416, 0x437 => 0x417, 0x438 => 0x418, 0x439 => 0x419, 0x43A => 0x41A, 0x43B => 0x41B, 0x43C => 0x41C, 0x43D => 0x41D, 0x43E => 0x41E, 0x43F => 0x41F, 0x440 => 0x420, 0x441 => 0x421, 0x442 => 0x422, 0x443 => 0x423, 0x444 => 0x424, 0x445 => 0x425, 0x446 => 0x426, 0x447 => 0x427, 0x448 => 0x428, 0x449 => 0x429, 0x44A => 0x42A, 0x44B => 0x42B, 0x44C => 0x42C, 0x44D => 0x42D, 0x44E => 0x42E, 0x44F => 0x42F, 0x450 => 0x400, 0x451 => 0x401, 0x452 => 0x402, 0x453 => 0x403, 0x454 => 0x404, 0x455 => 0x405, 0x456 => 0x406, 0x457 => 0x407, 0x458 => 0x408, 0x459 => 0x409, 0x45A => 0x40A, 0x45B => 0x40B, 0x45C => 0x40C, 0x45D => 0x40D, 0x45E => 0x40E, 0x45F => 0x40F, 0x461 => 0x460, 0x463 => 0x462, 0x465 => 0x464, 0x467 => 0x466, 0x469 => 0x468, 0x46B => 0x46A, 0x46D => 0x46C, 0x46F => 0x46E, 0x471 => 0x470, 0x473 => 0x472, 0x475 => 0x474, 0x477 => 0x476, 0x479 => 0x478, 0x47B => 0x47A, 0x47D => 0x47C, 0x47F => 0x47E, 0x481 => 0x480, 0x48B => 0x48A, 0x48D => 0x48C, 0x48F => 0x48E, 0x491 => 0x490, 0x493 => 0x492, 0x495 => 0x494, 0x497 => 0x496, 0x499 => 0x498, 0x49B => 0x49A, 0x49D => 0x49C, 0x49F => 0x49E, 0x4A1 => 0x4A0, 0x4A3 => 0x4A2, 0x4A5 => 0x4A4, 0x4A7 => 0x4A6, 0x4A9 => 0x4A8, 0x4AB => 0x4AA, 0x4AD => 0x4AC, 0x4AF => 0x4AE, 0x4B1 => 0x4B0, 0x4B3 => 0x4B2, 0x4B5 => 0x4B4, 0x4B7 => 0x4B6, 0x4B9 => 0x4B8, 0x4BB => 0x4BA, 0x4BD => 0x4BC, 0x4BF => 0x4BE, 0x4C2 => 0x4C1, 0x4C4 => 0x4C3, 0x4C6 => 0x4C5, 0x4C8 => 0x4C7, 0x4CA => 0x4C9, 0x4CC => 0x4CB, 0x4CE => 0x4CD, 0x4CF => 0x4C0, 0x4D1 => 0x4D0, 0x4D3 => 0x4D2, 0x4D5 => 0x4D4, 0x4D7 => 0x4D6, 0x4D9 => 0x4D8, 0x4DB => 0x4DA, 0x4DD => 0x4DC, 0x4DF => 0x4DE, 0x4E1 => 0x4E0, 0x4E3 => 0x4E2, 0x4E5 => 0x4E4, 0x4E7 => 0x4E6, 0x4E9 => 0x4E8, 0x4EB => 0x4EA, 0x4ED => 0x4EC, 0x4EF => 0x4EE, 0x4F1 => 0x4F0, 0x4F3 => 0x4F2, 0x4F5 => 0x4F4, 0x4F7 => 0x4F6, 0x4F9 => 0x4F8, 0x4FB => 0x4FA, 0x4FD => 0x4FC, 0x4FF => 0x4FE, 0x501 => 0x500, 0x503 => 0x502, 0x505 => 0x504, 0x507 => 0x506, 0x509 => 0x508, 0x50B => 0x50A, 0x50D => 0x50C, 0x50F => 0x50E, 0x511 => 0x510, 0x513 => 0x512, 0x515 => 0x514, 0x517 => 0x516, 0x519 => 0x518, 0x51B => 0x51A, 0x51D => 0x51C, 0x51F => 0x51E, 0x521 => 0x520, 0x523 => 0x522, 0x525 => 0x524, 0x527 => 0x526, 0x529 => 0x528, 0x52B => 0x52A, 0x52D => 0x52C, 0x52F => 0x52E, 0x561 => 0x531, 0x562 => 0x532, 0x563 => 0x533, 0x564 => 0x534, 0x565 => 0x535, 0x566 => 0x536, 0x567 => 0x537, 0x568 => 0x538, 0x569 => 0x539, 0x56A => 0x53A, 0x56B => 0x53B, 0x56C => 0x53C, 0x56D => 0x53D, 0x56E => 0x53E, 0x56F => 0x53F, 0x570 => 0x540, 0x571 => 0x541, 0x572 => 0x542, 0x573 => 0x543, 0x574 => 0x544, 0x575 => 0x545, 0x576 => 0x546, 0x577 => 0x547, 0x578 => 0x548, 0x579 => 0x549, 0x57A => 0x54A, 0x57B => 0x54B, 0x57C => 0x54C, 0x57D => 0x54D, 0x57E => 0x54E, 0x57F => 0x54F, 0x580 => 0x550, 0x581 => 0x551, 0x582 => 0x552, 0x583 => 0x553, 0x584 => 0x554, 0x585 => 0x555, 0x586 => 0x556, 0x10D0 => 0x1C90, 0x10D1 => 0x1C91, 0x10D2 => 0x1C92, 0x10D3 => 0x1C93, 0x10D4 => 0x1C94, 0x10D5 => 0x1C95, 0x10D6 => 0x1C96, 0x10D7 => 0x1C97, 0x10D8 => 0x1C98, 0x10D9 => 0x1C99, 0x10DA => 0x1C9A, 0x10DB => 0x1C9B, 0x10DC => 0x1C9C, 0x10DD => 0x1C9D, 0x10DE => 0x1C9E, 0x10DF => 0x1C9F, 0x10E0 => 0x1CA0, 0x10E1 => 0x1CA1, 0x10E2 => 0x1CA2, 0x10E3 => 0x1CA3, 0x10E4 => 0x1CA4, 0x10E5 => 0x1CA5, 0x10E6 => 0x1CA6, 0x10E7 => 0x1CA7, 0x10E8 => 0x1CA8, 0x10E9 => 0x1CA9, 0x10EA => 0x1CAA, 0x10EB => 0x1CAB, 0x10EC => 0x1CAC, 0x10ED => 0x1CAD, 0x10EE => 0x1CAE, 0x10EF => 0x1CAF, 0x10F0 => 0x1CB0, 0x10F1 => 0x1CB1, 0x10F2 => 0x1CB2, 0x10F3 => 0x1CB3, 0x10F4 => 0x1CB4, 0x10F5 => 0x1CB5, 0x10F6 => 0x1CB6, 0x10F7 => 0x1CB7, 0x10F8 => 0x1CB8, 0x10F9 => 0x1CB9, 0x10FA => 0x1CBA, 0x10FD => 0x1CBD, 0x10FE => 0x1CBE, 0x10FF => 0x1CBF, 0x13F8 => 0x13F0, 0x13F9 => 0x13F1, 0x13FA => 0x13F2, 0x13FB => 0x13F3, 0x13FC => 0x13F4, 0x13FD => 0x13F5, 0x1C80 => 0x412, 0x1C81 => 0x414, 0x1C82 => 0x41E, 0x1C83 => 0x421, 0x1C84 => 0x422, 0x1C85 => 0x422, 0x1C86 => 0x42A, 0x1C87 => 0x462, 0x1C88 => 0xA64A, 0x1D79 => 0xA77D, 0x1D7D => 0x2C63, 0x1D8E => 0xA7C6, 0x1E01 => 0x1E00, 0x1E03 => 0x1E02, 0x1E05 => 0x1E04, 0x1E07 => 0x1E06, 0x1E09 => 0x1E08, 0x1E0B => 0x1E0A, 0x1E0D => 0x1E0C, 0x1E0F => 0x1E0E, 0x1E11 => 0x1E10, 0x1E13 => 0x1E12, 0x1E15 => 0x1E14, 0x1E17 => 0x1E16, 0x1E19 => 0x1E18, 0x1E1B => 0x1E1A, 0x1E1D => 0x1E1C, 0x1E1F => 0x1E1E, 0x1E21 => 0x1E20, 0x1E23 => 0x1E22, 0x1E25 => 0x1E24, 0x1E27 => 0x1E26, 0x1E29 => 0x1E28, 0x1E2B => 0x1E2A, 0x1E2D => 0x1E2C, 0x1E2F => 0x1E2E, 0x1E31 => 0x1E30, 0x1E33 => 0x1E32, 0x1E35 => 0x1E34, 0x1E37 => 0x1E36, 0x1E39 => 0x1E38, 0x1E3B => 0x1E3A, 0x1E3D => 0x1E3C, 0x1E3F => 0x1E3E, 0x1E41 => 0x1E40, 0x1E43 => 0x1E42, 0x1E45 => 0x1E44, 0x1E47 => 0x1E46, 0x1E49 => 0x1E48, 0x1E4B => 0x1E4A, 0x1E4D => 0x1E4C, 0x1E4F => 0x1E4E, 0x1E51 => 0x1E50, 0x1E53 => 0x1E52, 0x1E55 => 0x1E54, 0x1E57 => 0x1E56, 0x1E59 => 0x1E58, 0x1E5B => 0x1E5A, 0x1E5D => 0x1E5C, 0x1E5F => 0x1E5E, 0x1E61 => 0x1E60, 0x1E63 => 0x1E62, 0x1E65 => 0x1E64, 0x1E67 => 0x1E66, 0x1E69 => 0x1E68, 0x1E6B => 0x1E6A, 0x1E6D => 0x1E6C, 0x1E6F => 0x1E6E, 0x1E71 => 0x1E70, 0x1E73 => 0x1E72, 0x1E75 => 0x1E74, 0x1E77 => 0x1E76, 0x1E79 => 0x1E78, 0x1E7B => 0x1E7A, 0x1E7D => 0x1E7C, 0x1E7F => 0x1E7E, 0x1E81 => 0x1E80, 0x1E83 => 0x1E82, 0x1E85 => 0x1E84, 0x1E87 => 0x1E86, 0x1E89 => 0x1E88, 0x1E8B => 0x1E8A, 0x1E8D => 0x1E8C, 0x1E8F => 0x1E8E, 0x1E91 => 0x1E90, 0x1E93 => 0x1E92, 0x1E95 => 0x1E94, 0x1E9B => 0x1E60, 0x1EA1 => 0x1EA0, 0x1EA3 => 0x1EA2, 0x1EA5 => 0x1EA4, 0x1EA7 => 0x1EA6, 0x1EA9 => 0x1EA8, 0x1EAB => 0x1EAA, 0x1EAD => 0x1EAC, 0x1EAF => 0x1EAE, 0x1EB1 => 0x1EB0, 0x1EB3 => 0x1EB2, 0x1EB5 => 0x1EB4, 0x1EB7 => 0x1EB6, 0x1EB9 => 0x1EB8, 0x1EBB => 0x1EBA, 0x1EBD => 0x1EBC, 0x1EBF => 0x1EBE, 0x1EC1 => 0x1EC0, 0x1EC3 => 0x1EC2, 0x1EC5 => 0x1EC4, 0x1EC7 => 0x1EC6, 0x1EC9 => 0x1EC8, 0x1ECB => 0x1ECA, 0x1ECD => 0x1ECC, 0x1ECF => 0x1ECE, 0x1ED1 => 0x1ED0, 0x1ED3 => 0x1ED2, 0x1ED5 => 0x1ED4, 0x1ED7 => 0x1ED6, 0x1ED9 => 0x1ED8, 0x1EDB => 0x1EDA, 0x1EDD => 0x1EDC, 0x1EDF => 0x1EDE, 0x1EE1 => 0x1EE0, 0x1EE3 => 0x1EE2, 0x1EE5 => 0x1EE4, 0x1EE7 => 0x1EE6, 0x1EE9 => 0x1EE8, 0x1EEB => 0x1EEA, 0x1EED => 0x1EEC, 0x1EEF => 0x1EEE, 0x1EF1 => 0x1EF0, 0x1EF3 => 0x1EF2, 0x1EF5 => 0x1EF4, 0x1EF7 => 0x1EF6, 0x1EF9 => 0x1EF8, 0x1EFB => 0x1EFA, 0x1EFD => 0x1EFC, 0x1EFF => 0x1EFE, 0x1F00 => 0x1F08, 0x1F01 => 0x1F09, 0x1F02 => 0x1F0A, 0x1F03 => 0x1F0B, 0x1F04 => 0x1F0C, 0x1F05 => 0x1F0D, 0x1F06 => 0x1F0E, 0x1F07 => 0x1F0F, 0x1F10 => 0x1F18, 0x1F11 => 0x1F19, 0x1F12 => 0x1F1A, 0x1F13 => 0x1F1B, 0x1F14 => 0x1F1C, 0x1F15 => 0x1F1D, 0x1F20 => 0x1F28, 0x1F21 => 0x1F29, 0x1F22 => 0x1F2A, 0x1F23 => 0x1F2B, 0x1F24 => 0x1F2C, 0x1F25 => 0x1F2D, 0x1F26 => 0x1F2E, 0x1F27 => 0x1F2F, 0x1F30 => 0x1F38, 0x1F31 => 0x1F39, 0x1F32 => 0x1F3A, 0x1F33 => 0x1F3B, 0x1F34 => 0x1F3C, 0x1F35 => 0x1F3D, 0x1F36 => 0x1F3E, 0x1F37 => 0x1F3F, 0x1F40 => 0x1F48, 0x1F41 => 0x1F49, 0x1F42 => 0x1F4A, 0x1F43 => 0x1F4B, 0x1F44 => 0x1F4C, 0x1F45 => 0x1F4D, 0x1F51 => 0x1F59, 0x1F53 => 0x1F5B, 0x1F55 => 0x1F5D, 0x1F57 => 0x1F5F, 0x1F60 => 0x1F68, 0x1F61 => 0x1F69, 0x1F62 => 0x1F6A, 0x1F63 => 0x1F6B, 0x1F64 => 0x1F6C, 0x1F65 => 0x1F6D, 0x1F66 => 0x1F6E, 0x1F67 => 0x1F6F, 0x1F70 => 0x1FBA, 0x1F71 => 0x1FBB, 0x1F72 => 0x1FC8, 0x1F73 => 0x1FC9, 0x1F74 => 0x1FCA, 0x1F75 => 0x1FCB, 0x1F76 => 0x1FDA, 0x1F77 => 0x1FDB, 0x1F78 => 0x1FF8, 0x1F79 => 0x1FF9, 0x1F7A => 0x1FEA, 0x1F7B => 0x1FEB, 0x1F7C => 0x1FFA, 0x1F7D => 0x1FFB, 0x1F80 => 0x1F88, 0x1F81 => 0x1F89, 0x1F82 => 0x1F8A, 0x1F83 => 0x1F8B, 0x1F84 => 0x1F8C, 0x1F85 => 0x1F8D, 0x1F86 => 0x1F8E, 0x1F87 => 0x1F8F, 0x1F90 => 0x1F98, 0x1F91 => 0x1F99, 0x1F92 => 0x1F9A, 0x1F93 => 0x1F9B, 0x1F94 => 0x1F9C, 0x1F95 => 0x1F9D, 0x1F96 => 0x1F9E, 0x1F97 => 0x1F9F, 0x1FA0 => 0x1FA8, 0x1FA1 => 0x1FA9, 0x1FA2 => 0x1FAA, 0x1FA3 => 0x1FAB, 0x1FA4 => 0x1FAC, 0x1FA5 => 0x1FAD, 0x1FA6 => 0x1FAE, 0x1FA7 => 0x1FAF, 0x1FB0 => 0x1FB8, 0x1FB1 => 0x1FB9, 0x1FB3 => 0x1FBC, 0x1FBE => 0x399, 0x1FC3 => 0x1FCC, 0x1FD0 => 0x1FD8, 0x1FD1 => 0x1FD9, 0x1FE0 => 0x1FE8, 0x1FE1 => 0x1FE9, 0x1FE5 => 0x1FEC, 0x1FF3 => 0x1FFC, 0x214E => 0x2132, 0x2170 => 0x2160, 0x2171 => 0x2161, 0x2172 => 0x2162, 0x2173 => 0x2163, 0x2174 => 0x2164, 0x2175 => 0x2165, 0x2176 => 0x2166, 0x2177 => 0x2167, 0x2178 => 0x2168, 0x2179 => 0x2169, 0x217A => 0x216A, 0x217B => 0x216B, 0x217C => 0x216C, 0x217D => 0x216D, 0x217E => 0x216E, 0x217F => 0x216F, 0x2184 => 0x2183, 0x24D0 => 0x24B6, 0x24D1 => 0x24B7, 0x24D2 => 0x24B8, 0x24D3 => 0x24B9, 0x24D4 => 0x24BA, 0x24D5 => 0x24BB, 0x24D6 => 0x24BC, 0x24D7 => 0x24BD, 0x24D8 => 0x24BE, 0x24D9 => 0x24BF, 0x24DA => 0x24C0, 0x24DB => 0x24C1, 0x24DC => 0x24C2, 0x24DD => 0x24C3, 0x24DE => 0x24C4, 0x24DF => 0x24C5, 0x24E0 => 0x24C6, 0x24E1 => 0x24C7, 0x24E2 => 0x24C8, 0x24E3 => 0x24C9, 0x24E4 => 0x24CA, 0x24E5 => 0x24CB, 0x24E6 => 0x24CC, 0x24E7 => 0x24CD, 0x24E8 => 0x24CE, 0x24E9 => 0x24CF, 0x2C30 => 0x2C00, 0x2C31 => 0x2C01, 0x2C32 => 0x2C02, 0x2C33 => 0x2C03, 0x2C34 => 0x2C04, 0x2C35 => 0x2C05, 0x2C36 => 0x2C06, 0x2C37 => 0x2C07, 0x2C38 => 0x2C08, 0x2C39 => 0x2C09, 0x2C3A => 0x2C0A, 0x2C3B => 0x2C0B, 0x2C3C => 0x2C0C, 0x2C3D => 0x2C0D, 0x2C3E => 0x2C0E, 0x2C3F => 0x2C0F, 0x2C40 => 0x2C10, 0x2C41 => 0x2C11, 0x2C42 => 0x2C12, 0x2C43 => 0x2C13, 0x2C44 => 0x2C14, 0x2C45 => 0x2C15, 0x2C46 => 0x2C16, 0x2C47 => 0x2C17, 0x2C48 => 0x2C18, 0x2C49 => 0x2C19, 0x2C4A => 0x2C1A, 0x2C4B => 0x2C1B, 0x2C4C => 0x2C1C, 0x2C4D => 0x2C1D, 0x2C4E => 0x2C1E, 0x2C4F => 0x2C1F, 0x2C50 => 0x2C20, 0x2C51 => 0x2C21, 0x2C52 => 0x2C22, 0x2C53 => 0x2C23, 0x2C54 => 0x2C24, 0x2C55 => 0x2C25, 0x2C56 => 0x2C26, 0x2C57 => 0x2C27, 0x2C58 => 0x2C28, 0x2C59 => 0x2C29, 0x2C5A => 0x2C2A, 0x2C5B => 0x2C2B, 0x2C5C => 0x2C2C, 0x2C5D => 0x2C2D, 0x2C5E => 0x2C2E, 0x2C61 => 0x2C60, 0x2C65 => 0x23A, 0x2C66 => 0x23E, 0x2C68 => 0x2C67, 0x2C6A => 0x2C69, 0x2C6C => 0x2C6B, 0x2C73 => 0x2C72, 0x2C76 => 0x2C75, 0x2C81 => 0x2C80, 0x2C83 => 0x2C82, 0x2C85 => 0x2C84, 0x2C87 => 0x2C86, 0x2C89 => 0x2C88, 0x2C8B => 0x2C8A, 0x2C8D => 0x2C8C, 0x2C8F => 0x2C8E, 0x2C91 => 0x2C90, 0x2C93 => 0x2C92, 0x2C95 => 0x2C94, 0x2C97 => 0x2C96, 0x2C99 => 0x2C98, 0x2C9B => 0x2C9A, 0x2C9D => 0x2C9C, 0x2C9F => 0x2C9E, 0x2CA1 => 0x2CA0, 0x2CA3 => 0x2CA2, 0x2CA5 => 0x2CA4, 0x2CA7 => 0x2CA6, 0x2CA9 => 0x2CA8, 0x2CAB => 0x2CAA, 0x2CAD => 0x2CAC, 0x2CAF => 0x2CAE, 0x2CB1 => 0x2CB0, 0x2CB3 => 0x2CB2, 0x2CB5 => 0x2CB4, 0x2CB7 => 0x2CB6, 0x2CB9 => 0x2CB8, 0x2CBB => 0x2CBA, 0x2CBD => 0x2CBC, 0x2CBF => 0x2CBE, 0x2CC1 => 0x2CC0, 0x2CC3 => 0x2CC2, 0x2CC5 => 0x2CC4, 0x2CC7 => 0x2CC6, 0x2CC9 => 0x2CC8, 0x2CCB => 0x2CCA, 0x2CCD => 0x2CCC, 0x2CCF => 0x2CCE, 0x2CD1 => 0x2CD0, 0x2CD3 => 0x2CD2, 0x2CD5 => 0x2CD4, 0x2CD7 => 0x2CD6, 0x2CD9 => 0x2CD8, 0x2CDB => 0x2CDA, 0x2CDD => 0x2CDC, 0x2CDF => 0x2CDE, 0x2CE1 => 0x2CE0, 0x2CE3 => 0x2CE2, 0x2CEC => 0x2CEB, 0x2CEE => 0x2CED, 0x2CF3 => 0x2CF2, 0x2D00 => 0x10A0, 0x2D01 => 0x10A1, 0x2D02 => 0x10A2, 0x2D03 => 0x10A3, 0x2D04 => 0x10A4, 0x2D05 => 0x10A5, 0x2D06 => 0x10A6, 0x2D07 => 0x10A7, 0x2D08 => 0x10A8, 0x2D09 => 0x10A9, 0x2D0A => 0x10AA, 0x2D0B => 0x10AB, 0x2D0C => 0x10AC, 0x2D0D => 0x10AD, 0x2D0E => 0x10AE, 0x2D0F => 0x10AF, 0x2D10 => 0x10B0, 0x2D11 => 0x10B1, 0x2D12 => 0x10B2, 0x2D13 => 0x10B3, 0x2D14 => 0x10B4, 0x2D15 => 0x10B5, 0x2D16 => 0x10B6, 0x2D17 => 0x10B7, 0x2D18 => 0x10B8, 0x2D19 => 0x10B9, 0x2D1A => 0x10BA, 0x2D1B => 0x10BB, 0x2D1C => 0x10BC, 0x2D1D => 0x10BD, 0x2D1E => 0x10BE, 0x2D1F => 0x10BF, 0x2D20 => 0x10C0, 0x2D21 => 0x10C1, 0x2D22 => 0x10C2, 0x2D23 => 0x10C3, 0x2D24 => 0x10C4, 0x2D25 => 0x10C5, 0x2D27 => 0x10C7, 0x2D2D => 0x10CD, 0xA641 => 0xA640, 0xA643 => 0xA642, 0xA645 => 0xA644, 0xA647 => 0xA646, 0xA649 => 0xA648, 0xA64B => 0xA64A, 0xA64D => 0xA64C, 0xA64F => 0xA64E, 0xA651 => 0xA650, 0xA653 => 0xA652, 0xA655 => 0xA654, 0xA657 => 0xA656, 0xA659 => 0xA658, 0xA65B => 0xA65A, 0xA65D => 0xA65C, 0xA65F => 0xA65E, 0xA661 => 0xA660, 0xA663 => 0xA662, 0xA665 => 0xA664, 0xA667 => 0xA666, 0xA669 => 0xA668, 0xA66B => 0xA66A, 0xA66D => 0xA66C, 0xA681 => 0xA680, 0xA683 => 0xA682, 0xA685 => 0xA684, 0xA687 => 0xA686, 0xA689 => 0xA688, 0xA68B => 0xA68A, 0xA68D => 0xA68C, 0xA68F => 0xA68E, 0xA691 => 0xA690, 0xA693 => 0xA692, 0xA695 => 0xA694, 0xA697 => 0xA696, 0xA699 => 0xA698, 0xA69B => 0xA69A, 0xA723 => 0xA722, 0xA725 => 0xA724, 0xA727 => 0xA726, 0xA729 => 0xA728, 0xA72B => 0xA72A, 0xA72D => 0xA72C, 0xA72F => 0xA72E, 0xA733 => 0xA732, 0xA735 => 0xA734, 0xA737 => 0xA736, 0xA739 => 0xA738, 0xA73B => 0xA73A, 0xA73D => 0xA73C, 0xA73F => 0xA73E, 0xA741 => 0xA740, 0xA743 => 0xA742, 0xA745 => 0xA744, 0xA747 => 0xA746, 0xA749 => 0xA748, 0xA74B => 0xA74A, 0xA74D => 0xA74C, 0xA74F => 0xA74E, 0xA751 => 0xA750, 0xA753 => 0xA752, 0xA755 => 0xA754, 0xA757 => 0xA756, 0xA759 => 0xA758, 0xA75B => 0xA75A, 0xA75D => 0xA75C, 0xA75F => 0xA75E, 0xA761 => 0xA760, 0xA763 => 0xA762, 0xA765 => 0xA764, 0xA767 => 0xA766, 0xA769 => 0xA768, 0xA76B => 0xA76A, 0xA76D => 0xA76C, 0xA76F => 0xA76E, 0xA77A => 0xA779, 0xA77C => 0xA77B, 0xA77F => 0xA77E, 0xA781 => 0xA780, 0xA783 => 0xA782, 0xA785 => 0xA784, 0xA787 => 0xA786, 0xA78C => 0xA78B, 0xA791 => 0xA790, 0xA793 => 0xA792, 0xA794 => 0xA7C4, 0xA797 => 0xA796, 0xA799 => 0xA798, 0xA79B => 0xA79A, 0xA79D => 0xA79C, 0xA79F => 0xA79E, 0xA7A1 => 0xA7A0, 0xA7A3 => 0xA7A2, 0xA7A5 => 0xA7A4, 0xA7A7 => 0xA7A6, 0xA7A9 => 0xA7A8, 0xA7B5 => 0xA7B4, 0xA7B7 => 0xA7B6, 0xA7B9 => 0xA7B8, 0xA7BB => 0xA7BA, 0xA7BD => 0xA7BC, 0xA7BF => 0xA7BE, 0xA7C3 => 0xA7C2, 0xA7C8 => 0xA7C7, 0xA7CA => 0xA7C9, 0xA7F6 => 0xA7F5, 0xAB53 => 0xA7B3, 0xAB70 => 0x13A0, 0xAB71 => 0x13A1, 0xAB72 => 0x13A2, 0xAB73 => 0x13A3, 0xAB74 => 0x13A4, 0xAB75 => 0x13A5, 0xAB76 => 0x13A6, 0xAB77 => 0x13A7, 0xAB78 => 0x13A8, 0xAB79 => 0x13A9, 0xAB7A => 0x13AA, 0xAB7B => 0x13AB, 0xAB7C => 0x13AC, 0xAB7D => 0x13AD, 0xAB7E => 0x13AE, 0xAB7F => 0x13AF, 0xAB80 => 0x13B0, 0xAB81 => 0x13B1, 0xAB82 => 0x13B2, 0xAB83 => 0x13B3, 0xAB84 => 0x13B4, 0xAB85 => 0x13B5, 0xAB86 => 0x13B6, 0xAB87 => 0x13B7, 0xAB88 => 0x13B8, 0xAB89 => 0x13B9, 0xAB8A => 0x13BA, 0xAB8B => 0x13BB, 0xAB8C => 0x13BC, 0xAB8D => 0x13BD, 0xAB8E => 0x13BE, 0xAB8F => 0x13BF, 0xAB90 => 0x13C0, 0xAB91 => 0x13C1, 0xAB92 => 0x13C2, 0xAB93 => 0x13C3, 0xAB94 => 0x13C4, 0xAB95 => 0x13C5, 0xAB96 => 0x13C6, 0xAB97 => 0x13C7, 0xAB98 => 0x13C8, 0xAB99 => 0x13C9, 0xAB9A => 0x13CA, 0xAB9B => 0x13CB, 0xAB9C => 0x13CC, 0xAB9D => 0x13CD, 0xAB9E => 0x13CE, 0xAB9F => 0x13CF, 0xABA0 => 0x13D0, 0xABA1 => 0x13D1, 0xABA2 => 0x13D2, 0xABA3 => 0x13D3, 0xABA4 => 0x13D4, 0xABA5 => 0x13D5, 0xABA6 => 0x13D6, 0xABA7 => 0x13D7, 0xABA8 => 0x13D8, 0xABA9 => 0x13D9, 0xABAA => 0x13DA, 0xABAB => 0x13DB, 0xABAC => 0x13DC, 0xABAD => 0x13DD, 0xABAE => 0x13DE, 0xABAF => 0x13DF, 0xABB0 => 0x13E0, 0xABB1 => 0x13E1, 0xABB2 => 0x13E2, 0xABB3 => 0x13E3, 0xABB4 => 0x13E4, 0xABB5 => 0x13E5, 0xABB6 => 0x13E6, 0xABB7 => 0x13E7, 0xABB8 => 0x13E8, 0xABB9 => 0x13E9, 0xABBA => 0x13EA, 0xABBB => 0x13EB, 0xABBC => 0x13EC, 0xABBD => 0x13ED, 0xABBE => 0x13EE, 0xABBF => 0x13EF, 0xFF41 => 0xFF21, 0xFF42 => 0xFF22, 0xFF43 => 0xFF23, 0xFF44 => 0xFF24, 0xFF45 => 0xFF25, 0xFF46 => 0xFF26, 0xFF47 => 0xFF27, 0xFF48 => 0xFF28, 0xFF49 => 0xFF29, 0xFF4A => 0xFF2A, 0xFF4B => 0xFF2B, 0xFF4C => 0xFF2C, 0xFF4D => 0xFF2D, 0xFF4E => 0xFF2E, 0xFF4F => 0xFF2F, 0xFF50 => 0xFF30, 0xFF51 => 0xFF31, 0xFF52 => 0xFF32, 0xFF53 => 0xFF33, 0xFF54 => 0xFF34, 0xFF55 => 0xFF35, 0xFF56 => 0xFF36, 0xFF57 => 0xFF37, 0xFF58 => 0xFF38, 0xFF59 => 0xFF39, 0xFF5A => 0xFF3A, 0x10428 => 0x10400, 0x10429 => 0x10401, 0x1042A => 0x10402, 0x1042B => 0x10403, 0x1042C => 0x10404, 0x1042D => 0x10405, 0x1042E => 0x10406, 0x1042F => 0x10407, 0x10430 => 0x10408, 0x10431 => 0x10409, 0x10432 => 0x1040A, 0x10433 => 0x1040B, 0x10434 => 0x1040C, 0x10435 => 0x1040D, 0x10436 => 0x1040E, 0x10437 => 0x1040F, 0x10438 => 0x10410, 0x10439 => 0x10411, 0x1043A => 0x10412, 0x1043B => 0x10413, 0x1043C => 0x10414, 0x1043D => 0x10415, 0x1043E => 0x10416, 0x1043F => 0x10417, 0x10440 => 0x10418, 0x10441 => 0x10419, 0x10442 => 0x1041A, 0x10443 => 0x1041B, 0x10444 => 0x1041C, 0x10445 => 0x1041D, 0x10446 => 0x1041E, 0x10447 => 0x1041F, 0x10448 => 0x10420, 0x10449 => 0x10421, 0x1044A => 0x10422, 0x1044B => 0x10423, 0x1044C => 0x10424, 0x1044D => 0x10425, 0x1044E => 0x10426, 0x1044F => 0x10427, 0x104D8 => 0x104B0, 0x104D9 => 0x104B1, 0x104DA => 0x104B2, 0x104DB => 0x104B3, 0x104DC => 0x104B4, 0x104DD => 0x104B5, 0x104DE => 0x104B6, 0x104DF => 0x104B7, 0x104E0 => 0x104B8, 0x104E1 => 0x104B9, 0x104E2 => 0x104BA, 0x104E3 => 0x104BB, 0x104E4 => 0x104BC, 0x104E5 => 0x104BD, 0x104E6 => 0x104BE, 0x104E7 => 0x104BF, 0x104E8 => 0x104C0, 0x104E9 => 0x104C1, 0x104EA => 0x104C2, 0x104EB => 0x104C3, 0x104EC => 0x104C4, 0x104ED => 0x104C5, 0x104EE => 0x104C6, 0x104EF => 0x104C7, 0x104F0 => 0x104C8, 0x104F1 => 0x104C9, 0x104F2 => 0x104CA, 0x104F3 => 0x104CB, 0x104F4 => 0x104CC, 0x104F5 => 0x104CD, 0x104F6 => 0x104CE, 0x104F7 => 0x104CF, 0x104F8 => 0x104D0, 0x104F9 => 0x104D1, 0x104FA => 0x104D2, 0x104FB => 0x104D3, 0x10CC0 => 0x10C80, 0x10CC1 => 0x10C81, 0x10CC2 => 0x10C82, 0x10CC3 => 0x10C83, 0x10CC4 => 0x10C84, 0x10CC5 => 0x10C85, 0x10CC6 => 0x10C86, 0x10CC7 => 0x10C87, 0x10CC8 => 0x10C88, 0x10CC9 => 0x10C89, 0x10CCA => 0x10C8A, 0x10CCB => 0x10C8B, 0x10CCC => 0x10C8C, 0x10CCD => 0x10C8D, 0x10CCE => 0x10C8E, 0x10CCF => 0x10C8F, 0x10CD0 => 0x10C90, 0x10CD1 => 0x10C91, 0x10CD2 => 0x10C92, 0x10CD3 => 0x10C93, 0x10CD4 => 0x10C94, 0x10CD5 => 0x10C95, 0x10CD6 => 0x10C96, 0x10CD7 => 0x10C97, 0x10CD8 => 0x10C98, 0x10CD9 => 0x10C99, 0x10CDA => 0x10C9A, 0x10CDB => 0x10C9B, 0x10CDC => 0x10C9C, 0x10CDD => 0x10C9D, 0x10CDE => 0x10C9E, 0x10CDF => 0x10C9F, 0x10CE0 => 0x10CA0, 0x10CE1 => 0x10CA1, 0x10CE2 => 0x10CA2, 0x10CE3 => 0x10CA3, 0x10CE4 => 0x10CA4, 0x10CE5 => 0x10CA5, 0x10CE6 => 0x10CA6, 0x10CE7 => 0x10CA7, 0x10CE8 => 0x10CA8, 0x10CE9 => 0x10CA9, 0x10CEA => 0x10CAA, 0x10CEB => 0x10CAB, 0x10CEC => 0x10CAC, 0x10CED => 0x10CAD, 0x10CEE => 0x10CAE, 0x10CEF => 0x10CAF, 0x10CF0 => 0x10CB0, 0x10CF1 => 0x10CB1, 0x10CF2 => 0x10CB2, 0x118C0 => 0x118A0, 0x118C1 => 0x118A1, 0x118C2 => 0x118A2, 0x118C3 => 0x118A3, 0x118C4 => 0x118A4, 0x118C5 => 0x118A5, 0x118C6 => 0x118A6, 0x118C7 => 0x118A7, 0x118C8 => 0x118A8, 0x118C9 => 0x118A9, 0x118CA => 0x118AA, 0x118CB => 0x118AB, 0x118CC => 0x118AC, 0x118CD => 0x118AD, 0x118CE => 0x118AE, 0x118CF => 0x118AF, 0x118D0 => 0x118B0, 0x118D1 => 0x118B1, 0x118D2 => 0x118B2, 0x118D3 => 0x118B3, 0x118D4 => 0x118B4, 0x118D5 => 0x118B5, 0x118D6 => 0x118B6, 0x118D7 => 0x118B7, 0x118D8 => 0x118B8, 0x118D9 => 0x118B9, 0x118DA => 0x118BA, 0x118DB => 0x118BB, 0x118DC => 0x118BC, 0x118DD => 0x118BD, 0x118DE => 0x118BE, 0x118DF => 0x118BF, 0x16E60 => 0x16E40, 0x16E61 => 0x16E41, 0x16E62 => 0x16E42, 0x16E63 => 0x16E43, 0x16E64 => 0x16E44, 0x16E65 => 0x16E45, 0x16E66 => 0x16E46, 0x16E67 => 0x16E47, 0x16E68 => 0x16E48, 0x16E69 => 0x16E49, 0x16E6A => 0x16E4A, 0x16E6B => 0x16E4B, 0x16E6C => 0x16E4C, 0x16E6D => 0x16E4D, 0x16E6E => 0x16E4E, 0x16E6F => 0x16E4F, 0x16E70 => 0x16E50, 0x16E71 => 0x16E51, 0x16E72 => 0x16E52, 0x16E73 => 0x16E53, 0x16E74 => 0x16E54, 0x16E75 => 0x16E55, 0x16E76 => 0x16E56, 0x16E77 => 0x16E57, 0x16E78 => 0x16E58, 0x16E79 => 0x16E59, 0x16E7A => 0x16E5A, 0x16E7B => 0x16E5B, 0x16E7C => 0x16E5C, 0x16E7D => 0x16E5D, 0x16E7E => 0x16E5E, 0x16E7F => 0x16E5F, 0x1E922 => 0x1E900, 0x1E923 => 0x1E901, 0x1E924 => 0x1E902, 0x1E925 => 0x1E903, 0x1E926 => 0x1E904, 0x1E927 => 0x1E905, 0x1E928 => 0x1E906, 0x1E929 => 0x1E907, 0x1E92A => 0x1E908, 0x1E92B => 0x1E909, 0x1E92C => 0x1E90A, 0x1E92D => 0x1E90B, 0x1E92E => 0x1E90C, 0x1E92F => 0x1E90D, 0x1E930 => 0x1E90E, 0x1E931 => 0x1E90F, 0x1E932 => 0x1E910, 0x1E933 => 0x1E911, 0x1E934 => 0x1E912, 0x1E935 => 0x1E913, 0x1E936 => 0x1E914, 0x1E937 => 0x1E915, 0x1E938 => 0x1E916, 0x1E939 => 0x1E917, 0x1E93A => 0x1E918, 0x1E93B => 0x1E919, 0x1E93C => 0x1E91A, 0x1E93D => 0x1E91B, 0x1E93E => 0x1E91C, 0x1E93F => 0x1E91D, 0x1E940 => 0x1E91E, 0x1E941 => 0x1E91F, 0x1E942 => 0x1E920, 0x1E943 => 0x1E921, ]; res/lower.php 0000777 00000057623 15251721406 0007225 0 ustar 00 <?php return [ 0x41 => 0x61, 0x42 => 0x62, 0x43 => 0x63, 0x44 => 0x64, 0x45 => 0x65, 0x46 => 0x66, 0x47 => 0x67, 0x48 => 0x68, 0x49 => 0x69, 0x4A => 0x6A, 0x4B => 0x6B, 0x4C => 0x6C, 0x4D => 0x6D, 0x4E => 0x6E, 0x4F => 0x6F, 0x50 => 0x70, 0x51 => 0x71, 0x52 => 0x72, 0x53 => 0x73, 0x54 => 0x74, 0x55 => 0x75, 0x56 => 0x76, 0x57 => 0x77, 0x58 => 0x78, 0x59 => 0x79, 0x5A => 0x7A, 0xC0 => 0xE0, 0xC1 => 0xE1, 0xC2 => 0xE2, 0xC3 => 0xE3, 0xC4 => 0xE4, 0xC5 => 0xE5, 0xC6 => 0xE6, 0xC7 => 0xE7, 0xC8 => 0xE8, 0xC9 => 0xE9, 0xCA => 0xEA, 0xCB => 0xEB, 0xCC => 0xEC, 0xCD => 0xED, 0xCE => 0xEE, 0xCF => 0xEF, 0xD0 => 0xF0, 0xD1 => 0xF1, 0xD2 => 0xF2, 0xD3 => 0xF3, 0xD4 => 0xF4, 0xD5 => 0xF5, 0xD6 => 0xF6, 0xD8 => 0xF8, 0xD9 => 0xF9, 0xDA => 0xFA, 0xDB => 0xFB, 0xDC => 0xFC, 0xDD => 0xFD, 0xDE => 0xFE, 0x100 => 0x101, 0x102 => 0x103, 0x104 => 0x105, 0x106 => 0x107, 0x108 => 0x109, 0x10A => 0x10B, 0x10C => 0x10D, 0x10E => 0x10F, 0x110 => 0x111, 0x112 => 0x113, 0x114 => 0x115, 0x116 => 0x117, 0x118 => 0x119, 0x11A => 0x11B, 0x11C => 0x11D, 0x11E => 0x11F, 0x120 => 0x121, 0x122 => 0x123, 0x124 => 0x125, 0x126 => 0x127, 0x128 => 0x129, 0x12A => 0x12B, 0x12C => 0x12D, 0x12E => 0x12F, 0x130 => 0x69, 0x132 => 0x133, 0x134 => 0x135, 0x136 => 0x137, 0x139 => 0x13A, 0x13B => 0x13C, 0x13D => 0x13E, 0x13F => 0x140, 0x141 => 0x142, 0x143 => 0x144, 0x145 => 0x146, 0x147 => 0x148, 0x14A => 0x14B, 0x14C => 0x14D, 0x14E => 0x14F, 0x150 => 0x151, 0x152 => 0x153, 0x154 => 0x155, 0x156 => 0x157, 0x158 => 0x159, 0x15A => 0x15B, 0x15C => 0x15D, 0x15E => 0x15F, 0x160 => 0x161, 0x162 => 0x163, 0x164 => 0x165, 0x166 => 0x167, 0x168 => 0x169, 0x16A => 0x16B, 0x16C => 0x16D, 0x16E => 0x16F, 0x170 => 0x171, 0x172 => 0x173, 0x174 => 0x175, 0x176 => 0x177, 0x178 => 0xFF, 0x179 => 0x17A, 0x17B => 0x17C, 0x17D => 0x17E, 0x181 => 0x253, 0x182 => 0x183, 0x184 => 0x185, 0x186 => 0x254, 0x187 => 0x188, 0x189 => 0x256, 0x18A => 0x257, 0x18B => 0x18C, 0x18E => 0x1DD, 0x18F => 0x259, 0x190 => 0x25B, 0x191 => 0x192, 0x193 => 0x260, 0x194 => 0x263, 0x196 => 0x269, 0x197 => 0x268, 0x198 => 0x199, 0x19C => 0x26F, 0x19D => 0x272, 0x19F => 0x275, 0x1A0 => 0x1A1, 0x1A2 => 0x1A3, 0x1A4 => 0x1A5, 0x1A6 => 0x280, 0x1A7 => 0x1A8, 0x1A9 => 0x283, 0x1AC => 0x1AD, 0x1AE => 0x288, 0x1AF => 0x1B0, 0x1B1 => 0x28A, 0x1B2 => 0x28B, 0x1B3 => 0x1B4, 0x1B5 => 0x1B6, 0x1B7 => 0x292, 0x1B8 => 0x1B9, 0x1BC => 0x1BD, 0x1C4 => 0x1C6, 0x1C5 => 0x1C6, 0x1C7 => 0x1C9, 0x1C8 => 0x1C9, 0x1CA => 0x1CC, 0x1CB => 0x1CC, 0x1CD => 0x1CE, 0x1CF => 0x1D0, 0x1D1 => 0x1D2, 0x1D3 => 0x1D4, 0x1D5 => 0x1D6, 0x1D7 => 0x1D8, 0x1D9 => 0x1DA, 0x1DB => 0x1DC, 0x1DE => 0x1DF, 0x1E0 => 0x1E1, 0x1E2 => 0x1E3, 0x1E4 => 0x1E5, 0x1E6 => 0x1E7, 0x1E8 => 0x1E9, 0x1EA => 0x1EB, 0x1EC => 0x1ED, 0x1EE => 0x1EF, 0x1F1 => 0x1F3, 0x1F2 => 0x1F3, 0x1F4 => 0x1F5, 0x1F6 => 0x195, 0x1F7 => 0x1BF, 0x1F8 => 0x1F9, 0x1FA => 0x1FB, 0x1FC => 0x1FD, 0x1FE => 0x1FF, 0x200 => 0x201, 0x202 => 0x203, 0x204 => 0x205, 0x206 => 0x207, 0x208 => 0x209, 0x20A => 0x20B, 0x20C => 0x20D, 0x20E => 0x20F, 0x210 => 0x211, 0x212 => 0x213, 0x214 => 0x215, 0x216 => 0x217, 0x218 => 0x219, 0x21A => 0x21B, 0x21C => 0x21D, 0x21E => 0x21F, 0x220 => 0x19E, 0x222 => 0x223, 0x224 => 0x225, 0x226 => 0x227, 0x228 => 0x229, 0x22A => 0x22B, 0x22C => 0x22D, 0x22E => 0x22F, 0x230 => 0x231, 0x232 => 0x233, 0x23A => 0x2C65, 0x23B => 0x23C, 0x23D => 0x19A, 0x23E => 0x2C66, 0x241 => 0x242, 0x243 => 0x180, 0x244 => 0x289, 0x245 => 0x28C, 0x246 => 0x247, 0x248 => 0x249, 0x24A => 0x24B, 0x24C => 0x24D, 0x24E => 0x24F, 0x370 => 0x371, 0x372 => 0x373, 0x376 => 0x377, 0x37F => 0x3F3, 0x386 => 0x3AC, 0x388 => 0x3AD, 0x389 => 0x3AE, 0x38A => 0x3AF, 0x38C => 0x3CC, 0x38E => 0x3CD, 0x38F => 0x3CE, 0x391 => 0x3B1, 0x392 => 0x3B2, 0x393 => 0x3B3, 0x394 => 0x3B4, 0x395 => 0x3B5, 0x396 => 0x3B6, 0x397 => 0x3B7, 0x398 => 0x3B8, 0x399 => 0x3B9, 0x39A => 0x3BA, 0x39B => 0x3BB, 0x39C => 0x3BC, 0x39D => 0x3BD, 0x39E => 0x3BE, 0x39F => 0x3BF, 0x3A0 => 0x3C0, 0x3A1 => 0x3C1, 0x3A3 => 0x3C3, 0x3A4 => 0x3C4, 0x3A5 => 0x3C5, 0x3A6 => 0x3C6, 0x3A7 => 0x3C7, 0x3A8 => 0x3C8, 0x3A9 => 0x3C9, 0x3AA => 0x3CA, 0x3AB => 0x3CB, 0x3CF => 0x3D7, 0x3D8 => 0x3D9, 0x3DA => 0x3DB, 0x3DC => 0x3DD, 0x3DE => 0x3DF, 0x3E0 => 0x3E1, 0x3E2 => 0x3E3, 0x3E4 => 0x3E5, 0x3E6 => 0x3E7, 0x3E8 => 0x3E9, 0x3EA => 0x3EB, 0x3EC => 0x3ED, 0x3EE => 0x3EF, 0x3F4 => 0x3B8, 0x3F7 => 0x3F8, 0x3F9 => 0x3F2, 0x3FA => 0x3FB, 0x3FD => 0x37B, 0x3FE => 0x37C, 0x3FF => 0x37D, 0x400 => 0x450, 0x401 => 0x451, 0x402 => 0x452, 0x403 => 0x453, 0x404 => 0x454, 0x405 => 0x455, 0x406 => 0x456, 0x407 => 0x457, 0x408 => 0x458, 0x409 => 0x459, 0x40A => 0x45A, 0x40B => 0x45B, 0x40C => 0x45C, 0x40D => 0x45D, 0x40E => 0x45E, 0x40F => 0x45F, 0x410 => 0x430, 0x411 => 0x431, 0x412 => 0x432, 0x413 => 0x433, 0x414 => 0x434, 0x415 => 0x435, 0x416 => 0x436, 0x417 => 0x437, 0x418 => 0x438, 0x419 => 0x439, 0x41A => 0x43A, 0x41B => 0x43B, 0x41C => 0x43C, 0x41D => 0x43D, 0x41E => 0x43E, 0x41F => 0x43F, 0x420 => 0x440, 0x421 => 0x441, 0x422 => 0x442, 0x423 => 0x443, 0x424 => 0x444, 0x425 => 0x445, 0x426 => 0x446, 0x427 => 0x447, 0x428 => 0x448, 0x429 => 0x449, 0x42A => 0x44A, 0x42B => 0x44B, 0x42C => 0x44C, 0x42D => 0x44D, 0x42E => 0x44E, 0x42F => 0x44F, 0x460 => 0x461, 0x462 => 0x463, 0x464 => 0x465, 0x466 => 0x467, 0x468 => 0x469, 0x46A => 0x46B, 0x46C => 0x46D, 0x46E => 0x46F, 0x470 => 0x471, 0x472 => 0x473, 0x474 => 0x475, 0x476 => 0x477, 0x478 => 0x479, 0x47A => 0x47B, 0x47C => 0x47D, 0x47E => 0x47F, 0x480 => 0x481, 0x48A => 0x48B, 0x48C => 0x48D, 0x48E => 0x48F, 0x490 => 0x491, 0x492 => 0x493, 0x494 => 0x495, 0x496 => 0x497, 0x498 => 0x499, 0x49A => 0x49B, 0x49C => 0x49D, 0x49E => 0x49F, 0x4A0 => 0x4A1, 0x4A2 => 0x4A3, 0x4A4 => 0x4A5, 0x4A6 => 0x4A7, 0x4A8 => 0x4A9, 0x4AA => 0x4AB, 0x4AC => 0x4AD, 0x4AE => 0x4AF, 0x4B0 => 0x4B1, 0x4B2 => 0x4B3, 0x4B4 => 0x4B5, 0x4B6 => 0x4B7, 0x4B8 => 0x4B9, 0x4BA => 0x4BB, 0x4BC => 0x4BD, 0x4BE => 0x4BF, 0x4C0 => 0x4CF, 0x4C1 => 0x4C2, 0x4C3 => 0x4C4, 0x4C5 => 0x4C6, 0x4C7 => 0x4C8, 0x4C9 => 0x4CA, 0x4CB => 0x4CC, 0x4CD => 0x4CE, 0x4D0 => 0x4D1, 0x4D2 => 0x4D3, 0x4D4 => 0x4D5, 0x4D6 => 0x4D7, 0x4D8 => 0x4D9, 0x4DA => 0x4DB, 0x4DC => 0x4DD, 0x4DE => 0x4DF, 0x4E0 => 0x4E1, 0x4E2 => 0x4E3, 0x4E4 => 0x4E5, 0x4E6 => 0x4E7, 0x4E8 => 0x4E9, 0x4EA => 0x4EB, 0x4EC => 0x4ED, 0x4EE => 0x4EF, 0x4F0 => 0x4F1, 0x4F2 => 0x4F3, 0x4F4 => 0x4F5, 0x4F6 => 0x4F7, 0x4F8 => 0x4F9, 0x4FA => 0x4FB, 0x4FC => 0x4FD, 0x4FE => 0x4FF, 0x500 => 0x501, 0x502 => 0x503, 0x504 => 0x505, 0x506 => 0x507, 0x508 => 0x509, 0x50A => 0x50B, 0x50C => 0x50D, 0x50E => 0x50F, 0x510 => 0x511, 0x512 => 0x513, 0x514 => 0x515, 0x516 => 0x517, 0x518 => 0x519, 0x51A => 0x51B, 0x51C => 0x51D, 0x51E => 0x51F, 0x520 => 0x521, 0x522 => 0x523, 0x524 => 0x525, 0x526 => 0x527, 0x528 => 0x529, 0x52A => 0x52B, 0x52C => 0x52D, 0x52E => 0x52F, 0x531 => 0x561, 0x532 => 0x562, 0x533 => 0x563, 0x534 => 0x564, 0x535 => 0x565, 0x536 => 0x566, 0x537 => 0x567, 0x538 => 0x568, 0x539 => 0x569, 0x53A => 0x56A, 0x53B => 0x56B, 0x53C => 0x56C, 0x53D => 0x56D, 0x53E => 0x56E, 0x53F => 0x56F, 0x540 => 0x570, 0x541 => 0x571, 0x542 => 0x572, 0x543 => 0x573, 0x544 => 0x574, 0x545 => 0x575, 0x546 => 0x576, 0x547 => 0x577, 0x548 => 0x578, 0x549 => 0x579, 0x54A => 0x57A, 0x54B => 0x57B, 0x54C => 0x57C, 0x54D => 0x57D, 0x54E => 0x57E, 0x54F => 0x57F, 0x550 => 0x580, 0x551 => 0x581, 0x552 => 0x582, 0x553 => 0x583, 0x554 => 0x584, 0x555 => 0x585, 0x556 => 0x586, 0x10A0 => 0x2D00, 0x10A1 => 0x2D01, 0x10A2 => 0x2D02, 0x10A3 => 0x2D03, 0x10A4 => 0x2D04, 0x10A5 => 0x2D05, 0x10A6 => 0x2D06, 0x10A7 => 0x2D07, 0x10A8 => 0x2D08, 0x10A9 => 0x2D09, 0x10AA => 0x2D0A, 0x10AB => 0x2D0B, 0x10AC => 0x2D0C, 0x10AD => 0x2D0D, 0x10AE => 0x2D0E, 0x10AF => 0x2D0F, 0x10B0 => 0x2D10, 0x10B1 => 0x2D11, 0x10B2 => 0x2D12, 0x10B3 => 0x2D13, 0x10B4 => 0x2D14, 0x10B5 => 0x2D15, 0x10B6 => 0x2D16, 0x10B7 => 0x2D17, 0x10B8 => 0x2D18, 0x10B9 => 0x2D19, 0x10BA => 0x2D1A, 0x10BB => 0x2D1B, 0x10BC => 0x2D1C, 0x10BD => 0x2D1D, 0x10BE => 0x2D1E, 0x10BF => 0x2D1F, 0x10C0 => 0x2D20, 0x10C1 => 0x2D21, 0x10C2 => 0x2D22, 0x10C3 => 0x2D23, 0x10C4 => 0x2D24, 0x10C5 => 0x2D25, 0x10C7 => 0x2D27, 0x10CD => 0x2D2D, 0x13A0 => 0xAB70, 0x13A1 => 0xAB71, 0x13A2 => 0xAB72, 0x13A3 => 0xAB73, 0x13A4 => 0xAB74, 0x13A5 => 0xAB75, 0x13A6 => 0xAB76, 0x13A7 => 0xAB77, 0x13A8 => 0xAB78, 0x13A9 => 0xAB79, 0x13AA => 0xAB7A, 0x13AB => 0xAB7B, 0x13AC => 0xAB7C, 0x13AD => 0xAB7D, 0x13AE => 0xAB7E, 0x13AF => 0xAB7F, 0x13B0 => 0xAB80, 0x13B1 => 0xAB81, 0x13B2 => 0xAB82, 0x13B3 => 0xAB83, 0x13B4 => 0xAB84, 0x13B5 => 0xAB85, 0x13B6 => 0xAB86, 0x13B7 => 0xAB87, 0x13B8 => 0xAB88, 0x13B9 => 0xAB89, 0x13BA => 0xAB8A, 0x13BB => 0xAB8B, 0x13BC => 0xAB8C, 0x13BD => 0xAB8D, 0x13BE => 0xAB8E, 0x13BF => 0xAB8F, 0x13C0 => 0xAB90, 0x13C1 => 0xAB91, 0x13C2 => 0xAB92, 0x13C3 => 0xAB93, 0x13C4 => 0xAB94, 0x13C5 => 0xAB95, 0x13C6 => 0xAB96, 0x13C7 => 0xAB97, 0x13C8 => 0xAB98, 0x13C9 => 0xAB99, 0x13CA => 0xAB9A, 0x13CB => 0xAB9B, 0x13CC => 0xAB9C, 0x13CD => 0xAB9D, 0x13CE => 0xAB9E, 0x13CF => 0xAB9F, 0x13D0 => 0xABA0, 0x13D1 => 0xABA1, 0x13D2 => 0xABA2, 0x13D3 => 0xABA3, 0x13D4 => 0xABA4, 0x13D5 => 0xABA5, 0x13D6 => 0xABA6, 0x13D7 => 0xABA7, 0x13D8 => 0xABA8, 0x13D9 => 0xABA9, 0x13DA => 0xABAA, 0x13DB => 0xABAB, 0x13DC => 0xABAC, 0x13DD => 0xABAD, 0x13DE => 0xABAE, 0x13DF => 0xABAF, 0x13E0 => 0xABB0, 0x13E1 => 0xABB1, 0x13E2 => 0xABB2, 0x13E3 => 0xABB3, 0x13E4 => 0xABB4, 0x13E5 => 0xABB5, 0x13E6 => 0xABB6, 0x13E7 => 0xABB7, 0x13E8 => 0xABB8, 0x13E9 => 0xABB9, 0x13EA => 0xABBA, 0x13EB => 0xABBB, 0x13EC => 0xABBC, 0x13ED => 0xABBD, 0x13EE => 0xABBE, 0x13EF => 0xABBF, 0x13F0 => 0x13F8, 0x13F1 => 0x13F9, 0x13F2 => 0x13FA, 0x13F3 => 0x13FB, 0x13F4 => 0x13FC, 0x13F5 => 0x13FD, 0x1C90 => 0x10D0, 0x1C91 => 0x10D1, 0x1C92 => 0x10D2, 0x1C93 => 0x10D3, 0x1C94 => 0x10D4, 0x1C95 => 0x10D5, 0x1C96 => 0x10D6, 0x1C97 => 0x10D7, 0x1C98 => 0x10D8, 0x1C99 => 0x10D9, 0x1C9A => 0x10DA, 0x1C9B => 0x10DB, 0x1C9C => 0x10DC, 0x1C9D => 0x10DD, 0x1C9E => 0x10DE, 0x1C9F => 0x10DF, 0x1CA0 => 0x10E0, 0x1CA1 => 0x10E1, 0x1CA2 => 0x10E2, 0x1CA3 => 0x10E3, 0x1CA4 => 0x10E4, 0x1CA5 => 0x10E5, 0x1CA6 => 0x10E6, 0x1CA7 => 0x10E7, 0x1CA8 => 0x10E8, 0x1CA9 => 0x10E9, 0x1CAA => 0x10EA, 0x1CAB => 0x10EB, 0x1CAC => 0x10EC, 0x1CAD => 0x10ED, 0x1CAE => 0x10EE, 0x1CAF => 0x10EF, 0x1CB0 => 0x10F0, 0x1CB1 => 0x10F1, 0x1CB2 => 0x10F2, 0x1CB3 => 0x10F3, 0x1CB4 => 0x10F4, 0x1CB5 => 0x10F5, 0x1CB6 => 0x10F6, 0x1CB7 => 0x10F7, 0x1CB8 => 0x10F8, 0x1CB9 => 0x10F9, 0x1CBA => 0x10FA, 0x1CBD => 0x10FD, 0x1CBE => 0x10FE, 0x1CBF => 0x10FF, 0x1E00 => 0x1E01, 0x1E02 => 0x1E03, 0x1E04 => 0x1E05, 0x1E06 => 0x1E07, 0x1E08 => 0x1E09, 0x1E0A => 0x1E0B, 0x1E0C => 0x1E0D, 0x1E0E => 0x1E0F, 0x1E10 => 0x1E11, 0x1E12 => 0x1E13, 0x1E14 => 0x1E15, 0x1E16 => 0x1E17, 0x1E18 => 0x1E19, 0x1E1A => 0x1E1B, 0x1E1C => 0x1E1D, 0x1E1E => 0x1E1F, 0x1E20 => 0x1E21, 0x1E22 => 0x1E23, 0x1E24 => 0x1E25, 0x1E26 => 0x1E27, 0x1E28 => 0x1E29, 0x1E2A => 0x1E2B, 0x1E2C => 0x1E2D, 0x1E2E => 0x1E2F, 0x1E30 => 0x1E31, 0x1E32 => 0x1E33, 0x1E34 => 0x1E35, 0x1E36 => 0x1E37, 0x1E38 => 0x1E39, 0x1E3A => 0x1E3B, 0x1E3C => 0x1E3D, 0x1E3E => 0x1E3F, 0x1E40 => 0x1E41, 0x1E42 => 0x1E43, 0x1E44 => 0x1E45, 0x1E46 => 0x1E47, 0x1E48 => 0x1E49, 0x1E4A => 0x1E4B, 0x1E4C => 0x1E4D, 0x1E4E => 0x1E4F, 0x1E50 => 0x1E51, 0x1E52 => 0x1E53, 0x1E54 => 0x1E55, 0x1E56 => 0x1E57, 0x1E58 => 0x1E59, 0x1E5A => 0x1E5B, 0x1E5C => 0x1E5D, 0x1E5E => 0x1E5F, 0x1E60 => 0x1E61, 0x1E62 => 0x1E63, 0x1E64 => 0x1E65, 0x1E66 => 0x1E67, 0x1E68 => 0x1E69, 0x1E6A => 0x1E6B, 0x1E6C => 0x1E6D, 0x1E6E => 0x1E6F, 0x1E70 => 0x1E71, 0x1E72 => 0x1E73, 0x1E74 => 0x1E75, 0x1E76 => 0x1E77, 0x1E78 => 0x1E79, 0x1E7A => 0x1E7B, 0x1E7C => 0x1E7D, 0x1E7E => 0x1E7F, 0x1E80 => 0x1E81, 0x1E82 => 0x1E83, 0x1E84 => 0x1E85, 0x1E86 => 0x1E87, 0x1E88 => 0x1E89, 0x1E8A => 0x1E8B, 0x1E8C => 0x1E8D, 0x1E8E => 0x1E8F, 0x1E90 => 0x1E91, 0x1E92 => 0x1E93, 0x1E94 => 0x1E95, 0x1E9E => 0xDF, 0x1EA0 => 0x1EA1, 0x1EA2 => 0x1EA3, 0x1EA4 => 0x1EA5, 0x1EA6 => 0x1EA7, 0x1EA8 => 0x1EA9, 0x1EAA => 0x1EAB, 0x1EAC => 0x1EAD, 0x1EAE => 0x1EAF, 0x1EB0 => 0x1EB1, 0x1EB2 => 0x1EB3, 0x1EB4 => 0x1EB5, 0x1EB6 => 0x1EB7, 0x1EB8 => 0x1EB9, 0x1EBA => 0x1EBB, 0x1EBC => 0x1EBD, 0x1EBE => 0x1EBF, 0x1EC0 => 0x1EC1, 0x1EC2 => 0x1EC3, 0x1EC4 => 0x1EC5, 0x1EC6 => 0x1EC7, 0x1EC8 => 0x1EC9, 0x1ECA => 0x1ECB, 0x1ECC => 0x1ECD, 0x1ECE => 0x1ECF, 0x1ED0 => 0x1ED1, 0x1ED2 => 0x1ED3, 0x1ED4 => 0x1ED5, 0x1ED6 => 0x1ED7, 0x1ED8 => 0x1ED9, 0x1EDA => 0x1EDB, 0x1EDC => 0x1EDD, 0x1EDE => 0x1EDF, 0x1EE0 => 0x1EE1, 0x1EE2 => 0x1EE3, 0x1EE4 => 0x1EE5, 0x1EE6 => 0x1EE7, 0x1EE8 => 0x1EE9, 0x1EEA => 0x1EEB, 0x1EEC => 0x1EED, 0x1EEE => 0x1EEF, 0x1EF0 => 0x1EF1, 0x1EF2 => 0x1EF3, 0x1EF4 => 0x1EF5, 0x1EF6 => 0x1EF7, 0x1EF8 => 0x1EF9, 0x1EFA => 0x1EFB, 0x1EFC => 0x1EFD, 0x1EFE => 0x1EFF, 0x1F08 => 0x1F00, 0x1F09 => 0x1F01, 0x1F0A => 0x1F02, 0x1F0B => 0x1F03, 0x1F0C => 0x1F04, 0x1F0D => 0x1F05, 0x1F0E => 0x1F06, 0x1F0F => 0x1F07, 0x1F18 => 0x1F10, 0x1F19 => 0x1F11, 0x1F1A => 0x1F12, 0x1F1B => 0x1F13, 0x1F1C => 0x1F14, 0x1F1D => 0x1F15, 0x1F28 => 0x1F20, 0x1F29 => 0x1F21, 0x1F2A => 0x1F22, 0x1F2B => 0x1F23, 0x1F2C => 0x1F24, 0x1F2D => 0x1F25, 0x1F2E => 0x1F26, 0x1F2F => 0x1F27, 0x1F38 => 0x1F30, 0x1F39 => 0x1F31, 0x1F3A => 0x1F32, 0x1F3B => 0x1F33, 0x1F3C => 0x1F34, 0x1F3D => 0x1F35, 0x1F3E => 0x1F36, 0x1F3F => 0x1F37, 0x1F48 => 0x1F40, 0x1F49 => 0x1F41, 0x1F4A => 0x1F42, 0x1F4B => 0x1F43, 0x1F4C => 0x1F44, 0x1F4D => 0x1F45, 0x1F59 => 0x1F51, 0x1F5B => 0x1F53, 0x1F5D => 0x1F55, 0x1F5F => 0x1F57, 0x1F68 => 0x1F60, 0x1F69 => 0x1F61, 0x1F6A => 0x1F62, 0x1F6B => 0x1F63, 0x1F6C => 0x1F64, 0x1F6D => 0x1F65, 0x1F6E => 0x1F66, 0x1F6F => 0x1F67, 0x1F88 => 0x1F80, 0x1F89 => 0x1F81, 0x1F8A => 0x1F82, 0x1F8B => 0x1F83, 0x1F8C => 0x1F84, 0x1F8D => 0x1F85, 0x1F8E => 0x1F86, 0x1F8F => 0x1F87, 0x1F98 => 0x1F90, 0x1F99 => 0x1F91, 0x1F9A => 0x1F92, 0x1F9B => 0x1F93, 0x1F9C => 0x1F94, 0x1F9D => 0x1F95, 0x1F9E => 0x1F96, 0x1F9F => 0x1F97, 0x1FA8 => 0x1FA0, 0x1FA9 => 0x1FA1, 0x1FAA => 0x1FA2, 0x1FAB => 0x1FA3, 0x1FAC => 0x1FA4, 0x1FAD => 0x1FA5, 0x1FAE => 0x1FA6, 0x1FAF => 0x1FA7, 0x1FB8 => 0x1FB0, 0x1FB9 => 0x1FB1, 0x1FBA => 0x1F70, 0x1FBB => 0x1F71, 0x1FBC => 0x1FB3, 0x1FC8 => 0x1F72, 0x1FC9 => 0x1F73, 0x1FCA => 0x1F74, 0x1FCB => 0x1F75, 0x1FCC => 0x1FC3, 0x1FD8 => 0x1FD0, 0x1FD9 => 0x1FD1, 0x1FDA => 0x1F76, 0x1FDB => 0x1F77, 0x1FE8 => 0x1FE0, 0x1FE9 => 0x1FE1, 0x1FEA => 0x1F7A, 0x1FEB => 0x1F7B, 0x1FEC => 0x1FE5, 0x1FF8 => 0x1F78, 0x1FF9 => 0x1F79, 0x1FFA => 0x1F7C, 0x1FFB => 0x1F7D, 0x1FFC => 0x1FF3, 0x2126 => 0x3C9, 0x212A => 0x6B, 0x212B => 0xE5, 0x2132 => 0x214E, 0x2160 => 0x2170, 0x2161 => 0x2171, 0x2162 => 0x2172, 0x2163 => 0x2173, 0x2164 => 0x2174, 0x2165 => 0x2175, 0x2166 => 0x2176, 0x2167 => 0x2177, 0x2168 => 0x2178, 0x2169 => 0x2179, 0x216A => 0x217A, 0x216B => 0x217B, 0x216C => 0x217C, 0x216D => 0x217D, 0x216E => 0x217E, 0x216F => 0x217F, 0x2183 => 0x2184, 0x24B6 => 0x24D0, 0x24B7 => 0x24D1, 0x24B8 => 0x24D2, 0x24B9 => 0x24D3, 0x24BA => 0x24D4, 0x24BB => 0x24D5, 0x24BC => 0x24D6, 0x24BD => 0x24D7, 0x24BE => 0x24D8, 0x24BF => 0x24D9, 0x24C0 => 0x24DA, 0x24C1 => 0x24DB, 0x24C2 => 0x24DC, 0x24C3 => 0x24DD, 0x24C4 => 0x24DE, 0x24C5 => 0x24DF, 0x24C6 => 0x24E0, 0x24C7 => 0x24E1, 0x24C8 => 0x24E2, 0x24C9 => 0x24E3, 0x24CA => 0x24E4, 0x24CB => 0x24E5, 0x24CC => 0x24E6, 0x24CD => 0x24E7, 0x24CE => 0x24E8, 0x24CF => 0x24E9, 0x2C00 => 0x2C30, 0x2C01 => 0x2C31, 0x2C02 => 0x2C32, 0x2C03 => 0x2C33, 0x2C04 => 0x2C34, 0x2C05 => 0x2C35, 0x2C06 => 0x2C36, 0x2C07 => 0x2C37, 0x2C08 => 0x2C38, 0x2C09 => 0x2C39, 0x2C0A => 0x2C3A, 0x2C0B => 0x2C3B, 0x2C0C => 0x2C3C, 0x2C0D => 0x2C3D, 0x2C0E => 0x2C3E, 0x2C0F => 0x2C3F, 0x2C10 => 0x2C40, 0x2C11 => 0x2C41, 0x2C12 => 0x2C42, 0x2C13 => 0x2C43, 0x2C14 => 0x2C44, 0x2C15 => 0x2C45, 0x2C16 => 0x2C46, 0x2C17 => 0x2C47, 0x2C18 => 0x2C48, 0x2C19 => 0x2C49, 0x2C1A => 0x2C4A, 0x2C1B => 0x2C4B, 0x2C1C => 0x2C4C, 0x2C1D => 0x2C4D, 0x2C1E => 0x2C4E, 0x2C1F => 0x2C4F, 0x2C20 => 0x2C50, 0x2C21 => 0x2C51, 0x2C22 => 0x2C52, 0x2C23 => 0x2C53, 0x2C24 => 0x2C54, 0x2C25 => 0x2C55, 0x2C26 => 0x2C56, 0x2C27 => 0x2C57, 0x2C28 => 0x2C58, 0x2C29 => 0x2C59, 0x2C2A => 0x2C5A, 0x2C2B => 0x2C5B, 0x2C2C => 0x2C5C, 0x2C2D => 0x2C5D, 0x2C2E => 0x2C5E, 0x2C60 => 0x2C61, 0x2C62 => 0x26B, 0x2C63 => 0x1D7D, 0x2C64 => 0x27D, 0x2C67 => 0x2C68, 0x2C69 => 0x2C6A, 0x2C6B => 0x2C6C, 0x2C6D => 0x251, 0x2C6E => 0x271, 0x2C6F => 0x250, 0x2C70 => 0x252, 0x2C72 => 0x2C73, 0x2C75 => 0x2C76, 0x2C7E => 0x23F, 0x2C7F => 0x240, 0x2C80 => 0x2C81, 0x2C82 => 0x2C83, 0x2C84 => 0x2C85, 0x2C86 => 0x2C87, 0x2C88 => 0x2C89, 0x2C8A => 0x2C8B, 0x2C8C => 0x2C8D, 0x2C8E => 0x2C8F, 0x2C90 => 0x2C91, 0x2C92 => 0x2C93, 0x2C94 => 0x2C95, 0x2C96 => 0x2C97, 0x2C98 => 0x2C99, 0x2C9A => 0x2C9B, 0x2C9C => 0x2C9D, 0x2C9E => 0x2C9F, 0x2CA0 => 0x2CA1, 0x2CA2 => 0x2CA3, 0x2CA4 => 0x2CA5, 0x2CA6 => 0x2CA7, 0x2CA8 => 0x2CA9, 0x2CAA => 0x2CAB, 0x2CAC => 0x2CAD, 0x2CAE => 0x2CAF, 0x2CB0 => 0x2CB1, 0x2CB2 => 0x2CB3, 0x2CB4 => 0x2CB5, 0x2CB6 => 0x2CB7, 0x2CB8 => 0x2CB9, 0x2CBA => 0x2CBB, 0x2CBC => 0x2CBD, 0x2CBE => 0x2CBF, 0x2CC0 => 0x2CC1, 0x2CC2 => 0x2CC3, 0x2CC4 => 0x2CC5, 0x2CC6 => 0x2CC7, 0x2CC8 => 0x2CC9, 0x2CCA => 0x2CCB, 0x2CCC => 0x2CCD, 0x2CCE => 0x2CCF, 0x2CD0 => 0x2CD1, 0x2CD2 => 0x2CD3, 0x2CD4 => 0x2CD5, 0x2CD6 => 0x2CD7, 0x2CD8 => 0x2CD9, 0x2CDA => 0x2CDB, 0x2CDC => 0x2CDD, 0x2CDE => 0x2CDF, 0x2CE0 => 0x2CE1, 0x2CE2 => 0x2CE3, 0x2CEB => 0x2CEC, 0x2CED => 0x2CEE, 0x2CF2 => 0x2CF3, 0xA640 => 0xA641, 0xA642 => 0xA643, 0xA644 => 0xA645, 0xA646 => 0xA647, 0xA648 => 0xA649, 0xA64A => 0xA64B, 0xA64C => 0xA64D, 0xA64E => 0xA64F, 0xA650 => 0xA651, 0xA652 => 0xA653, 0xA654 => 0xA655, 0xA656 => 0xA657, 0xA658 => 0xA659, 0xA65A => 0xA65B, 0xA65C => 0xA65D, 0xA65E => 0xA65F, 0xA660 => 0xA661, 0xA662 => 0xA663, 0xA664 => 0xA665, 0xA666 => 0xA667, 0xA668 => 0xA669, 0xA66A => 0xA66B, 0xA66C => 0xA66D, 0xA680 => 0xA681, 0xA682 => 0xA683, 0xA684 => 0xA685, 0xA686 => 0xA687, 0xA688 => 0xA689, 0xA68A => 0xA68B, 0xA68C => 0xA68D, 0xA68E => 0xA68F, 0xA690 => 0xA691, 0xA692 => 0xA693, 0xA694 => 0xA695, 0xA696 => 0xA697, 0xA698 => 0xA699, 0xA69A => 0xA69B, 0xA722 => 0xA723, 0xA724 => 0xA725, 0xA726 => 0xA727, 0xA728 => 0xA729, 0xA72A => 0xA72B, 0xA72C => 0xA72D, 0xA72E => 0xA72F, 0xA732 => 0xA733, 0xA734 => 0xA735, 0xA736 => 0xA737, 0xA738 => 0xA739, 0xA73A => 0xA73B, 0xA73C => 0xA73D, 0xA73E => 0xA73F, 0xA740 => 0xA741, 0xA742 => 0xA743, 0xA744 => 0xA745, 0xA746 => 0xA747, 0xA748 => 0xA749, 0xA74A => 0xA74B, 0xA74C => 0xA74D, 0xA74E => 0xA74F, 0xA750 => 0xA751, 0xA752 => 0xA753, 0xA754 => 0xA755, 0xA756 => 0xA757, 0xA758 => 0xA759, 0xA75A => 0xA75B, 0xA75C => 0xA75D, 0xA75E => 0xA75F, 0xA760 => 0xA761, 0xA762 => 0xA763, 0xA764 => 0xA765, 0xA766 => 0xA767, 0xA768 => 0xA769, 0xA76A => 0xA76B, 0xA76C => 0xA76D, 0xA76E => 0xA76F, 0xA779 => 0xA77A, 0xA77B => 0xA77C, 0xA77D => 0x1D79, 0xA77E => 0xA77F, 0xA780 => 0xA781, 0xA782 => 0xA783, 0xA784 => 0xA785, 0xA786 => 0xA787, 0xA78B => 0xA78C, 0xA78D => 0x265, 0xA790 => 0xA791, 0xA792 => 0xA793, 0xA796 => 0xA797, 0xA798 => 0xA799, 0xA79A => 0xA79B, 0xA79C => 0xA79D, 0xA79E => 0xA79F, 0xA7A0 => 0xA7A1, 0xA7A2 => 0xA7A3, 0xA7A4 => 0xA7A5, 0xA7A6 => 0xA7A7, 0xA7A8 => 0xA7A9, 0xA7AA => 0x266, 0xA7AB => 0x25C, 0xA7AC => 0x261, 0xA7AD => 0x26C, 0xA7AE => 0x26A, 0xA7B0 => 0x29E, 0xA7B1 => 0x287, 0xA7B2 => 0x29D, 0xA7B3 => 0xAB53, 0xA7B4 => 0xA7B5, 0xA7B6 => 0xA7B7, 0xA7B8 => 0xA7B9, 0xA7BA => 0xA7BB, 0xA7BC => 0xA7BD, 0xA7BE => 0xA7BF, 0xA7C2 => 0xA7C3, 0xA7C4 => 0xA794, 0xA7C5 => 0x282, 0xA7C6 => 0x1D8E, 0xA7C7 => 0xA7C8, 0xA7C9 => 0xA7CA, 0xA7F5 => 0xA7F6, 0xFF21 => 0xFF41, 0xFF22 => 0xFF42, 0xFF23 => 0xFF43, 0xFF24 => 0xFF44, 0xFF25 => 0xFF45, 0xFF26 => 0xFF46, 0xFF27 => 0xFF47, 0xFF28 => 0xFF48, 0xFF29 => 0xFF49, 0xFF2A => 0xFF4A, 0xFF2B => 0xFF4B, 0xFF2C => 0xFF4C, 0xFF2D => 0xFF4D, 0xFF2E => 0xFF4E, 0xFF2F => 0xFF4F, 0xFF30 => 0xFF50, 0xFF31 => 0xFF51, 0xFF32 => 0xFF52, 0xFF33 => 0xFF53, 0xFF34 => 0xFF54, 0xFF35 => 0xFF55, 0xFF36 => 0xFF56, 0xFF37 => 0xFF57, 0xFF38 => 0xFF58, 0xFF39 => 0xFF59, 0xFF3A => 0xFF5A, 0x10400 => 0x10428, 0x10401 => 0x10429, 0x10402 => 0x1042A, 0x10403 => 0x1042B, 0x10404 => 0x1042C, 0x10405 => 0x1042D, 0x10406 => 0x1042E, 0x10407 => 0x1042F, 0x10408 => 0x10430, 0x10409 => 0x10431, 0x1040A => 0x10432, 0x1040B => 0x10433, 0x1040C => 0x10434, 0x1040D => 0x10435, 0x1040E => 0x10436, 0x1040F => 0x10437, 0x10410 => 0x10438, 0x10411 => 0x10439, 0x10412 => 0x1043A, 0x10413 => 0x1043B, 0x10414 => 0x1043C, 0x10415 => 0x1043D, 0x10416 => 0x1043E, 0x10417 => 0x1043F, 0x10418 => 0x10440, 0x10419 => 0x10441, 0x1041A => 0x10442, 0x1041B => 0x10443, 0x1041C => 0x10444, 0x1041D => 0x10445, 0x1041E => 0x10446, 0x1041F => 0x10447, 0x10420 => 0x10448, 0x10421 => 0x10449, 0x10422 => 0x1044A, 0x10423 => 0x1044B, 0x10424 => 0x1044C, 0x10425 => 0x1044D, 0x10426 => 0x1044E, 0x10427 => 0x1044F, 0x104B0 => 0x104D8, 0x104B1 => 0x104D9, 0x104B2 => 0x104DA, 0x104B3 => 0x104DB, 0x104B4 => 0x104DC, 0x104B5 => 0x104DD, 0x104B6 => 0x104DE, 0x104B7 => 0x104DF, 0x104B8 => 0x104E0, 0x104B9 => 0x104E1, 0x104BA => 0x104E2, 0x104BB => 0x104E3, 0x104BC => 0x104E4, 0x104BD => 0x104E5, 0x104BE => 0x104E6, 0x104BF => 0x104E7, 0x104C0 => 0x104E8, 0x104C1 => 0x104E9, 0x104C2 => 0x104EA, 0x104C3 => 0x104EB, 0x104C4 => 0x104EC, 0x104C5 => 0x104ED, 0x104C6 => 0x104EE, 0x104C7 => 0x104EF, 0x104C8 => 0x104F0, 0x104C9 => 0x104F1, 0x104CA => 0x104F2, 0x104CB => 0x104F3, 0x104CC => 0x104F4, 0x104CD => 0x104F5, 0x104CE => 0x104F6, 0x104CF => 0x104F7, 0x104D0 => 0x104F8, 0x104D1 => 0x104F9, 0x104D2 => 0x104FA, 0x104D3 => 0x104FB, 0x10C80 => 0x10CC0, 0x10C81 => 0x10CC1, 0x10C82 => 0x10CC2, 0x10C83 => 0x10CC3, 0x10C84 => 0x10CC4, 0x10C85 => 0x10CC5, 0x10C86 => 0x10CC6, 0x10C87 => 0x10CC7, 0x10C88 => 0x10CC8, 0x10C89 => 0x10CC9, 0x10C8A => 0x10CCA, 0x10C8B => 0x10CCB, 0x10C8C => 0x10CCC, 0x10C8D => 0x10CCD, 0x10C8E => 0x10CCE, 0x10C8F => 0x10CCF, 0x10C90 => 0x10CD0, 0x10C91 => 0x10CD1, 0x10C92 => 0x10CD2, 0x10C93 => 0x10CD3, 0x10C94 => 0x10CD4, 0x10C95 => 0x10CD5, 0x10C96 => 0x10CD6, 0x10C97 => 0x10CD7, 0x10C98 => 0x10CD8, 0x10C99 => 0x10CD9, 0x10C9A => 0x10CDA, 0x10C9B => 0x10CDB, 0x10C9C => 0x10CDC, 0x10C9D => 0x10CDD, 0x10C9E => 0x10CDE, 0x10C9F => 0x10CDF, 0x10CA0 => 0x10CE0, 0x10CA1 => 0x10CE1, 0x10CA2 => 0x10CE2, 0x10CA3 => 0x10CE3, 0x10CA4 => 0x10CE4, 0x10CA5 => 0x10CE5, 0x10CA6 => 0x10CE6, 0x10CA7 => 0x10CE7, 0x10CA8 => 0x10CE8, 0x10CA9 => 0x10CE9, 0x10CAA => 0x10CEA, 0x10CAB => 0x10CEB, 0x10CAC => 0x10CEC, 0x10CAD => 0x10CED, 0x10CAE => 0x10CEE, 0x10CAF => 0x10CEF, 0x10CB0 => 0x10CF0, 0x10CB1 => 0x10CF1, 0x10CB2 => 0x10CF2, 0x118A0 => 0x118C0, 0x118A1 => 0x118C1, 0x118A2 => 0x118C2, 0x118A3 => 0x118C3, 0x118A4 => 0x118C4, 0x118A5 => 0x118C5, 0x118A6 => 0x118C6, 0x118A7 => 0x118C7, 0x118A8 => 0x118C8, 0x118A9 => 0x118C9, 0x118AA => 0x118CA, 0x118AB => 0x118CB, 0x118AC => 0x118CC, 0x118AD => 0x118CD, 0x118AE => 0x118CE, 0x118AF => 0x118CF, 0x118B0 => 0x118D0, 0x118B1 => 0x118D1, 0x118B2 => 0x118D2, 0x118B3 => 0x118D3, 0x118B4 => 0x118D4, 0x118B5 => 0x118D5, 0x118B6 => 0x118D6, 0x118B7 => 0x118D7, 0x118B8 => 0x118D8, 0x118B9 => 0x118D9, 0x118BA => 0x118DA, 0x118BB => 0x118DB, 0x118BC => 0x118DC, 0x118BD => 0x118DD, 0x118BE => 0x118DE, 0x118BF => 0x118DF, 0x16E40 => 0x16E60, 0x16E41 => 0x16E61, 0x16E42 => 0x16E62, 0x16E43 => 0x16E63, 0x16E44 => 0x16E64, 0x16E45 => 0x16E65, 0x16E46 => 0x16E66, 0x16E47 => 0x16E67, 0x16E48 => 0x16E68, 0x16E49 => 0x16E69, 0x16E4A => 0x16E6A, 0x16E4B => 0x16E6B, 0x16E4C => 0x16E6C, 0x16E4D => 0x16E6D, 0x16E4E => 0x16E6E, 0x16E4F => 0x16E6F, 0x16E50 => 0x16E70, 0x16E51 => 0x16E71, 0x16E52 => 0x16E72, 0x16E53 => 0x16E73, 0x16E54 => 0x16E74, 0x16E55 => 0x16E75, 0x16E56 => 0x16E76, 0x16E57 => 0x16E77, 0x16E58 => 0x16E78, 0x16E59 => 0x16E79, 0x16E5A => 0x16E7A, 0x16E5B => 0x16E7B, 0x16E5C => 0x16E7C, 0x16E5D => 0x16E7D, 0x16E5E => 0x16E7E, 0x16E5F => 0x16E7F, 0x1E900 => 0x1E922, 0x1E901 => 0x1E923, 0x1E902 => 0x1E924, 0x1E903 => 0x1E925, 0x1E904 => 0x1E926, 0x1E905 => 0x1E927, 0x1E906 => 0x1E928, 0x1E907 => 0x1E929, 0x1E908 => 0x1E92A, 0x1E909 => 0x1E92B, 0x1E90A => 0x1E92C, 0x1E90B => 0x1E92D, 0x1E90C => 0x1E92E, 0x1E90D => 0x1E92F, 0x1E90E => 0x1E930, 0x1E90F => 0x1E931, 0x1E910 => 0x1E932, 0x1E911 => 0x1E933, 0x1E912 => 0x1E934, 0x1E913 => 0x1E935, 0x1E914 => 0x1E936, 0x1E915 => 0x1E937, 0x1E916 => 0x1E938, 0x1E917 => 0x1E939, 0x1E918 => 0x1E93A, 0x1E919 => 0x1E93B, 0x1E91A => 0x1E93C, 0x1E91B => 0x1E93D, 0x1E91C => 0x1E93E, 0x1E91D => 0x1E93F, 0x1E91E => 0x1E940, 0x1E91F => 0x1E941, 0x1E920 => 0x1E942, 0x1E921 => 0x1E943, ]; res/ascii.php 0000777 00000026301 15251721406 0007152 0 ustar 00 <?php return [ 0xA9 => 0x28, 0xAA => 0x61, 0xB0 => 0x30, 0xB2 => 0x32, 0xB3 => 0x33, 0xB5 => 0x75, 0xB9 => 0x31, 0xBA => 0x6F, 0xC0 => 0x41, 0xC1 => 0x41, 0xC2 => 0x41, 0xC3 => 0x41, 0xC4 => 0x41, 0xC5 => 0x41, 0xC6 => 0x41, 0xC7 => 0x43, 0xC8 => 0x45, 0xC9 => 0x45, 0xCA => 0x45, 0xCB => 0x45, 0xCC => 0x49, 0xCD => 0x49, 0xCE => 0x49, 0xCF => 0x49, 0xD0 => 0x44, 0xD1 => 0x4E, 0xD2 => 0x4F, 0xD3 => 0x4F, 0xD4 => 0x4F, 0xD5 => 0x4F, 0xD6 => 0x4F, 0xD8 => 0x4F, 0xD9 => 0x55, 0xDA => 0x55, 0xDB => 0x55, 0xDC => 0x55, 0xDD => 0x59, 0xDE => 0x54, 0xDF => 0x73, 0xE0 => 0x61, 0xE1 => 0x61, 0xE2 => 0x61, 0xE3 => 0x61, 0xE4 => 0x61, 0xE5 => 0x61, 0xE6 => 0x61, 0xE7 => 0x63, 0xE8 => 0x65, 0xE9 => 0x65, 0xEA => 0x65, 0xEB => 0x65, 0xEC => 0x69, 0xED => 0x69, 0xEE => 0x69, 0xEF => 0x69, 0xF0 => 0x64, 0xF1 => 0x6E, 0xF2 => 0x6F, 0xF3 => 0x6F, 0xF4 => 0x6F, 0xF5 => 0x6F, 0xF6 => 0x6F, 0xF8 => 0x6F, 0xF9 => 0x75, 0xFA => 0x75, 0xFB => 0x75, 0xFC => 0x75, 0xFD => 0x79, 0xFE => 0x74, 0xFF => 0x79, 0x100 => 0x41, 0x101 => 0x61, 0x102 => 0x41, 0x103 => 0x61, 0x104 => 0x41, 0x105 => 0x61, 0x106 => 0x43, 0x107 => 0x63, 0x108 => 0x43, 0x109 => 0x63, 0x10A => 0x43, 0x10B => 0x63, 0x10C => 0x43, 0x10D => 0x63, 0x10E => 0x44, 0x10F => 0x64, 0x110 => 0x44, 0x111 => 0x64, 0x112 => 0x45, 0x113 => 0x65, 0x114 => 0x45, 0x115 => 0x65, 0x116 => 0x45, 0x117 => 0x65, 0x118 => 0x45, 0x119 => 0x65, 0x11A => 0x45, 0x11B => 0x65, 0x11C => 0x47, 0x11D => 0x67, 0x11E => 0x47, 0x11F => 0x67, 0x120 => 0x47, 0x121 => 0x67, 0x122 => 0x47, 0x123 => 0x67, 0x124 => 0x48, 0x125 => 0x68, 0x126 => 0x48, 0x127 => 0x68, 0x128 => 0x49, 0x129 => 0x69, 0x12A => 0x49, 0x12B => 0x69, 0x12C => 0x49, 0x12D => 0x69, 0x12E => 0x49, 0x12F => 0x69, 0x130 => 0x49, 0x131 => 0x69, 0x132 => 0x49, 0x133 => 0x69, 0x134 => 0x4A, 0x135 => 0x6A, 0x136 => 0x6B, 0x137 => 0x6B, 0x138 => 0x6B, 0x139 => 0x4C, 0x13A => 0x6C, 0x13B => 0x4C, 0x13C => 0x6C, 0x13D => 0x4C, 0x13E => 0x6C, 0x13F => 0x4C, 0x140 => 0x6C, 0x141 => 0x4C, 0x142 => 0x6C, 0x143 => 0x4E, 0x144 => 0x6E, 0x145 => 0x4E, 0x146 => 0x6E, 0x147 => 0x4E, 0x148 => 0x6E, 0x149 => 0x6E, 0x14A => 0x4E, 0x14B => 0x6E, 0x14C => 0x4F, 0x14D => 0x6F, 0x14E => 0x4F, 0x14F => 0x6F, 0x150 => 0x4F, 0x151 => 0x6F, 0x152 => 0x4F, 0x153 => 0x6F, 0x154 => 0x52, 0x155 => 0x72, 0x156 => 0x52, 0x157 => 0x72, 0x158 => 0x52, 0x159 => 0x72, 0x15A => 0x53, 0x15B => 0x73, 0x15C => 0x53, 0x15D => 0x73, 0x15E => 0x53, 0x15F => 0x73, 0x160 => 0x53, 0x161 => 0x73, 0x162 => 0x54, 0x163 => 0x74, 0x164 => 0x54, 0x165 => 0x74, 0x166 => 0x54, 0x167 => 0x74, 0x168 => 0x55, 0x169 => 0x75, 0x16A => 0x55, 0x16B => 0x75, 0x16C => 0x55, 0x16D => 0x75, 0x16E => 0x55, 0x16F => 0x75, 0x170 => 0x55, 0x171 => 0x75, 0x172 => 0x55, 0x173 => 0x75, 0x174 => 0x57, 0x175 => 0x77, 0x176 => 0x59, 0x177 => 0x79, 0x178 => 0x59, 0x179 => 0x5A, 0x17A => 0x7A, 0x17B => 0x5A, 0x17C => 0x7A, 0x17D => 0x5A, 0x17E => 0x7A, 0x17F => 0x73, 0x189 => 0x44, 0x18A => 0x44, 0x18B => 0x44, 0x18C => 0x64, 0x18F => 0x45, 0x192 => 0x66, 0x1A0 => 0x4F, 0x1A1 => 0x6F, 0x1AF => 0x55, 0x1B0 => 0x75, 0x1CD => 0x41, 0x1CE => 0x61, 0x1CF => 0x49, 0x1D0 => 0x69, 0x1D1 => 0x4F, 0x1D2 => 0x6F, 0x1D3 => 0x55, 0x1D4 => 0x75, 0x1D5 => 0x55, 0x1D6 => 0x75, 0x1D7 => 0x55, 0x1D8 => 0x75, 0x1D9 => 0x55, 0x1DA => 0x75, 0x1DB => 0x55, 0x1DC => 0x75, 0x1FA => 0x41, 0x1FB => 0x61, 0x1FC => 0x41, 0x1FD => 0x61, 0x1FE => 0x4F, 0x1FF => 0x6F, 0x218 => 0x53, 0x219 => 0x73, 0x21A => 0x54, 0x21B => 0x74, 0x221 => 0x64, 0x256 => 0x64, 0x257 => 0x64, 0x259 => 0x65, 0x386 => 0x41, 0x388 => 0x45, 0x389 => 0x48, 0x38A => 0x49, 0x38C => 0x4F, 0x38E => 0x59, 0x38F => 0x57, 0x390 => 0x69, 0x391 => 0x41, 0x392 => 0x42, 0x393 => 0x47, 0x394 => 0x44, 0x395 => 0x45, 0x396 => 0x5A, 0x397 => 0x48, 0x398 => 0x4F, 0x399 => 0x49, 0x39A => 0x4B, 0x39B => 0x4C, 0x39C => 0x4D, 0x39D => 0x4E, 0x39E => 0x58, 0x39F => 0x4F, 0x3A0 => 0x50, 0x3A1 => 0x52, 0x3A3 => 0x53, 0x3A4 => 0x54, 0x3A5 => 0x59, 0x3A6 => 0x46, 0x3A7 => 0x58, 0x3A8 => 0x50, 0x3A9 => 0x57, 0x3AA => 0x49, 0x3AB => 0x59, 0x3AC => 0x61, 0x3AD => 0x65, 0x3AE => 0x68, 0x3AF => 0x69, 0x3B0 => 0x79, 0x3B1 => 0x61, 0x3B2 => 0x62, 0x3B3 => 0x67, 0x3B4 => 0x64, 0x3B5 => 0x65, 0x3B6 => 0x7A, 0x3B7 => 0x68, 0x3B8 => 0x6F, 0x3B9 => 0x69, 0x3BA => 0x6B, 0x3BB => 0x6C, 0x3BC => 0x6D, 0x3BD => 0x6E, 0x3BE => 0x78, 0x3BF => 0x6F, 0x3C0 => 0x70, 0x3C1 => 0x72, 0x3C2 => 0x73, 0x3C3 => 0x73, 0x3C4 => 0x74, 0x3C5 => 0x79, 0x3C6 => 0x66, 0x3C7 => 0x78, 0x3C8 => 0x70, 0x3C9 => 0x77, 0x3CA => 0x69, 0x3CB => 0x79, 0x3CC => 0x6F, 0x3CD => 0x79, 0x3CE => 0x77, 0x3D0 => 0x76, 0x3D1 => 0x74, 0x3D2 => 0x49, 0x401 => 0x45, 0x402 => 0x44, 0x404 => 0x45, 0x406 => 0x49, 0x407 => 0x49, 0x408 => 0x6A, 0x409 => 0x4C, 0x40A => 0x4E, 0x40F => 0x44, 0x410 => 0x41, 0x411 => 0x42, 0x412 => 0x56, 0x413 => 0x47, 0x414 => 0x44, 0x415 => 0x45, 0x416 => 0x5A, 0x417 => 0x5A, 0x418 => 0x49, 0x419 => 0x59, 0x41A => 0x4B, 0x41B => 0x4C, 0x41C => 0x4D, 0x41D => 0x4E, 0x41E => 0x4F, 0x41F => 0x50, 0x420 => 0x52, 0x421 => 0x53, 0x422 => 0x54, 0x423 => 0x55, 0x424 => 0x46, 0x425 => 0x4B, 0x426 => 0x54, 0x427 => 0x43, 0x428 => 0x53, 0x429 => 0x53, 0x42A => 0x62, 0x42B => 0x59, 0x42C => 0x62, 0x42D => 0x45, 0x42E => 0x59, 0x42F => 0x59, 0x430 => 0x61, 0x431 => 0x62, 0x432 => 0x76, 0x433 => 0x67, 0x434 => 0x64, 0x435 => 0x65, 0x436 => 0x7A, 0x437 => 0x7A, 0x438 => 0x69, 0x439 => 0x79, 0x43A => 0x6B, 0x43B => 0x6C, 0x43C => 0x6D, 0x43D => 0x6E, 0x43E => 0x6F, 0x43F => 0x70, 0x440 => 0x72, 0x441 => 0x73, 0x442 => 0x74, 0x443 => 0x75, 0x444 => 0x66, 0x445 => 0x6B, 0x446 => 0x74, 0x447 => 0x63, 0x448 => 0x73, 0x449 => 0x73, 0x44B => 0x79, 0x44D => 0x65, 0x44E => 0x79, 0x44F => 0x79, 0x451 => 0x65, 0x452 => 0x64, 0x454 => 0x65, 0x456 => 0x69, 0x457 => 0x69, 0x458 => 0x6A, 0x459 => 0x6C, 0x45A => 0x6E, 0x45F => 0x64, 0x490 => 0x47, 0x491 => 0x67, 0x4E8 => 0x4F, 0x622 => 0x61, 0x623 => 0x61, 0x624 => 0x6F, 0x625 => 0x65, 0x626 => 0x65, 0x627 => 0x61, 0x628 => 0x62, 0x62A => 0x74, 0x62B => 0x74, 0x62C => 0x6A, 0x62D => 0x68, 0x62E => 0x6B, 0x62F => 0x64, 0x630 => 0x74, 0x631 => 0x72, 0x632 => 0x7A, 0x633 => 0x73, 0x634 => 0x73, 0x635 => 0x73, 0x636 => 0x64, 0x637 => 0x74, 0x638 => 0x74, 0x639 => 0x61, 0x63A => 0x67, 0x641 => 0x66, 0x642 => 0x6B, 0x643 => 0x6B, 0x644 => 0x6C, 0x645 => 0x6D, 0x646 => 0x6E, 0x647 => 0x68, 0x648 => 0x6F, 0x64A => 0x79, 0x664 => 0x34, 0x665 => 0x35, 0x666 => 0x36, 0x67E => 0x70, 0x686 => 0x63, 0x698 => 0x7A, 0x6A9 => 0x6B, 0x6AF => 0x67, 0x6CC => 0x69, 0x6F0 => 0x30, 0x6F1 => 0x31, 0x6F2 => 0x32, 0x6F3 => 0x33, 0x6F4 => 0x34, 0x6F5 => 0x35, 0x6F6 => 0x36, 0x6F7 => 0x37, 0x6F8 => 0x38, 0x6F9 => 0x39, 0x905 => 0x61, 0x906 => 0x61, 0x907 => 0x69, 0x908 => 0x69, 0x909 => 0x75, 0x90A => 0x75, 0x90D => 0x65, 0x90F => 0x65, 0x910 => 0x61, 0x911 => 0x6F, 0x912 => 0x6F, 0x913 => 0x6F, 0x92C => 0x42, 0x932 => 0x4C, 0x1000 => 0x6B, 0x1002 => 0x67, 0x1005 => 0x73, 0x1007 => 0x7A, 0x1009 => 0x75, 0x100A => 0x69, 0x100B => 0x74, 0x100D => 0x64, 0x1010 => 0x74, 0x1012 => 0x64, 0x1014 => 0x6E, 0x1015 => 0x70, 0x1017 => 0x62, 0x1019 => 0x6D, 0x101A => 0x79, 0x101C => 0x6C, 0x101D => 0x77, 0x101F => 0x68, 0x1021 => 0x61, 0x1023 => 0x69, 0x1027 => 0x65, 0x102B => 0x61, 0x102C => 0x61, 0x102D => 0x6F, 0x102E => 0x69, 0x102F => 0x75, 0x1030 => 0x75, 0x1031 => 0x65, 0x1032 => 0x65, 0x103D => 0x77, 0x103E => 0x68, 0x10D0 => 0x61, 0x10D1 => 0x62, 0x10D2 => 0x67, 0x10D3 => 0x64, 0x10D4 => 0x65, 0x10D5 => 0x76, 0x10D6 => 0x7A, 0x10D7 => 0x74, 0x10D8 => 0x69, 0x10D9 => 0x6B, 0x10DA => 0x6C, 0x10DB => 0x6D, 0x10DC => 0x6E, 0x10DD => 0x6F, 0x10DE => 0x70, 0x10DF => 0x7A, 0x10E0 => 0x72, 0x10E1 => 0x73, 0x10E2 => 0x74, 0x10E3 => 0x75, 0x10E4 => 0x66, 0x10E5 => 0x6B, 0x10E6 => 0x67, 0x10E7 => 0x71, 0x10E8 => 0x73, 0x10E9 => 0x63, 0x10EA => 0x74, 0x10EB => 0x64, 0x10EC => 0x74, 0x10ED => 0x63, 0x10EE => 0x6B, 0x10EF => 0x6A, 0x10F0 => 0x68, 0x1D05 => 0x44, 0x1D06 => 0x44, 0x1D6D => 0x64, 0x1D81 => 0x64, 0x1D91 => 0x64, 0x1E9E => 0x53, 0x1EA0 => 0x41, 0x1EA1 => 0x61, 0x1EA2 => 0x41, 0x1EA3 => 0x61, 0x1EA4 => 0x41, 0x1EA5 => 0x61, 0x1EA6 => 0x41, 0x1EA7 => 0x61, 0x1EA8 => 0x41, 0x1EA9 => 0x61, 0x1EAA => 0x41, 0x1EAB => 0x61, 0x1EAC => 0x41, 0x1EAD => 0x61, 0x1EAE => 0x41, 0x1EAF => 0x61, 0x1EB0 => 0x41, 0x1EB1 => 0x61, 0x1EB2 => 0x41, 0x1EB3 => 0x61, 0x1EB4 => 0x41, 0x1EB5 => 0x61, 0x1EB6 => 0x41, 0x1EB7 => 0x61, 0x1EB8 => 0x45, 0x1EB9 => 0x65, 0x1EBA => 0x45, 0x1EBB => 0x65, 0x1EBC => 0x45, 0x1EBD => 0x65, 0x1EBE => 0x45, 0x1EBF => 0x65, 0x1EC0 => 0x45, 0x1EC1 => 0x65, 0x1EC2 => 0x45, 0x1EC3 => 0x65, 0x1EC4 => 0x45, 0x1EC5 => 0x65, 0x1EC6 => 0x45, 0x1EC7 => 0x65, 0x1EC8 => 0x49, 0x1EC9 => 0x69, 0x1ECA => 0x49, 0x1ECB => 0x69, 0x1ECC => 0x4F, 0x1ECD => 0x6F, 0x1ECE => 0x4F, 0x1ECF => 0x6F, 0x1ED0 => 0x4F, 0x1ED1 => 0x6F, 0x1ED2 => 0x4F, 0x1ED3 => 0x6F, 0x1ED4 => 0x4F, 0x1ED5 => 0x6F, 0x1ED6 => 0x4F, 0x1ED7 => 0x6F, 0x1ED8 => 0x4F, 0x1ED9 => 0x6F, 0x1EDA => 0x4F, 0x1EDB => 0x6F, 0x1EDC => 0x4F, 0x1EDD => 0x6F, 0x1EDE => 0x4F, 0x1EDF => 0x6F, 0x1EE0 => 0x4F, 0x1EE1 => 0x6F, 0x1EE2 => 0x4F, 0x1EE3 => 0x6F, 0x1EE4 => 0x55, 0x1EE5 => 0x75, 0x1EE6 => 0x55, 0x1EE7 => 0x75, 0x1EE8 => 0x55, 0x1EE9 => 0x75, 0x1EEA => 0x55, 0x1EEB => 0x75, 0x1EEC => 0x55, 0x1EED => 0x75, 0x1EEE => 0x55, 0x1EEF => 0x75, 0x1EF0 => 0x55, 0x1EF1 => 0x75, 0x1EF2 => 0x59, 0x1EF3 => 0x79, 0x1EF4 => 0x59, 0x1EF5 => 0x79, 0x1EF6 => 0x59, 0x1EF7 => 0x79, 0x1EF8 => 0x59, 0x1EF9 => 0x79, 0x1F00 => 0x61, 0x1F01 => 0x61, 0x1F02 => 0x61, 0x1F03 => 0x61, 0x1F04 => 0x61, 0x1F05 => 0x61, 0x1F06 => 0x61, 0x1F07 => 0x61, 0x1F08 => 0x41, 0x1F09 => 0x41, 0x1F0A => 0x41, 0x1F0B => 0x41, 0x1F0C => 0x41, 0x1F0D => 0x41, 0x1F0E => 0x41, 0x1F0F => 0x41, 0x1F10 => 0x65, 0x1F11 => 0x65, 0x1F12 => 0x65, 0x1F13 => 0x65, 0x1F14 => 0x65, 0x1F15 => 0x65, 0x1F18 => 0x45, 0x1F19 => 0x45, 0x1F1A => 0x45, 0x1F1B => 0x45, 0x1F1C => 0x45, 0x1F1D => 0x45, 0x1F30 => 0x69, 0x1F31 => 0x69, 0x1F32 => 0x69, 0x1F33 => 0x69, 0x1F34 => 0x69, 0x1F35 => 0x69, 0x1F36 => 0x69, 0x1F37 => 0x69, 0x1F38 => 0x49, 0x1F39 => 0x49, 0x1F3B => 0x49, 0x1F3C => 0x49, 0x1F3D => 0x49, 0x1F3E => 0x49, 0x1F3F => 0x49, 0x1F40 => 0x6F, 0x1F41 => 0x6F, 0x1F42 => 0x6F, 0x1F43 => 0x6F, 0x1F44 => 0x6F, 0x1F45 => 0x6F, 0x1F48 => 0x4F, 0x1F49 => 0x4F, 0x1F4A => 0x4F, 0x1F4B => 0x4F, 0x1F4C => 0x4F, 0x1F4D => 0x4F, 0x1F70 => 0x61, 0x1F72 => 0x65, 0x1F76 => 0x69, 0x1F78 => 0x6F, 0x1F80 => 0x61, 0x1F81 => 0x61, 0x1F82 => 0x61, 0x1F83 => 0x61, 0x1F84 => 0x61, 0x1F85 => 0x61, 0x1F86 => 0x61, 0x1F87 => 0x61, 0x1F88 => 0x41, 0x1F89 => 0x41, 0x1F8A => 0x41, 0x1F8B => 0x41, 0x1F8C => 0x41, 0x1F8D => 0x41, 0x1F8E => 0x41, 0x1F8F => 0x41, 0x1FB0 => 0x61, 0x1FB1 => 0x61, 0x1FB2 => 0x61, 0x1FB3 => 0x61, 0x1FB4 => 0x61, 0x1FB6 => 0x61, 0x1FB7 => 0x61, 0x1FB8 => 0x41, 0x1FB9 => 0x41, 0x1FBA => 0x41, 0x1FBC => 0x41, 0x1FC8 => 0x45, 0x1FD0 => 0x69, 0x1FD1 => 0x69, 0x1FD2 => 0x69, 0x1FD6 => 0x69, 0x1FD7 => 0x69, 0x1FD8 => 0x49, 0x1FD9 => 0x49, 0x1FDA => 0x49, 0x1FE8 => 0x59, 0x1FE9 => 0x59, 0x1FEA => 0x59, 0x1FF8 => 0x4F, 0x2000 => 0x20, 0x2001 => 0x20, 0x2002 => 0x20, 0x2003 => 0x20, 0x2004 => 0x20, 0x2005 => 0x20, 0x2006 => 0x20, 0x2007 => 0x20, 0x2008 => 0x20, 0x2009 => 0x20, 0x200A => 0x20, 0x202F => 0x20, 0x205F => 0x20, 0x2074 => 0x34, 0x2075 => 0x35, 0x2076 => 0x36, 0x2077 => 0x37, 0x2078 => 0x38, 0x2079 => 0x39, 0x2080 => 0x30, 0x2081 => 0x31, 0x2082 => 0x32, 0x2083 => 0x33, 0x2084 => 0x34, 0x2085 => 0x35, 0x2086 => 0x36, 0x2087 => 0x37, 0x2088 => 0x38, 0x2089 => 0x39, 0x3000 => 0x20, ]; res/fold.php 0000777 00000060357 15251721406 0007017 0 ustar 00 <?php return [ 0x41 => 0x61, 0x42 => 0x62, 0x43 => 0x63, 0x44 => 0x64, 0x45 => 0x65, 0x46 => 0x66, 0x47 => 0x67, 0x48 => 0x68, 0x49 => 0x69, 0x4A => 0x6A, 0x4B => 0x6B, 0x4C => 0x6C, 0x4D => 0x6D, 0x4E => 0x6E, 0x4F => 0x6F, 0x50 => 0x70, 0x51 => 0x71, 0x52 => 0x72, 0x53 => 0x73, 0x54 => 0x74, 0x55 => 0x75, 0x56 => 0x76, 0x57 => 0x77, 0x58 => 0x78, 0x59 => 0x79, 0x5A => 0x7A, 0xB5 => 0x3BC, 0xC0 => 0xE0, 0xC1 => 0xE1, 0xC2 => 0xE2, 0xC3 => 0xE3, 0xC4 => 0xE4, 0xC5 => 0xE5, 0xC6 => 0xE6, 0xC7 => 0xE7, 0xC8 => 0xE8, 0xC9 => 0xE9, 0xCA => 0xEA, 0xCB => 0xEB, 0xCC => 0xEC, 0xCD => 0xED, 0xCE => 0xEE, 0xCF => 0xEF, 0xD0 => 0xF0, 0xD1 => 0xF1, 0xD2 => 0xF2, 0xD3 => 0xF3, 0xD4 => 0xF4, 0xD5 => 0xF5, 0xD6 => 0xF6, 0xD8 => 0xF8, 0xD9 => 0xF9, 0xDA => 0xFA, 0xDB => 0xFB, 0xDC => 0xFC, 0xDD => 0xFD, 0xDE => 0xFE, 0x100 => 0x101, 0x102 => 0x103, 0x104 => 0x105, 0x106 => 0x107, 0x108 => 0x109, 0x10A => 0x10B, 0x10C => 0x10D, 0x10E => 0x10F, 0x110 => 0x111, 0x112 => 0x113, 0x114 => 0x115, 0x116 => 0x117, 0x118 => 0x119, 0x11A => 0x11B, 0x11C => 0x11D, 0x11E => 0x11F, 0x120 => 0x121, 0x122 => 0x123, 0x124 => 0x125, 0x126 => 0x127, 0x128 => 0x129, 0x12A => 0x12B, 0x12C => 0x12D, 0x12E => 0x12F, 0x132 => 0x133, 0x134 => 0x135, 0x136 => 0x137, 0x139 => 0x13A, 0x13B => 0x13C, 0x13D => 0x13E, 0x13F => 0x140, 0x141 => 0x142, 0x143 => 0x144, 0x145 => 0x146, 0x147 => 0x148, 0x14A => 0x14B, 0x14C => 0x14D, 0x14E => 0x14F, 0x150 => 0x151, 0x152 => 0x153, 0x154 => 0x155, 0x156 => 0x157, 0x158 => 0x159, 0x15A => 0x15B, 0x15C => 0x15D, 0x15E => 0x15F, 0x160 => 0x161, 0x162 => 0x163, 0x164 => 0x165, 0x166 => 0x167, 0x168 => 0x169, 0x16A => 0x16B, 0x16C => 0x16D, 0x16E => 0x16F, 0x170 => 0x171, 0x172 => 0x173, 0x174 => 0x175, 0x176 => 0x177, 0x178 => 0xFF, 0x179 => 0x17A, 0x17B => 0x17C, 0x17D => 0x17E, 0x17F => 0x73, 0x181 => 0x253, 0x182 => 0x183, 0x184 => 0x185, 0x186 => 0x254, 0x187 => 0x188, 0x189 => 0x256, 0x18A => 0x257, 0x18B => 0x18C, 0x18E => 0x1DD, 0x18F => 0x259, 0x190 => 0x25B, 0x191 => 0x192, 0x193 => 0x260, 0x194 => 0x263, 0x196 => 0x269, 0x197 => 0x268, 0x198 => 0x199, 0x19C => 0x26F, 0x19D => 0x272, 0x19F => 0x275, 0x1A0 => 0x1A1, 0x1A2 => 0x1A3, 0x1A4 => 0x1A5, 0x1A6 => 0x280, 0x1A7 => 0x1A8, 0x1A9 => 0x283, 0x1AC => 0x1AD, 0x1AE => 0x288, 0x1AF => 0x1B0, 0x1B1 => 0x28A, 0x1B2 => 0x28B, 0x1B3 => 0x1B4, 0x1B5 => 0x1B6, 0x1B7 => 0x292, 0x1B8 => 0x1B9, 0x1BC => 0x1BD, 0x1C4 => 0x1C6, 0x1C5 => 0x1C6, 0x1C7 => 0x1C9, 0x1C8 => 0x1C9, 0x1CA => 0x1CC, 0x1CB => 0x1CC, 0x1CD => 0x1CE, 0x1CF => 0x1D0, 0x1D1 => 0x1D2, 0x1D3 => 0x1D4, 0x1D5 => 0x1D6, 0x1D7 => 0x1D8, 0x1D9 => 0x1DA, 0x1DB => 0x1DC, 0x1DE => 0x1DF, 0x1E0 => 0x1E1, 0x1E2 => 0x1E3, 0x1E4 => 0x1E5, 0x1E6 => 0x1E7, 0x1E8 => 0x1E9, 0x1EA => 0x1EB, 0x1EC => 0x1ED, 0x1EE => 0x1EF, 0x1F1 => 0x1F3, 0x1F2 => 0x1F3, 0x1F4 => 0x1F5, 0x1F6 => 0x195, 0x1F7 => 0x1BF, 0x1F8 => 0x1F9, 0x1FA => 0x1FB, 0x1FC => 0x1FD, 0x1FE => 0x1FF, 0x200 => 0x201, 0x202 => 0x203, 0x204 => 0x205, 0x206 => 0x207, 0x208 => 0x209, 0x20A => 0x20B, 0x20C => 0x20D, 0x20E => 0x20F, 0x210 => 0x211, 0x212 => 0x213, 0x214 => 0x215, 0x216 => 0x217, 0x218 => 0x219, 0x21A => 0x21B, 0x21C => 0x21D, 0x21E => 0x21F, 0x220 => 0x19E, 0x222 => 0x223, 0x224 => 0x225, 0x226 => 0x227, 0x228 => 0x229, 0x22A => 0x22B, 0x22C => 0x22D, 0x22E => 0x22F, 0x230 => 0x231, 0x232 => 0x233, 0x23A => 0x2C65, 0x23B => 0x23C, 0x23D => 0x19A, 0x23E => 0x2C66, 0x241 => 0x242, 0x243 => 0x180, 0x244 => 0x289, 0x245 => 0x28C, 0x246 => 0x247, 0x248 => 0x249, 0x24A => 0x24B, 0x24C => 0x24D, 0x24E => 0x24F, 0x345 => 0x3B9, 0x370 => 0x371, 0x372 => 0x373, 0x376 => 0x377, 0x37F => 0x3F3, 0x386 => 0x3AC, 0x388 => 0x3AD, 0x389 => 0x3AE, 0x38A => 0x3AF, 0x38C => 0x3CC, 0x38E => 0x3CD, 0x38F => 0x3CE, 0x391 => 0x3B1, 0x392 => 0x3B2, 0x393 => 0x3B3, 0x394 => 0x3B4, 0x395 => 0x3B5, 0x396 => 0x3B6, 0x397 => 0x3B7, 0x398 => 0x3B8, 0x399 => 0x3B9, 0x39A => 0x3BA, 0x39B => 0x3BB, 0x39C => 0x3BC, 0x39D => 0x3BD, 0x39E => 0x3BE, 0x39F => 0x3BF, 0x3A0 => 0x3C0, 0x3A1 => 0x3C1, 0x3A3 => 0x3C3, 0x3A4 => 0x3C4, 0x3A5 => 0x3C5, 0x3A6 => 0x3C6, 0x3A7 => 0x3C7, 0x3A8 => 0x3C8, 0x3A9 => 0x3C9, 0x3AA => 0x3CA, 0x3AB => 0x3CB, 0x3C2 => 0x3C3, 0x3CF => 0x3D7, 0x3D0 => 0x3B2, 0x3D1 => 0x3B8, 0x3D5 => 0x3C6, 0x3D6 => 0x3C0, 0x3D8 => 0x3D9, 0x3DA => 0x3DB, 0x3DC => 0x3DD, 0x3DE => 0x3DF, 0x3E0 => 0x3E1, 0x3E2 => 0x3E3, 0x3E4 => 0x3E5, 0x3E6 => 0x3E7, 0x3E8 => 0x3E9, 0x3EA => 0x3EB, 0x3EC => 0x3ED, 0x3EE => 0x3EF, 0x3F0 => 0x3BA, 0x3F1 => 0x3C1, 0x3F4 => 0x3B8, 0x3F5 => 0x3B5, 0x3F7 => 0x3F8, 0x3F9 => 0x3F2, 0x3FA => 0x3FB, 0x3FD => 0x37B, 0x3FE => 0x37C, 0x3FF => 0x37D, 0x400 => 0x450, 0x401 => 0x451, 0x402 => 0x452, 0x403 => 0x453, 0x404 => 0x454, 0x405 => 0x455, 0x406 => 0x456, 0x407 => 0x457, 0x408 => 0x458, 0x409 => 0x459, 0x40A => 0x45A, 0x40B => 0x45B, 0x40C => 0x45C, 0x40D => 0x45D, 0x40E => 0x45E, 0x40F => 0x45F, 0x410 => 0x430, 0x411 => 0x431, 0x412 => 0x432, 0x413 => 0x433, 0x414 => 0x434, 0x415 => 0x435, 0x416 => 0x436, 0x417 => 0x437, 0x418 => 0x438, 0x419 => 0x439, 0x41A => 0x43A, 0x41B => 0x43B, 0x41C => 0x43C, 0x41D => 0x43D, 0x41E => 0x43E, 0x41F => 0x43F, 0x420 => 0x440, 0x421 => 0x441, 0x422 => 0x442, 0x423 => 0x443, 0x424 => 0x444, 0x425 => 0x445, 0x426 => 0x446, 0x427 => 0x447, 0x428 => 0x448, 0x429 => 0x449, 0x42A => 0x44A, 0x42B => 0x44B, 0x42C => 0x44C, 0x42D => 0x44D, 0x42E => 0x44E, 0x42F => 0x44F, 0x460 => 0x461, 0x462 => 0x463, 0x464 => 0x465, 0x466 => 0x467, 0x468 => 0x469, 0x46A => 0x46B, 0x46C => 0x46D, 0x46E => 0x46F, 0x470 => 0x471, 0x472 => 0x473, 0x474 => 0x475, 0x476 => 0x477, 0x478 => 0x479, 0x47A => 0x47B, 0x47C => 0x47D, 0x47E => 0x47F, 0x480 => 0x481, 0x48A => 0x48B, 0x48C => 0x48D, 0x48E => 0x48F, 0x490 => 0x491, 0x492 => 0x493, 0x494 => 0x495, 0x496 => 0x497, 0x498 => 0x499, 0x49A => 0x49B, 0x49C => 0x49D, 0x49E => 0x49F, 0x4A0 => 0x4A1, 0x4A2 => 0x4A3, 0x4A4 => 0x4A5, 0x4A6 => 0x4A7, 0x4A8 => 0x4A9, 0x4AA => 0x4AB, 0x4AC => 0x4AD, 0x4AE => 0x4AF, 0x4B0 => 0x4B1, 0x4B2 => 0x4B3, 0x4B4 => 0x4B5, 0x4B6 => 0x4B7, 0x4B8 => 0x4B9, 0x4BA => 0x4BB, 0x4BC => 0x4BD, 0x4BE => 0x4BF, 0x4C0 => 0x4CF, 0x4C1 => 0x4C2, 0x4C3 => 0x4C4, 0x4C5 => 0x4C6, 0x4C7 => 0x4C8, 0x4C9 => 0x4CA, 0x4CB => 0x4CC, 0x4CD => 0x4CE, 0x4D0 => 0x4D1, 0x4D2 => 0x4D3, 0x4D4 => 0x4D5, 0x4D6 => 0x4D7, 0x4D8 => 0x4D9, 0x4DA => 0x4DB, 0x4DC => 0x4DD, 0x4DE => 0x4DF, 0x4E0 => 0x4E1, 0x4E2 => 0x4E3, 0x4E4 => 0x4E5, 0x4E6 => 0x4E7, 0x4E8 => 0x4E9, 0x4EA => 0x4EB, 0x4EC => 0x4ED, 0x4EE => 0x4EF, 0x4F0 => 0x4F1, 0x4F2 => 0x4F3, 0x4F4 => 0x4F5, 0x4F6 => 0x4F7, 0x4F8 => 0x4F9, 0x4FA => 0x4FB, 0x4FC => 0x4FD, 0x4FE => 0x4FF, 0x500 => 0x501, 0x502 => 0x503, 0x504 => 0x505, 0x506 => 0x507, 0x508 => 0x509, 0x50A => 0x50B, 0x50C => 0x50D, 0x50E => 0x50F, 0x510 => 0x511, 0x512 => 0x513, 0x514 => 0x515, 0x516 => 0x517, 0x518 => 0x519, 0x51A => 0x51B, 0x51C => 0x51D, 0x51E => 0x51F, 0x520 => 0x521, 0x522 => 0x523, 0x524 => 0x525, 0x526 => 0x527, 0x528 => 0x529, 0x52A => 0x52B, 0x52C => 0x52D, 0x52E => 0x52F, 0x531 => 0x561, 0x532 => 0x562, 0x533 => 0x563, 0x534 => 0x564, 0x535 => 0x565, 0x536 => 0x566, 0x537 => 0x567, 0x538 => 0x568, 0x539 => 0x569, 0x53A => 0x56A, 0x53B => 0x56B, 0x53C => 0x56C, 0x53D => 0x56D, 0x53E => 0x56E, 0x53F => 0x56F, 0x540 => 0x570, 0x541 => 0x571, 0x542 => 0x572, 0x543 => 0x573, 0x544 => 0x574, 0x545 => 0x575, 0x546 => 0x576, 0x547 => 0x577, 0x548 => 0x578, 0x549 => 0x579, 0x54A => 0x57A, 0x54B => 0x57B, 0x54C => 0x57C, 0x54D => 0x57D, 0x54E => 0x57E, 0x54F => 0x57F, 0x550 => 0x580, 0x551 => 0x581, 0x552 => 0x582, 0x553 => 0x583, 0x554 => 0x584, 0x555 => 0x585, 0x556 => 0x586, 0x10A0 => 0x2D00, 0x10A1 => 0x2D01, 0x10A2 => 0x2D02, 0x10A3 => 0x2D03, 0x10A4 => 0x2D04, 0x10A5 => 0x2D05, 0x10A6 => 0x2D06, 0x10A7 => 0x2D07, 0x10A8 => 0x2D08, 0x10A9 => 0x2D09, 0x10AA => 0x2D0A, 0x10AB => 0x2D0B, 0x10AC => 0x2D0C, 0x10AD => 0x2D0D, 0x10AE => 0x2D0E, 0x10AF => 0x2D0F, 0x10B0 => 0x2D10, 0x10B1 => 0x2D11, 0x10B2 => 0x2D12, 0x10B3 => 0x2D13, 0x10B4 => 0x2D14, 0x10B5 => 0x2D15, 0x10B6 => 0x2D16, 0x10B7 => 0x2D17, 0x10B8 => 0x2D18, 0x10B9 => 0x2D19, 0x10BA => 0x2D1A, 0x10BB => 0x2D1B, 0x10BC => 0x2D1C, 0x10BD => 0x2D1D, 0x10BE => 0x2D1E, 0x10BF => 0x2D1F, 0x10C0 => 0x2D20, 0x10C1 => 0x2D21, 0x10C2 => 0x2D22, 0x10C3 => 0x2D23, 0x10C4 => 0x2D24, 0x10C5 => 0x2D25, 0x10C7 => 0x2D27, 0x10CD => 0x2D2D, 0x13F8 => 0x13F0, 0x13F9 => 0x13F1, 0x13FA => 0x13F2, 0x13FB => 0x13F3, 0x13FC => 0x13F4, 0x13FD => 0x13F5, 0x1C80 => 0x432, 0x1C81 => 0x434, 0x1C82 => 0x43E, 0x1C83 => 0x441, 0x1C84 => 0x442, 0x1C85 => 0x442, 0x1C86 => 0x44A, 0x1C87 => 0x463, 0x1C88 => 0xA64B, 0x1C90 => 0x10D0, 0x1C91 => 0x10D1, 0x1C92 => 0x10D2, 0x1C93 => 0x10D3, 0x1C94 => 0x10D4, 0x1C95 => 0x10D5, 0x1C96 => 0x10D6, 0x1C97 => 0x10D7, 0x1C98 => 0x10D8, 0x1C99 => 0x10D9, 0x1C9A => 0x10DA, 0x1C9B => 0x10DB, 0x1C9C => 0x10DC, 0x1C9D => 0x10DD, 0x1C9E => 0x10DE, 0x1C9F => 0x10DF, 0x1CA0 => 0x10E0, 0x1CA1 => 0x10E1, 0x1CA2 => 0x10E2, 0x1CA3 => 0x10E3, 0x1CA4 => 0x10E4, 0x1CA5 => 0x10E5, 0x1CA6 => 0x10E6, 0x1CA7 => 0x10E7, 0x1CA8 => 0x10E8, 0x1CA9 => 0x10E9, 0x1CAA => 0x10EA, 0x1CAB => 0x10EB, 0x1CAC => 0x10EC, 0x1CAD => 0x10ED, 0x1CAE => 0x10EE, 0x1CAF => 0x10EF, 0x1CB0 => 0x10F0, 0x1CB1 => 0x10F1, 0x1CB2 => 0x10F2, 0x1CB3 => 0x10F3, 0x1CB4 => 0x10F4, 0x1CB5 => 0x10F5, 0x1CB6 => 0x10F6, 0x1CB7 => 0x10F7, 0x1CB8 => 0x10F8, 0x1CB9 => 0x10F9, 0x1CBA => 0x10FA, 0x1CBD => 0x10FD, 0x1CBE => 0x10FE, 0x1CBF => 0x10FF, 0x1E00 => 0x1E01, 0x1E02 => 0x1E03, 0x1E04 => 0x1E05, 0x1E06 => 0x1E07, 0x1E08 => 0x1E09, 0x1E0A => 0x1E0B, 0x1E0C => 0x1E0D, 0x1E0E => 0x1E0F, 0x1E10 => 0x1E11, 0x1E12 => 0x1E13, 0x1E14 => 0x1E15, 0x1E16 => 0x1E17, 0x1E18 => 0x1E19, 0x1E1A => 0x1E1B, 0x1E1C => 0x1E1D, 0x1E1E => 0x1E1F, 0x1E20 => 0x1E21, 0x1E22 => 0x1E23, 0x1E24 => 0x1E25, 0x1E26 => 0x1E27, 0x1E28 => 0x1E29, 0x1E2A => 0x1E2B, 0x1E2C => 0x1E2D, 0x1E2E => 0x1E2F, 0x1E30 => 0x1E31, 0x1E32 => 0x1E33, 0x1E34 => 0x1E35, 0x1E36 => 0x1E37, 0x1E38 => 0x1E39, 0x1E3A => 0x1E3B, 0x1E3C => 0x1E3D, 0x1E3E => 0x1E3F, 0x1E40 => 0x1E41, 0x1E42 => 0x1E43, 0x1E44 => 0x1E45, 0x1E46 => 0x1E47, 0x1E48 => 0x1E49, 0x1E4A => 0x1E4B, 0x1E4C => 0x1E4D, 0x1E4E => 0x1E4F, 0x1E50 => 0x1E51, 0x1E52 => 0x1E53, 0x1E54 => 0x1E55, 0x1E56 => 0x1E57, 0x1E58 => 0x1E59, 0x1E5A => 0x1E5B, 0x1E5C => 0x1E5D, 0x1E5E => 0x1E5F, 0x1E60 => 0x1E61, 0x1E62 => 0x1E63, 0x1E64 => 0x1E65, 0x1E66 => 0x1E67, 0x1E68 => 0x1E69, 0x1E6A => 0x1E6B, 0x1E6C => 0x1E6D, 0x1E6E => 0x1E6F, 0x1E70 => 0x1E71, 0x1E72 => 0x1E73, 0x1E74 => 0x1E75, 0x1E76 => 0x1E77, 0x1E78 => 0x1E79, 0x1E7A => 0x1E7B, 0x1E7C => 0x1E7D, 0x1E7E => 0x1E7F, 0x1E80 => 0x1E81, 0x1E82 => 0x1E83, 0x1E84 => 0x1E85, 0x1E86 => 0x1E87, 0x1E88 => 0x1E89, 0x1E8A => 0x1E8B, 0x1E8C => 0x1E8D, 0x1E8E => 0x1E8F, 0x1E90 => 0x1E91, 0x1E92 => 0x1E93, 0x1E94 => 0x1E95, 0x1E9B => 0x1E61, 0x1E9E => 0xDF, 0x1EA0 => 0x1EA1, 0x1EA2 => 0x1EA3, 0x1EA4 => 0x1EA5, 0x1EA6 => 0x1EA7, 0x1EA8 => 0x1EA9, 0x1EAA => 0x1EAB, 0x1EAC => 0x1EAD, 0x1EAE => 0x1EAF, 0x1EB0 => 0x1EB1, 0x1EB2 => 0x1EB3, 0x1EB4 => 0x1EB5, 0x1EB6 => 0x1EB7, 0x1EB8 => 0x1EB9, 0x1EBA => 0x1EBB, 0x1EBC => 0x1EBD, 0x1EBE => 0x1EBF, 0x1EC0 => 0x1EC1, 0x1EC2 => 0x1EC3, 0x1EC4 => 0x1EC5, 0x1EC6 => 0x1EC7, 0x1EC8 => 0x1EC9, 0x1ECA => 0x1ECB, 0x1ECC => 0x1ECD, 0x1ECE => 0x1ECF, 0x1ED0 => 0x1ED1, 0x1ED2 => 0x1ED3, 0x1ED4 => 0x1ED5, 0x1ED6 => 0x1ED7, 0x1ED8 => 0x1ED9, 0x1EDA => 0x1EDB, 0x1EDC => 0x1EDD, 0x1EDE => 0x1EDF, 0x1EE0 => 0x1EE1, 0x1EE2 => 0x1EE3, 0x1EE4 => 0x1EE5, 0x1EE6 => 0x1EE7, 0x1EE8 => 0x1EE9, 0x1EEA => 0x1EEB, 0x1EEC => 0x1EED, 0x1EEE => 0x1EEF, 0x1EF0 => 0x1EF1, 0x1EF2 => 0x1EF3, 0x1EF4 => 0x1EF5, 0x1EF6 => 0x1EF7, 0x1EF8 => 0x1EF9, 0x1EFA => 0x1EFB, 0x1EFC => 0x1EFD, 0x1EFE => 0x1EFF, 0x1F08 => 0x1F00, 0x1F09 => 0x1F01, 0x1F0A => 0x1F02, 0x1F0B => 0x1F03, 0x1F0C => 0x1F04, 0x1F0D => 0x1F05, 0x1F0E => 0x1F06, 0x1F0F => 0x1F07, 0x1F18 => 0x1F10, 0x1F19 => 0x1F11, 0x1F1A => 0x1F12, 0x1F1B => 0x1F13, 0x1F1C => 0x1F14, 0x1F1D => 0x1F15, 0x1F28 => 0x1F20, 0x1F29 => 0x1F21, 0x1F2A => 0x1F22, 0x1F2B => 0x1F23, 0x1F2C => 0x1F24, 0x1F2D => 0x1F25, 0x1F2E => 0x1F26, 0x1F2F => 0x1F27, 0x1F38 => 0x1F30, 0x1F39 => 0x1F31, 0x1F3A => 0x1F32, 0x1F3B => 0x1F33, 0x1F3C => 0x1F34, 0x1F3D => 0x1F35, 0x1F3E => 0x1F36, 0x1F3F => 0x1F37, 0x1F48 => 0x1F40, 0x1F49 => 0x1F41, 0x1F4A => 0x1F42, 0x1F4B => 0x1F43, 0x1F4C => 0x1F44, 0x1F4D => 0x1F45, 0x1F59 => 0x1F51, 0x1F5B => 0x1F53, 0x1F5D => 0x1F55, 0x1F5F => 0x1F57, 0x1F68 => 0x1F60, 0x1F69 => 0x1F61, 0x1F6A => 0x1F62, 0x1F6B => 0x1F63, 0x1F6C => 0x1F64, 0x1F6D => 0x1F65, 0x1F6E => 0x1F66, 0x1F6F => 0x1F67, 0x1F88 => 0x1F80, 0x1F89 => 0x1F81, 0x1F8A => 0x1F82, 0x1F8B => 0x1F83, 0x1F8C => 0x1F84, 0x1F8D => 0x1F85, 0x1F8E => 0x1F86, 0x1F8F => 0x1F87, 0x1F98 => 0x1F90, 0x1F99 => 0x1F91, 0x1F9A => 0x1F92, 0x1F9B => 0x1F93, 0x1F9C => 0x1F94, 0x1F9D => 0x1F95, 0x1F9E => 0x1F96, 0x1F9F => 0x1F97, 0x1FA8 => 0x1FA0, 0x1FA9 => 0x1FA1, 0x1FAA => 0x1FA2, 0x1FAB => 0x1FA3, 0x1FAC => 0x1FA4, 0x1FAD => 0x1FA5, 0x1FAE => 0x1FA6, 0x1FAF => 0x1FA7, 0x1FB8 => 0x1FB0, 0x1FB9 => 0x1FB1, 0x1FBA => 0x1F70, 0x1FBB => 0x1F71, 0x1FBC => 0x1FB3, 0x1FBE => 0x3B9, 0x1FC8 => 0x1F72, 0x1FC9 => 0x1F73, 0x1FCA => 0x1F74, 0x1FCB => 0x1F75, 0x1FCC => 0x1FC3, 0x1FD8 => 0x1FD0, 0x1FD9 => 0x1FD1, 0x1FDA => 0x1F76, 0x1FDB => 0x1F77, 0x1FE8 => 0x1FE0, 0x1FE9 => 0x1FE1, 0x1FEA => 0x1F7A, 0x1FEB => 0x1F7B, 0x1FEC => 0x1FE5, 0x1FF8 => 0x1F78, 0x1FF9 => 0x1F79, 0x1FFA => 0x1F7C, 0x1FFB => 0x1F7D, 0x1FFC => 0x1FF3, 0x2126 => 0x3C9, 0x212A => 0x6B, 0x212B => 0xE5, 0x2132 => 0x214E, 0x2160 => 0x2170, 0x2161 => 0x2171, 0x2162 => 0x2172, 0x2163 => 0x2173, 0x2164 => 0x2174, 0x2165 => 0x2175, 0x2166 => 0x2176, 0x2167 => 0x2177, 0x2168 => 0x2178, 0x2169 => 0x2179, 0x216A => 0x217A, 0x216B => 0x217B, 0x216C => 0x217C, 0x216D => 0x217D, 0x216E => 0x217E, 0x216F => 0x217F, 0x2183 => 0x2184, 0x24B6 => 0x24D0, 0x24B7 => 0x24D1, 0x24B8 => 0x24D2, 0x24B9 => 0x24D3, 0x24BA => 0x24D4, 0x24BB => 0x24D5, 0x24BC => 0x24D6, 0x24BD => 0x24D7, 0x24BE => 0x24D8, 0x24BF => 0x24D9, 0x24C0 => 0x24DA, 0x24C1 => 0x24DB, 0x24C2 => 0x24DC, 0x24C3 => 0x24DD, 0x24C4 => 0x24DE, 0x24C5 => 0x24DF, 0x24C6 => 0x24E0, 0x24C7 => 0x24E1, 0x24C8 => 0x24E2, 0x24C9 => 0x24E3, 0x24CA => 0x24E4, 0x24CB => 0x24E5, 0x24CC => 0x24E6, 0x24CD => 0x24E7, 0x24CE => 0x24E8, 0x24CF => 0x24E9, 0x2C00 => 0x2C30, 0x2C01 => 0x2C31, 0x2C02 => 0x2C32, 0x2C03 => 0x2C33, 0x2C04 => 0x2C34, 0x2C05 => 0x2C35, 0x2C06 => 0x2C36, 0x2C07 => 0x2C37, 0x2C08 => 0x2C38, 0x2C09 => 0x2C39, 0x2C0A => 0x2C3A, 0x2C0B => 0x2C3B, 0x2C0C => 0x2C3C, 0x2C0D => 0x2C3D, 0x2C0E => 0x2C3E, 0x2C0F => 0x2C3F, 0x2C10 => 0x2C40, 0x2C11 => 0x2C41, 0x2C12 => 0x2C42, 0x2C13 => 0x2C43, 0x2C14 => 0x2C44, 0x2C15 => 0x2C45, 0x2C16 => 0x2C46, 0x2C17 => 0x2C47, 0x2C18 => 0x2C48, 0x2C19 => 0x2C49, 0x2C1A => 0x2C4A, 0x2C1B => 0x2C4B, 0x2C1C => 0x2C4C, 0x2C1D => 0x2C4D, 0x2C1E => 0x2C4E, 0x2C1F => 0x2C4F, 0x2C20 => 0x2C50, 0x2C21 => 0x2C51, 0x2C22 => 0x2C52, 0x2C23 => 0x2C53, 0x2C24 => 0x2C54, 0x2C25 => 0x2C55, 0x2C26 => 0x2C56, 0x2C27 => 0x2C57, 0x2C28 => 0x2C58, 0x2C29 => 0x2C59, 0x2C2A => 0x2C5A, 0x2C2B => 0x2C5B, 0x2C2C => 0x2C5C, 0x2C2D => 0x2C5D, 0x2C2E => 0x2C5E, 0x2C60 => 0x2C61, 0x2C62 => 0x26B, 0x2C63 => 0x1D7D, 0x2C64 => 0x27D, 0x2C67 => 0x2C68, 0x2C69 => 0x2C6A, 0x2C6B => 0x2C6C, 0x2C6D => 0x251, 0x2C6E => 0x271, 0x2C6F => 0x250, 0x2C70 => 0x252, 0x2C72 => 0x2C73, 0x2C75 => 0x2C76, 0x2C7E => 0x23F, 0x2C7F => 0x240, 0x2C80 => 0x2C81, 0x2C82 => 0x2C83, 0x2C84 => 0x2C85, 0x2C86 => 0x2C87, 0x2C88 => 0x2C89, 0x2C8A => 0x2C8B, 0x2C8C => 0x2C8D, 0x2C8E => 0x2C8F, 0x2C90 => 0x2C91, 0x2C92 => 0x2C93, 0x2C94 => 0x2C95, 0x2C96 => 0x2C97, 0x2C98 => 0x2C99, 0x2C9A => 0x2C9B, 0x2C9C => 0x2C9D, 0x2C9E => 0x2C9F, 0x2CA0 => 0x2CA1, 0x2CA2 => 0x2CA3, 0x2CA4 => 0x2CA5, 0x2CA6 => 0x2CA7, 0x2CA8 => 0x2CA9, 0x2CAA => 0x2CAB, 0x2CAC => 0x2CAD, 0x2CAE => 0x2CAF, 0x2CB0 => 0x2CB1, 0x2CB2 => 0x2CB3, 0x2CB4 => 0x2CB5, 0x2CB6 => 0x2CB7, 0x2CB8 => 0x2CB9, 0x2CBA => 0x2CBB, 0x2CBC => 0x2CBD, 0x2CBE => 0x2CBF, 0x2CC0 => 0x2CC1, 0x2CC2 => 0x2CC3, 0x2CC4 => 0x2CC5, 0x2CC6 => 0x2CC7, 0x2CC8 => 0x2CC9, 0x2CCA => 0x2CCB, 0x2CCC => 0x2CCD, 0x2CCE => 0x2CCF, 0x2CD0 => 0x2CD1, 0x2CD2 => 0x2CD3, 0x2CD4 => 0x2CD5, 0x2CD6 => 0x2CD7, 0x2CD8 => 0x2CD9, 0x2CDA => 0x2CDB, 0x2CDC => 0x2CDD, 0x2CDE => 0x2CDF, 0x2CE0 => 0x2CE1, 0x2CE2 => 0x2CE3, 0x2CEB => 0x2CEC, 0x2CED => 0x2CEE, 0x2CF2 => 0x2CF3, 0xA640 => 0xA641, 0xA642 => 0xA643, 0xA644 => 0xA645, 0xA646 => 0xA647, 0xA648 => 0xA649, 0xA64A => 0xA64B, 0xA64C => 0xA64D, 0xA64E => 0xA64F, 0xA650 => 0xA651, 0xA652 => 0xA653, 0xA654 => 0xA655, 0xA656 => 0xA657, 0xA658 => 0xA659, 0xA65A => 0xA65B, 0xA65C => 0xA65D, 0xA65E => 0xA65F, 0xA660 => 0xA661, 0xA662 => 0xA663, 0xA664 => 0xA665, 0xA666 => 0xA667, 0xA668 => 0xA669, 0xA66A => 0xA66B, 0xA66C => 0xA66D, 0xA680 => 0xA681, 0xA682 => 0xA683, 0xA684 => 0xA685, 0xA686 => 0xA687, 0xA688 => 0xA689, 0xA68A => 0xA68B, 0xA68C => 0xA68D, 0xA68E => 0xA68F, 0xA690 => 0xA691, 0xA692 => 0xA693, 0xA694 => 0xA695, 0xA696 => 0xA697, 0xA698 => 0xA699, 0xA69A => 0xA69B, 0xA722 => 0xA723, 0xA724 => 0xA725, 0xA726 => 0xA727, 0xA728 => 0xA729, 0xA72A => 0xA72B, 0xA72C => 0xA72D, 0xA72E => 0xA72F, 0xA732 => 0xA733, 0xA734 => 0xA735, 0xA736 => 0xA737, 0xA738 => 0xA739, 0xA73A => 0xA73B, 0xA73C => 0xA73D, 0xA73E => 0xA73F, 0xA740 => 0xA741, 0xA742 => 0xA743, 0xA744 => 0xA745, 0xA746 => 0xA747, 0xA748 => 0xA749, 0xA74A => 0xA74B, 0xA74C => 0xA74D, 0xA74E => 0xA74F, 0xA750 => 0xA751, 0xA752 => 0xA753, 0xA754 => 0xA755, 0xA756 => 0xA757, 0xA758 => 0xA759, 0xA75A => 0xA75B, 0xA75C => 0xA75D, 0xA75E => 0xA75F, 0xA760 => 0xA761, 0xA762 => 0xA763, 0xA764 => 0xA765, 0xA766 => 0xA767, 0xA768 => 0xA769, 0xA76A => 0xA76B, 0xA76C => 0xA76D, 0xA76E => 0xA76F, 0xA779 => 0xA77A, 0xA77B => 0xA77C, 0xA77D => 0x1D79, 0xA77E => 0xA77F, 0xA780 => 0xA781, 0xA782 => 0xA783, 0xA784 => 0xA785, 0xA786 => 0xA787, 0xA78B => 0xA78C, 0xA78D => 0x265, 0xA790 => 0xA791, 0xA792 => 0xA793, 0xA796 => 0xA797, 0xA798 => 0xA799, 0xA79A => 0xA79B, 0xA79C => 0xA79D, 0xA79E => 0xA79F, 0xA7A0 => 0xA7A1, 0xA7A2 => 0xA7A3, 0xA7A4 => 0xA7A5, 0xA7A6 => 0xA7A7, 0xA7A8 => 0xA7A9, 0xA7AA => 0x266, 0xA7AB => 0x25C, 0xA7AC => 0x261, 0xA7AD => 0x26C, 0xA7AE => 0x26A, 0xA7B0 => 0x29E, 0xA7B1 => 0x287, 0xA7B2 => 0x29D, 0xA7B3 => 0xAB53, 0xA7B4 => 0xA7B5, 0xA7B6 => 0xA7B7, 0xA7B8 => 0xA7B9, 0xA7BA => 0xA7BB, 0xA7BC => 0xA7BD, 0xA7BE => 0xA7BF, 0xA7C2 => 0xA7C3, 0xA7C4 => 0xA794, 0xA7C5 => 0x282, 0xA7C6 => 0x1D8E, 0xA7C7 => 0xA7C8, 0xA7C9 => 0xA7CA, 0xA7F5 => 0xA7F6, 0xAB70 => 0x13A0, 0xAB71 => 0x13A1, 0xAB72 => 0x13A2, 0xAB73 => 0x13A3, 0xAB74 => 0x13A4, 0xAB75 => 0x13A5, 0xAB76 => 0x13A6, 0xAB77 => 0x13A7, 0xAB78 => 0x13A8, 0xAB79 => 0x13A9, 0xAB7A => 0x13AA, 0xAB7B => 0x13AB, 0xAB7C => 0x13AC, 0xAB7D => 0x13AD, 0xAB7E => 0x13AE, 0xAB7F => 0x13AF, 0xAB80 => 0x13B0, 0xAB81 => 0x13B1, 0xAB82 => 0x13B2, 0xAB83 => 0x13B3, 0xAB84 => 0x13B4, 0xAB85 => 0x13B5, 0xAB86 => 0x13B6, 0xAB87 => 0x13B7, 0xAB88 => 0x13B8, 0xAB89 => 0x13B9, 0xAB8A => 0x13BA, 0xAB8B => 0x13BB, 0xAB8C => 0x13BC, 0xAB8D => 0x13BD, 0xAB8E => 0x13BE, 0xAB8F => 0x13BF, 0xAB90 => 0x13C0, 0xAB91 => 0x13C1, 0xAB92 => 0x13C2, 0xAB93 => 0x13C3, 0xAB94 => 0x13C4, 0xAB95 => 0x13C5, 0xAB96 => 0x13C6, 0xAB97 => 0x13C7, 0xAB98 => 0x13C8, 0xAB99 => 0x13C9, 0xAB9A => 0x13CA, 0xAB9B => 0x13CB, 0xAB9C => 0x13CC, 0xAB9D => 0x13CD, 0xAB9E => 0x13CE, 0xAB9F => 0x13CF, 0xABA0 => 0x13D0, 0xABA1 => 0x13D1, 0xABA2 => 0x13D2, 0xABA3 => 0x13D3, 0xABA4 => 0x13D4, 0xABA5 => 0x13D5, 0xABA6 => 0x13D6, 0xABA7 => 0x13D7, 0xABA8 => 0x13D8, 0xABA9 => 0x13D9, 0xABAA => 0x13DA, 0xABAB => 0x13DB, 0xABAC => 0x13DC, 0xABAD => 0x13DD, 0xABAE => 0x13DE, 0xABAF => 0x13DF, 0xABB0 => 0x13E0, 0xABB1 => 0x13E1, 0xABB2 => 0x13E2, 0xABB3 => 0x13E3, 0xABB4 => 0x13E4, 0xABB5 => 0x13E5, 0xABB6 => 0x13E6, 0xABB7 => 0x13E7, 0xABB8 => 0x13E8, 0xABB9 => 0x13E9, 0xABBA => 0x13EA, 0xABBB => 0x13EB, 0xABBC => 0x13EC, 0xABBD => 0x13ED, 0xABBE => 0x13EE, 0xABBF => 0x13EF, 0xFF21 => 0xFF41, 0xFF22 => 0xFF42, 0xFF23 => 0xFF43, 0xFF24 => 0xFF44, 0xFF25 => 0xFF45, 0xFF26 => 0xFF46, 0xFF27 => 0xFF47, 0xFF28 => 0xFF48, 0xFF29 => 0xFF49, 0xFF2A => 0xFF4A, 0xFF2B => 0xFF4B, 0xFF2C => 0xFF4C, 0xFF2D => 0xFF4D, 0xFF2E => 0xFF4E, 0xFF2F => 0xFF4F, 0xFF30 => 0xFF50, 0xFF31 => 0xFF51, 0xFF32 => 0xFF52, 0xFF33 => 0xFF53, 0xFF34 => 0xFF54, 0xFF35 => 0xFF55, 0xFF36 => 0xFF56, 0xFF37 => 0xFF57, 0xFF38 => 0xFF58, 0xFF39 => 0xFF59, 0xFF3A => 0xFF5A, 0x10400 => 0x10428, 0x10401 => 0x10429, 0x10402 => 0x1042A, 0x10403 => 0x1042B, 0x10404 => 0x1042C, 0x10405 => 0x1042D, 0x10406 => 0x1042E, 0x10407 => 0x1042F, 0x10408 => 0x10430, 0x10409 => 0x10431, 0x1040A => 0x10432, 0x1040B => 0x10433, 0x1040C => 0x10434, 0x1040D => 0x10435, 0x1040E => 0x10436, 0x1040F => 0x10437, 0x10410 => 0x10438, 0x10411 => 0x10439, 0x10412 => 0x1043A, 0x10413 => 0x1043B, 0x10414 => 0x1043C, 0x10415 => 0x1043D, 0x10416 => 0x1043E, 0x10417 => 0x1043F, 0x10418 => 0x10440, 0x10419 => 0x10441, 0x1041A => 0x10442, 0x1041B => 0x10443, 0x1041C => 0x10444, 0x1041D => 0x10445, 0x1041E => 0x10446, 0x1041F => 0x10447, 0x10420 => 0x10448, 0x10421 => 0x10449, 0x10422 => 0x1044A, 0x10423 => 0x1044B, 0x10424 => 0x1044C, 0x10425 => 0x1044D, 0x10426 => 0x1044E, 0x10427 => 0x1044F, 0x104B0 => 0x104D8, 0x104B1 => 0x104D9, 0x104B2 => 0x104DA, 0x104B3 => 0x104DB, 0x104B4 => 0x104DC, 0x104B5 => 0x104DD, 0x104B6 => 0x104DE, 0x104B7 => 0x104DF, 0x104B8 => 0x104E0, 0x104B9 => 0x104E1, 0x104BA => 0x104E2, 0x104BB => 0x104E3, 0x104BC => 0x104E4, 0x104BD => 0x104E5, 0x104BE => 0x104E6, 0x104BF => 0x104E7, 0x104C0 => 0x104E8, 0x104C1 => 0x104E9, 0x104C2 => 0x104EA, 0x104C3 => 0x104EB, 0x104C4 => 0x104EC, 0x104C5 => 0x104ED, 0x104C6 => 0x104EE, 0x104C7 => 0x104EF, 0x104C8 => 0x104F0, 0x104C9 => 0x104F1, 0x104CA => 0x104F2, 0x104CB => 0x104F3, 0x104CC => 0x104F4, 0x104CD => 0x104F5, 0x104CE => 0x104F6, 0x104CF => 0x104F7, 0x104D0 => 0x104F8, 0x104D1 => 0x104F9, 0x104D2 => 0x104FA, 0x104D3 => 0x104FB, 0x10C80 => 0x10CC0, 0x10C81 => 0x10CC1, 0x10C82 => 0x10CC2, 0x10C83 => 0x10CC3, 0x10C84 => 0x10CC4, 0x10C85 => 0x10CC5, 0x10C86 => 0x10CC6, 0x10C87 => 0x10CC7, 0x10C88 => 0x10CC8, 0x10C89 => 0x10CC9, 0x10C8A => 0x10CCA, 0x10C8B => 0x10CCB, 0x10C8C => 0x10CCC, 0x10C8D => 0x10CCD, 0x10C8E => 0x10CCE, 0x10C8F => 0x10CCF, 0x10C90 => 0x10CD0, 0x10C91 => 0x10CD1, 0x10C92 => 0x10CD2, 0x10C93 => 0x10CD3, 0x10C94 => 0x10CD4, 0x10C95 => 0x10CD5, 0x10C96 => 0x10CD6, 0x10C97 => 0x10CD7, 0x10C98 => 0x10CD8, 0x10C99 => 0x10CD9, 0x10C9A => 0x10CDA, 0x10C9B => 0x10CDB, 0x10C9C => 0x10CDC, 0x10C9D => 0x10CDD, 0x10C9E => 0x10CDE, 0x10C9F => 0x10CDF, 0x10CA0 => 0x10CE0, 0x10CA1 => 0x10CE1, 0x10CA2 => 0x10CE2, 0x10CA3 => 0x10CE3, 0x10CA4 => 0x10CE4, 0x10CA5 => 0x10CE5, 0x10CA6 => 0x10CE6, 0x10CA7 => 0x10CE7, 0x10CA8 => 0x10CE8, 0x10CA9 => 0x10CE9, 0x10CAA => 0x10CEA, 0x10CAB => 0x10CEB, 0x10CAC => 0x10CEC, 0x10CAD => 0x10CED, 0x10CAE => 0x10CEE, 0x10CAF => 0x10CEF, 0x10CB0 => 0x10CF0, 0x10CB1 => 0x10CF1, 0x10CB2 => 0x10CF2, 0x118A0 => 0x118C0, 0x118A1 => 0x118C1, 0x118A2 => 0x118C2, 0x118A3 => 0x118C3, 0x118A4 => 0x118C4, 0x118A5 => 0x118C5, 0x118A6 => 0x118C6, 0x118A7 => 0x118C7, 0x118A8 => 0x118C8, 0x118A9 => 0x118C9, 0x118AA => 0x118CA, 0x118AB => 0x118CB, 0x118AC => 0x118CC, 0x118AD => 0x118CD, 0x118AE => 0x118CE, 0x118AF => 0x118CF, 0x118B0 => 0x118D0, 0x118B1 => 0x118D1, 0x118B2 => 0x118D2, 0x118B3 => 0x118D3, 0x118B4 => 0x118D4, 0x118B5 => 0x118D5, 0x118B6 => 0x118D6, 0x118B7 => 0x118D7, 0x118B8 => 0x118D8, 0x118B9 => 0x118D9, 0x118BA => 0x118DA, 0x118BB => 0x118DB, 0x118BC => 0x118DC, 0x118BD => 0x118DD, 0x118BE => 0x118DE, 0x118BF => 0x118DF, 0x16E40 => 0x16E60, 0x16E41 => 0x16E61, 0x16E42 => 0x16E62, 0x16E43 => 0x16E63, 0x16E44 => 0x16E64, 0x16E45 => 0x16E65, 0x16E46 => 0x16E66, 0x16E47 => 0x16E67, 0x16E48 => 0x16E68, 0x16E49 => 0x16E69, 0x16E4A => 0x16E6A, 0x16E4B => 0x16E6B, 0x16E4C => 0x16E6C, 0x16E4D => 0x16E6D, 0x16E4E => 0x16E6E, 0x16E4F => 0x16E6F, 0x16E50 => 0x16E70, 0x16E51 => 0x16E71, 0x16E52 => 0x16E72, 0x16E53 => 0x16E73, 0x16E54 => 0x16E74, 0x16E55 => 0x16E75, 0x16E56 => 0x16E76, 0x16E57 => 0x16E77, 0x16E58 => 0x16E78, 0x16E59 => 0x16E79, 0x16E5A => 0x16E7A, 0x16E5B => 0x16E7B, 0x16E5C => 0x16E7C, 0x16E5D => 0x16E7D, 0x16E5E => 0x16E7E, 0x16E5F => 0x16E7F, 0x1E900 => 0x1E922, 0x1E901 => 0x1E923, 0x1E902 => 0x1E924, 0x1E903 => 0x1E925, 0x1E904 => 0x1E926, 0x1E905 => 0x1E927, 0x1E906 => 0x1E928, 0x1E907 => 0x1E929, 0x1E908 => 0x1E92A, 0x1E909 => 0x1E92B, 0x1E90A => 0x1E92C, 0x1E90B => 0x1E92D, 0x1E90C => 0x1E92E, 0x1E90D => 0x1E92F, 0x1E90E => 0x1E930, 0x1E90F => 0x1E931, 0x1E910 => 0x1E932, 0x1E911 => 0x1E933, 0x1E912 => 0x1E934, 0x1E913 => 0x1E935, 0x1E914 => 0x1E936, 0x1E915 => 0x1E937, 0x1E916 => 0x1E938, 0x1E917 => 0x1E939, 0x1E918 => 0x1E93A, 0x1E919 => 0x1E93B, 0x1E91A => 0x1E93C, 0x1E91B => 0x1E93D, 0x1E91C => 0x1E93E, 0x1E91D => 0x1E93F, 0x1E91E => 0x1E940, 0x1E91F => 0x1E941, 0x1E920 => 0x1E942, 0x1E921 => 0x1E943, ]; NOTICE 0000777 00000000462 15251721406 0005464 0 ustar 00 Opis String Copyright 2018-2021 Zindex Software This product includes software developed at Zindex Software (http://zindex.software). This software was originally developed by Marius Sarca and Sorin Sarca (Copyright 2016-2018). The copyright info was changed with the permission of the original authors.
| ver. 1.6 |
Github
|
.
| PHP 8.1.34 | Генерация страницы: 0 |
proxy
|
phpinfo
|
Настройка