とみたです。

[matz / zetabits.com (Yukihiro Matsumoto)さんが]
["[ruby-dev:11416] Re: Ruby I18N" で曰く]

> |個人的には String の下位クラスを作るのが単純で速くていいと
> |思いますけどね。破壊的にコード変換をしなければクラスを
> |差しかえたりする必要もないし…

> しかし、そうするとstring.cのほとんどコピーが各文字コード系毎
> に発生することになりそうなんですよねえ。

string.c をもうちょっと汎用的にして、言語に依存する部分を他に出す
ってのはどうでしょう?

# オーバーヘッドがある分、遅くなるでしょうが…。

私が MySQL にマルチバイト文字列対応の機能を組み込んだ時には、

	#define MBMAXLEN n      // 1文字の最大バイト数
	#define ismbchar(p, e)  // char* p にある1文字(eを超えない)のバイト数
	#define ismbhead(c)     // char c はマルチバイト文字の先頭バイトか?
	#define mbcharlen(c)    // char c で始まる文字のバイト数

というマクロを定義して、文字列を操作する部分のソースコードはそのマクロを
使用することで共通にしました。ヘッダファイル中でマクロを適当に定義する
ことで各言語に対応させるという形で。

例えば日本語EUCの場合は、こんな感じで、

	#define isujis(c)     ((0xa1<=((c)&0xff) && ((c)&0xff)<=0xfe))
	#define iskata(c)     ((0xa1<=((c)&0xff) && ((c)&0xff)<=0xdf))
	#define isujis_ss2(c) (((c)&0xff) == 0x8e)
	#define isujis_ss3(c) (((c)&0xff) == 0x8f)
	#define ismbchar(p, end)        ((*(uchar*)(p)<0x80)? 0:\
	        isujis(*(p)) && (end)-(p)>1 && isujis(*((p)+1))? 2:\
	        isujis_ss2(*(p)) && (end)-(p)>1 && iskata(*((p)+1))? 2:\
	        isujis_ss3(*(p)) && (end)-(p)>2 && isujis(*((p)+1)) && isujis(*((p)+2))? 3:\
	        0)
	#define ismbhead(c)     (isujis(c) || isujis_ss2(c) || isujis_ss3(c))
	#define mbcharlen(c)    (isujis(c)? 2: isujis_ss2(c)? 2: isujis_ss3(c)? 3: 0)
	#define MBMAXLEN        3

シフトJISの場合は、こんな感じ。

	#define issjishead(c) ((0x81<=((c)&0xff) && ((c)&0xff)<=0x9f) || (0xe0<=((c)&0xff) && ((c)&0xff)<=0xfc))
	#define issjistail(c) ((0x40<=((c)&0xff) && ((c)&0xff)<=0x7e) || (0x80<=((c)&0xff) && ((c)&0xff)<=0xfc))
	#define ismbchar(p, end)        (issjishead(*(p)) && (end)-(p)>1 && issjistail(*((p)+1))? 2: 0)
	#define ismbhead(c)     issjishead(c)
	#define mbcharlen(c)    (issjishead(c)? 2: 0)
	#define MBMAXLEN        2

当時は、コンパイル時に一つの言語しか選択できなかったので、こんな形
だったんですが、現在の MySQL は一つのバイナリで複数の言語を使用できる
ようになってます(既に私の手を離れてますが…)。

上記のマクロは関数になっていて、言語毎に ctype-***.c というソースに
収まってます。文字列操作時には、その文字列の言語に応じた関数を呼び出す
ことで処理されています。

ctype-***.c 内の関数は基本的に上記マクロと同じように、言語固有の判定に
使われているだけなので、文字列の処理部分のソースは共通(つまり一つだけ)です。

言語によっては、単純なバイトコード順じゃないソートをする必要があるのも
あるみたいで、独自のソート関数を ctype-***.c に記述することができるように
もなっています。

以上ご参考まで…。

---
とみたまさひろ <tommy / tmtm.org> http://www.tmtm.org
日本MySQLユーザ会 http://www.mysql.gr.jp