Beim MSVC ist die Konvertierung von utf-16 zu utf-32 mit dem codecvt_utf16-Lokalisierungsmerkmal von C11 einfach. Aber bei GCC (gcc (Debian 4.7.2-5) 4.7.2) scheint dieses neue Feature noch nicht implementiert worden zu sein. Gibt es eine Möglichkeit, eine solche Konvertierung auf Linux ohne iconv durchzuführen (bevorzugt mit den Konvertierungstools der Standardbibliothek)?
Antwort
Zu viele Anzeigen?Das Dekodieren von UTF-16 in UTF-32 ist äußerst einfach.
Sie möchten möglicherweise zur Kompilierzeit die libc-Version erkennen, die Sie verwenden, und Ihre Konvertierungsroutine bereitstellen, wenn Sie eine fehlerhafte libc erkennen (ohne die benötigten Funktionen).
Eingaben:
- ein Zeiger auf die Quell-UTF-16-Daten (
char16_t *
,ushort *
, -- für BequemlichkeitUTF16 *
); - der Größe;
- ein Zeiger auf die UTF-32-Daten (
char32_t *
,uint *
-- für BequemlichkeitUTF32 *
).
Der Code sieht wie folgt aus:
void convert_utf16_to_utf32(const UTF16 *input,
size_t input_size,
UTF32 *output)
{
const UTF16 * const end = input + input_size;
while (input < end) {
const UTF16 uc = *input++;
if (!is_surrogate(uc)) {
*output++ = uc;
} else {
if (is_high_surrogate(uc) && input < end && is_low_surrogate(*input))
*output++ = surrogate_to_utf32(uc, *input++);
else
// ERROR
}
}
}
Die Fehlerbehandlung ist noch ausstehend. Sie könnten ein U+FFFD
¹ in den Stream einfügen und einfach weitermachen, oder aber auch abbrechen, das liegt ganz bei Ihnen. Die Hilfsfunktionen sind trivial:
int is_surrogate(UTF16 uc) { return (uc - 0xd800u) < 2048u; }
int is_high_surrogate(UTF16 uc) { return (uc & 0xfffffc00) == 0xd800; }
int is_low_surrogate(UTF16 uc) { return (uc & 0xfffffc00) == 0xdc00; }
UTF32 surrogate_to_utf32(UTF16 high, UTF16 low) {
return (high << 10) + low - 0x35fdc00;
}
¹ Vgl. Unicode:
- § 3.9 Unicode Encoding Forms (Best Practices for Using U+FFFD)
- § 5.22 Best Practice for U+FFFD Substitution
² Beachten Sie auch, dass der Zweig !is_surrogate(uc)
bei weitem am häufigsten ist (auch der nicht-fehlerhafte Pfad im zweiten if), so dass Sie dies möglicherweise mit __builtin_expect
oder ähnlichem optimieren möchten.