UTF-8 が正確にどのように機能するかについて記憶を新たにする必要がありましたが、ここにutf8_ord()
関数と補完的なutf8_chr()
. これは、私の回答herechr()
からほぼ逐語的に持ち上げられています。
function utf8_ord ($chr)
{
$bytes = array_values(unpack('C*', $chr));
switch (count($bytes)) {
case 1:
return $bytes[0] < 0x80
? $bytes[0]
: false;
case 2:
return ($bytes[0] & 0xE0) === 0xC0 && ($bytes[1] & 0xC0) === 0x80
? (($bytes[0] & 0x1F) << 6) | ($bytes[1] & 0x3F)
: false;
case 3:
return ($bytes[0] & 0xF0) === 0xE0 && ($bytes[1] & 0xC0) === 0x80 && ($bytes[2] & 0xC0) === 0x80
? (($bytes[0] & 0x0F) << 12) | (($bytes[1] & 0x3F) << 6) | ($bytes[2] & 0x3F)
: false;
case 4:
return ($bytes[0] & 0xF8) === 0xF0 && ($bytes[1] & 0xC0) === 0x80 && ($bytes[2] & 0xC0) === 0x80 && ($bytes[3] & 0xC0) === 0x80
? (($bytes[0] & 0x07) << 18) | (($bytes[1] & 0x3F) << 12) | (($bytes[2] & 0x3F) << 6) | ($bytes[3] & 0x3F)
: false;
}
return false;
}
function utf8_chr ($ord)
{
switch (true) {
case $ord < 0x80:
return pack('C*', $ord & 0x7F);
case $ord < 0x0800:
return pack('C*', (($ord & 0x07C0) >> 6) | 0xC0, ($ord & 0x3F) | 0x80);
case $ord < 0x010000:
return pack('C*', (($ord & 0xF000) >> 12) | 0xE0, (($ord & 0x0FC0) >> 6) | 0x80, ($ord & 0x3F) | 0x80);
case $ord < 0x110000:
return pack('C*', (($ord & 0x1C0000) >> 18) | 0xF0, (($ord & 0x03F000) >> 12) | 0x80, (($ord & 0x0FC0) >> 6) | 0x80, ($ord & 0x3F) | 0x80);
}
return false;
}