I know I believe in nothing but it is my sweet nothing.:2008年07月19日分

2008/07/19(Sat)

続 mutt-dev

引き続き tamoさんとこ。

なにこの 1024 って!? それを倍々ってどういうこと!? 悔しい、キーッ

ちょwww 蟹飯先生曰く俺の本読んでないってどういうこと!? 悔しい、キーッ
mutt-devそんな感じですか、まぁバイバインも問題がないわけじゃないんですが。

derek氏のポストより

It would be nice if iconv() worked like the snprintf() family of
functions (more recently) where if the buffer used is too small, the
function returns the lenght of the string it *would* write into the
buffer, if it were large enough. :)

要するにこんなのが欲しいのかなーと。

SYNOPSIS
	size_t iconv_snprintf_alike(iconv_t cd,
	    char *out, size_t outlen, const char *in);
EXAMPLE
	iconv_t cd;
	size_t n;
	char *s;
	cd = iconv_open("Shift_JIS", "eucJP");
	n = iconv_snprintf_alike(cd, NULL, 0, "あいうえお");
	s = malloc(n);
	if (s == NULL)
		abort();
	(void)iconv_snprintf_alike(cd,  s, n, "あいうえお");

inはiconv_open(3)で指定した変換前の符号化手法における
初期シフト状態で開始しnul-terminateで終わる文字列ね。
んでoutには必ずnul-terminateされて書き込まれると。
こんなwrapperが欲しいと理解したわけですが。

しかしこれ実際に実装しようとすると、snprintf(3)の%lsの実装でもぶちあたるんだけど
stateful encodingのことを考えると結構めんどくさいし性能的に不利なのよね。

第一にoutの末尾をnul-terminateするには、初期シフト状態に戻すための
エスケープ分の長さが必要な上に、その長さは実際に変換してみないとわからん問題がある *1

ちゅーことはiconv(3)で変換が成功するたびに、inputにNULL喰わせて初期シフトに戻し
エスケープの長さでoutlenが溢れないか確認しないとならないのよね。しかーしiconv_tは
save/restoreペケなので毎回先頭に戻って変換しなおさなきゃならん、よって性能的に大きく不利。
更にはNULL食わせてもnul-terminateはしてくれないので、その分のサイズも知る必要がある。
nulは変換後の符号化手法がUTF-16/UTF-32なんかの場合単純に1byteではないからにゅ。

うーんめんどくせぇ。
というわけでiconv(3)のwrapper書くのに固定長に拘ると余計バグ仕込みかねないちゅうことで。

*1:ちなみに今のNetBSDの vfwprintf.cの実装は初期シフトに戻さず'\0'書き込んでるのでダメぽ、__wcsconv()参照。