drupflare/worker - v1.0.4
    Preparing search index...

    Variable MB_ASCIIConst

    MB_ASCII: "\n// NO eval(), unlike the wrappers below: these two names are ours, so they cannot collide\n// with an internal function and nothing has to be deferred to runtime. Plain PHP is what\n// lets tests/node/php-fragments.spec.ts see inside the body.\n\nuse Symfony\\Polyfill\\Iconv\\Iconv;\nuse Symfony\\Polyfill\\Mbstring\\Mbstring;\n\nif (!function_exists('cfw_mb_ascii')) {\n\t/**\n\t * True when no byte is >= 0x80, so the single-byte string functions are exact.\n\t *\n\t * @param mixed $s\n\t * The value to test.\n\t */\n\tfunction cfw_mb_ascii($s): bool\n\t{\n\t\treturn is_string($s) && !preg_match('/[\\x80-\\xff]/', $s);\n\t}\n\n\t/**\n\t * Applies Unicode SpecialCasing final-sigma to an ALREADY-lowercased string.\n\t *\n\t * Not applied to mb_strtoupper: there is no uppercase counterpart and\n\t * running it there would corrupt correct output. The strpos() guard is the common\n\t * case -- a string with no sigma in it cannot need this.\n\t *\n\t * @param string $lo\n\t * The lowercased text.\n\t *\n\t * @return string|null\n\t * The text with final sigmas applied, or NULL when the pattern failed.\n\t */\n\tfunction cfw_mb_final_sigma($lo)\n\t{\n\t\tif (strpos($lo, \"\\xcf\\x83\") === false) {\n\t\t\treturn $lo;\n\t\t}\n\t\treturn preg_replace(\n\t\t\t'/(?<=\\p{Ll}|\\p{Lu}|\\p{Lt}|\\p{Lm}|\\p{Lo})\\x{03C3}(?!\\p{L})/u',\n\t\t\t\"\\xcf\\x82\",\n\t\t\t$lo,\n\t\t);\n\t}\n\n\t/**\n\t * The case tables are keyed by utf-8, so a caller naming another encoding must not reach them.\n\t *\n\t * @param string|null $encoding\n\t * The encoding the caller named.\n\t */\n\tfunction cfw_mb_utf8($encoding): bool\n\t{\n\t\treturn $encoding === null ||\n\t\t\tstrcasecmp($encoding, 'UTF-8') === 0 ||\n\t\t\tstrcasecmp($encoding, 'UTF8') === 0;\n\t}\n\n\t/**\n\t * The word-boundary pattern for titlecasing, built from the polyfill's Case_Ignorable data.\n\t *\n\t * The 6,201-byte character class is READ from the package rather than copied, so upstream\n\t * keeps owning the Unicode half; the two-line grammar around it is replaced, because\n\t * upstream's lookbehind-then-two-letter-groups is wrong in both directions. It blocks a\n\t * match on the letter after an ignorable and then RE-ENTERS on the letter after that, so\n\t * \"abc<SHY>def\" comes out \"Abc<SHY>dEf\" where mbstring gives \"Abc<SHY>def\". Consuming\n\t * ignorables in the word TAIL fixes it: a character inside a match is never offered a\n\t * second start.\n\t *\n\t * null means the package moved and every caller falls back to the polyfill's own title path.\n\t *\n\t * @return string|null\n\t * The pattern, or NULL when the polyfill's data file is not where it was.\n\t */\n\tfunction cfw_mb_title_regexp()\n\t{\n\t\tstatic $re = false;\n\t\tif ($re === false) {\n\t\t\t$re = null;\n\t\t\t$file = class_exists(Mbstring::class)\n\t\t\t\t? (new ReflectionClass(Mbstring::class))->getFileName()\n\t\t\t\t: false;\n\t\t\t$path =\n\t\t\t\t$file === false ? '' : dirname($file) . '/Resources/unidata/titleCaseRegexp.php';\n\t\t\tif ($path !== '' && is_file($path)) {\n\t\t\t\t$re = require $path;\n\t\t\t}\n\t\t\t$end = $re === null ? false : strpos($re, '])(\\pL)(\\pL*+)/u');\n\t\t\tif ($end !== false && strpos($re, '/(?<![') === 0) {\n\t\t\t\t$ignorable = substr($re, 6, $end - 6);\n\t\t\t\t// mbstring titlecases roman numerals and circled letters; PCRE does not call\n\t\t\t\t// them letters, so the polyfill never offers them to the callback at all\n\t\t\t\t$word = '\\pL' . cfw_mb_title_extra();\n\t\t\t\t$re = '/(?<![' . $word . '])([' . $word . '])([' . $word . $ignorable . ']*+)/u';\n\t\t\t}\n\t\t}\n\t\treturn $re;\n\t}\n\n\t/**\n\t * One word: its first character titlecased, the rest lowercased.\n\t *\n\t * The polyfill UPPERCASES the first character, which is a different operation for the 31\n\t * Lt digraphs and for every ligature that expands (native titlecases U+FB01 to \"Fi\", the\n\t * polyfill uppercases it to \"FI\").\n\t *\n\t * @param array<int, string> $m\n\t * The match: the whole word, its first character, and its tail.\n\t */\n\tfunction cfw_mb_title_word($m): string\n\t{\n\t\t$title = cfw_mb_title_char($m[1]);\n\t\t// 0 and 1 rather than MB_CASE_UPPER / MB_CASE_LOWER: this fragment is installed before\n\t\t// the polyfill's bootstrap, which is what defines those constants\n\t\t$head = $title ?? Mbstring::mb_convert_case(cfw_mb_patch($m[1], 'upper'), 0, 'UTF-8');\n\t\treturn $head . Mbstring::mb_convert_case(cfw_mb_patch($m[2], 'lower'), 1, 'UTF-8');\n\t}\n\n\t/**\n\t * Replaces every character the TARGET encoding cannot represent with \"?\", which is what\n\t * native mb_convert_encoding does and what the polyfill does not.\n\t *\n\t * The polyfill converts with //IGNORE, so an unmappable character is DROPPED: a Cyrillic\n\t * sentence converted to ISO-8859-1 comes back as its spaces. One whole-string probe\n\t * decides -- iconv without //IGNORE answers false only when something is unmappable -- so\n\t * the per-character loop is paid by the strings that actually need it.\n\t *\n\t * @param string $s\n\t * Well-formed UTF-8.\n\t * @param string $to\n\t * The target charset.\n\t */\n\tfunction cfw_mb_encode_subst($s, $to): string\n\t{\n\t\tif ($s === '' || !class_exists(Iconv::class)) {\n\t\t\treturn $s;\n\t\t}\n\t\t// a target iconv does not know (BASE64, HTML-ENTITIES) fails on ASCII too; leave those\n\t\t// to the polyfill, which handles them before it ever reaches a charset conversion\n\t\tif (@Iconv::iconv('UTF-8', $to, 'a') !== 'a') {\n\t\t\treturn $s;\n\t\t}\n\t\tif (@Iconv::iconv('UTF-8', $to, $s) !== false) {\n\t\t\treturn $s;\n\t\t}\n\t\t$out = '';\n\t\tforeach (preg_split('//u', $s, -1, PREG_SPLIT_NO_EMPTY) as $ch) {\n\t\t\t$out .= @Iconv::iconv('UTF-8', $to, $ch) === false ? '?' : $ch;\n\t\t}\n\t\treturn $out;\n\t}\n\n\t/**\n\t * Spells a charset the way symfony/polyfill-iconv's alias table spells it.\n\t *\n\t * THE CHARMAPS ARE PRESENT AND THE NAMES ARE NOT. Measured against the polyfill rather than\n\t * against the real extension: SJIS, GBK, BIG5 and EUC-KR are all REFUSED outright, while\n\t * Shift_JIS, CP936, CP950 and CP949 decode -- out of the same 55 from.*.php files. So the gap\n\t * that looked like missing capability is six alias entries.\n\t *\n\t * CP950 and CP949 are SUPERSETS of Big5 and EUC-KR, so those two decode every assigned byte\n\t * correctly and additionally decode bytes the narrower charset leaves unassigned, where\n\t * mbstring substitutes. That is a real difference and it is why they are named here rather\n\t * than presented as exact. EUC-JP and ISO-2022-JP ship no charmap at all and stay refused.\n\t *\n\t * @param mixed $enc\n\t * The charset the caller named.\n\t *\n\t * @return mixed\n\t * The polyfill's spelling, or the input when it is not a string or needs no alias.\n\t */\n\tfunction cfw_mb_iconv_label($enc)\n\t{\n\t\tstatic $alias = [\n\t\t\t'sjis' => 'Shift_JIS',\n\t\t\t'sjis-win' => 'CP932',\n\t\t\t'ms_kanji' => 'CP932',\n\t\t\t'gbk' => 'CP936',\n\t\t\t'big5' => 'CP950',\n\t\t\t'big-5' => 'CP950',\n\t\t\t'euc-kr' => 'CP949',\n\t\t\t'uhc' => 'CP949',\n\t\t];\n\t\treturn is_string($enc) ? $alias[strtolower($enc)] ?? $enc : $enc;\n\t}\n\n\t/**\n\t * The same substitution in the DECODE direction: a source byte the charmap does not know\n\t * becomes \"?\" instead of vanishing.\n\t *\n\t * Walks the source the way the polyfill's own mapToUtf8 does -- a two-byte key first, then a\n\t * one-byte key -- so it is right for SJIS and Big5 as well as for the single-byte charsets.\n\t * The pair was used exactly when its answer is not the two singles concatenated; where those\n\t * agree, either choice produces the same bytes.\n\t *\n\t * Returns null when it does not apply, which leaves the polyfill's answer alone: an unknown\n\t * charset (no charmap ships for EUC-JP) and a source with nothing unmappable both take that\n\t * path, and the second is the common one.\n\t *\n\t * @param string $s\n\t * Source bytes in the named charset.\n\t * @param string $from\n\t * The charset the bytes are in.\n\t */\n\tfunction cfw_mb_decode_subst($s, $from): ?string\n\t{\n\t\t$from = cfw_mb_iconv_label($from);\n\t\tif ($s === '' || !class_exists(Iconv::class)) {\n\t\t\treturn null;\n\t\t}\n\t\tif (@Iconv::iconv($from, 'UTF-8', 'a') !== 'a') {\n\t\t\treturn null;\n\t\t}\n\t\tif (@Iconv::iconv($from, 'UTF-8', $s) !== false) {\n\t\t\treturn null;\n\t\t}\n\t\t$out = '';\n\t\t$len = strlen($s);\n\t\t$i = 0;\n\t\twhile ($i < $len) {\n\t\t\t$one = (string) @Iconv::iconv($from, 'UTF-8//IGNORE', $s[$i]);\n\t\t\tif ($i + 1 < $len) {\n\t\t\t\t$pair = (string) @Iconv::iconv($from, 'UTF-8//IGNORE', substr($s, $i, 2));\n\t\t\t\t$next = (string) @Iconv::iconv($from, 'UTF-8//IGNORE', $s[$i + 1]);\n\t\t\t\tif ($pair !== '' && $pair !== $one . $next) {\n\t\t\t\t\t$out .= $pair;\n\t\t\t\t\t$i += 2;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t\t$out .= $one === '' ? '?' : $one;\n\t\t\t$i++;\n\t\t}\n\t\treturn $out;\n\t}\n\n\t/**\n\t * Case-insensitive search on the ORIGINAL haystack.\n\t *\n\t * The polyfill returns a slice of its own lowercased copy, so a haystack containing a\n\t * character that lowercases to two comes back with different bytes than went in.\n\t *\n\t * @param string $haystack\n\t * The original text.\n\t * @param int|false $pos\n\t * Where the needle was found, or FALSE.\n\t * @param bool $before\n\t * Return the part before the match rather than from it.\n\t * @param string|null $encoding\n\t * The encoding the caller named.\n\t *\n\t * @return string|false\n\t */\n\tfunction cfw_mb_isubpart($haystack, $pos, $before, $encoding)\n\t{\n\t\tif ($pos === false) {\n\t\t\treturn false;\n\t\t}\n\t\treturn $before\n\t\t\t? Mbstring::mb_substr($haystack, 0, $pos, $encoding)\n\t\t\t: Mbstring::mb_substr($haystack, $pos, null, $encoding);\n\t}\n}\n" = MB_ASCII_PHP

    The corrections that need no host call and no generated table, separate from the wrappers so scripts/measure/mb-parity.ts can price each on its own.

    The ASCII fast path skips iconv for the common all-ASCII inputs (machine names, langcodes, header names); strtolower() is a safe substitute only because it is ASCII-only since PHP 8.2. The final-sigma post-pass lowercases a word-final capital sigma to U+03C2, which the polyfill's flat table cannot express (it is contextual: a letter precedes it and none follows).