C言語でEast Asian Widthを調べる
1. はじめに
C言語でEast Asian Widthを調べるコードを作りました。
作ったといってもnptのソースから抜き出しただけですが。
配布はここ。
https://github.com/nptcl/hypd/tree/main/develop/eastasian
ある機能がnpt内だけで使えるというのは個人的に不便だったので、 いくつかの機能を分離させて登録することにしました。
East Asian Widthとは、全角/半角のUnicode版です。
「あ
」という文字は全角で、「A
」という文字は半角です。
しかし「A
」という文字は全角になります。
ブラウザによっては見づらいかもしれません。
ファイルは下記の通り。
- eastasian.c
- eastasian.h
- unicode.h
このうちunicode.h
はダミーファイルの位置づけであり、
あとでUnicodeを操作する本物のファイルをどこかに登録する予定です。
ダミーの内容はtypedef int32_t unicode;
だけです。
2. 使い方
使い方は簡単です。
unsinged x; x = eastasian_width('A');
「A
」は半角なので、x
には1
が入ります
x = eastasian_width(0x3042); /* あ */
「あ
」は全角なので、x
は2
が入ります。
East Asian Widthというのは、全角と半角だけではなく、
種類がいくつかあります。
いったい何の種類なのかを調べたいときはeastasian_symbol
関数を使用します。
enum EastAsianType y; y = eastasian_symbol('A');
「A
」はNa
という型なので、y
にはEastAsian_Na
が入ります。
y = eastasian_symbol(0x3042); /* あ */
「あ
」はW
という型なので、y
にはEastAsian_W
が入ります。
返却される種類は下記の通り。
EastAsian_error EastAsian_N EastAsian_A EastAsian_H EastAsian_W EastAsian_F EastAsian_Na
このうち、どの種類が全角なのか、あるいは半角なのかは、
いろんな都合で違っているようです。
一応変更できるようにしています。
初期値に戻すinit_eastasian
関数を見てみましょう。
void init_eastasian(void) { EastAsianSymbol[EastAsian_error] = 0; EastAsianSymbol[EastAsian_N] = 1; EastAsianSymbol[EastAsian_A] = 2; EastAsianSymbol[EastAsian_H] = 1; EastAsianSymbol[EastAsian_W] = 2; EastAsianSymbol[EastAsian_F] = 2; EastAsianSymbol[EastAsian_Na] = 1; }
こんな感じで自由に変えてください。
EastAsianSymbol
はグローバル変数の配列です。
eastasian_width
関数はこの変数を見ます。
スレッド使ってるからグローバル変数なんて使いたくないやって方は、
eastasian_symbol
関数で種類を取って自分で判定してください。
3. 技術的なこと
East Asian Widthの値は、Unicodeの本家でファイルとして配布されています。
具体的にはここです。
http://www.unicode.org/Public/UNIDATA/EastAsianWidth.txt
このファイルを読み込み、C言語のソースを直接出力しました。
それをやっているのがmake/hypd.eastasian.lisp
です。
Common Lispで作成してあります。
ファイルの内容はまあまあ大きいので、
調べたい文字を頭から順に探索するわけにはいきません。
かといってUnicodeの全文字を配列にするのも
メモリがもったいないなという気がしたので、
C言語のソースにはソートした内容を出力し、
それを二分探索して型を調べています。
二分探索なのでまあまあ早いのですが、
最速ではないということだけは覚えておいてください。
ちなみに文字コード0x00
から0x80
までは配列に格納されているので
調べるのは一瞬です。