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?
hecho. id 10935025 – bames53
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
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