Convert UTF-8 Character to Codepoint

Pear看到的Codes, 因為用的到, 所以紀錄一下.


function utf8ToCodepoint( $char ) {
$z = ord( $char{0} );
if ( $z & 0x80 ) {
$length = 0;
while ( $z & 0x80 ) {
$length++;
$z <<= 1; } } else { $length = 1; } if ( $length != strlen( $char ) ) { return false; } if ( $length == 1 ) { return ord( $char ); } $z &= 0xff; $z >>= $length;
for ( $i=1; $i<$length; $i++ ) { $z <<= 6; $z |= ord( $char{$i} ) & 0x3f; } return $z; }

另外一個是在這裡看到的, 他的功能多一些, 是可以一次轉一整個String到一個Codepoint Array中


function utf8ToUnicode(&$str)
{
$mState = 0; // cached expected number of octets after the current octet
// until the beginning of the next UTF8 character sequence
$mUcs4 = 0; // cached Unicode character
$mBytes = 1; // cached expected number of octets in the current sequence

$out = array();

$len = strlen($str);
for($i = 0; $i < $len; $i++) { $in = ord($str{$i}); if (0 == $mState) { // When mState is zero we expect either a US-ASCII character or a // multi-octet sequence. if (0 == (0x80 & ($in))) { // US-ASCII, pass straight through. $out[] = $in; $mBytes = 1; } else if (0xC0 == (0xE0 & ($in))) { // First octet of 2 octet sequence $mUcs4 = ($in); $mUcs4 = ($mUcs4 & 0x1F) << 6; $mState = 1; $mBytes = 2; } else if (0xE0 == (0xF0 & ($in))) { // First octet of 3 octet sequence $mUcs4 = ($in); $mUcs4 = ($mUcs4 & 0x0F) << 12; $mState = 2; $mBytes = 3; } else if (0xF0 == (0xF8 & ($in))) { // First octet of 4 octet sequence $mUcs4 = ($in); $mUcs4 = ($mUcs4 & 0x07) << 18; $mState = 3; $mBytes = 4; } else if (0xF8 == (0xFC & ($in))) { /* First octet of 5 octet sequence. * * This is illegal because the encoded codepoint must be either * (a) not the shortest form or * (b) outside the Unicode range of 0-0x10FFFF. * Rather than trying to resynchronize, we will carry on until the end * of the sequence and let the later error handling code catch it. */ $mUcs4 = ($in); $mUcs4 = ($mUcs4 & 0x03) << 24; $mState = 4; $mBytes = 5; } else if (0xFC == (0xFE & ($in))) { // First octet of 6 octet sequence, see comments for 5 octet sequence. $mUcs4 = ($in); $mUcs4 = ($mUcs4 & 1) << 30; $mState = 5; $mBytes = 6; } else { /* Current octet is neither in the US-ASCII range nor a legal first * octet of a multi-octet sequence. */ return false; } } else { // When mState is non-zero, we expect a continuation of the multi-octet // sequence if (0x80 == (0xC0 & ($in))) { // Legal continuation. $shift = ($mState - 1) * 6; $tmp = $in; $tmp = ($tmp & 0x0000003F) << $shift; $mUcs4 |= $tmp; if (0 == --$mState) { /* End of the multi-octet sequence. mUcs4 now contains the final * Unicode codepoint to be output * * Check for illegal sequences and codepoints. */ // From Unicode 3.1, non-shortest form is illegal if [1](2 == $mBytes) && ($mUcs4 < 0x0080 || [2]3 == $mBytes) && ($mUcs4 < 0x0800 || [3]4 == $mBytes) && ($mUcs4 < 0x10000 || (4 < $mBytes) || // From Unicode 3.2, surrogate characters are illegal [4]$mUcs4 & 0xFFFFF800) == 0xD800) || // Codepoints outside the Unicode range are illegal ($mUcs4 > 0x10FFFF {
return false;
}
if (0xFEFF != $mUcs4) {
// BOM is legal but we don’t want to output it
$out[] = $mUcs4;
}
//initialize UTF8 cache
$mState = 0;
$mUcs4 = 0;
$mBytes = 1;
}
} else {
/* [5]0xC0 & (*in) != 0x80) && (mState != 0
*
* Incomplete multi-octet sequence.
*/
return false;
}
}
}
return $out;
}

兩個都能轉出我要的東西, 而且第二個在Parsing上對我比較方便, 但是自從PHP支援Multibyte function後, 就不這麼重要了, 兩個function拿來轉同樣10個字的String, 第一個只要0.000017秒, 第二個卻要整整三倍多的0.000052秒. 看來, 我應該會用第一個吧.

太久沒有去鑽PHP, 反應變遲鈍了, 唉.

References

References
1 (2 == $mBytes) && ($mUcs4 < 0x0080
2 3 == $mBytes) && ($mUcs4 < 0x0800
3 4 == $mBytes) && ($mUcs4 < 0x10000
4 $mUcs4 & 0xFFFFF800) == 0xD800) || // Codepoints outside the Unicode range are illegal ($mUcs4 > 0x10FFFF
5 0xC0 & (*in) != 0x80) && (mState != 0
  • Post a comment

    Threaded commenting powered by interconnect/it code.