У меня есть простая программа, которая проверяет преобразование между wchar_t и char, используя серию локалей, переданных ему в командной строке. Он выводит список преобразований, которые не удается распечатать имя локали и строку, которая не удалось преобразовать.xlocale сломан на OS X?
Я строю его с помощью clang и libC++. Мое понимание заключается в том, что поддержка языка libC++ по умолчанию поддерживается библиотекой xlocale на OS X.
Я вижу некоторые неожиданные сбои, а также некоторые случаи, когда преобразование должно завершиться неудачей, но это не так.
Вот программа.
#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++. Является xlocale на Mac OS X просто сломанной с плохими определениями локали? Есть ли способ исправить это? Или проблемы, которые я вижу в результате чего-то еще?
сделано. id 10935025 – bames53
По-прежнему выглядит сломанным в 10.8 :(Может быть, есть какой-то способ получить данные xlocale и вручную взломать исправление? – bames53
Оказывается, UTF-32 на самом деле не используется как кодировка wchar_t всеми локалями на OS X , что довольно неудачно. – bames53