💨

Goの標準のutf8.RuneStart関数がエレガントすぎる

2024/05/19に公開

先日以下の記事を書きました。

https://zenn.dev/catatsuy/articles/fc916f2cd04f8d

ここでUTF-8の最初の文字かどうかの判定を以下の自作した関数で実装していました。

const (
	t1 = 0b00000000
	tx = 0b10000000
	t2 = 0b00000110
	t3 = 0b00001110
	t4 = 0b00011110
)

func isUTF8LeadByte(tmp byte) bool {
	if tmp&tx == t1 {
		return true
	}
	tmp >>= 3
	if tmp == t4 {
		return true
	}
	tmp >>= 1
	if tmp == t3 {
		return true
	}
	tmp >>= 1
	if tmp == t2 {
		return true
	}
	return false
}

と思ったらなんと、標準パッケージに全く同趣旨のutf8.RuneStart関数が存在していました。しかも実装はたったの1行でした。

func RuneStart(b byte) bool { return b&0xC0 != 0x80 }

何でこうなるのか、ぱっと見では分からなかったのですが、以下の本より図を引用します。

[改訂新版]プログラマのための文字コード技術入門:書籍案内|技術評論社の153pより

これを眺めると、00か01始まりならASCIIで、それ以外は11で始まることは明白です。つまり10でないことを確認するだけで十分です。

全く思いつかなかったですし、こんなエレガントな解決方法があることを知って驚きました。計測していませんが、速度も圧倒的に速いはずです。脱帽です。早速自作関数は捨てて、標準パッケージに書き換えます。

Discussion