mirror of
https://gitlab.com/signalytic/client-external/streamline/streamline-emr.git
synced 2026-09-12 11:11:31 +00:00
The official image from streamline does not currently work for the arm64 platform. As a temporary measure, the source code and docker build scripts have been lifted from the official images and are used to build locally. Some additional modifications are made to reduce overall image size, these are documented in docker/README.md
311 lines
9.3 KiB
PHP
311 lines
9.3 KiB
PHP
<?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 Symfony\Polyfill\Intl\Normalizer;
|
|
|
|
/**
|
|
* Normalizer is a PHP fallback implementation of the Normalizer class provided by the intl extension.
|
|
*
|
|
* It has been validated with Unicode 6.3 Normalization Conformance Test.
|
|
* See http://www.unicode.org/reports/tr15/ for detailed info about Unicode normalizations.
|
|
*
|
|
* @author Nicolas Grekas <p@tchwork.com>
|
|
*
|
|
* @internal
|
|
*/
|
|
class Normalizer
|
|
{
|
|
public const FORM_D = \Normalizer::FORM_D;
|
|
public const FORM_KD = \Normalizer::FORM_KD;
|
|
public const FORM_C = \Normalizer::FORM_C;
|
|
public const FORM_KC = \Normalizer::FORM_KC;
|
|
public const NFD = \Normalizer::NFD;
|
|
public const NFKD = \Normalizer::NFKD;
|
|
public const NFC = \Normalizer::NFC;
|
|
public const NFKC = \Normalizer::NFKC;
|
|
|
|
private static $C;
|
|
private static $D;
|
|
private static $KD;
|
|
private static $cC;
|
|
private static $ulenMask = ["\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4];
|
|
private static $ASCII = "\x20\x65\x69\x61\x73\x6E\x74\x72\x6F\x6C\x75\x64\x5D\x5B\x63\x6D\x70\x27\x0A\x67\x7C\x68\x76\x2E\x66\x62\x2C\x3A\x3D\x2D\x71\x31\x30\x43\x32\x2A\x79\x78\x29\x28\x4C\x39\x41\x53\x2F\x50\x22\x45\x6A\x4D\x49\x6B\x33\x3E\x35\x54\x3C\x44\x34\x7D\x42\x7B\x38\x46\x77\x52\x36\x37\x55\x47\x4E\x3B\x4A\x7A\x56\x23\x48\x4F\x57\x5F\x26\x21\x4B\x3F\x58\x51\x25\x59\x5C\x09\x5A\x2B\x7E\x5E\x24\x40\x60\x7F\x00\x01\x02\x03\x04\x05\x06\x07\x08\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F";
|
|
|
|
public static function isNormalized(string $s, int $form = self::FORM_C)
|
|
{
|
|
if (!\in_array($form, [self::NFD, self::NFKD, self::NFC, self::NFKC])) {
|
|
return false;
|
|
}
|
|
if (!isset($s[strspn($s, self::$ASCII)])) {
|
|
return true;
|
|
}
|
|
if (self::NFC == $form && preg_match('//u', $s) && !preg_match('/[^\x00-\x{2FF}]/u', $s)) {
|
|
return true;
|
|
}
|
|
|
|
return self::normalize($s, $form) === $s;
|
|
}
|
|
|
|
public static function normalize(string $s, int $form = self::FORM_C)
|
|
{
|
|
if (!preg_match('//u', $s)) {
|
|
return false;
|
|
}
|
|
|
|
switch ($form) {
|
|
case self::NFC: $C = true; $K = false; break;
|
|
case self::NFD: $C = false; $K = false; break;
|
|
case self::NFKC: $C = true; $K = true; break;
|
|
case self::NFKD: $C = false; $K = true; break;
|
|
default:
|
|
if (\defined('Normalizer::NONE') && \Normalizer::NONE == $form) {
|
|
return $s;
|
|
}
|
|
|
|
if (80000 > \PHP_VERSION_ID) {
|
|
return false;
|
|
}
|
|
|
|
throw new \ValueError('normalizer_normalize(): Argument #2 ($form) must be a a valid normalization form');
|
|
}
|
|
|
|
if ('' === $s) {
|
|
return '';
|
|
}
|
|
|
|
if ($K && null === self::$KD) {
|
|
self::$KD = self::getData('compatibilityDecomposition');
|
|
}
|
|
|
|
if (null === self::$D) {
|
|
self::$D = self::getData('canonicalDecomposition');
|
|
self::$cC = self::getData('combiningClass');
|
|
}
|
|
|
|
if (null !== $mbEncoding = (2 /* MB_OVERLOAD_STRING */ & (int) \ini_get('mbstring.func_overload')) ? mb_internal_encoding() : null) {
|
|
mb_internal_encoding('8bit');
|
|
}
|
|
|
|
$r = self::decompose($s, $K);
|
|
|
|
if ($C) {
|
|
if (null === self::$C) {
|
|
self::$C = self::getData('canonicalComposition');
|
|
}
|
|
|
|
$r = self::recompose($r);
|
|
}
|
|
if (null !== $mbEncoding) {
|
|
mb_internal_encoding($mbEncoding);
|
|
}
|
|
|
|
return $r;
|
|
}
|
|
|
|
private static function recompose($s)
|
|
{
|
|
$ASCII = self::$ASCII;
|
|
$compMap = self::$C;
|
|
$combClass = self::$cC;
|
|
$ulenMask = self::$ulenMask;
|
|
|
|
$result = $tail = '';
|
|
|
|
$i = $s[0] < "\x80" ? 1 : $ulenMask[$s[0] & "\xF0"];
|
|
$len = \strlen($s);
|
|
|
|
$lastUchr = substr($s, 0, $i);
|
|
$lastUcls = isset($combClass[$lastUchr]) ? 256 : 0;
|
|
|
|
while ($i < $len) {
|
|
if ($s[$i] < "\x80") {
|
|
// ASCII chars
|
|
|
|
if ($tail) {
|
|
$lastUchr .= $tail;
|
|
$tail = '';
|
|
}
|
|
|
|
if ($j = strspn($s, $ASCII, $i + 1)) {
|
|
$lastUchr .= substr($s, $i, $j);
|
|
$i += $j;
|
|
}
|
|
|
|
$result .= $lastUchr;
|
|
$lastUchr = $s[$i];
|
|
$lastUcls = 0;
|
|
++$i;
|
|
continue;
|
|
}
|
|
|
|
$ulen = $ulenMask[$s[$i] & "\xF0"];
|
|
$uchr = substr($s, $i, $ulen);
|
|
|
|
if ($lastUchr < "\xE1\x84\x80" || "\xE1\x84\x92" < $lastUchr
|
|
|| $uchr < "\xE1\x85\xA1" || "\xE1\x85\xB5" < $uchr
|
|
|| $lastUcls) {
|
|
// Table lookup and combining chars composition
|
|
|
|
$ucls = $combClass[$uchr] ?? 0;
|
|
|
|
if (isset($compMap[$lastUchr.$uchr]) && (!$lastUcls || $lastUcls < $ucls)) {
|
|
$lastUchr = $compMap[$lastUchr.$uchr];
|
|
} elseif ($lastUcls = $ucls) {
|
|
$tail .= $uchr;
|
|
} else {
|
|
if ($tail) {
|
|
$lastUchr .= $tail;
|
|
$tail = '';
|
|
}
|
|
|
|
$result .= $lastUchr;
|
|
$lastUchr = $uchr;
|
|
}
|
|
} else {
|
|
// Hangul chars
|
|
|
|
$L = \ord($lastUchr[2]) - 0x80;
|
|
$V = \ord($uchr[2]) - 0xA1;
|
|
$T = 0;
|
|
|
|
$uchr = substr($s, $i + $ulen, 3);
|
|
|
|
if ("\xE1\x86\xA7" <= $uchr && $uchr <= "\xE1\x87\x82") {
|
|
$T = \ord($uchr[2]) - 0xA7;
|
|
0 > $T && $T += 0x40;
|
|
$ulen += 3;
|
|
}
|
|
|
|
$L = 0xAC00 + ($L * 21 + $V) * 28 + $T;
|
|
$lastUchr = \chr(0xE0 | $L >> 12).\chr(0x80 | $L >> 6 & 0x3F).\chr(0x80 | $L & 0x3F);
|
|
}
|
|
|
|
$i += $ulen;
|
|
}
|
|
|
|
return $result.$lastUchr.$tail;
|
|
}
|
|
|
|
private static function decompose($s, $c)
|
|
{
|
|
$result = '';
|
|
|
|
$ASCII = self::$ASCII;
|
|
$decompMap = self::$D;
|
|
$combClass = self::$cC;
|
|
$ulenMask = self::$ulenMask;
|
|
if ($c) {
|
|
$compatMap = self::$KD;
|
|
}
|
|
|
|
$c = [];
|
|
$i = 0;
|
|
$len = \strlen($s);
|
|
|
|
while ($i < $len) {
|
|
if ($s[$i] < "\x80") {
|
|
// ASCII chars
|
|
|
|
if ($c) {
|
|
ksort($c);
|
|
$result .= implode('', $c);
|
|
$c = [];
|
|
}
|
|
|
|
$j = 1 + strspn($s, $ASCII, $i + 1);
|
|
$result .= substr($s, $i, $j);
|
|
$i += $j;
|
|
continue;
|
|
}
|
|
|
|
$ulen = $ulenMask[$s[$i] & "\xF0"];
|
|
$uchr = substr($s, $i, $ulen);
|
|
$i += $ulen;
|
|
|
|
if ($uchr < "\xEA\xB0\x80" || "\xED\x9E\xA3" < $uchr) {
|
|
// Table lookup
|
|
|
|
if ($uchr !== $j = $compatMap[$uchr] ?? ($decompMap[$uchr] ?? $uchr)) {
|
|
$uchr = $j;
|
|
|
|
$j = \strlen($uchr);
|
|
$ulen = $uchr[0] < "\x80" ? 1 : $ulenMask[$uchr[0] & "\xF0"];
|
|
|
|
if ($ulen != $j) {
|
|
// Put trailing chars in $s
|
|
|
|
$j -= $ulen;
|
|
$i -= $j;
|
|
|
|
if (0 > $i) {
|
|
$s = str_repeat(' ', -$i).$s;
|
|
$len -= $i;
|
|
$i = 0;
|
|
}
|
|
|
|
while ($j--) {
|
|
$s[$i + $j] = $uchr[$ulen + $j];
|
|
}
|
|
|
|
$uchr = substr($uchr, 0, $ulen);
|
|
}
|
|
}
|
|
if (isset($combClass[$uchr])) {
|
|
// Combining chars, for sorting
|
|
|
|
if (!isset($c[$combClass[$uchr]])) {
|
|
$c[$combClass[$uchr]] = '';
|
|
}
|
|
$c[$combClass[$uchr]] .= $uchr;
|
|
continue;
|
|
}
|
|
} else {
|
|
// Hangul chars
|
|
|
|
$uchr = unpack('C*', $uchr);
|
|
$j = (($uchr[1] - 224) << 12) + (($uchr[2] - 128) << 6) + $uchr[3] - 0xAC80;
|
|
|
|
$uchr = "\xE1\x84".\chr(0x80 + (int) ($j / 588))
|
|
."\xE1\x85".\chr(0xA1 + (int) (($j % 588) / 28));
|
|
|
|
if ($j %= 28) {
|
|
$uchr .= $j < 25
|
|
? ("\xE1\x86".\chr(0xA7 + $j))
|
|
: ("\xE1\x87".\chr(0x67 + $j));
|
|
}
|
|
}
|
|
if ($c) {
|
|
ksort($c);
|
|
$result .= implode('', $c);
|
|
$c = [];
|
|
}
|
|
|
|
$result .= $uchr;
|
|
}
|
|
|
|
if ($c) {
|
|
ksort($c);
|
|
$result .= implode('', $c);
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
private static function getData($file)
|
|
{
|
|
if (file_exists($file = __DIR__.'/Resources/unidata/'.$file.'.php')) {
|
|
return require $file;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
}
|