in src/_Private/strip_hh_prefix.hack [18:99]
function strip_hh_prefix(
string $str,
bool $nonobject_types_only = false,
): string {
if (!Str\starts_with($str, 'HH\\')) {
// Bail out early if $str doesn't contain 'HH\'
return $str;
}
$nonobject_types = ImmSet {
'bool',
'boolean',
'int',
'integer',
'float',
'double',
'real',
'num',
'string',
'resource',
'mixed',
'void',
'this',
'arraykey',
};
$len = \strlen($str);
$in_literal = '';
$out = '';
$c = ' ';
for ($i = 0; $i < $len; ++$i) {
$prev = $c;
$c = $str[$i];
if ($in_literal !== '') {
if ($c === '\\') {
$out .= $c;
++$i;
if ($i >= $len) {
break;
}
$c = $str[$i];
$out .= $c;
continue;
}
if ($c === $in_literal) {
$in_literal = '';
}
} else {
if (
($c === 'H' || $c === 'h') &&
\strtoupper(\substr($str, $i, 3)) === 'HH\\' &&
!\ctype_alnum($prev) &&
$prev !== '_' &&
$prev !== '\\'
) {
if ($nonobject_types_only) {
$sub = \substr($str, $i + 3, 9);
$sub_len = \strlen($sub);
$k = 0;
for (; $k < $sub_len; ++$k) {
$sub_c = $sub[$k];
if (!\ctype_alnum($sub_c) && $sub_c !== '_' && $sub_c !== '\\') {
break;
}
}
$sub = \strtolower(\substr($sub, 0, $k));
$strip = ($nonobject_types->contains($sub));
} else {
$strip = true;
}
if ($strip) {
$i += 2;
$c = '\\';
continue;
}
}
if ($c === '\'' || $c === '"') {
$in_literal = $c;
}
}
$out .= $c;
}
return $out;
}