2012-02-26 15 views
5

मेरे पास एक साधारण प्रोग्राम है जो कमांड लाइन पर पास की गई लोकेशंस की एक श्रृंखला का उपयोग करके wchar_t और char के बीच परिवर्तित करने का परीक्षण करता है। यह उन रूपांतरणों की एक सूची आउटपुट करता है जो लोकेल नाम और स्ट्रिंग को परिवर्तित करने में विफल होने वाली स्ट्रिंग को प्रिंट करके विफल हो जाते हैं।ओएस एक्स पर टूटा हुआ xlocale?

मैं इसे क्लैंग और libC++ का उपयोग कर बना रहा हूं। मेरी समझ यह है कि libC++ का नाम लोकेल समर्थन ओएस एक्स पर 0l30 लाइब्रेरी द्वारा प्रदान किया जाता है।

मुझे कुछ अप्रत्याशित विफलताओं, साथ ही साथ कुछ उदाहरण जहां रूपांतरण विफल होना चाहिए, लेकिन नहीं।

यहां कार्यक्रम है।

#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 : € 

यूरो चरित्र आईएसओ 8859-15 चारसेट में मौजूद हैं और करता है तो यह असफल नहीं होना चाहिए।

यहाँ है कि मैं उम्मीद लेकिन

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

यह मुद्रा प्रतीक है कि आईएसओ 8859-1 में मौजूद है लेकिन उसे निकाला और आईएसओ 8859-15 में यूरो प्रतीक के साथ बदल दिया गया था है प्राप्त नहीं होता है उत्पादन के उदाहरण हैं। यह रूपांतरण सफल नहीं होना चाहिए, लेकिन कोई त्रुटि संकेत नहीं दी जा रही है। इस मामले की जांच करते समय मुझे लगता है कि दोनों मामलों में '¤' को 0xA4 में परिवर्तित किया जा रहा है, जो '¤' का आईएसओ 885 9 -1 प्रतिनिधित्व है।

मैं सीधे xlocale का उपयोग नहीं कर रहा हूं, केवल अप्रत्यक्ष रूप से libC++ के माध्यम से। मैक ओएस एक्स पर xlocale बस खराब लोकेल परिभाषाओं के साथ टूट गया है? क्या इसे ठीक करने का कोई तरीका है? या क्या मैं कुछ और मुद्दों का परिणाम देख रहा हूं?

उत्तर

3

मुझे संदेह है कि आप xlocale प्रणाली के साथ समस्याएं देख रहे हैं। एक bug report की सराहना की जाएगी!

+2

किया गया। आईडी 10935025 – bames53

+0

अभी भी 10.8 में टूटा हुआ दिखता है :(हो सकता है कि xlocale डेटा प्राप्त करने और मैन्युअल रूप से एक फिक्स हैक करने का कोई तरीका है? – bames53

+0

यह पता चला है कि यूटीएफ -32 वास्तव में ओएस एक्स पर सभी लोकेशंस द्वारा wchar_t एन्कोडिंग के रूप में उपयोग नहीं किया जाता है , जो काफी दुर्भाग्यपूर्ण है। – bames53

-1

मुझे नहीं पता कि आप wchar_t को यूटीएफ -32 होने की उम्मीद क्यों कर रहे हैं या आपने सुना है कि "ओएस एक्स का सम्मेलन जो wchar_t यूटीएफ -32 है।" यह निश्चित रूप से गलत है। wchar_t केवल 16 बिट चौड़े हैं।

wchar_t के बारे में अधिक जानकारी के लिए http://en.wikipedia.org/wiki/Wide_character देखें।

+3

'wchar_t' ओएस एक्स पर 32 बिट चौड़ा है और अधिकांश यूनिक्स ऑपरेटिंग सिस्टम नहीं है, 16. नहीं। – bames53

+1

... तथ्य यह है कि विकिपीडिया का उल्लेख है कि यह अन्य प्लेटफार्मों पर 8 बिट भी हो सकता है। सी + +11 इसे हल करने के लिए 'char16_t' और' char32_t' जोड़ता है, लेकिन यह असंबंधित है। – Potatoswatter