2012-02-26 14 views
5

Tengo un programa simple que prueba la conversión entre wchar_t y char utilizando una serie de configuraciones regionales que se le pasan en la línea de comandos. Muestra una lista de las conversiones que fallan imprimiendo el nombre de la configuración regional y la cadena que no se pudo convertir.xlocale roto en OS X?

Lo estoy construyendo usando clang y libC++. Según tengo entendido, la biblioteca xlocale en OS X admite compatibilidad con locale con nombre de libC++.

Estoy viendo algunos fallos inesperados, así como algunos casos en los que la conversión debería fallar, pero no es así.

Aquí está el programa.

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

Éstos son algunos ejemplos de salida correcta

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

He aquí un ejemplo de la producción que no se espera

en_US.ISO8859-15 : € 

El carácter del euro existe en la norma ISO 8859-15 y charset entonces esto no debería estar fallando.

Aquí son ejemplos de salida que esperar, pero no reciben

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

Este es el símbolo de moneda que existe en ISO 8859-1 pero fue eliminado y reemplazado con el símbolo del euro en la norma ISO 8859-15. Esta conversión no debería tener éxito, pero no se está señalando ningún error. Al examinar más este caso, encuentro que en ambos casos '¤' se está convirtiendo a 0xA4, que es la representación ISO 8859-1 de '¤'.

No estoy usando xlocale directamente, solo indirectamente vía libC++. ¿Xlocale en Mac OS X simplemente se rompe con las definiciones de configuración incorrecta? ¿Hay alguna forma de arreglarlo? ¿O los problemas que veo son resultado de otra cosa?

Respuesta

3

Sospecho que está teniendo problemas con el sistema xlocale. ¡A bug report sería muy apreciado!

+2

hecho. id 10935025 – bames53

+0

Todavía se ve roto en 10.8 :(¿Tal vez hay alguna forma de obtener los datos de xlocale y hackear una corrección de forma manual? – bames53

+0

Resulta que UTF-32 no se usa de hecho como la codificación wchar_t para todas las configuraciones regionales en OS X , que es bastante desafortunado. – bames53

-1

No sé por qué esperas que wchar_t sea UTF-32 o donde escuchaste que "la convención de OS X es que wchar_t es UTF-32". Eso es ciertamente incorrecto. wchar_t tiene solo 16 bits de ancho.

Consulte http://en.wikipedia.org/wiki/Wide_character para obtener más información sobre wchar_t.

+3

'wchar_t' tiene 32 bits de ancho en OS X y la mayoría de los sistemas operativos Unix, no 16. – bames53

+1

... un hecho que Wikipedia menciona, junto con el chisme, que también podría ser de 8 bits en otras plataformas. +11 agrega 'char16_t' y' char32_t' para resolver esto, pero eso no está relacionado. – Potatoswatter