Unicode Strings

Programmiersprachen, APIs, Bibliotheken, Open Source Engines, Debugging, Quellcode Fehler und alles was mit praktischer Programmierung zu tun hat.
Niki
Establishment
Beiträge: 309
Registriert: 01.01.2013, 21:52

Unicode Strings

Beitrag von Niki »

Hallo Leute!

Ich wollte mich mal umhören wie ihr in heutigen Zeiten mit Unicode Strings umgeht.

Am liebsten würde ich UTF-16 Strings benutzen, also fällt std::string schon mal weg. Auch std::wstring fällt weg, da man es leider nicht geschafft hat die Größe von wchar_t zu standardisieren. Eine Möglichkeit wäre std::basic_string<UTF16>, wobei UTF16 ein unsigned short ist. Oder man kann natürlich auch, wie ich momentan, seine eigene String-Klasse benutzen. Aber ich kann irgendwie nicht glauben, dass es im Jahre 2013 keine Standard UTF-16 String-Klasse gibt, denn es handelt sich ja immerhin um das UTF-Format welches in der 16-Bit Basic Multilingual Plane die meisten Sprachen der Welt vereint.

Auch suche ich nach etwas wie L"Hallo Welt!" welches immer 16-Bit Zeichen benutzt. Grund ist, dass ich die Strings auch für nicht-ASCII-7 Dateinamen benutzen will, und manche davon stehen direkt im Code. Das muss doch auch ohne Konvertierungsfunktionen gehen...
Niki
Establishment
Beiträge: 309
Registriert: 01.01.2013, 21:52

Re: Unicode Strings

Beitrag von Niki »

Mein erster Ansatz wäre nun wie folgt:

Code: Alles auswählen

typedef unsigned short  QxUtf16;
typedef std::basic_string<QxUtf16, std::char_traits<QxUtf16>, std::allocator<QxUtf16> >    QxString16;

...

QxString16 s = (const QxUtf16 *)L"Hallo Welt!";
... aber schon die Art wie ich da den konstanten String L"Hallo Welt!" zuweise löst bei mir einen Würgreiz aus. Mal abgesehen davon, dass das L-Präfix zwar auf allen Plattformen existiert, aber nicht auf allen Plattformen in 16-Bit Zeichen resultiert.

Außerdem habe ich da eine Wissenslücke bei std::basic_string. So weiß ich nicht, ob ich std::basic_string einfach auf diese Weise nutzen sollte. Irgendwie liest sich das wie STL-interne Klasse.
Niki
Establishment
Beiträge: 309
Registriert: 01.01.2013, 21:52

Re: Unicode Strings

Beitrag von Niki »

Oh wow... ich sehe es gibt std::u16string. Aber wie kriege ich die Konstantenzuweisung in VC 2010 besser hin?

Code: Alles auswählen

std::u16string a = (const char16_t *)L"Hallo";
Benutzeravatar
Krishty
Establishment
Beiträge: 8267
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Unicode Strings

Beitrag von Krishty »

Niki hat geschrieben:Grund ist, dass ich die Strings auch für nicht-ASCII-7 Dateinamen benutzen will, und manche davon stehen direkt im Code. Das muss doch auch ohne Konvertierungsfunktionen gehen...
Dann änder die festgeschriebenen Dateinamen doch so, dass nur 7-Bit-ASCII drin vorkommt. Oder wenn du weißt, dass wchar_t zu UTF-16 kodiert (immer auf Windows), schreib die nicht-ASCII-Zeichen via \x048C in den Wide-Character-String.

Was musst du denn mit den Strings machen? Mir fiele nur Verketten ein (um z.B. den Dateinamen einer Ressource zu bauen). Dabei stammen normalerweise schon alle Pfade direkt oder indirekt aus der Win32-API (sind also UTF-16) oder aus Quellen, deren Kodierungshoheit du hast (vorschreiben, dass die Asset-Liste in UTF-16-LE vorliegt; im Quelltext vorgeschriebene Dateiendung auf ASCII reduzieren). Sowas geht dann auch ohne einen extra Container.

Stellen, wo UTF-16 tatsächlich verarbeitet werden muss (Namen in Highscore-Listen verifizieren, die gern durch exotische Zeichen verziert werden / Textinhalte, die vom Anwender stammen, durchsuchen) habe ich in den letzten Jahren nie gehabt, würde sie aber via utf8cpp lösen (vor allem, weil man dort nicht auf die bescheuerte abschließende Null angewiesen ist).

Gruß, Ky
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Niki
Establishment
Beiträge: 309
Registriert: 01.01.2013, 21:52

Re: Unicode Strings

Beitrag von Niki »

Danke für die Antwort Krishty,

Ich arbeite für eine französische Firma, die evtl. irgendwann in das Projekt einsteigt. Aus Erfahrung weiß ich, dass die keine Scheu davor haben auch mal irgendwelche diakritischen Zeichen in Dateienamen zu benutzen.

Momentan benötige ich Strings um einen Ressourcen-Manager zu schreiben. Aber auch ansonsten braucht ein Programm natürlich Strings. Letztendlich sollen so wenige Strings wie möglich gehardcodet werden, aber trotzdem möchte ich jetzt einmal einen ordentlichen String haben, nur um dann später nicht mehr drüber nachdenken zu müssen. Ganz im Sinne von "Was ich hinter mir habe, das habe ich hinter mir!".

Nun gibt es für das Problem mit den String-Konstanten natürlich eine Lösung, nämlich die u/U Präfixe. Aber die gibt es in VC 2010 noch nicht. Ich werde es also vorerst wohl per Makro für Windows-only lösen (indem ich den L-Präfix im Makro benutze). Sobald ich dann auf u/U Präfix bauen kann, sollte es nicht so schlimm sein das Makro zu entfernen. Zumindest dann nicht, wenn die Anzahl der gehardcodedeten Strings niedrig gehalten wird.
Benutzeravatar
Krishty
Establishment
Beiträge: 8267
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Unicode Strings

Beitrag von Krishty »

Niki hat geschrieben:Ich arbeite für eine französische Firma, die evtl. irgendwann in das Projekt einsteigt. Aus Erfahrung weiß ich, dass die keine Scheu davor haben auch mal irgendwelche diakritischen Zeichen in Dateienamen zu benutzen.
Das behandelt aber doch schon die WinAPI für dich, oder?
Niki hat geschrieben:Aber auch ansonsten braucht ein Programm natürlich Strings.
Wofür?
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Niki
Establishment
Beiträge: 309
Registriert: 01.01.2013, 21:52

Re: Unicode Strings

Beitrag von Niki »

Krishty hat geschrieben:Das behandelt aber doch schon die WinAPI für dich, oder?
Ja, natürlich. Ich will das Projekt aber irgendwann mal auf andere Plattformen porten. Deshalb ist der WinAPI-Kram weggekapselt. Das heißt ich habe eine Zwischenebene wo Strings übergeben werden.
Krishty hat geschrieben:Wofür?
Wenn ich ein Spiel direkt implementiere, ohne eigene SDKs, dann selten bis gar nicht. Kommt auf das Spiel drauf an. Bei mir ist allerdings das Spiel selbst von einer Engine (also einem eigenen SDK) getrennt. Wenn ich dann im SDK eine Funktion habe à la "Lade mir die Datei X in einen Buffer", dann würd ich X schon gerne angeben dürfen.

Dein plattes "Wofür?" verwundert mich allerdings. Kommst du tatsächlich komplett ohne Strings aus? (ausgenommen sowas wie Highscores)

EDIT: Ich glaube ich habe "Wofür?" mit "Wozu?" verwechselt... Wahrscheinlich meintest du eher wo ich Strings einsetze. Ein paar wenige Beispiele:
- Strings die aus Textresourcen kommen und an den Font-Renderer gehen
- Strings zum debuggen. Zum Beispiel zum Benennen von Spielobjekten
- Log-Ausgaben
- Ein UTF-16 Lexer nimmt bei mir einen null-terminierten UTF16-String also Input. Das Teil wird allerdings in einem separaten Script-Compiler-Projekt gehalten.
- Der JSON Parser liefert Arrays und Dictionaries die eher oft Strings enthalten
- ...

Ich will das ganze im Zuge einer Generalüberholung etwas vereinheitlichen. Das war's zwar vorher auch schon, aber... Oh Mann, wo fange ich da an?! Mein altes SDK basiert z.B. auf Reference Counting, inklusive Autorelease-Pools, falls du Cocoa kennst. Auch die Strings sind darauf basiert. Ich versuche Reference Counting schrittweise zu entfernen und auch die Komponenten mehr voneinander zu lösen, und einige Teile durch Standard-Klassen zu ersetzen. Eine Riesenaufgabe, und Strings sind nunmal ein Teil davon.
Benutzeravatar
Krishty
Establishment
Beiträge: 8267
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Unicode Strings

Beitrag von Krishty »

Niki hat geschrieben:Ich will das ganze im Zuge einer Generalüberholung etwas vereinheitlichen. Das war's zwar vorher auch schon, aber... Oh Mann, wo fange ich da an?! Mein altes SDK basiert z.B. auf Reference Counting, inklusive Autorelease-Pools, falls du Cocoa kennst. Auch die Strings sind darauf basiert. Ich versuche Reference Counting schrittweise zu entfernen und auch die Komponenten mehr voneinander zu lösen, und einige Teile durch Standard-Klassen zu ersetzen. Eine Riesenaufgabe, und Strings sind nunmal ein Teil davon.
Achso – Refactoring. Stimmt: Bei dem Wulst hat man keine Kodierungshoheit; da komme ich mit meinem Idealismus nicht weit. Nevermind.
Niki hat geschrieben:
Krishty hat geschrieben:Das behandelt aber doch schon die WinAPI für dich, oder?
Ja, natürlich. Ich will das Projekt aber irgendwann mal auf andere Plattformen porten. Deshalb ist der WinAPI-Kram weggekapselt. Das heißt ich habe eine Zwischenebene wo Strings übergeben werden.
Dann mach die Strings doch einfach ebenfalls plattformabhängig. Wenn auf Linux alles UCS-32 ist und du dich jetzt auf UTF-16 festlegtest, müsstest du ja für einen API-Programm-API-Rundgang von UCS-32 zu UTF-16 und wieder zurück zu UCS-32 konvertieren. Wozu?
Niki hat geschrieben:
Krishty hat geschrieben:Wofür?
Wenn ich ein Spiel direkt implementiere, ohne eigene SDKs, dann selten bis gar nicht. Kommt auf das Spiel drauf an. Bei mir ist allerdings das Spiel selbst von einer Engine (also einem eigenen SDK) getrennt. Wenn ich dann im SDK eine Funktion habe à la "Lade mir die Datei X in einen Buffer", dann würd ich X schon gerne angeben dürfen.

Dein plattes "Wofür?" verwundert mich allerdings. Kommst du tatsächlich komplett ohne Strings aus? (ausgenommen sowas wie Highscores)
Nein, aber ich komme ohne Stringverarbeitung aus. Wie gesagt kommt alles direkt oder indirekt aus der WinAPI (Kommandozeile und blabla), und wandert auch wieder direkt oder indirekt dahin zurück (CreateFileW()). Dazwischen muss ich höchstens mal einen Dateipfad und -Namen konkatenieren – aber dabei ist ja egal, in welcher Kodierung der String vorliegt; das wird einfach aneinanderkopiert.

Eine Stelle, wo ich Strings tatsächlich verarbeite, sind meine Skript-Interpreter. Die Skriptsprachen sind aber komplett in 7-Bit-ASCII gehalten und was den Rest des Programms erreicht, sind eh keine String-Daten.

Klar: wenn irgendeine französische Firma ihre Texte fest in den Quelltext schreibt, ist man behupst. Einer macht eben immer alles kaputt.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
BeRsErKeR
Establishment
Beiträge: 689
Registriert: 27.04.2002, 22:01

Re: Unicode Strings

Beitrag von BeRsErKeR »

Niki hat geschrieben:Hallo Leute!

Ich wollte mich mal umhören wie ihr in heutigen Zeiten mit Unicode Strings umgeht.

Am liebsten würde ich UTF-16 Strings benutzen, also fällt std::string schon mal weg. Auch std::wstring fällt weg, da man es leider nicht geschafft hat die Größe von wchar_t zu standardisieren. Eine Möglichkeit wäre std::basic_string<UTF16>, wobei UTF16 ein unsigned short ist. Oder man kann natürlich auch, wie ich momentan, seine eigene String-Klasse benutzen. Aber ich kann irgendwie nicht glauben, dass es im Jahre 2013 keine Standard UTF-16 String-Klasse gibt, denn es handelt sich ja immerhin um das UTF-Format welches in der 16-Bit Basic Multilingual Plane die meisten Sprachen der Welt vereint.

Auch suche ich nach etwas wie L"Hallo Welt!" welches immer 16-Bit Zeichen benutzt. Grund ist, dass ich die Strings auch für nicht-ASCII-7 Dateinamen benutzen will, und manche davon stehen direkt im Code. Das muss doch auch ohne Konvertierungsfunktionen gehen...

Ich hab mich zwar noch nicht mit C++11 beschäftigt, aber soweit ich weiß bietet das den Typ char16_t an und auch neue Stringliterale für UTF-16:

Code: Alles auswählen

u"Mein UTF-16 String-Literal"
Bzw. es gibt noch weitere nützliche Neuerungen zum Thema String-Literale. Weiß nicht ob dir das was bringt. Ich würde unabhängig davon aber sowieso auf UTF-8 zurückgreifen und vielleicht einfach eine geeignete UTF-8-fähige String-Klasse wie Glib::ustring o.ä. verwenden.
Ohne Input kein Output.
Benutzeravatar
Krishty
Establishment
Beiträge: 8267
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Unicode Strings

Beitrag von Krishty »

Die Literale gehen leider unter VC 2010 nicht. (Unter VC 2012 auch erst ab dem November CTP.)

Weil die meisten Windows-APIs mit UTF-16 arbeiten, ist das dort auch UTF-8 vorzuziehen.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
BeRsErKeR
Establishment
Beiträge: 689
Registriert: 27.04.2002, 22:01

Re: Unicode Strings

Beitrag von BeRsErKeR »

Krishty hat geschrieben:Weil die meisten Windows-APIs mit UTF-16 arbeiten, ist das dort auch UTF-8 vorzuziehen.
Es scheint mir nicht so, dass das nur auf Windows laufen soll. Oder liege ich da falsch?
Ohne Input kein Output.
Niki
Establishment
Beiträge: 309
Registriert: 01.01.2013, 21:52

Re: Unicode Strings

Beitrag von Niki »

Krishty hat geschrieben:Achso – Refactoring. Stimmt: Da komme ich mit meinem Idealismus nicht weit. Nevermind.
Es ist sehr viel Refactoring, ja. Aber sag nicht das man da mit deinem Idealismus nicht weit kommt. Du hast ja bei sehr vielen Kommentaren recht.

Insgesamt geht es mir, mit Ausnahmen, mehr um das Durchreichen von Strings als um deren Verarbeitung. Wie du schon sagtest, könnte ich die Strings ja wirklich plattformabhängig machen (z.B.: "const std::wstring &" zum Durchreichen benutzen). Nur habe ich ein wenig Angst davor. UCS-32 auf einem Unix-System bedeutet ungefähr doppelten Speicherverbrauch für Strings. Eigentlich egal, denn Speicher gibt es mehr als genug. Was ich aber nicht global abschätzen kann ist, ob ich mir da ein Performance-Problem einhandle, weil die Cache Misses häufiger werden. Doch mal ein wenig String-Verarbeitung an der falschen Stelle kann da schon stören. Aber wahrscheinlich mache ich mir hier schon wieder zu viele Gedanken... Na, ja, so bin ich halt :)
Benutzeravatar
Krishty
Establishment
Beiträge: 8267
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Unicode Strings

Beitrag von Krishty »

BeRsErKeR hat geschrieben:
Krishty hat geschrieben:Weil die meisten Windows-APIs mit UTF-16 arbeiten, ist das dort auch UTF-8 vorzuziehen.
Es scheint mir nicht so, dass das nur auf Windows laufen soll. Oder liege ich da falsch?
Alles in eine Kodierung zu quetschen macht es aber nicht leichter portabel, sondern im Gegenteil schwerer. Darum habe ich ihm gesagt, er soll die Kodierung plattformabhängig machen.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
BeRsErKeR
Establishment
Beiträge: 689
Registriert: 27.04.2002, 22:01

Re: Unicode Strings

Beitrag von BeRsErKeR »

Niki hat geschrieben:Nur habe ich ein wenig Angst davor. UCS-32 auf einem Unix-System bedeutet ungefähr doppelten Speicherverbrauch für Strings. Eigentlich egal, denn Speicher gibt es mehr als genug. Was ich aber nicht global abschätzen kann ist, ob ich mir da ein Performance-Problem einhandle, weil die Cache Misses häufiger werden. Doch mal ein wenig String-Verarbeitung an der falschen Stelle kann da schon stören. Aber wahrscheinlich mache ich mir hier schon wieder zu viele Gedanken... Na, ja, so bin ich halt :)
Also ich weiß ja nicht was du genau vor hast aber ich glaube kaum dass ein paar Dateinamen irgendwelche Performanceeinflüsse oder Speicherprobleme verursachen könnten. Ob das nun 30 oder 120 Bytes pro Dateinamen sind ist doch wirklich egal, zumal man sowas in der Regel nicht die ganze Programmlaufzeit im Speicher halten muss.
Krishty hat geschrieben:
BeRsErKeR hat geschrieben:
Krishty hat geschrieben:Weil die meisten Windows-APIs mit UTF-16 arbeiten, ist das dort auch UTF-8 vorzuziehen.
Es scheint mir nicht so, dass das nur auf Windows laufen soll. Oder liege ich da falsch?
Alles in eine Kodierung zu quetschen macht es aber nicht leichter portabel, sondern im Gegenteil schwerer. Darum habe ich ihm gesagt, er soll die Kodierung plattformabhängig machen.
Naja aber es gibt wie gesagt schon fertige String-Klassen, die plattformunabhängig sind und alle möglichen Encodings schlucken und auch wieder ausspucken können.
Ohne Input kein Output.
Niki
Establishment
Beiträge: 309
Registriert: 01.01.2013, 21:52

Re: Unicode Strings

Beitrag von Niki »

BeRsErKeR hat geschrieben:Es scheint mir nicht so, dass das nur auf Windows laufen soll. Oder liege ich da falsch?
Momentan nur Windows. Muss aber sehr viel später auf diverse mobile Plattformen (mindestens iOS) portierbar sein. Das ist dann nochmal ein zusätzlicher Schwung Arbeit. Momentan allerdings übertreibe ich es mit der Plattformunabhängigkeit aber noch nicht, denn dadurch würde mein Fortschritt noch mehr gedrosselt werden als es sowieso schon der Fall ist. Ich denke grob über Plattformunabhängigkeit nach, aber noch nicht im Detail.
Benutzeravatar
Krishty
Establishment
Beiträge: 8267
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Unicode Strings

Beitrag von Krishty »

Niki hat geschrieben:Wie du schon sagtest, könnte ich die Strings ja wirklich plattformabhängig machen (z.B.: "const std::wstring &" zum Durchreichen benutzen).
Ich meinte eher sowas wie:

    #ifdef WIN32
        typedef wchar_t NativeChar; // Die WinAPI baut auf UTF-16
    #elif defined WATEVR
        // UTF-8; UCS-32; oder was auch immer die Laufzeitumgebung bevorzugt
    #endif

    typedef std::basic_string<NativeChar> NativeString;


… und solche rumreichen.
Nur habe ich ein wenig Angst davor. UCS-32 auf einem Unix-System bedeutet ungefähr doppelten Speicherverbrauch für Strings. Eigentlich egal, denn Speicher gibt es mehr als genug. Was ich aber nicht global abschätzen kann ist, ob ich mir da ein Performance-Problem einhandle, weil die Cache Misses häufiger werden. Doch mal ein wenig String-Verarbeitung an der falschen Stelle kann da schon stören. Aber wahrscheinlich mache ich mir hier schon wieder zu viele Gedanken... Na, ja, so bin ich halt :)
Darum sollst du die Strings auch so speichern, wie es für die Plattform am besten ist (im Beispiel NativeChar[]) – dann hast du überhaupt keine Konvertierungen nötig (denn Cache Misses entstehen ja nur, wenn du die Strings auch verarbeitest; nicht, wenn sie rumliegen oder rumgereicht werden).

Dann hättest du zwar – wie eingangs erwähnt – das Problem, dass du in Visual C++ nicht die UTF-8-Literale anlegen kannst, die das Linux-Dateisystem erwarten würde – aber du kompilierst deine Linux-Version ja eh nicht mit Visual C++, sondern nur die Windows-Version, und da ist die native Kodierung UTF-16, die problemlos funktioniert.

Nur ist in deinem speziellen Fall das Problem, dass viele Drittbibliotheken dranhängen, die wohl auf jeder Plattform identische Kodierung erwarten. Da wirst du dann konvertieren müssen.
Zuletzt geändert von Krishty am 13.04.2013, 16:47, insgesamt 3-mal geändert.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Niki
Establishment
Beiträge: 309
Registriert: 01.01.2013, 21:52

Re: Unicode Strings

Beitrag von Niki »

BeRsErKeR hat geschrieben:Also ich weiß ja nicht was du genau vor hast aber ich glaube kaum dass ein paar Dateinamen irgendwelche Performanceeinflüsse oder Speicherprobleme verursachen könnten. Ob das nun 30 oder 120 Bytes pro Dateinamen sind ist doch wirklich egal, zumal man sowas in der Regel nicht die ganze Programmlaufzeit im Speicher halten muss.
Wie ich schon sagte mache ich mir wahrscheinlich zu viele Gedanken, auch wenn es sich um mehr als nur Dateinamen handelt. Ein Fall wo ich tatsächlich String-Verarbeitung UND Formatkonvertierung hätte ist beim Rendern von Text. Und ganz besonders dann, wenn der Text länger ist und Wortumbruch unterstützen muss.
Benutzeravatar
BeRsErKeR
Establishment
Beiträge: 689
Registriert: 27.04.2002, 22:01

Re: Unicode Strings

Beitrag von BeRsErKeR »

Naja ich weiß nicht ob du auf andere Bibliotheken zurückgreifen willst. Ich kann halt nur aus meiner Erfahrung sagen, dass ich mit Glib ganz gut gefahren bin was Encodings angeht. Und das gibts auch für Windows.

Die bieten halt auch sowas wie Glib::filename_to_utf8 an. Oder allgemeiner locale_to_utf8.

Krishty hat geschrieben: #ifdef WIN32
typedef wchar_t NativeChar; // Die WinAPI baut auf UTF-16
#elif defined WATEVR
// UTF-8; UCS-32; oder was auch immer die Laufzeitumgebung bevorzugt
#endif

typedef std::basic_string<NativeChar> NativeString;
Dann muss man doch aber auch den ganzen File-I/O-Krams anpassen, was man ja in der Regel über eine Extra-Ebene einheitlich (plattformunabhängig) zusammenführt. Die Strings brauchst du aber auch jenseits dieser Ebene.
Ohne Input kein Output.
Niki
Establishment
Beiträge: 309
Registriert: 01.01.2013, 21:52

Re: Unicode Strings

Beitrag von Niki »

Krishty hat geschrieben:     #ifdef WIN32
        typedef wchar_t NativeChar; // Die WinAPI baut auf UTF-16
    #elif defined WATEVR
        // UTF-8; UCS-32; oder was auch immer die Laufzeitumgebung bevorzugt
    #endif

    typedef std::basic_string<NativeChar> NativeString;


… und solche rumreichen.
Ist das nicht dasselbe wie std::wstring? Auf einem Mac, z.B. ist wchar_t 32 Bits. Aber ein typedef nach NativeString is sicher trotzdem sinnvol.
Krishty hat geschrieben:Nur ist in deinem speziellen Fall das Problem, dass viele Drittbibliotheken dranhängen, die wohl auf jeder Plattform identische Kodierung erwarten. Da wirst du dann konvertieren müssen.
Momentan sind es wenige Drittbibliotheken. Eigentlich nur Theora, Vorbis, OpenAL und natürlich DirectX. Der Rest ist von mir.
Benutzeravatar
Krishty
Establishment
Beiträge: 8267
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Unicode Strings

Beitrag von Krishty »

BeRsErKeR hat geschrieben:Dann muss man doch aber auch den ganzen File-I/O-Krams anpassen, was man ja in der Regel über eine Extra-Ebene einheitlich (plattformunabhängig) zusammenführt. Die Strings brauchst du aber auch jenseits dieser Ebene.
Wie meinen? Kram um die E/A zu verwalten, zu verarbeiten, oder die E/A-Daten selbst?
Niki hat geschrieben:Ist das nicht dasselbe wie std::wstring? Auf einem Mac, z.B. ist wchar_t 32 Bits. Aber ein typedef nach NativeString is sicher trotzdem sinnvoll.
Schlagt mich tot weil ich zu wenig Linux-Erfahrung habe, aber: Afaik ist auf Linux wchar_t zwar UCS-32, aber die E/A-Funktionen wollen als Dateinamen UTF-8-kodierte chars.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Niki
Establishment
Beiträge: 309
Registriert: 01.01.2013, 21:52

Re: Unicode Strings

Beitrag von Niki »

BeRsErKeR hat geschrieben:
Krishty hat geschrieben: #ifdef WIN32
typedef wchar_t NativeChar; // Die WinAPI baut auf UTF-16
#elif defined WATEVR
// UTF-8; UCS-32; oder was auch immer die Laufzeitumgebung bevorzugt
#endif

typedef std::basic_string<NativeChar> NativeString;
Dann muss man doch aber auch den ganzen File-I/O-Krams anpassen, was man ja in der Regel über eine Extra-Ebene einheitlich (plattformunabhängig) zusammenführt. Die Strings brauchst du aber auch jenseits dieser Ebene.
File I/O ist bei mir eh plattformabhängig weggekapselt. Und die Systeme sollen ja wohl Funktionen bieten, die mit dem nativen wchar_t zusammen funktionieren. Unter WinAPI z.B. CreateFileW oder wfopen mit der CRT.
Niki
Establishment
Beiträge: 309
Registriert: 01.01.2013, 21:52

Re: Unicode Strings

Beitrag von Niki »

Krishty hat geschrieben:
Niki hat geschrieben:Ist das nicht dasselbe wie std::wstring? Auf einem Mac, z.B. ist wchar_t 32 Bits. Aber ein typedef nach NativeString is sicher trotzdem sinnvoll.
Schlagt mich tot weil ich zu wenig Linux-Erfahrung habe, aber: Afaik ist auf Linux wchar_t zwar UCS-32, aber die E/A-Funktionen wollen als Dateinamen UTF-8-kodierte chars.
Hehe, das geht schon klar. Den Superplan von Unix habe ich auch nicht. Auch wenn iOS auf Unix basiert, so nutzt man in der Regel doch Cocoa, welches einen Zugriff auf Low-Level Unix-Funktionen doch sehr reduziert. Aber selbst wenn, dann muss ich da halt konvertieren. Verglichen mit dem tatsächlichen Dateizugriff sollte das doch fast egal sein.
Benutzeravatar
BeRsErKeR
Establishment
Beiträge: 689
Registriert: 27.04.2002, 22:01

Re: Unicode Strings

Beitrag von BeRsErKeR »

Krishty hat geschrieben:
BeRsErKeR hat geschrieben:Dann muss man doch aber auch den ganzen File-I/O-Krams anpassen, was man ja in der Regel über eine Extra-Ebene einheitlich (plattformunabhängig) zusammenführt. Die Strings brauchst du aber auch jenseits dieser Ebene.
Wie meinen? Kram um die E/A zu verwalten, zu verarbeiten, oder die E/A-Daten selbst?
Niki hat geschrieben:File I/O ist bei mir eh plattformabhängig weggekapselt. Und die Systeme sollen ja wohl Funktionen bieten, die mit dem nativen wchar_t zusammen funktionieren. Unter WinAPI z.B. CreateFileW oder wfopen mit der CRT.
Genau das meine ich. Man nutzt plattformabhängige E/A-Funktionen wie CreateFile usw. Aber an irgendeiner Stelle werden die so gekapselt, dass man mit einer plattformunabhängigen Schnittstelle arbeiten kann. Sonst müsste man ja den halben Code mit #ifdefs bestücken. Und gerade da sehe ich das Problem, denn die Strings benötigt man auch außerhalb dieser Kapselung. Entweder bietet die Schnittstelle dann verschiedene Parameter- und Rückgabetypen je nach Plattform an oder sie arbeitet nach außen mit einem einheitlichen String-Typ. Die Frage ist halt ob es dann noch sinnvoll ist plattformabhängige String-Typen außerhalb dieser Kapselung zu verwenden oder nur innerhalb der Kapselung verschiedene String-Typen zu nutzen und dann z.B. in und von std::wstring zu konvertieren, der dann von der Schnittstelle verwendet wird.
Ohne Input kein Output.
Benutzeravatar
Krishty
Establishment
Beiträge: 8267
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Unicode Strings

Beitrag von Krishty »

BeRsErKeR hat geschrieben:Genau das meine ich. Man nutzt plattformabhängige E/A-Funktionen wie CreateFile usw. Aber an irgendeiner Stelle werden die so gekapselt, dass man mit einer plattformunabhängigen Schnittstelle arbeiten kann. Sonst müsste man ja den halben Code mit #ifdefs bestücken.
Ja, äh, oder mit einem einzigen typedef für die Kodierung, die man auf der aktuellen Plattform einsetzen will und einem Makro, das String-Literalen diese Kodierung verpasst.

Kapselung und Plattformunabhängigkeit haben nichts, rein garnichts damit zu tun, auf allen Plattformen dieselbe Kodierung zu benutzen. Dadurch wird im Gegenteil alles saukompliziert weil ein String für jeden Rundgang durchs Programm tausend Mal konvertiert werden muss.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Niki
Establishment
Beiträge: 309
Registriert: 01.01.2013, 21:52

Re: Unicode Strings

Beitrag von Niki »

BeRsErKeR hat geschrieben:Die Frage ist halt ob es dann noch sinnvoll ist plattformabhängige String-Typen außerhalb dieser Kapselung zu verwenden oder nur innerhalb der Kapselung verschiedene String-Typen zu nutzen und dann z.B. in und von std::wstring zu konvertieren, der dann von der Schnittstelle verwendet wird.
Das ist in der Tat eine gute Frage, und ich hoffe wir finden in diesem Thread eine möglichst schmerzlose Antwort auf genau jene Frage.
Benutzeravatar
Krishty
Establishment
Beiträge: 8267
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Unicode Strings

Beitrag von Krishty »

Die Antwort ist, dass das pure Idiotie wäre.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
BeRsErKeR
Establishment
Beiträge: 689
Registriert: 27.04.2002, 22:01

Re: Unicode Strings

Beitrag von BeRsErKeR »

Krishty hat geschrieben:
BeRsErKeR hat geschrieben:Genau das meine ich. Man nutzt plattformabhängige E/A-Funktionen wie CreateFile usw. Aber an irgendeiner Stelle werden die so gekapselt, dass man mit einer plattformunabhängigen Schnittstelle arbeiten kann. Sonst müsste man ja den halben Code mit #ifdefs bestücken.
Ja, äh, oder mit einem einzigen typedef für die Kodierung, die man auf der aktuellen Plattform einsetzen will und einem Makro, das String-Literalen diese Kodierung verpasst.

Kapselung und Plattformunabhängigkeit haben nichts, rein garnichts damit zu tun, auf allen Plattformen dieselbe Kodierung zu benutzen. Dadurch wird im Gegenteil alles saukompliziert weil ein String für jeden Rundgang durchs Programm tausend Mal konvertiert werden muss.

Naja eigentlich muss man nur konvertieren wenn man den String von der Plattform abholt oder ihr wieder übergeben will. Ansonsten kann man ja einfach mit std::wstring arbeiten ohne Konvertierungen. Ich weiß nicht ob man unbedingt plattformabhängige Strings braucht, wenn man sich in einem plattformunabhängigen Code-Bereich bewegt.

Davon abgesehen musst du eh irgendwo "konvertieren", da die OS-APIs mit char*, wchar_t* usw. arbeiten und nicht mit std::basic_string<char> usw.
Ohne Input kein Output.
Niki
Establishment
Beiträge: 309
Registriert: 01.01.2013, 21:52

Re: Unicode Strings

Beitrag von Niki »

Also zusammenfassend:

Krishty bevorzugt plattformabhängige Strings überall
Berserker bevorzugt plattformunabhängige Strings mit Konvertierung beim Aufruf von Systemfunktionen
Niki hat noch keine klare Meinung und versucht das Für und Wider abzuwägen, hat aber momentan eine leichte Tendenz zum plattformabhängigen String.

Warum habe ich diese Tendenz? Ein Grund ist, dass ich mindestens 16-Bit Zeichen erwarte. Gleichzeitig ist aber die Nutzung von Zeichen außerhalb der Basic Multilingual Plane nicht wirklich geplant. Da würde einem ja das Grauen mit Font-Texturen erwarten. Also bedeutet eine Konvertierung von UCS-32 nach UTF-16 für mich lediglich eine Typkonvertierung von uint32 nach uint16. Das ist verschmerzbar.
Zuletzt geändert von Niki am 13.04.2013, 17:32, insgesamt 2-mal geändert.
Niki
Establishment
Beiträge: 309
Registriert: 01.01.2013, 21:52

Re: Unicode Strings

Beitrag von Niki »

BeRsErKeR hat geschrieben:Davon abgesehen musst du eh irgendwo "konvertieren", da die OS-APIs mit char*, wchar_t* usw. arbeiten und nicht mit std::basic_string<char> usw.
std::basic_string<char>::c_str() gibt den null-terminierten String zurück. Ob das immer und überall so ist, das ist natürlich fraglich, aber ich glaube schon das das ein Standardverhalten ist.
Benutzeravatar
Krishty
Establishment
Beiträge: 8267
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Unicode Strings

Beitrag von Krishty »

Niki hat geschrieben:
BeRsErKeR hat geschrieben:Davon abgesehen musst du eh irgendwo "konvertieren", da die OS-APIs mit char*, wchar_t* usw. arbeiten und nicht mit std::basic_string<char> usw.
std::basic_string<char>::c_str() gibt den null-terminierten String zurück. Ob das immer und überall so ist, das ist natürlich fraglich, aber ich glaube schon das das ein Standardverhalten ist.
Ja; ab C++11 ist string immer nullterminiert und c_str() effektiv ein no-op.

Ich pflastere gerade ein Beispiel zusammen.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Antworten