5

コマンドラインで渡された一連のロケールを使用して、wchar_t と char の間の変換をテストする簡単なプログラムがあります。ロケール名と変換に失敗した文字列を出力することで、失敗した変換のリストを出力します。

私はclangとlibc ++を使って構築しています。私の理解では、libc++ の名前付きロケール サポートは、OS X の xlocale ライブラリによって提供されます。

予期しないエラーが発生したり、変換が失敗するはずのインスタンスが発生したりしません。

これがプログラムです。

#warning call this program like: "locale -a | ./a.out" or pass \
locale names valid for your platform, one per line via standard input

#include <iostream>
#include <codecvt>
#include <locale>
#include <array>

template <class Facet>
class usable_facet : public Facet {
public:
    // FIXME: use inheriting constructors when available
    // using Facet::Facet;
    template <class ...Args>
    usable_facet(Args&& ...args) : Facet(std::forward<Args>(args)...) {}
    ~usable_facet() {}
};

int main() {
    std::array<std::wstring,11> args = {L"a",L"é",L"¤",L"€",L"Да",L"Ψ",L"א",L"আ",L"✈",L"가",L""};

    std::wstring_convert<usable_facet<std::codecvt_utf8<wchar_t>>> u8cvt; // wchar_t uses UCS-4/UTF-32 on this platform

    int convert_failures = 0;
    std::string line;
    while(std::getline(std::cin,line)) {
        if(line.empty())
            continue;

        using codecvt = usable_facet<std::codecvt_byname<wchar_t,char,std::mbstate_t>>;
        std::wstring_convert<codecvt> convert(new codecvt(line));

        for(auto const &s : args) {
            try {
                convert.to_bytes(s);
            } catch (std::range_error &e) {
                convert_failures++;
                std::cout << line << " : " << u8cvt.to_bytes(s) << '\n';
            }
        }
    }

    std::cout << std::string(80,'=') << '\n';
    std::cout << convert_failures << " wstring_convert to_bytes failures.\n";
}

正しい出力の例をいくつか示します

en_US.ISO8859-1 : €
en_US.US-ASCII : ✈

予期しない出力の例を次に示します。

en_US.ISO8859-15 : €

ユーロ文字は ISO 8859-15 文字セットに存在するため、これが失敗することはありません。

期待しているが受け取っていない出力の例を次に示します

en_US.ISO8859-15 : ¤
en_US.US-ASCII : ¤

これは、ISO 8859-1 に存在する通貨記号ですが、ISO 8859-15 では削除され、ユーロ記号に置き換えられました。この変換は成功しないはずですが、エラーは通知されていません。このケースをさらに調べると、両方のケースで「¤」が「¤」の ISO 8859-1 表現である 0xA4 に変換されていることがわかります。

xlocale を直接使用しているのではなく、libc++ を介して間接的に使用しています。Mac OS X の xlocale は単に悪いロケール定義で壊れているのですか? それを修正する方法はありますか?それとも、私が見ている問題は何か別の結果ですか?

4

2 に答える 2

3

xlocale システムに問題があると思われます。バグレポートをいただければ幸いです。

于 2012-02-26T15:53:25.053 に答える
-1

wchar_t が UTF-32 であることを期待している理由や、「wchar_t が UTF-32 であるという OS X の規則」と聞いた場所がわかりません。それは確かに間違っています。wchar_t は 16 ビット幅のみです。

wchar_t の詳細については、 http://en.wikipedia.org/wiki/Wide_characterを参照してください。

于 2013-02-20T16:53:36.270 に答える