#はじめに
Flutterで湯婆婆を実装してみるの続編です。
@everylittleさんのC#婆婆などで言及されている通り、サロゲートペア文字を処理しないと「𠮷」田さんは契約させてもらえません。
サロゲートペア文字とは
Unicodeでは通常2バイトで1文字を表すところ、4バイトで表すものがあります。
それをサロゲートペアといって、上位2バイトを「上位サロゲート」、下位2バイトを「下位サロゲート」と呼んだりします。
サロゲートペア文字に関してはこの辺の記事を読んでおけばわかると思います。
#どうして文字化けしたの?
文字列操作するときに2つで1つの文字の半分だけとってきて表示したためです。
#どうすればいいの?
ゴリゴリと対応するならば、入力した名前のから抽出した1文字の文字コードが
- 上位サロゲート(0xD800~0xDBFF):後方の1文字を追加
- 下位サロゲート(0xDC00~0xDFFF):前方の1文字を追加
みたいな処理をすればよいです。
実装例
bool _isHighSurrogate(int charCode) {
return (0xD800 <= charCode && 0xDBFF >= charCode);
}
bool _isLowSurrogate(int charCode) {
return (0xDC00 <= charCode && 0xDFFF >= charCode);
}
String _zeitaku(String name) {
if (name == null && name.isEmpty) {
return "";
}
final rand = Random();
int index = rand.nextInt(name.length);
String newName = name.substring(index, index + 1);
// 文字コードが上位サロゲート文字なら下位を追加、下位サロゲート文字なら上位を追加
if (_isHighSurrogate(newName.codeUnitAt(0))) {
newName = name.substring(index, index + 2);
} else if (_isLowSurrogate(newName.codeUnitAt(0))) {
newName = name.substring(index - 1, index + 1);
}
return newName;
}
もう少し簡単に実現
上記でも実現できますが、Dartの場合Charactersクラスを使えばもっと簡単に実現できそうです。
Charactersクラスではサロゲートペアをきちんと1文字とカウントしてくれるみたいですね。
String _zeitaku(String name) {
if (name == null && name.isEmpty) {
return "";
}
var characters = Characters(name);
final rand = Random();
int index = rand.nextInt(characters.length);
return characters.characterAt(index).string;
}
GitHub
#結果
https://flutter-baba.web.app/#/
良かったね!𠮷田さん!
副作用
ちなみにサロゲートペア文字を理解したFu婆婆は絵文字にも対応できる。
高性能で可愛いババアになりました。
#おわりに
今回、サロゲートペア文字の対応をさせてみました。
ゴリゴリ書く版とCharactersクラスを使う版の両方を記載しましたが、
他の言語で対応しなければいけなかったりすることを考えるとゴリゴリ書く版も知っておいていいと思います。