2020/06/04 Unicodeだいっきらい!
いわゆる半角文字か全角文字かを判定したかっただけなんですよ。C#で。
…なんて事を言うと、字面の小理屈を捏ね回して能書きを垂れる方々が湧いて出たりするんですけどね。それじゃ問題の解決にならんのですよ。
文字列の印刷において、OCR-Bフォントで用意されてる文字だけをOCR-Bフォントにして、それ以外は仕方ないので適当な日本語フォントにして印刷したい。というのがそもそもの課題です。
ああ、ASCII文字相当部分だけOCR-Bに置き換えた新フォントを作れってのは無しですぜ。正論だけど、ライセンス問題が死ぬほど面倒。これは商用アプリの開発だって事もついでに言っときます。できるもんならやってください、半日くらいなら待ちますから。余談ですがこんな物の為に出してもらえるカネもありませんぜ。
こういう課題を解決しようと思ったら、OCR-Bフォントに含まれる文字を判別してフォントを切り替える、という発想が出てくる訳です。そこで最初の半角/全角文字判定に戻る。
用語として半角文字・全角文字って言葉が大問題を含んでいる事も知ってます。そこを突っつくなら、代わりに同じくらい使い勝手の良い用語を考えて下さい。意外と無いんですよね。
そして本題の判定問題ですが。恐ろしい事に、少なくともC#では判定の関数が存在しないようです。Shift_JISに変換してからバイト数を数えろなんて無茶なコードばかりヒットします。アホですか。Shift_JISでは表現できないUnicode文字なんかゴマンとありますぜ。
色々調べた結果、コードポイントを調べるしかない。余計なグループ分けは掃いて捨てるほど用意されてるのに、文字がUnicodeRangeに所属するかどうかを判定する関数が無い。どうやらUnicodeRangeってのは「コードポイントの範囲」なので、自力で大小判定しろって事なのかな、と。
っていうかコードポイントと言う用語。これも私は嫌いなんですが、まあいいや。
という訳で。BasicLatinのコードポイントの範囲を調べて、文字ごとに大小判定して、何とかしました。
でもね、これでもまだちょっと不安があるんですよ。C#の文字列はUTF-16に基づいていて、要するに文字型は16ビットなんです。これもどうかと思うんですが、それはそれとして。周知の通り、1文字で数十バイト消費するような文字が次から次へと追加されている昨今、そんな文字のバイト列の途中でBasicLatin文字が入らないかどうかは未調査です。ちょっとバカバカしいんで調べる気にもならない。多分大丈夫なんでしょう。駄目だったらその時考えます。問題の先送り。
1文字で数十バイトを使ってる文字があるとか、意識してる人ってプログラマでもなかなかいないんじゃないかなぁ。結構ヤバい問題なんですがね。文字数に制限を掛けても、用意するバッファの「バイト数」に制限が掛からないって事だから。ああ、C#とかでstring型しか使わないと意識しないのか。
この問題ですね、Linuxなんかで顕著に現れるんですよ。話が飛ぶんですけども。
Linuxは、ファイル名の最大長が255バイト以下に制限されてるようです。いまだに広がってないのはリーナスの馬鹿垂れ(私はこの人にもあんまり良い感情を持ってません)の無理解だか怠慢だかじゃないかと思ってるんですが。
LinuxでシステムロケールをUTF-8にしちゃったりなんかして、そうすると絵文字なんかをファイル名に使えたりなんかしちゃうんですけど、ところがほんの数文字で255バイトを超えちゃうんですね。
これ、WebサービスでWikiみたいのを作って、ユーザーが入力した見出しをそのままファイル名に使うような設計にしてると、あっという間にエラーになります。しかも恐らくはSEは想定してないですよね。でも一般ユーザーはそういうのやりたがりますよね、だから無視する訳にもいきません。
もうね、ほんっと、Unicodeは大っ嫌いです。




