Ho un semplice programma che verifica la conversione tra wchar_t e char usando una serie di impostazioni locali passate ad essa sulla riga di comando. Emette un elenco delle conversioni che falliscono stampando il nome della locale e la stringa che non è riuscita a convertire.xlocale rotto su OS X?
Lo sto costruendo usando clang e libC++. La mia comprensione è che il supporto locale di libC++ è fornito dalla libreria xlocale su OS X.
Sto riscontrando alcuni errori imprevisti, così come alcuni casi in cui la conversione dovrebbe fallire, ma non lo fa.
Ecco il programma.
#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";
}
Ecco alcuni esempi di uscita corretta
en_US.ISO8859-1 : €
en_US.US-ASCII : ✈
Ecco un esempio di output che non è previsto
en_US.ISO8859-15 : €
Il carattere dell'euro esiste nella norma ISO 8859-15 charset e quindi questo non dovrebbe fallire.
Ecco alcuni esempi di uscita che mi aspetto, ma non ricevo
en_US.ISO8859-15 : ¤
en_US.US-ASCII : ¤
Questo è il simbolo di valuta che esiste nella norma ISO 8859-1, ma è stato rimosso e sostituito con il simbolo dell'euro nella norma ISO 8859-15. Questa conversione non dovrebbe avere successo, ma nessun errore viene segnalato. Esaminando ulteriormente questo caso, trovo che in entrambi i casi "¤" viene convertito in 0xA4, che è la rappresentazione ISO 8859-1 di "¤".
Non sto usando xlocale direttamente, solo indirettamente tramite libC++. Xlocale su Mac OS X è semplicemente rotto con definizioni locali errate? C'è un modo per risolverlo? O i problemi che sto vedendo sono il risultato di qualcos'altro?
terminato. id 10935025 – bames53
Sembra ancora rotto in 10.8 :(Forse c'è un modo per ottenere i dati xlocale e hackerare una correzione manualmente? – bames53
Si scopre che UTF-32 non è in effetti utilizzato come codifica wchar_t da tutte le impostazioni locali su OS X – bames53