8 Stimmen

Wie konvertiert man auf Linux mit der Standardbibliothek von UTF-16 nach UTF-32?

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)?

15voto

peppe Punkte 21344

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 Bequemlichkeit UTF16 *);
  • der Größe;
  • ein Zeiger auf die UTF-32-Daten (char32_t *, uint * -- für Bequemlichkeit UTF32 *).

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:

² 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.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X