The Man Who Fell From The Wrong Side Of The Sky:2007年9月8日分

[最新版] [一覧] [前月] [今月] [翌月]

2007/9/8(Sat)

続 iconv(3)によるコード変換

shiroさんからコメントもらったので。

EINVALになったら残った入力をシフトして、出来たすき間に新しい入力を

読めば良い(状態遷移を起こす入力は消費されるから、すき間が出来ない
ということはない、と思う)

状態遷移 = escape sequence は必ず出現はしませんし。
Unicode Normarization Form Composition/Decompositionによる変換
JIS2004の丸付き数字とUnicodeとの変換の際のように
N:1変換が行われる場合、隙間が無くなる可能性があります。

E2BIGの場合も、出力バッファをフラッシュしてから処理を続行することを念頭に置いている。

これも同様ですね、1:1ならoutbufに最低でもMB_LEN_MAX保証すれば良さそうですが
1:N変換の時にはinは完全に変換できるバイト列であっても
outbufには1バイトも書き込めない可能性があり、無限ループに陥ります。
以下、GNU libiconvの//TRANSLITの挙動。

#include <iconv.h>
#include <errno.h>

int
main(void)
{
	iconv_t cd;
	char *in = "\\u3231", *out, outbuf[3];
	size_t nin, nout;
	cd = iconv_open("EUC-JP//TRANSLIT", "C99");
	if (cd == (iconv_t)-1)
		exit(1);
	nin = strlen(in);
	out = &outbuf[0];
	nout = sizeof(outbuf);
	printf("%d\n", iconv(cd, &in, &nin, &out, &nout));
	printf("%s\n", strerror(errno));
	printf("%.*s\n", sizeof(outbuf) - nout, outbuf);
}

\\u3231は//TRANSLITで

(株)

に転写されて変換されますが、outbufのサイズがEUC-JPのMB_CUR_MAX=3なら

(株

までは書き込めるはずなんだけど、1バイトもoutに書き込まれないんですよ。
(これは転写した文字は不可逆変換とカウントしてiconvの戻り値として返す仕様との整合を取る為ですな)

このあたりの事情を考慮して入出力バッファですらdynamic allocationが必要ですってのが私の主張。
まあ元々の仕様は固定長バッファを想定して策定されたんだとは思いますが。

"実用上は" と "理論上は" の温度差もあるかも。
固定長であってもある程度のサイズがあれば実用上問題無いからねぇ。
100%問題無いコードを書くとこうなりますよ、ってことで。


[ホームへ] [ページトップへ]