Ziel ist es, einen vollständig kompatiblen Konverter zwischen den offiziellen Unicode-Codierungen zu erstellen, wie in den UTF-FAQ angegeben . Da dies auf Unicode zentriert ist, akzeptiere ich die Antwort mit der niedrigsten Byteanzahl unter Verwendung der bestmöglichen der beteiligten Codierungen (die wahrscheinlich UTF-8 sein wird, es sei denn, Sie programmieren sie in APL). Ich entschuldige mich für den langen Beitrag, aber ein Großteil davon erklärt die Kodierungen, auf die auch in der offiziellen Spezifikation (pdf, Abschnitt 3.9 D90 - D92) oder in Wikipedia zugegriffen werden kann .
Spezifikationen
Wenn Ihre gewählte Sprache zu irgendeinem Zeitpunkt eine Anforderung nicht genau erfüllen kann, ersetzen Sie sie durch etwas, das dem Geist der angegebenen Regeln entspricht. Z.B. Nicht jede Sprache verfügt über eingebaute Arrays, Funktionen usw.
Verwenden Sie keine Zeichenfolgenbibliotheken / -funktionen oder Kodierungsbibliotheken / -funktionen. Der Sinn dieses Codegolfs besteht darin, den Konverter unter Verwendung von Bit / Byte-Manipulation zu implementieren. Die Verwendung von Strings selbst als Zeichen- oder Byte-Array ist jedoch zulässig. Oh, und auch keine OS-Aufrufe, die die Konvertierung durchführen.
Der Konverter ist eine Funktion, die drei Parameter akzeptiert: ein Byte-Array, das die codierte Eingabezeichenfolge darstellt, und die als Zahlen dargestellten "Eingabe" - und "Ausgabe" -Codierungen. Beliebig vergeben wir
UTF-8, UTF-16, UTF-16BE, UTF-16LE, UTF-32, UTF-32BE, and UTF32LE
Nummern von 0 bis 6 in dieser Reihenfolge. Es muss nicht überprüft werden, ob die Zahl< 0
oder> 6
ist. Wir gehen davon aus, dass diese Parameter korrekt sind. Der Konverter gibt ein gültiges Byte-Array in der gewünschten Ausgabecodierung zurück.Wir werden das Nullzeichen (
U+0000
) als Zeichenkettenabschluss verwenden. Alles was danach passiert ist egal. Wir gehen davon aus, dass das Eingabearray irgendwo das Null-Zeichen hat, sodass Sie keine Begrenzungsprüfung durchführen müssen.Laut FAQ müssen wir einen Fehler melden , wenn das Eingabebyte-Array für seine deklarierte Codierung ungültig ist. Wir werden dies auf eine der folgenden Arten tun: Absturz des Programms, Auslösen einer Ausnahme, Zurückgeben von Null oder Zurückgeben eines Arrays, dessen erste vier Bytes alle 0 sind (damit es wie
U+0000
in jeder Codierung erkannt werden kann ).
Die Kodierungen
Die offiziellen Spezifikationen müssen befolgt werden, aber Wikipedia bietet eine gute (und meines Erachtens korrekte) Erklärung der Kodierungen, und der Vollständigkeit halber werde ich sie hier zusammenfassen. Beachten Sie, dass UTF-16 und UTF-32 Varianten für Endianness haben .
UTF-32, UTF-32LE, UTF-32BE
Bei der einfachsten Codierung wird jeder Codepunkt einfach in 4 Bytes entsprechend seinem numerischen Wert codiert. LE / BE steht für Endianness (Little Endian / Big Endian).
UTF-16, UTF-16LE, UTF-16BE
Codepunkte von U+0000 - U+FFFF
werden in 2 Bytes entsprechend ihrem numerischen Wert codiert. Größere Werte werden mit einem Paar Ersatzzeichen codiert, die reservierte Werte von sind U+D800 - U+DFFF
. Um Punkte zu kodieren U+FFFF
, die größer als sind , kann der folgende Algorithmus verwendet werden (unverschämt aus Wikipedia kopiert ):
- 0x010000 wird vom Codepunkt abgezogen, wobei eine 20-Bit-Zahl im Bereich von 0..0x0FFFFF verbleibt.
- Die oberen zehn Bits (eine Zahl im Bereich 0..0x03FF) werden zu 0xD800 hinzugefügt, um die erste Codeeinheit oder den ersten Ersatz zu erhalten, der im Bereich 0xD800..0xDBFF [...] liegt.
- Die unteren zehn Bits (ebenfalls im Bereich 0..0x03FF) werden zu 0xDC00 addiert, um die zweite Codeeinheit oder den zweiten Ersatz zu ergeben, der im Bereich 0xDC00..0xDFFF [...] liegt.
UTF-8
Codepunkte von U+0000 - U+007F
werden als 1 Byte entsprechend ihrem numerischen Wert codiert. Von U+0080 - U+07FF
sie als codiert sind 110xxxxx 10xxxxxx
, U+0800 - U+FFFF
ist 1110xxxx 10xxxxxx 10xxxxxx
, sind höhere Werte 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
. Die x
‚s sind die Bits aus dem numerischen Wert des Codepunktes.
Stückliste
Die Bytereihenfolge-Markierung (BOM U+FEFF
) wird als erster Codepunkt verwendet, um die Endianität anzuzeigen. Gemäß den FAQ-Richtlinien zu Stücklisten wird die Stückliste wie folgt verwendet: UTF-8, UTF-16 and UTF-32
Sie ist optional. Fehlt die Stückliste in UTF-16
oder UTF-32
, wird von einem Big Endian ausgegangen. Die Stückliste darf nicht in erscheinen UTF-16LE, UTF-16BE, UTF-32LE and UTF-32BE
.
Häufige Fehler, die zu ungültigem UTF führen
Verschiedene Dinge können dazu führen, dass eine Byte-Sequenz ungültiges UTF ist.
- UTF-8 und UTF-32: Direktes Codieren von Ersatzcodepunkten (
U+D800 - U+DFFF
) oder Codepunkten größer alsU+10FFFF
. - UTF-8: Viele ungültige Bytefolgen.
- UTF-16: Nicht gepaarte oder falsch gepaarte Ersatzzeichen.
- Stückliste: Muss wie im Codierungsabschnitt angegeben verwendet werden. Beachten Sie, dass Sie bei der Ausgabe
UTF-16
oderUTF-32
(ohne Angabe einer inhärenten Endianzahl) auswählen können, bei Little Endian jedoch die Stückliste einbeziehen müssen.
Beachten Sie, dass Nicht-Zeichen und nicht zugewiesene Codepunkte (beide von Surrogaten verschieden) wie normale Zeichen behandelt werden.
''⎕R''⍠'InEnc' 'UTF16BE' 'OutEnc' 'UTF8-BOM'
.Antworten:
C ++, (UTF-8) 971 Bytes
Das unten stehende lesbare Programm kann durch Filtern mit dem folgenden Perl-Befehl auf die obige Form komprimiert werden:
Der obige Befehl
#include
LinienLesbarer Code
Die Funktion wird aufgerufen ist
t()
, mit Ein- und Ausgang Kodierungen in den globalen Variablen übergebeni
undo
bzw. undp
zeigte auf dem Bytes des Eingangs, der muss nullterminierte sein.q
zeigt auf den Ausgabepuffer, der überschrieben wird und für das Ergebnis groß genug sein muss - es wird nicht versucht, einen Pufferüberlauf zu vermeiden.Ich hoffe, die Code-Kommentare sind ausreichend erklärend - fragen Sie unten, ob einer von ihnen zu kryptisch ist (aber versuchen Sie es zuerst!).
Ich habe eine umfangreiche Testsuite zusammengestellt, während ich diese Antwort entwickelte. Ich füge es unten zum Nutzen anderer Teilnehmer ein und dokumentiere meine Interpretation der Anforderungen:
Testfunktionen
Testsuite
quelle
Python - 1367 UTF-8-Zeichen
In Ordung! Dies war eine äußerst schwierige Frage, da das Verstehen und Implementieren aller Spezifikationen viel Arbeit gekostet hat, aber ich denke, dass ich eine korrekte Implementierung habe.
convert
ist die Funktion, die das Datenobjekt "Bytes", die Eingabe-ID und die Ausgabe-ID verwendet. Es scheint zu funktionieren - obwohl in Python die Verwendung von Stücklisten anscheinend leicht fehlerhaft ist, wenn dies in der Codierung nicht angegeben ist, funktioniert es nicht, die in Python integrierte Codierung zum Testen der Modi 1 und 4 zu verwenden.Fun Tatsache: Die Größe ist auch 555 16 oder 10101010101 2 .
773 Zeichen für die Dekodierung, 452 für die Kodierung, 59 für die Verifizierung und 83 für verschiedene Teile.
quelle
Python 3, 1138 Bytes (UTF-8)
Es stellt sich also heraus, dass 14 Stunden internationale Reise eine fantastische Gelegenheit sind, eine Golfherausforderung abzuschließen ...
Die Konvertierungsfunktion ist
C()
. Diese Anrufeu()
,v()
undw()
zu dekodieren, undU()
,V()
undW()
zu kodieren, UTF-8, -16 und -32 ist. Keiner der Encoder gibt eine Stückliste aus, aber alle Decoder verarbeiten eine Stückliste korrekt. Fehlerzustände führen zu einer Ausnahme (normalerweiseZeroDivisionError
mit freundlicher Genehmigung der Funktion "Plötzlich sterben"E()
).quelle