【问题标题】:xlocale broken on OS X?xlocale 在 OS X 上坏了?
【发布时间】:2012-03-16 02:57:25
【问题描述】:

我有一个简单的程序,它使用在命令行上传递给它的一系列语言环境来测试 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 中已被删除并替换为欧元符号。此转换不应成功,但不会发出错误信号。在进一步检查这个案例时,我发现在这两种情况下,“¤”都被转换为 0xA4,这是“¤”的 ISO 8859-1 表示。

我没有直接使用 xlocale,只是通过 libc++ 间接使用。 Mac OS X 上的 xlocale 是否被错误的语言环境定义破坏了?有没有办法解决它?还是我看到的问题是由其他原因造成的?

【问题讨论】:

    标签: c++ macos locale libc++ xlocale


    【解决方案1】:

    我怀疑您发现 xlocale 系统存在问题。 bug report 将不胜感激!

    【讨论】:

    • 在 10.8 中看起来仍然很糟糕 :( 也许有一些方法可以获取 xlocale 数据并手动修复?
    • 事实证明,UTF-32 实际上并没有被 OS X 上的所有语言环境用作 wchar_t 编码,这很不幸。
    【解决方案2】:

    我不知道你为什么期望 wchar_t 是 UTF-32 或者你在哪里听说过“OS X 的 wchar_t 是 UTF-32 的约定”。这当然是不正确的。 wchar_t 只有 16 位宽。

    有关 wchar_t 的更多信息,请参阅http://en.wikipedia.org/wiki/Wide_character

    【讨论】:

    • wchar_t 在 OS X 和大多数 unix 操作系统上是 32 位宽,而不是 16 位。
    • ... Wikipedia 提到的一个事实,以及它在其他平台上也可能是 8 位的花絮。 C++11 增加了char16_tchar32_t 来解决这个问题,但这并不相关。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-18
    • 1970-01-01
    • 1970-01-01
    • 2013-11-04
    • 1970-01-01
    相关资源
    最近更新 更多