2012-02-26 9 views
5

Tôi có một chương trình đơn giản kiểm tra chuyển đổi giữa wchar_t và char bằng cách sử dụng một loạt các ngôn ngữ được truyền cho nó trên dòng lệnh. Nó xuất ra danh sách các chuyển đổi không thành công bằng cách in ra tên miền địa phương và chuỗi không chuyển đổi được.xlocale bị hỏng trên OS X?

Tôi đang xây dựng nó bằng cách sử dụng tiếng kêu và libC++. Sự hiểu biết của tôi là hỗ trợ miền địa phương của libC++ được cung cấp bởi thư viện xlocale trên OS X.

Tôi thấy một số lỗi không mong muốn, cũng như một số trường hợp chuyển đổi không thành công, nhưng không.

Đây là chương trình.

#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"; 
} 

Dưới đây là một số ví dụ về đúng sản lượng

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

Dưới đây là một ví dụ về sản lượng mà không được mong đợi

en_US.ISO8859-15 : € 

Nhân vật euro tồn tại trong ISO 8859-15 charset và vì vậy điều này không nên thất bại.

Dưới đây là ví dụ về sản lượng mà tôi mong đợi nhưng không nhận được

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

Đây là ký hiệu tiền tệ tồn tại trong ISO 8859-1 nhưng đã được gỡ bỏ và thay thế bằng biểu tượng đồng euro trong ISO 8859-15. Chuyển đổi này không nên thành công, nhưng không có lỗi nào được báo hiệu. Khi kiểm tra trường hợp này hơn nữa, tôi thấy rằng trong cả hai trường hợp '¤' đang được chuyển đổi thành 0xA4, là biểu diễn ISO 8859-1 của '¤'.

Tôi không sử dụng trực tiếp xlocale, chỉ gián tiếp qua libC++. Xlocale trên Mac OS X có bị hỏng với định nghĩa địa phương không? Có cách nào để khắc phục nó? Hoặc là những vấn đề tôi thấy là kết quả của một thứ gì đó khác?

Trả lời

3

Tôi nghi ngờ bạn đang gặp sự cố với hệ thống xlocale. A bug report sẽ được đánh giá cao nhất!

+2

hoàn tất. id 10935025 – bames53

+0

Vẫn còn bị hỏng trong 10,8 :(Có thể có một số cách để có được dữ liệu xlocale và hack một sửa chữa bằng tay? – bames53

+0

Nó chỉ ra rằng UTF-32 là không thực tế được sử dụng như là mã hóa wchar_t bởi tất cả các ngôn ngữ trên OS X – bames53

-1

Tôi không biết tại sao bạn mong đợi wchar_t là UTF-32 hoặc nơi bạn nghe nói rằng "quy ước của OS X rằng wchar_t là UTF-32". Đó chắc chắn là không chính xác. wchar_t chỉ rộng 16 bit.

Xem http://en.wikipedia.org/wiki/Wide_character để biết thêm thông tin về wchar_t.

+3

'wchar_t' rộng 32 bit trên OS X và hầu hết các hệ điều hành unix, chứ không phải 16. – bames53

+1

… một thực tế mà Wikipedia đề cập, cùng với miếng ngon rằng nó cũng có thể là 8 bit trên các nền tảng khác. +11 thêm 'char16_t' và' char32_t' để giải quyết vấn đề này, nhưng điều đó không liên quan. – Potatoswatter