Design UTF-8-Lib



  • IchNutzeComputer schrieb:

    Wie kann ein Typ wahlweise 8 / 16 / 24 / 32 Bit groß sein?

    So funktioniert nunmal UTF-8

    IchNutzeComputer schrieb:

    Ich sagte ja, dass der UTF-8-String intern 8Bit-Chars speichert

    Und wie willst du dann die 2, 3 oder 4 Byte langen UTF-8 zeichen speichern?



  • tkausl schrieb:

    IchNutzeComputer schrieb:

    Wie kann ein Typ wahlweise 8 / 16 / 24 / 32 Bit groß sein?

    So funktioniert nunmal UTF-8

    UTF-8 gibt 8 / 16 / 24 / 32 Bit-Sequenzen vor. Wie man diese speichert (das wird impliziert von "Typ"), hat nichts mit dem Standard zu tun. Und wenn man einen Typ für ein UTF-8-Zeichen machen möchte, dann muss man eben 32Bit nehmen (wie ich anfangs sagte). Alles andere ist in C++ nicht realistisch.

    tkausl schrieb:

    IchNutzeComputer schrieb:

    Ich sagte ja, dass der UTF-8-String intern 8Bit-Chars speichert

    Und wie willst du dann die 2, 3 oder 4 Byte langen UTF-8 zeichen speichern?

    Mit 2, 3 oder 4 Bytes? Die werden vom Wrapper eben speziell interpretiert und behandelt...



  • Edit zu oben:
    *Mit 2, 3 oder 4 Chars?

    Und ich will diesen 32Bit-Datentypen ja nur verwenden, wenn man ein einzelnes Zeichen handhabt (was man meistens nicht tut, stattdessen nutzt man Strings). Und da geht es wirklich nicht anders (in Strings habe ich ja vor, 8Bit-Chars zu verwenden wie gesagt).



  • IchNutzeComputer schrieb:

    - Ein String-Wrapper, der intern nur 8Bit-Zeichen hält, nach außen (operator[], Iteratoren) aber so fungiert, als bestünde er aus 32Bit-Chars (siehe oben).

    Wie soll das funktionieren?



  • TyRoXx schrieb:

    IchNutzeComputer schrieb:

    - Ein String-Wrapper, der intern nur 8Bit-Zeichen hält, nach außen (operator[], Iteratoren) aber so fungiert, als bestünde er aus 32Bit-Chars (siehe oben).

    Wie soll das funktionieren?

    Z.B. mit Proxies. Wird ein 'a' durch ein spezielles 4Byte-Zeichen ersetzt via einem Iterator, dann werden 3 Bytes im String eingefügt und das Zeichen wird gespeichert. Wenn die Performance zu sehr darunter leidet, dann nutzt man darunter std::vector oder std::deque, die immer schön große Blöcke allozieren.



  • laut Wikipedia wird UTF-8 mit 8bit code-UNITS gespeichert
    d.h. zwischen 1-n bytes pro Zeichen (aka code-POINT) - und UTF-8 kann bis dato 1112064 code-POINTS (also Zeichen) abbilden

    und du willst jetzt die code-UNITs per [] zugreifebar machen - z.B. fuer ASCII-Parties - aber intern die n-bytes per code-POINT in einem int32 halten - oder?
    was den Speichervorteil von UTF8 ja irgendwie vernichtet

    btw: eine vector/list oder sonstiges ist für String-Behandlung trotzdem noch viel zu langsam - immer so viel Heap-Parties 🙂

    schau dir doch mal (nur aus spass) http://utfcpp.sourceforge.net/ an



  • Ich würde eine Klasse Char schreiben, welches ein Unicode-Zeichen enthält. Die Klasse ist dann natürlich 32 Bit groß. Dann bekommst Du mit typedef std::basic_string<Char> UnicodeString einen Unicode String. Separate Konvertierfunktionen von utf-8 und nach utf-8 machen dann den Rest.

    Nachteil ist, dass der String mehr Speicher verbraucht. Dafür ist die Verarbeitung sehr viel einfacher. Das 3. Zeichen ist dann das 3. Element im String und nicht je nach dem was im 1. oder 2. Byte steht.

    Übrigens haben wir das in etwa so in unseren cxxtools gemacht.



  • Es gibt zwei unterschiedliche Teile von Unicode-Handling:
    - Encoden/Decoden von verschiedenen Zeichensätzen auf Basis von Codepoints (UTF-8, UTF-32, etc.), mit allem was dazu gehört (Fehlererkennung/-behandlung, BOM, etc.)
    - Stringoperationen auf Grapheme-Clusters, z.B. lowercase, Anzahl Zeichen, Unicode Normalisierung durchführen, Leerzeichen erkennen, etc.

    Der erste Punkt ist relativ einfach, der zweite sehr sehr schwierig. Die Standardbibliothek macht das falsch und die cxxtools von tntnet daher ebenfalls (weil isupper z.B. nicht nur durch den Codepoint bestimmt werden kann).

    Auf Basis von Codepoints zu operieren ist nicht mehr zeitgemäss. Uppercase von "ß" ist "SS". Codepoints sind nicht gleich Buchstaben (Ç=C+◌̧ ). Zudem sind alle Operationen sprachenabhängig.

    Daher mein Rat: Beschränke dich auf den ersten Teil und lasse den zweiten bleiben. Besser nicht, als falsch.



  • Danke unicoder für den besseren Einblick. Ich hätte nicht erwartet, dass Unicode alleine eine solche Komplexität aufweist. Ursprünglich wollte ich Dateien in UTF-8 auslesen, verschiedene Transformationen machen (Uppercase <-> Lowercase), verschiedene Informationen sammeln (ob an Stelle so und soviel ein ö oder sowas ist) und letztendlich die Datei (modifiziert) in UTF-8 wieder abspeichern. Wenn ich dich richtig verstanden habe, dann ist schon das ein zu schwieriges Vorhaben.



  • IchNutzeComputer schrieb:

    Ursprünglich wollte ich Dateien in UTF-8 auslesen, verschiedene Transformationen machen (Uppercase <-> Lowercase), verschiedene Informationen sammeln (ob an Stelle so und soviel ein ö oder sowas ist) und letztendlich die Datei (modifiziert) in UTF-8 wieder abspeichern.

    Was soll denn mit dem Ergebnis passieren? Vielleicht reicht eine naive Herangehensweise.



  • Das Ergebnis wird später wieder vom Programm selbst und von anderen UTF-8-fähigen Programmen gelesen und weiterverarbeitet. Es handelt sich je Datei größtenteils um gewöhnlichen Text. Der Text wird auf Buchstabenhäufigkeiten / Wörter (hier möchte ich noch ein paar Sondertricks einbauen, um u.U. Wortstämme herauszufiltern) geprüft. Meinem Wissen nach nutzt keine Sprache außer Latein selbst bloß das lateinische Alphabet ohne zusätzliche Sonderzeichen, weswegen ich das hier mit UTF-8 machen möchte. Ich möchte nichts Fertiges nehmen und mein Programm dann kurz zusammenbasteln, sondern möchte auch zum ersten Mal in Kontakt mit Unicode kommen, weswegen ich die genannten Aspekte umsetzen möchte (auch wenn ich mir wegen dem Design noch unklar bin).


Anmelden zum Antworten