Я хотел бы сделать преобразование из UTF-8 в ISO 8859-15 в C / C ++, не включая дополнительную библиотеку.
Как мне этого добиться?
Я нашел следующий фрагмент кода, который работает для ISO 8859-1, но я не уверен, как справиться с различиями между ISO 8859-15 и ISO 8859-1 (https://en.wikipedia.org/wiki/ISO/IEC_8859-15):
std::string UTF8toISO8859_1(const char * in) {
std::string out;
if (in == NULL)
return out;
unsigned int codepoint;
while (*in != 0) {
unsigned char ch = static_cast<unsigned char>(*in);
if (ch <= 0x7f)
codepoint = ch;
else if (ch <= 0xbf)
codepoint = (codepoint << 6) | (ch & 0x3f);
else if (ch <= 0xdf)
codepoint = ch & 0x1f;
else if (ch <= 0xef)
codepoint = ch & 0x0f;
else
codepoint = ch & 0x07;
++in;
if (((*in & 0xc0) != 0x80) && (codepoint <= 0x10ffff)) {
if (codepoint <= 255) {
out.append(1, static_cast<char>(codepoint));
}
else {
out.append("?");
}
}
}
return out;
}
Мне нравится этот код Это удивительно коротко. Большая часть кода имеет дело только с декодированием многобайтовых последовательностей в кодовые точки. Как только кодовая точка была декодирована, преобразование в ISO-8859-1 очень просто:
out.append(1, static_cast<char>(codepoint));
out.append("?");
Поэтому, чтобы заставить его работать для ISO-8859-15, требуется больше кода для обработки символов, которые были заменены при введении ISO-8859-15 (см. Сравнивая ISO-8859-1 и ISO-8859-15). К сожалению, это значительно увеличивает размер кода.
Код ниже должен быть легким для понимания. Он может быть оптимизирован для повышения производительности, если это главное.
std::string UTF8toISO8859_1(const char * in) {
std::string out;
if (in == NULL)
return out;
unsigned int codepoint;
while (*in != 0) {
unsigned char ch = static_cast<unsigned char>(*in);
if (ch <= 0x7f)
codepoint = ch;
else if (ch <= 0xbf)
codepoint = (codepoint << 6) | (ch & 0x3f);
else if (ch <= 0xdf)
codepoint = ch & 0x1f;
else if (ch <= 0xef)
codepoint = ch & 0x0f;
else
codepoint = ch & 0x07;
++in;
if (((*in & 0xc0) != 0x80) && (codepoint <= 0x10ffff)) {
// a valid codepoint has been decoded; convert it to ISO-8859-15
char outc;
if (codepoint <= 255) {
// codepoints up to 255 can be directly converted wit a few exceptions
if (codepoint != 0xa4 && codepoint != 0xa6 && codepoint != 0xa8
&& codepoint != 0xb4 && codepoint != 0xb8 && codepoint != 0xbc
&& codepoint != 0xbd && codepoint != 0xbe) {
outc = static_cast<char>(codepoint);
}
else {
outc = '?';
}
}
else {
// With a few exceptions, codepoints above 255 cannot be converted
if (codepoint == 0x20AC) {
outc = 0xa4;
}
else if (codepoint == 0x0160) {
outc = 0xa6;
}
else if (codepoint == 0x0161) {
outc = 0xa8;
}
else if (codepoint == 0x017d) {
outc = 0xb4;
}
else if (codepoint == 0x017e) {
outc = 0xb8;
}
else if (codepoint == 0x0152) {
outc = 0xbc;
}
else if (codepoint == 0x0153) {
outc = 0xbd;
}
else if (codepoint == 0x0178) {
outc = 0xbe;
}
else {
outc = '?';
}
}
out.append(1, outc);
}
}
return out;
}
Других решений пока нет …