今日は先日の unichr() 関数を PHP エクステンションとして作ってみます。
pecl-gen に喰わせる XML はこんな感じで。
(Safari から投稿しているため、バックスラッシュが文字化けしています。'?0' は '\0' に、"?n" は "\n" に読み替えてください)
<?xml version="1.0" ?> <extension name="unichr" version="0.0.1"> <summary>Unicode character PHP extension</summary> <description><![CDATA[ Get the UTF-8 encoded string which corresponds to the given code point. ]]></description> <function name="unichr"> <proto>string unichr(int code)</proto> <code><![CDATA[ if (code < 0 || code > 0xFFFF) { RETURN_FALSE; } char ustr[4] = { '?0' }; int ulen = 0; if (code < 0x80) { ustr[0] = (char)code; ulen = 1; } else if (code < 0x800) { ustr[0] = 0xC0 | (char)(code >> 6); ustr[1] = 0x80 | (char)(code & 0x3F); ulen = 2; } else { ustr[0] = 0xE0 | (char)(code >> 12); ustr[1] = 0x80 | (char)(code >> 6 & 0x3F); ustr[2] = 0x80 | (char)(code & 0x3F); ulen = 3; } RETURN_STRINGL(ustr, ulen, 1); ]]></code> </function> </extension>
これを例によって
pecl-gen unichr.xml cd unichr phpize ./configure make sudo make install
でインストールできます。
Pure PHP の関数との比較はこうなりました。
スクリプト:
<?php dl('unichr.so'); function unichr_purephp($cp) { if ($cp < 0 || $cp > 0xFFFF) { return false; } if ($cp < 0x80) { return chr($cp); } if ($cp < 0x800) { return pack('CC', 0xC0 | $cp >> 6, 0x80 | $cp & 0x3F); } return pack('CCC', 0xE0 | $cp >> 12, 0x80 | $cp >> 6 & 0x3F, 0x80 | $cp & 0x3F); } $t0 = microtime(true); for ($i = 0; $i < 10000; $i++) unichr_purephp(0x3000); $t1 = microtime(true); for ($i = 0; $i < 10000; $i++) unichr(0x3000); $t2 = microtime(true); printf("%0.6f / %0.6f?n", $t1 - $t0, $t2 - $t1); ?>
結果:
0.166844 / 0.030950
だいたい 5〜6 倍は速いですね。また、C で書いた方が実行速度のばらつきが非常に小さかったです。