Skip to content

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Schriftcode

Jedes Zeichen, Byte für Byte. UTF-8 ist die Regel, die aus Unicode-Zahlen Bytes macht — und der Vorrat ist endlich: 1 112 064 Zeichen, kein Stück mehr. Was endlich ist, lässt sich vollständig prüfen. Dieses Blatt codiert jeden einzelnen Wert von Hand, Bit für Bit, und hält das Ergebnis gegen den eingebauten Encoder des Browsers — beide Richtungen, keine Stichprobe.

Anschauen

  • Vier Formen: 1, 2, 3 oder 4 Bytes — die führenden Bits sagen die Länge, das Präfix
  • Übersetzer: Text eingeben, Zeichen für Zeichen die Bytes sehen, inklusive Bitmuster
  • Fallen: Umlaute, Währungen, Astralzeichen, ZWJ-Familien — wo .length lügt
  • Prüflauf: alle 1 112 064 Zeichen hin und zurück, feste Proben, Verwerfungen, zwei Gegenproben

Warum das überhaupt prüfbar ist

Der Unicode-Skalarenraum ist geschlossen und endlich: 0 bis 0x10FFFF, abzüglich der Surrogate 0xD800–0xDFFF, ergibt genau 1 112 064 Werte. Jeder davon wird hier einzeln durchprobiert — gestichprobt wird nichts. Dazu kommt ein Präfixcode: Die führenden Bits eines Bytes kündigen unmissverständlich an, wie viele Bytes dazugehören, und jedes Fortsetzungsbyte beginnt mit 10. Deshalb ist der Code selbstverständlich zur vollständigen Prüfung geeignet, und die Zählung muss mit der Theorie übereinstimmen.

Was der Prüflauf zeigt

Behauptung Ergebnis
alle Zeichen hin, Byte für Byte 1 112 064 Zeichen von Hand codiert gegen den eingebauten Encoder · 0 Abweichungen
und wieder zurück alle eigenen Bytefolgen zurückgedeutet · 0 daneben
die Längen liegen fest 128 · 1 920 · 61 440 · 1 048 576 — gezählt und erwartet deckungsgleich
feste Proben aus der Dokumentation 7 Proben ($ ¢ € ß ä 𝄞 𐍈) · 7 treffen Eigenbau und Browser zugleich
Verwerfungen, wo nichts zu holen ist 10 kaputte Folgen · 10 von beiden Deutern zurückgewiesen
Gegenprobe: stille Ersetzung ertappt der nachgiebige Dekoder: 10 von 10 still durchgelassen — ertappt
Gegenprobe: der Eine-Bahn-Codierer 12 000 Proben · 12 000 erwischt
echte Sätze, zufällig gesät 300 Sätze, bis zu 40 Zeichen · hin und zurück · 0 daneben

Der Prüflauf läuft in 4,9 Sekunden — der gesamte Vorrat, beide Richtungen.

Was mich das gekostet hat

Der Überlang-Index war um eins verschoben. Im Deuter liegt die Untergrenze pro Bahnlänge in einem Array: [0, 0x80, 0x800, 0x10000]. Ich hatte [...][bahnen] geschrieben — für bahnen=2 greift Index 2, also 0x800 statt 0x80. Ergebnis: alle 2-Byte- und 3-Byte-Werte wurden als „überlang" verworfen. 63 360 Fehler, exakt die Summe aus 1 920 und 61 440 — die Prüfung hat es sofort gemeldet, und die Zahl war so deutlich, dass die Ursache sofort klar war.

Der hexadezimale Index-Leck. Die Prüfungen vergleichen Strings wie „E2 82 AC" — selbst geschrieben, Byte für Byte. Für die Zählung habe ich gruppe(punkt).map(hex) verwendet. map() übermittelt aber den Array-Index als zweites Argument an die Callback-Funktion, und mein hex-Helper akzeptiert ein zweites Argument für die Breite: padStart(st || 2, "0"). Für das vierte Byte einer Vierergruppe (Index 3) wurde padStart(3, "0") aufgerufen — „9E" wurde zu „09E". Zwei von sieben Proben schlugen fehl, und die Differenz war auf den ersten Blick unsichtbar: ein führendes Nullbyte mehr. Der Fix war, .map(hex) durch .map((b) => hex(b)) zu ersetzen — die Stellschraube war nicht die Logik, sondern eine unbeabsichtigte Seitenwirkung von .map().

Was der Browser hier ausmacht. Verglichen wird nicht mit sich selbst: TextEncoder und TextDecoder sind die fertigen Implementierungen des Browsers — ein zweites Werkzeug mit anderer Herkunft. Dazu kommen feste Proben aus der Unicode-Dokumentation mit hingeschriebenen Bytes. Wenn eigene Bits, Browser und schriftliche Quelle übereinstimmen, sprechen zwei unabhängige Zeugen — und die Gegenproben zeigen zusätzlich, dass der Vergleich überhaupt anschlagen kann.

Technik

Eine einzelne HTML-Datei. Kein Build, keine Bibliothek, nichts verlässt den Browser. Codierung per Bit-Schieberei, Deutung als State-Machine mit strenger Fehlerbehandlung, Prüflauf als asynchroner Block mit Fortschrittsanzeige. Hell und dunkel über prefers-color-scheme und [data-theme].

Die ganze Sammlung

Alle Blätter nach Feld geordnet, jedes mit eigenem Repo: ssims437.github.io

Lizenz

MIT

About

UTF-8 von Hand: wie aus jedem Unicode-Zeichen seine Bytes werden

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages