WindowsでUTFを使う
Dの文字列は、UTF文字列です。 Microsoft Windows の API は通常、入力文字列の受け取り方に応じて、 関数ごとに二つのバージョン - "A" バージョンと "W" バージョンが用意されています。"W" バージョンは UTF-16 を文字列引数の形式として受け取るので、D の wchar[] 文字列と直接対応します。しかし、比較的初期の Windows では、 多くのAPI関数の "W" バージョンが実装されていません。 かといって、"A" バージョンを使うのも問題があります。"A" バージョンは 環境ごとの様々な文字エンコード方式を扱うので、 UTF-8 形式である D の char[] 文字列と、 直接の互換性を持っていないのです。
この問題に対処する正しい方法は、まず、"W" バージョンに対応した バージョンの Windows であるかどうか判別し、非対応であれば、 wchar[] 文字列を "A" バージョンで扱える形式に変換することです。 この方法は Phobos ランタイムライブラリで使用されており、 以下のようになっています:
private import std.c.windows.windows;
private import std.utf;
int useWfuncs = 1;
static this()
{
// Win 95, 98, ME では W 関数は実装されていない
useWfuncs = (GetVersion() < 0x80000000);
}
char* toMBSz(char[] s)
{
// 最上位ビットが立っている文字があるときのみ変換が必要
foreach (char c; s)
{
if (c >= 0x80)
{ char[] result;
int i;
wchar* ws = std.utf.toUTF16z(s);
result.length = WideCharToMultiByte(0, 0, ws, -1, null, 0, null, null);
i = WideCharToMultiByte(0, 0, ws, -1, result, result.length, null, null);
assert(i == result.length);
return result;
}
}
return std.string.toStringz(s);
}
uint getAttributes(char[] name)
{
uint result;
if (useWfuncs)
result = GetFileAttributesW(std.utf.toUTF16z(name));
else
result = GetFileAttributesA(toMBSz(name));
return result;
}
