Wie speichert ihr eure Strings?

Programmiersprachen, APIs, Bibliotheken, Open Source Engines, Debugging, Quellcode Fehler und alles was mit praktischer Programmierung zu tun hat.
Antworten
dawit
Beiträge: 42
Registriert: 05.02.2011, 17:06

Wie speichert ihr eure Strings?

Beitrag von dawit »

Moin Leute

Die Vorgeschichte:
Eigentlich wollte ich nur Umlaute darstellen. Das hat dann dazu geführt, dass ich mich mit Unicode beschäftigt habe (ok, Umlaute kann man auch mit Latin-1 (ISO-8859-1) darstellen, aber wenn, dann richtig :) ). Irgendwann habe ich mich dann für UTF-8 als interne Darstellung entschieden und hab UTF8-CPP für Konvertierungen benutzt.
Das ging so lange gut, bis ich Strings vergleichen wollte, denn man kann zwar theoretisch zwei UTF-8 Strings mit strcmp() vergleichen, jedoch kann ein Zeichen auf mehr als eine Weise kodiert werden, wofür strcmp() aber nicht ausgelegt ist. Aus diesem Grund müssen die Strings zuerst in eine einheitliche Form gebracht (normalisiert) werden, anschließend kann dann nach belieben verglichen werden.
So kann man zwei Strings zwar auf Gleichheit prüfen, dass bedeutet aber noch lange nicht, dass man sie auch Sortieren kann (und der Sortiervorgang ist auch noch von Sprache zu Sprache verschieden :( )
Die einzige Lib, die ich gefunden habe und das (und noch vieles mehr) anbietet, ist ICU. Die war mir dann allerdings zu Umfangreich (ich will doch bloß ein paar Strings vergleichen), also hab ich mir gedacht, dass ich mir das einfach selbst schreibe (zum Glück ist Programmieren 'nur' ein Hobby, und ich kann machen was ich will, auch wenns vollkommen unwirtschaftlich ist).
Das Projekt wird langsam aber ziemlich groß, und ich dachte bevor ich mich hier in irgendwas verrenne, frage ich mal, wir ihr es so handhabt.

Die Fragen:
Um mal die Frage ein bisschen zu verfeinern:
  • Benutzt ihr Unicode (UTF-8, UTF-16, UTF-32), wchar_t oder einfach ASCII kodierte Strings?
  • Benutzt ihr für Unicode irgendeine externe Bibliothek? Eine (eigene) String-Klasse?
dawit
Benutzeravatar
Krishty
Establishment
Beiträge: 8251
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Wie speichert ihr eure Strings?

Beitrag von Krishty »

Igitt, wchar_t … ich benutze – wie du – UTF-8 mit UTF-8 CPP. Die Probleme mit Normalisierung und Vergleichen umschiffe ich, indem ich alle nicht-symbolischen Strings – also die, die programminterne Bedeutung haben, z.B. Schlüssel für eine Datenbank – ASCII halte und nur in für die Programmlogik „unwichtigen“ Strings (wie Anzeigenamen) Sonderzeichen zulasse.

Naja … sowas kann ich mir bei kleinen 3D-Engines leisten … aber es gibt sicher auch Fälle, wo man nicht mehr um Logik auf UTF-8 herumkommt. Da würde mich auch mal interessieren, wie die anderen hier das gelöst haben.

Gruß, Ky
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Schrompf
Moderator
Beiträge: 4862
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: Wie speichert ihr eure Strings?

Beitrag von Schrompf »

Wir sind bisher komplett im Blindflug unterwegs - wir benutzen die Standard-Codepage von Windows, welche auch immer das ist. Allerdings beißt uns das jetzt langsam in den Hintern, Anfangs waren es nur versaute Umlaute in den Shaderquellen, inzwischen tauchen die Gurkenzeichen auch in Dialogen auf. Daher integriere ich gerade ICU mit boost::locale als Frontend.

Wie sieht es bei euch mit der Versionierung aus? Kann Subversion inzwischen mit UTF8-Files sinnvoll umgehen? Oder bewertet es die immernoch als Binärdateien, wodurch das Mergen mehr oder minder nutzlos ist.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Florian Keßeler
Beiträge: 75
Registriert: 24.07.2002, 00:00
Wohnort: Bremen
Kontaktdaten:

Re: Wie speichert ihr eure Strings?

Beitrag von Florian Keßeler »

GIT kommt super mit UTF8 klar. Zumindest zeigt git diff zeigt auch nur wirklich geänderte Zeilen trotz UTF8-Umlauten an...

Und zumindest SVN 1.6.16 kriegt es nicht gebacken...
kaiserludi
Establishment
Beiträge: 467
Registriert: 18.04.2002, 15:31

Re: Wie speichert ihr eure Strings?

Beitrag von kaiserludi »

Krishty hat geschrieben:Igitt, wchar_t
Wieso "igitt"?
Soweit ich das unicode-Thema in C++ überblicke ist wchar_t noch die sinnvollste Lösung:
- man kann es auch in C, und objC verwenden, da es zu C gehört und nicht C++ spezifisch ist
- es gehört zur C Standard Lib und ist damit auf allen standardkonformen Plattformen vorhanden

Dass wchar_t auf Windows 16Bit und UTF16 und auf Unix 32 Bit und UTF 32 ist, ist bei sauberem Softwaredesign völlig egal.

UTF8 ist zwar in der Theorie ganz toll, aber da es nicht im Standard ist, bietet leider nicht jede Plattform auch nur ansatzweise alle überlebenswichtigen Funktionen dafür an, weswegen ich in der API wchar_t für sinnvoller als multibytestrings halte und nur für die Serilization und Netzwerkübertragung zum Sparen von Bandbreite in UTF8 konvertiere.

Das einzige Problem mit wchar_t, dass ich bis jetzt habe, ist, dass der mingw in diesem Punkt auch nach so vielen Jahren immer noch nicht den Standard unterstützt, obwohl nicht nur VS und GCC sondern auch sonst jeder kleine Wald- und Wiesencompiler wchar_t-Support hat.
Zuletzt geändert von kaiserludi am 29.03.2011, 13:12, insgesamt 1-mal geändert.
"Mir ist auch klar, dass der Tag, an dem ZFX und Developia zusammengehen werden der selbe Tag sein wird, an dem DirectGL rauskommt."
DirectGL, endlich ist es da
:)

"According to the C++ standard, it's "undefined". That's a technical term that means, in theory, anything can happen: the program can crash, or keep running but generate garbage results, or send Bjarne Stroustrup an e-mail saying how ugly you are and how funny your mother dresses you." :shock:[/size]
dawit
Beiträge: 42
Registriert: 05.02.2011, 17:06

Re: Wie speichert ihr eure Strings?

Beitrag von dawit »

Ich denke, ich werde dann doch mal auf die bereits von Schrompf erwähnte Kombination aus ICU und boost::locale wechseln, da es ist leider scheinbar gar nicht möglich, eine kleine/kompakte UTF-8 lib zu schreiben, weil allein die ganzen lookup tables schon knapp 10Mb beanspruchen.
Benutzeravatar
Krishty
Establishment
Beiträge: 8251
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Wie speichert ihr eure Strings?

Beitrag von Krishty »

kaiserludi hat geschrieben:- es gehört zur C Standard Lib und ist damit auf allen standardkonformen Plattformen vorhanden
Wie kompatibel wchar_t zur Standardbibliothek ist, habe ich hier gesehen.
kaiserludi hat geschrieben:Dass wchar_t auf Windows 16Bit und UTF16 und auf Unix 32 Bit und UTF 32 ist, ist bei sauberem Softwaredesign völlig egal.
Zuerst einmal ist die Größe von wchar_t nicht vom Betriebssystem, sondern vom Compiler abhängig. Und genauso die Kodierung. Ich habe in meinen alten Quelltexten noch eine Notiz, dass Visual C++ UCS-2 verwendet und damit inkompatibel zur WinAPI ist, die UTF-16 erwartet (aber zumindest bei Visual C++ 2010 ist das nicht mehr der Fall, alles UTF-16 dort).
kaiserludi hat geschrieben:UTF8 ist zwar in der Theorie ganz toll, aber da es nicht im Standard ist, bietet leider nicht jede Plattform auch nur ansatzweise alle überlebenswichtigen Funktionen dafür an, weswegen ich in der API wchar_t für sinnvoller als multibytestrings halte
Wie du selber gesagt hast: wchar_t ist UTF-16, und das ist multi-byte. Die Standardbibliothek bietet nicht eine Zeile mehr Unicode-Unterstützung für wchar_t als für char. Steck ein UTF-16-Zeichen jenseits der 0xFFFF in einen ::std::wstring, frag length() ab und begreif, dass da nicht die Anzahl der Buchstaben (Code Points), sondern die Anzahl der Speichereinheiten (Code Units) zurückkommt (ist ja auch im Standard als gleichbedeutend mit size() definiert).

Noch dazu darf C++-Quelltext überhaupt keine Sonderzeichen enthalten. C++-Quelltext müsste ASCII-only sein. Das bedeutet: In dem Augenblick, wo du im Quelltext einen Umlaut in eine Zeichenkette schreibst – egal, ob normal oder mit L davor –, ist die Zeichenkette nicht mehr portabel.

Für solche Fälle hat der Standard Escape-Sequenzen vorgesehen; wenn du UTF-16 benutzen wolltest, würdest du den Umlaut ä also im Quelltext gemäß seiner Unicode-Position bei U+00E4 mit L'\x00E4' ausschreiben.

Das funktioniert bei den unteren 65536 Werten noch ganz gut. Jetzt willst du aber ein Zeichen an höherer Position kodieren. Geht nicht, weil Escape-Sequenzen nur vier Hex-Ziffern akzeptieren. Oh. Also jagst du das erstmal durch einen Online-Konvertierer, der dir (rein exemplarisch) die UTF-16-Folge 0xD0FE, 0xDE15 ausspuckt. Die schreibst du rein und die läuft. Unter Visual C++ jedenfalls. GCC produziert aber nur Müll, weil es wchar_t in 32 Bits kodiert und UTF-32 erwartet. Und das ist dann der Punkt, an dem man begreift, dass wchar_t eine an allen Ecken und Enden missratene Fehlgeburt ist, die provisorisch irgendwo an den Standard gekleistert wurde – und was von vorne bis hinten als implementation-defined „standardisiert“ ist, ist für breite Anwendung eben einen feuchten Kehricht wert.

Zusammengefasst: Die Standardbibliothek bietet keine Unicode-Unterstützung, C++ bietet (noch) keine Unicode-Unterstützung und wchar_t ist, auf den Punkt gebracht, nichts anderes als ein Container irgendeiner Größe für wenn man mal breite Buchstaben irgendwelcher Art braucht. Wenn du also UTF-16 oder UTF-32 benutzen möchtest, musst du dir so oder so eigene Funktionen zusammenschustern. Wenn du sie darüber hinaus auch noch mit wchar_t benutzen willst, musst du dir sogar doppelt so viel zusammenschustern, weil du auf der einen Plattform mit UTF-16 und auf der anderen mit UTF-32 arbeiten musst.

Darum ist die einfachste und beste Lösung: Scheiß auf wchar_t und benutz uint16_t, um deine Buchstaben überall in UTF-16 zu speichern. Und wenn du nicht damit rechnen musst, dass ein Großteil der Strings in deinem Programm mal auf Chinesisch sein wird oder sie dauernd durch die WinAPI müssen, bleib direkt bei UTF-8.

Falls ich da was verpeilt haben sollte, bitte korrigieren. Ist schon ein wenig her, dass ich mich mit wchar_t rumplagen musste.

(Das waren jetzt viele Betonungen … aber Rants machen mich immer so emotional, schon per Definition <3)
————
dawit hat geschrieben:da es ist leider scheinbar gar nicht möglich, eine kleine/kompakte UTF-8 lib zu schreiben, weil allein die ganzen lookup tables schon knapp 10Mb beanspruchen.
Welche LUTs? Wofür?
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
dawit
Beiträge: 42
Registriert: 05.02.2011, 17:06

Re: Wie speichert ihr eure Strings?

Beitrag von dawit »

Krishty hat geschrieben:Welche LUTs? Wofür?
Ooch, da gibts viele Bereiche:
  • Decomposition: Tabelle, die zu jedem Codepoint die zerlegte Form angibt: Ä -> U+0041 (LATIN CAPITAL LETTER A) + U+0308 (COMBINING DIAERESIS)
  • Tabelle, die die Reihenfolge der Combining Marks (Codepoints, die einen Buchstaben verändern, z.B. ä-Punkte) angibt
  • Bei der Composition werden mehrere Combining Marks zu einem Codepoint zusammengefasst, allerdings gibt es ausnahmen, bei denen dies nicht geschehen darf -> Tabelle
  • Tabellen für die richtige Sortierung in verschiedenen Sprachen
  • u.v.m., von denen ich noch nichts weiß
Benutzeravatar
Biolunar
Establishment
Beiträge: 154
Registriert: 27.06.2005, 17:42
Alter Benutzername: dLoB

Re: Wie speichert ihr eure Strings?

Beitrag von Biolunar »

Weiß jemand wie es mit den UTF Kodierungen in C++0x aussieht? Laut Wikipedia wird die Standardlib "Support for the UTF-16 encoding unit, and UTF-32 encoding unit Unicode character types" enthalten. Das heißt soviel für mich, dass so Dinge wie std::collate endlich vernünftig funktionieren werden. Allerdings habe ich in einem Draft (ich hoffe es ist der aktuelle ;)) gesehen, dass collate immernoch nur für char und wchar_t ausgelegt ist. WTF. Und es steht nicht einmal in dem Draft, dass collate das Encoding des aktuellen Locales berücksichtigen muss! Wozu gibt’s das Facet dann überhaupt? Im Grunde hat C++0x also auch keine Unicode unterstützung :(
Bitte sag mir jemand, dass ich was überlesen habe.
Benutzeravatar
Krishty
Establishment
Beiträge: 8251
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Wie speichert ihr eure Strings?

Beitrag von Krishty »

dawit hat geschrieben:
Krishty hat geschrieben:Welche LUTs? Wofür?
Ooch, da gibts viele Bereiche:
Okay … ich wollte jetzt eigentlich dazu aufrufen, OS-spezifische Funktionen zu recyclen, aber habe eben entdeckt, dass es die unter Windows nur für UTF-16 gibt. Nevermind.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Antworten