Wie funktioniert RawByteString? (ab FPC 3.x)

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Benutzeravatar
theo
Beiträge: 10899
Registriert: Mo 11. Sep 2006, 19:01

Re: Wie funktioniert RawByteString? (ab FPC 3.x)

Beitrag von theo »

mschnell hat geschrieben: Tja. Im mement reißen sich die paar FPC Entwickler die Beine aus, um die fürchterlichen Strings von Delphi XE2 zu implementieren. Und Embarcadero schafft sie gerade wieder ab.
Keine Ahnung ob sich jemand die Beine ausreißt. Ändert aber nichts an der Aussage, dass man nicht jeden Sch....

Eine - meinetwegen inkompatible - Anpassung der RTL an Unicode wäre aber schon wünschenswert.
Einfach damit man man auch mal einen kyrillischen Dateinamen unter Windows öffnen kann mit bspw. StringList.LoadFromFile.

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

Re: Wie funktioniert RawByteString? (ab FPC 3.x)

Beitrag von mse »

Patito hat geschrieben: In Delphi versucht der Compiler ja irgendwie zu raten und so ein #17 wird schon mal gern stillschweigend
beim compilieren von der System-Codepage (des Rechners auf dem der Compiler läuft) nach UTF-16 konvertiert.
Diese Raterei funktioniert zwar anscheinend (zumindest halbwegs) (für gültige Text-Zeichen).
Bei RawByteStrings wird es aber glaube ich schwieriger da etwas zu raten.
In FPC ist es noch etwas lustiger, da ändert eine Konstante 'abcdeäüö' die Bedeutung, falls noch + #1092#1080#1089#1074 angehängt wird.
http://www.mail-archive.com/fpc-devel%4 ... 27860.html
Und wenn in der Zwischenzeit nichts geändert wurde, sind RawByteString Variablen nicht möglich, lediglich Parameter sind erlaubt - AFAIK auch in Delphi.

Korrektur: Das scheint nicht zu stimmen:
http://docwiki.embarcadero.com/Librarie ... ByteString
Zuletzt geändert von mse am Mo 24. Jun 2013, 18:30, insgesamt 1-mal geändert.

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

Re: Wie funktioniert RawByteString? (ab FPC 3.x)

Beitrag von mse »

mschnell hat geschrieben: Tja. Im mement reißen sich die paar FPC Entwickler die Beine aus, um die fürchterlichen Strings von Delphi XE2 zu implementieren. Und Embarcadero schafft sie gerade wieder ab.
Das war schon vor Jahren abzusehen. Ich habe verschiedentlich lautstark und erfolglos darauf hingewiesen. Die Abkündigung gilt momentan auch nur für den Delphi "nextgen compiler".

Patito
Beiträge: 203
Registriert: Di 22. Sep 2009, 13:08
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit

Re: Wie funktioniert RawByteString? (ab FPC 3.x)

Beitrag von Patito »

mschnell hat geschrieben:
theo hat geschrieben:Wen interessiert's? Man muss ja nicht jeden Schei* mitmachen.
Tja. Im mement reißen sich die paar FPC Entwickler die Beine aus, um die fürchterlichen Strings von Delphi XE2 zu implementieren. Und Embarcadero schafft sie gerade wieder ab.

Ziemlich schräg.

-Michael
Mal schauen ob es so fürchterlich wird. Ein Problem von Delphi war, dass RawByteStrings einfach nicht richtig funktioniert haben.
Zuerst gab es glaube ich nur array of Bytes (keine String-Funktionen verfügbar), und dann war der RawByteString nicht mal kompatibel mit string
(Konvertierung zu UTF-16 wenn man ihn einem String zugewiesen hat). Schrott eben.

Ich habe mir die Sache bei FPC leider noch nicht gründlich angeschaut. Ich bin mal Zweck-Optimistisch (...und schreibe vorsichtshalber mal
an meinem Pascal-Parser weiter...).

Kriegt man sowas wirklich noch nicht hin(?!?)
Test = 'ABC' + #17 + #2 + 'ÄÖÜ' + 'ÄÖÜ'(UTF16_BE) + 'ÄÖÜ'(UTF8);
(Ich hätte sowas dann natürlich gerne ohne Typecasts von Konstanten in irgendwelche Zwischen-Strings).

Wäre eine Kurz-Syntax zur Typisierung von String-Konstanten (ohne explizite Typecasts) eine schlechte Idee?

MmVisual
Beiträge: 1581
Registriert: Fr 10. Okt 2008, 23:54
OS, Lazarus, FPC: Winuxarm (L 4 FPC 3.2.2)
CPU-Target: 32/64Bit

Re: Wie funktioniert RawByteString? (ab FPC 3.x)

Beitrag von MmVisual »

mschnell hat geschrieben:Tja. Im mement reißen sich die paar FPC Entwickler die Beine aus, um die fürchterlichen Strings von Delphi XE2 zu implementieren. Und Embarcadero schafft sie gerade wieder ab.
Alles was bisher hier diskutiert wird zeigt immer noch keine besser Lösung für das String Problem als die, die ich gezeigt habe. Nach wie vor bin ich der Meinung, dass mein Lösungsansatz für die Stringimplementierung die einzig zukunftssichere ist und man wäre damit in jedem Fall kompatibel zu allen Delphi-Versionen, egal was die nun wieder für eine neue Suppe ausbrüten. Der Konstrukt TUniString von Theo und meine Erweiterung sind einfach nur genial und super einfach für den User!
EleLa - Elektronik Lagerverwaltung - www.elela.de

Socke
Lazarusforum e. V.
Beiträge: 3178
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: Wie funktioniert RawByteString? (ab FPC 3.x)

Beitrag von Socke »

Patito hat geschrieben:Kriegt man sowas wirklich noch nicht hin(?!?)
Test = 'ABC' + #17 + #2 + 'ÄÖÜ' + 'ÄÖÜ'(UTF16_BE) + 'ÄÖÜ'(UTF8);
(Ich hätte sowas dann natürlich gerne ohne Typecasts von Konstanten in irgendwelche Zwischen-Strings).

Wäre eine Kurz-Syntax zur Typisierung von String-Konstanten (ohne explizite Typecasts) eine schlechte Idee?
Wie bekommst du denn so etwas in eine Quelltextdatei? Ich kenne keinen Editor, der mehre Zeichencodierungen in einer Datei bearbeiten kann.

Zur Typisierung von Konstanten verwendet man in Pascal immer Typecasts. Damit kann man einen bestimmten Datentypen für Zahlen erzwingen oder Records und Arrays definieren. Warum sollte das für Strings anders sein? Bei einer funktionsfähigen Multiencoding-Implementierung kann der Compiler einen Quelltext-codierungsabhängigen Typen automatisch auswählen, falls keiner angegeben ist.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

MmVisual
Beiträge: 1581
Registriert: Fr 10. Okt 2008, 23:54
OS, Lazarus, FPC: Winuxarm (L 4 FPC 3.2.2)
CPU-Target: 32/64Bit

Re: Wie funktioniert RawByteString? (ab FPC 3.x)

Beitrag von MmVisual »

Genau dieses Problem löst mein Vorschlag, ganz von alleine und voll automatisch: http://www.lazarusforum.de/viewtopic.php?p=62307#p62307
EleLa - Elektronik Lagerverwaltung - www.elela.de

Socke
Lazarusforum e. V.
Beiträge: 3178
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: Wie funktioniert RawByteString? (ab FPC 3.x)

Beitrag von Socke »

MmVisual hat geschrieben:Genau dieses Problem löst mein Vorschlag, ganz von alleine und voll automatisch: http://www.lazarusforum.de/viewtopic.php?p=62307#p62307
Welches Problem?! Jetzt habe ich etwas nicht mitbekommen.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

MmVisual
Beiträge: 1581
Registriert: Fr 10. Okt 2008, 23:54
OS, Lazarus, FPC: Winuxarm (L 4 FPC 3.2.2)
CPU-Target: 32/64Bit

Re: Wie funktioniert RawByteString? (ab FPC 3.x)

Beitrag von MmVisual »

Das addieren/bearbeiten von Strings unterschiedlicher Codierungen.
EleLa - Elektronik Lagerverwaltung - www.elela.de

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: Wie funktioniert RawByteString? (ab FPC 3.x)

Beitrag von mschnell »

Socke hat geschrieben:Zur Typisierung von Konstanten verwendet man in Pascal immer Typecasts.
Tpycast ist die Umwandlung eines Wertes in einen anderen Tpy.

Bei String constanten weiß des Compiler erst gar nicht, was mit den Bytes aus der Quelldatei gemeint ist. Es muss also wohl eine andere Syntax her.

-Michael

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: Wie funktioniert RawByteString? (ab FPC 3.x)

Beitrag von mschnell »

Die scheinen ja selbst nicht zu wissen, wie RawByteString funktioniert. Zumindest wird nicht beschrieben was passiert, wenn man einer "normalen" Stringvariable einen RawByteString zuordnet.

Wenn RawByteString wirklich dazu gedacht ist, beliebige Stringtypen ohne Konvertierung (als Parameter) aufzunehmen, sollte bei der Zuordnung eines RawByteString auf einen normalen String eine automatische Typumwandlung erfolgen, falls der dynamische Typ im RawByteString nicht schon stimmt.

Das wäre ziemlich sinnvoll und allgemeingültige Objekte wie TStringList sollten dann RawByteString aufnehmen, damit im Normalfall nicht konvertiert wird, egal mit welcher Kodierung der User (durchgängig) arbeitet.

-Michael

Socke
Lazarusforum e. V.
Beiträge: 3178
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: Wie funktioniert RawByteString? (ab FPC 3.x)

Beitrag von Socke »

mschnell hat geschrieben:
Die scheinen ja selbst nicht zu wissen, wie RawByteString funktioniert. Zumindest wird nicht beschrieben was passiert, wenn man einer "normalen" Stringvariable einen RawByteString zuordnet.

Wenn RawByteString wirklich dazu gedacht ist, beliebige Stringtypen ohne Konvertierung (als Parameter) aufzunehmen, sollte bei der Zuordnung eines RawByteString auf einen normalen String eine automatische Typumwandlung erfolgen, falls der dynamische Typ im RawByteString nicht schon stimmt.
Diese Definition ist auch gar nicht so einfach. Wie unten geschrieben, muss der Entwickler festlegen, was passieren soll.

Wenn ich in einem RawByteString einen Wert gespeichert habe, wie kann ich ihn dann an einen Typen mit fester Kodierung zuweisen? Es gibt zwei Möglichkeiten: 1. Der Wert wird als korrekt kodiert interpretiert und einfach übernommen. 2. Der Wert wird als nicht korrekt kodiert interpretiert und von einer (nicht) festgelegten Kodierung in die Zielkodierung umkodiert.

Szenario 1: Latin1-String -> RawByteString -> UTF-16-String; Im UTF-16-String sind ungültige Daten enthalten
Szenario 2: Latin5-String -> RawByteString -> UTF-16-String; Durch Compiler-Magic wurde erraten, dass der RawByteString eigentlich eine Latin1-/Laufzeit-/Übersetzungssystem-Kodierung (was denn jetzt?!) hatte; Im UTF-16-String sind zwar gültige Zeichen enthalten, diese stimmen aber nicht mit denen aus dem Ursprung überein.

Damit wäre gezeigt, dass die Anforderung, Strings in RawByteString abzulegen vollkommener Unsinn ist. Die einzige Berechtigung hat der Datentyp bei der Dateieingabe, aber auch hier nur, wenn die Kodierung unbekannt ist.

Datei -> RawByteString -> Heuristiken -> UTF-16-String
Hier muss durch Heuristiken (Metadaten, BOM, spezifische Eigenschaften einer Kodierung etc.) festgestellt werden, welche Kodierung wahrscheinlich verwendet wird. Besser wäre ein "UnkownEncodingString", mit dem klar ist, dass eine Heuristik angewendet wird. Ohne Heuristiken sind wir bei den undefinierten Ergebnissen wie oben gezeigt.

Ist die Kodierung bekannt, gibt es kein Problem (Bspw: Datei ist in UTF-8 kodiert):
Datei -> UTF-8-String

Meine Schlussfolgerung:
Der Typ RawByteString ist an sich vollkommen unnötig. Wenn die Kodierung unbekannt ist, werden die Daten als ASCII (Single-Byte, ein Codepoint ist maximal 1 Byte groß) geladen und mit Heuristiken entschieden, wie sie weiterverarbeitet werden.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: Wie funktioniert RawByteString? (ab FPC 3.x)

Beitrag von mschnell »

Socke hat geschrieben:Der Typ RawByteString ist an sich vollkommen unnötig.
Laut der obigen Beschreibung soll RawByteString als Parameter verwendet werden und es findet dann keine Umcodierung bei der Zuordnung (z.B. Funktionsaufruf) statt.

Der Typ des Strings wird aber (vermutlich) im RawByte String abgespeichert (der dann vermutlich "dynamisch" nicht mehr den Code-Typ $FFFF hat, unter dem der Compiler ihn führt.) Wenn man den String dann auf eine andere Variable zuordnet kann die Library den aktuellen dynamischen Typ erkennen und eine Umcodierung durchführen, wenn die Zielvariable einen anderen Codierungs-Typ hat, oder eben nicht, wenn die Codierung schon stimmt. (Offensichtlich braucht der String-Inhalt nicht kopiert werden, wenn ein String auf einen RawByteString zugeordnet wird oder ein RawByteString auf einen "normalen" String und der dynamische Kodierungstyp übereinstimmt.)

Das finde ich außerordentlich sinnvoll (ist aber anscheinend nirgendwo ernsthaft beschrieben).

Leider kann ich es auch nicht ausprobieren, weil ich keine Unicode Delphi Version habe.
Socke hat geschrieben:Wenn die Kodierung unbekannt ist, werden die Daten als ASCII (Single-Byte, ein Codepoint ist maximal 1 Byte groß) geladen und mit Heuristiken entschieden, wie sie weiterverarbeitet werden.
Heuristik braucht man nicht: der Codierungstpy und die Länge der einzelnen Codes (1, 2 oder 4 Byte) steht (neben Referenz-Zähler, Länge und Pointer auf den String-Inhalt) im Verwaltungs-Record des Strings.

Ein Heuristik-Problem gibt es nur bei String-Konstanten, wo der Compiler raten muss was der User mit seiner #1234 Notation meint

-Michael
Zuletzt geändert von mschnell am Di 25. Jun 2013, 12:49, insgesamt 1-mal geändert.

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

Re: Wie funktioniert RawByteString? (ab FPC 3.x)

Beitrag von mse »

mschnell hat geschrieben: Ein Heuristik-Problem gibt es nur bei String-Konstanten, wo der Compiler raten muss was der User mit seiner #1234 Notation meint
Delphi interpretiert #nnn immer als Unicode 16bit code unit, FPC je nach dem ob im string kein Zeichen grösser als 255 vorkommt auch als 8bit code unit, in welcher Codierung ist mir nicht klar.

EgonHugeist
Beiträge: 93
Registriert: Di 17. Apr 2012, 22:41

Re: Wie funktioniert RawByteString? (ab FPC 3.x)

Beitrag von EgonHugeist »

Hallo zusammen,

MMVisual hatte mir geschrieben...


Nun scheint mir hier große Verwirrung zu herschen?!

Nochmal zitiert:
const
CP_ACP = 0; // default to ANSI code page
CP_UTF16 = 1200; // utf-16
CP_UTF16BE = 1201; // unicodeFFFE
CP_UTF7 = 65000; // utf-7
CP_UTF8 = 65001; // utf-8
CP_ASCII = 20127; // us-ascii
CP_NONE = $FFFF; // rawbytestring encoding
das ist vollkomment richtig.

Um eines vorn weg zu nehmen der Typ RawByteString ist unabdingbar!

Eigentlich ist hier nur folgendes Problem zu sehen:

FPC und LCL gehen zwei verschiedene Wege. LCL hat alles auf UTF8 encodierung umgestellt welches der FPC jedoch nicht weiter verfolgt, sonst würden sie den Delphi-Compilern nicht hinterher kommen.

Um die Compiler-Magig vom FPC2.7.x & D2009+ etwas aufzuklären
String(GetACP) := AnsiString(GET_ACP, AnsiDaten)+UTFString(CP_UTF8, UTF8-Daten) sollte vollgendes durchführen:
String_Daten := AnsiDaten + WideToAnsiMove(UTF8ToWideMove(UTF8Daten)); somit ist Data-Loss möglich

AUTF8String_Daten := AnsiString(GET_ACP, AnsiDaten)+UTFString(CP_UTF8, UTF8-Daten) sollte vollgendes durchführen:
AUTF8String_Daten := WideToUTF8(AnsiToWide(AnsiDaten)) + UTFDaten; //Data-loss ist nicht möglich, da UTF8 Encodierung.

RawByteString_Daten := AnsiDaten + UTF8Daten; ohne konvertierung. Sicheres konvertien zu Unicode/Ansi/UTF8 ist nicht mehr möglich, da ein CP-"Mischmasch" vom Progger veranlaßt wurde!

Weiterhin gilt zu sagen, das Delphi ein begrenztes Tracking für den Ursprung der Daten vornimmt:

RawByteString := AnsiString/UTF8String; //bei direkter zuweisung weiß der compiler die (Get_ACP) codepage und kann danch den Rawbyte string sicher zu UTF8 oder Unicode oder Ansi konvertieren.
Das Tracking endet bei Delphi mit PAnsiChar Zuweisungen, move-mem, oder CodePage-Mischungen (RawByteString_Daten := AnsiDaten + UTF8Daten;)

Beim FPC derzeit noch nicht(mein Stand ist hier ein halbes Jahr alt, also nich hauen, wenn ich mich irre). Aber ihr könnt doch die String-CodePage selber setzen: DefaultSystemCodpe := CP_UTF8; Tata! (Sollte LCL eigentlich selber tun)

Das ganze Konstruckt dient aber eher dem UnicodeString(Compiler -> schnell)/WideString(COM-based, Global heap und langsam) und deren Casts wie folgt:

AnsiString(UnicodeString) = AAnsiString := WideToAnsiMove(UnicodeString) mit Ansi-codePage
UTF8String(UnicodeString) = AUtf8String := WideToAnsiMove(UnicodeString) mit UTF8-CodePage

Ein RBS cast nutzet die DefaultSystemCodePage..

Zusammenfassend:

Der RawByteString ist ein single-byte Allesfresser, welcher den Compiler automatisierten Convertierungen aus dem weg geht. Unabdingbar und hilfreich, wenn man z.B. Datenbank Anwendung schreibt, der Encodierung wechseln kann. Der Developer sollte hier aber wirklich sorgfälltig arbeiten und wissen, was er tut! Die Zeos Interna ist deher vollständig auf RBS umgesetzt, sonst könnten wir automatisierte convertieungen für MSSQL + LCL z.B. nicht lösen und würden in die Automatisierten compiler Konvertierungen, je nach DefaultSystemCodePage, rennen.

In custring.inc findet ihr die AnsiToWide/AnsiToUnicode und WideToAnsi/UnicodeToAnsi Routinen, welche !immer! (auch bei Delphi) benützt werden, wenn ihr Wide/Unicode casts oder Ansi-CodePages mischt (je nach Ergebnis-Typ). Wie sonst sollte der Compiler die 2Byte Chars auf Single-Byte umstellen können? Oder Ansi Codierungen auf UTF8 automatisch umstellen?

Michael

P.S.
Nun ist die Topic (ab FPC3.x) markiert. Davon weis ich auch. Ich kann mir vorstellen, daß bei einem neuen Major-Realease, der FPC auch auf Unicode ausetzt. Leider gibt es da noch keine eindeutigen Aussagen von FPC-core. Mich würde das jedoch nicht wundern. Nur was ist dann mit LCL? Im Prinzip ist der Nabel der Probleme, das LCL IMMER von String(cp_utf8) ausgeht(was eigentlich total daneben ist, aber alles universal macht), der FPC dem jedoch nicht Folge leistet und seine eigenen Wege geht. All das schafft Verwirrung, wenn euer Code nicht eindeutig ist, das sollten die oben genannten Bsp. zeigen können.
ZeosDevTeam

Antworten