Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Software-Projekte der Mitglieder (https://www.delphipraxis.net/26-software-projekte-der-mitglieder/)
-   -   Set of WideChar (TDynamicCharSet) (https://www.delphipraxis.net/144528-set-widechar-tdynamiccharset.html)

himitsu 9. Dez 2009 22:40


Set of WideChar (TDynamicCharSet)
 
Liste der Anhänge anzeigen (Anzahl: 1)
So, ich hab mir heute mal ein WideChar-Set zusammengebastelt,
da ja die normalen Sets nicht mit Unicode arbeiten.

Ja, ich kenn IWidecharSet von Peter Below (http://www.delphipraxis.net/internal....php?p=1006898),
allerdings hab ich damit ein kleines Problem. Hauptsächlich, daß dieses immer mehr als 8 KB pro Set belegt
und ich für ein Projekt mehrere/viele Sets benötige.

Also ist ein "Set" mit dynamischer Speicherverwaltung entstanden.
Dieses belegt pro "Set" jeweils etwa 8 Byte bis 8,02 KB, zuzüglich einem Standardencoding für's Ansi, wenn man eines angibt und dank der Referenzzählung bei dynamischen Arrays und Interfaces wird beim Kopieren sowieso nochmal Speicher eingespart.

Zusätzlich wurde es als Operator-Record ausgelegt, anstatt als Objekt/Interface:
Welche den Vorteil hat, daß es grundsätzlich fast wie ein "normales" (Ansi)CharSet verwendbar ist.

> Leider stellen die Operatoren keinen IN-Operator zur Verfügung. :?

Aber abgesehn von IN und den Functionen Include und Exclude (welche sich aber leicht zusammenstellen lassen) wird alles Mögliche unterstützt.
Die Operatoren + - und *, sowie die Vergleichsoperatoren < <= = >= > <> und zusätzlich noch OR, AND, XOR und NOT.
Nja, und dann gibt es noch einige weitere Befehle und Typumwandlungen...

Inzwischen wurde auch ein Enumerator verbaut, so daß For-In-Schleifen genutzt werden können.
Delphi-Quellcode:
Var C: Char;
For C in HexNumerals do S := S + C;
// S = '0123456789ABCDEFabcdef'
// da HexNumerals = ['0'..'9', 'A'..'F', 'a'..'f']
Delphi-Quellcode:
// Achtung: dieser Code wurde einen wesentlichen/wichtigen Anteil reduziert

TSetRelation   = (srEqual, srIsSubset, srIsSuperset, srOverlap, srDisjunct);

TDynamicCharSet = Record
Private
  _Map:     TDCSDynMap;
  _Encoding: TEncoding;
Public
  Property DefaultEncoding: TEncoding;
  Procedure Fill(CharSet:    TSysCharSet; Encoding: TEncoding);
  Procedure Fill(CharSet:    TDynamicCharSet);
  Procedure Fill(CharSet:    TDCSMap);
  Procedure Fill(Char:       AnsiChar;   Encoding: TEncoding);
  Procedure Fill(Char:       WideChar);
  Procedure Fill(First, Last: AnsiChar;   Encoding: TEncoding);
  Procedure Fill(First, Last: WideChar);
  Procedure Fill(S: RawByteString; Encoding: TEncoding; AllowCharGroups: Boolean);
  Procedure Fill(S: UTF8String;                        AllowCharGroups: Boolean);
  Procedure Fill(S: UnicodeString;                     AllowCharGroups: Boolean);
  Procedure FillAll;
  Procedure Invert;
  Procedure Clear;

  Function IsEmpty:   Boolean;
  Function IsFull:    Boolean;
  Function LowChar:   WideChar;
  Function HighChar:  WideChar;
  Function CountChars: Integer;

  Function GetAsSysCharSet(Encoding: TEncoding): TSysCharSet;
  Function GetAsMap:                            TDCSMap;
  Function GetAsAnsiString(Encoding: TEncoding): RawByteString;
  Function GetAsUTF8String:                     UTF8String;
  Function GetAsString:                         UnicodeString;
  Function GetAllChars:                         UnicodeString;

  Function ContainsAnyChar     (S: RawByteString; Encoding: TEncoding): Boolean;
  Function ContainsAnyChar     (S: UTF8String):                        Boolean;
  Function ContainsAnyChar     (S: UnicodeString):                     Boolean;
  Function ContainsAllChars    (S: RawByteString; Encoding: TEncoding): Boolean;
  Function ContainsAllChars    (S: UTF8String):                        Boolean;
  Function ContainsAllChars    (S: UnicodeString):                     Boolean;
  Function ContainsOnlyThisChars(S: RawByteString; Encoding: TEncoding): Boolean;
  Function ContainsOnlyThisChars(S: UTF8String):                        Boolean;
  Function ContainsOnlyThisChars(S: UnicodeString):                     Boolean;

  Function Compare (CharSet:    TSysCharSet;  Encoding: TEncoding): TSetRelation;
  Function Compare (CharSet:    TDynamicCharSet):                   TSetRelation;
  Function Contains(Char:       AnsiChar;     Encoding: TEncoding): Boolean;
  Function Contains(Char:       WideChar):                          Boolean;
  Function Compare (First, Last: AnsiChar;     Encoding: TEncoding): TSetRelation;
  Function Compare (First, Last: WideChar):                          TSetRelation;
  Function Compare (S:          RawByteString; Encoding: TEncoding): TSetRelation;
  Function Compare (S:          UTF8String):                        TSetRelation;
  Function Compare (S:          UnicodeString):                     TSetRelation;
  Procedure Include (CharSet:    TSysCharSet;  Encoding: TEncoding);
  Procedure Include (CharSet:    TDynamicCharSet);
  Procedure Include (Char:       AnsiChar;     Encoding: TEncoding);
  Procedure Include (Char:       WideChar);
  Procedure Include (First, Last: AnsiChar;     Encoding: TEncoding);
  Procedure Include (First, Last: WideChar);
  Procedure Include (S:          RawByteString; Encoding: TEncoding);
  Procedure Include (S:          UTF8String);
  Procedure Include (S:          UnicodeString);
  Procedure Exclude (CharSet:    TSysCharSet;  Encoding: TEncoding);
  ...
  Procedure Exclude   (S:       UnicodeString);
  Procedure Intersect (CharSet: TSysCharSet;  Encoding: TEncoding);
  ...
  Procedure Intersect (S:       UnicodeString);
  Procedure ExclusiveOr(CharSet: TSysCharSet;  Encoding: TEncoding);
  ...
  Procedure ExclusiveOr(S:       UnicodeString);

  Function GetEnumerator: TDCSEnumerator;
Public
  Class Operator Implicit(CharSet: TSysCharSet):  TDynamicCharSet;
  Class Operator Implicit(CharSet: TDCSMap):      TDynamicCharSet;
  Class Operator Implicit(S:      RawByteString): TDynamicCharSet;
  Class Operator Implicit(S:      UTF8String):   TDynamicCharSet;
  Class Operator Implicit(S:      UnicodeString): TDynamicCharSet;

  Class Operator Explicit(CharSet: TSysCharSet):  TDynamicCharSet;
  Class Operator Explicit(CharSet: TDCSMap):      TDynamicCharSet;
  Class Operator Explicit(S:      RawByteString): TDynamicCharSet;
  Class Operator Explicit(S:      UTF8String):   TDynamicCharSet;
  Class Operator Explicit(S:      WideString):   TDynamicCharSet;
  Class Operator Explicit(S:      UnicodeString): TDynamicCharSet;

  Class Operator Explicit(CharSet: TDynamicCharSet): TSysCharSet;
  Class Operator Explicit(CharSet: TDynamicCharSet): TDCSMap;
  Class Operator Explicit(CharSet: TDynamicCharSet): RawByteString;
  Class Operator Explicit(CharSet: TDynamicCharSet): UTF8String;
  Class Operator Explicit(CharSet: TDynamicCharSet): WideString;
  Class Operator Explicit(CharSet: TDynamicCharSet): UnicodeString;

  Class Operator Equal            (Oper1, Oper2: TDynamicCharSet): Boolean;
  Class Operator NotEqual         (Oper1, Oper2: TDynamicCharSet): Boolean;
  Class Operator LessThan         (Oper1, Oper2: TDynamicCharSet): Boolean;
  Class Operator LessThanOrEqual  (Oper1, Oper2: TDynamicCharSet): Boolean;
  Class Operator GreaterThan      (Oper1, Oper2: TDynamicCharSet): Boolean;
  Class Operator GreaterThanOrEqual(Oper1, Oper2: TDynamicCharSet): Boolean;

  Class Operator Add      (Oper1, Oper2: TDynamicCharSet): TDynamicCharSet;
  Class Operator Subtract (Oper1, Oper2: TDynamicCharSet): TDynamicCharSet;
  Class Operator Multiply (Oper1, Oper2: TDynamicCharSet): TDynamicCharSet;
  Class Operator BitwiseAnd(Oper1, Oper2: TDynamicCharSet): TDynamicCharSet;
  Class Operator BitwiseOr (Oper1, Oper2: TDynamicCharSet): TDynamicCharSet;
  Class Operator BitwiseXor(Oper1, Oper2: TDynamicCharSet): TDynamicCharSet;
  Class Operator LogicalNot(CharSet:     TDynamicCharSet): TDynamicCharSet;
End;

Const Signs:           TDynamicCharSet = (); // ['-', '+']
  DecimalDigits:       TDynamicCharSet = (); // ['0'..'9']
  Numbers:             TDynamicCharSet = (); // Signs + DecimalDigits
  FloatChars:          TDynamicCharSet = (); // Numbers + [DecimalSeparator]
  SciFloatChars:       TDynamicCharSet = (); // FloatChars + ['e', 'E']
  OctalNumerals:       TDynamicCharSet = (); // ['0'..'7']
  HexNumerals:         TDynamicCharSet = (); // ['0'..'9', 'A'..'F', 'a'..'f']
  FirstIdentifierChars: TDynamicCharSet = (); // ['A'..'Z', 'a'..'z', '_']
  IdentifierChars:     TDynamicCharSet = (); // ['A'..'Z', 'a'..'z', '0'..'9', '_']
  EditOperations:      TDynamicCharSet = (); // [^C, ^V, ^X, Backspace]
  AsciiControlChars:   TDynamicCharSet = (); // [#0..#31, #127]
  AsciiChars:          TDynamicCharSet = (); // [#0..#127]
  AsciiTextChars:      TDynamicCharSet = (); // [Tab, LF, CR, Space..#127]

  // The following constants are dependent on the existing unicode system of the OS.
  ControlChars:        TDynamicCharSet = (); // [#1..#$1F, #$7F..#$9F, #$70F and other]
  BlankChars:          TDynamicCharSet = (); // [#9, ' ', #160, #$3000, #$FEFF]
  SpaceChars:          TDynamicCharSet = (); // [#9..#$D, ' ', #$85 and other]
  Digits:              TDynamicCharSet = (); // '0123456789¹²³' and other digit chars
  HexDigits:           TDynamicCharSet = (); // HexNumerals + Bold:HexNumerals
  Numeric:             TDynamicCharSet = (); // copy of "Digits"
  Letters:             TDynamicCharSet = (); // LowerCaseLetters + UpperCaseLetters
  LowerCaseLetters:    TDynamicCharSet = (); // all lowercase characters
  UpperCaseLetters:    TDynamicCharSet = (); // all uppercase characters
  Alpha:               TDynamicCharSet = (); // any linguistic character
  AlphaNum:            TDynamicCharSet = (); // Alpha + Digits
  NonAlphaNum:         TDynamicCharSet = (); // AllChars - AlphaNum
  Punctuation:         TDynamicCharSet = (); // '!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~' and other
  Printable:           TDynamicCharSet = (); // graphic characters and blanks
  AllChars:            TDynamicCharSet = (); // Printable + ControlChars
Das Ganze setzt natürlich mindenstens Delphi 2009 voraus,
aber notfalls könnte man es auch unter Delphi 2006, 2007, sowie Turbo Delphi zu laufen bekommen.

PS: nicht über meine Konstanten wundern ... nach außen Konstante und nach innen nicht, da es doch typisierte Konstanten sind, welche in Delphi ja eh keine "echten" Konstanten sind. :angel2:

Und wenn falls es wer mal braucht, dann ließe sich bestimmt auch noch ein "Set of Integer" erstellen, mit einer zusätzlichen dynamischen Untergrenze, allerdings sollten dann die Werte nicht all zu "weit" auseinander liegen, wobei es auch dafür eine Lösung gäbe ... also mehrere Wertebereiche/Sets in Einem.

Jetzt aber noch ein Problem
Und zwar scheint es irgendwo einen Bufferoverrun oder Dergleichen zu geben. :cry:
Schon bei der Initialisierung der Konstanten kommt es offiziell zu einem OutOfMemory (in D2009+),
welches allerdings davon stammt, daß der Speichermanager (FastMM) defekte Verwaltungsdaten so anzeigt.
(hab über 'ne Strunde nach dem Speicherleck gesucht und mich gleichzeitig gewundert, warum der Taskmanager meint es wäre noch genügend frei)

Es wäre also schön, wenn da noch mit jemand reingucken könnte und mir eventuell einen Tipp gibt.
Bin den Code jetzt schon mehrmals nochmal komplett durchgegangen und konnte keinen noch Fehler finden, welcher dafür verantwortlich sein könnte. :?


[edit]
Grad gemerkt, daß hier die Bereichsprüfung nicht aktiv war (dabei hatte ich es doch in den Optionen aktiviert :shock: )
na mal sehn, was sich jetzt findet.

[edit 10.12.2009 v1.1]
Was so ein kleines -1 alles ausrichten kann, :wall:
aber nun gibt es schonmal keine Exceptions mehr. :-D
Jetzt kann ich endlich gucken, ob es auch wirklich so arbeitet, wie geplant.

[edit 13.01.2010 v1.2]
das Problem mit dem nichtinitialisiertem Standardencoding ( Beitrag #3 bis #6 ) wurde behoben

[add 10.02.2010 v1.3]
kleinere Erweiterungen und Änderungen an den Konstanten ... siehe Beitrag #7
sowie Fehlerbereinigung und hinzugefügter Enumerator ... siehe Beitrag #8

[edit 11.02.2010 v1.4]
Eingangspost überarbeitet und kleine Neuerungen hinzugefügt ... siehe letzes Edit in Beitrag #8

[edit 12.02.2010 v1.5]
schonwieder was Neues > siehe Beitrag #9

[edit 13.02.2010 v1.6]
'nen kleinen Fehler ausgebesserst, welcher bei einem Fill das DefaultEncoding nicht richtig übernahm und so zu einer Exception führte.
Auserdem wurde .FullClear und .ReadOnly eingefügt.
Leider wird der ReadOnly-Status mitkopiert, wenn man ein SET per := kopiert.

[edit 13.02.2010 v1.7]
Fehlerbeseitigung (siehe #15)

[edit 08.04.2010 v1.8]
restliche Fehler beseitigt ... alle neuen Prüfungen meinen jetzt es sei alles OK


[edit 33.04.2010 v2.2]
Ups, hab grade gemerkt, daß ich die Fehlerbeseitigung dieses saublöden Compilerfehlers
http://qc.embarcadero.com/wc/qcmain.aspx?d=44634
http://www.delphipraxis.net/internal...t.php?t=176345
noch nicht hochgeladen hatte. :oops:

himitsu 8. Jan 2010 21:49

Re: Set of WideChar (TDynamicCharSet)
 
Da es grade eine Frage zur Speicherverwaltung gab:
Zitat:

Zitat von kroimon
müssten die impliziten und expliziten Casts nicht eine neue TDynamicCharSet Instanz zurückgeben, statt sie zur aktuellen Instanz (die nicht unbedingt existiert) hinzuzufügen?

Nee, muß man nicht, denn hier wird ja nicht mit Instanzen/Objekten gearbeitet, sondern mit Records und da hat Delphi den Speicher netter Weise schon resserviert.

Es muß hier also nichts an Speicher, bzw. Instanzen reserviert, erstellt oder freigegeben werden. :angel:

und im Prinzip geht auch sowas:
Delphi-Quellcode:
if TDynamicCharSet(['#', '$']).Contains('a') then
  beep;
if TDynamicCharSet('#$a..z&#26787;&#20799;&#26760;&#26821;&#26827;&#13063;').Contains('a') then
  beep;

kroimon 8. Jan 2010 23:41

Re: Set of WideChar (TDynamicCharSet)
 
Zur Speicherverwaltung: Ah ja, hatte übersehen, dass du ja mit records arbeitest :)

Zitat:

Zitat von himitsu
und im Prinzip geht auch sowas:
Delphi-Quellcode:
if TDynamicCharSet(['#', '$']).Contains('a') then
  beep;
if TDynamicCharSet('#$a..z&#26787;&#20799;&#26760;&#26821;&#26827;&#13063;').Contains('a') then
  beep;

Hm, ja leider eben nicht...
Delphi 2010. Neues VCL-Projekt. TButton hinzugefügt. OnClick:
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
begin
  TDynamicCharSet(['#', '$']).Contains('$');
end;
Start. Button drücken. Freuen:
Code:
Im Projekt Project1.exe ist eine Exception der Klasse EAccessViolation mit der Meldung 'Zugriffsverletzung bei Adresse 00418441 in Modul 'Project1.exe'. Lesen von Adresse 0574C08C' aufgetreten.

Stack-Trace:
DynSet.TDynamicCharSet.Fill('#$', nil)
DynSet.TDynamicCharSet.Fill(['#'..'$'], nil)
DynSet.TDynamicCharSet.&op_Explicit(['#'..'$'])
Unit1.TForm1.Button1Click(???)
Bis TDynamicCharSet.Fill(Const S: RawByteString; Encoding: TEncoding = nil) geht also alles gut.
Dort wird dann CheckEncode(nil) aufgerufen, wobei Encoding auf _Encoding gesetzt wird, was hier merkwürdigerweise nicht genullt ist, sondern zufällige Werte beinhaltet: (FIsSingleByte:True; FMaxCharSize:1589654467)
Die nächste Zeile (229) crasht dann erwartungsgemäß.

Scheinbar wird bei diesem expliziten Cast das Record nicht mit Nullen gefüllt :shock:
Edit: grade nochmal im Debugger überprüft: Beim Aufruf von &op_Explicit ist Result._Encoding schon direkt zu Beginn nicht nil, sondern mit (FIsSingleByte:True; FMaxCharSize:1589654467) gefüllt...

Könnte das noch jemand unter Delphi 2010 testen und bestätigen bitte?

himitsu 9. Jan 2010 09:12

Re: Set of WideChar (TDynamicCharSet)
 
Hmmm, also in D2009 geht es ... werd' es nächte Woche mal im D2010 probieren (hab's grad nich dabei)

kroimon 9. Jan 2010 10:07

Re: Set of WideChar (TDynamicCharSet)
 
:shock:
Ich hab grade festgestellt, dass das _Encoding-Feld überhaupt nicht :!: initialisiert wird!
Selbst solch ein Code:
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var cs: TDynamicCharSet;
begin
  cs := 'ab';

  if cs.Contains('a') then
    Beep;
end;
zeigt beim Ausführen mit dem Debugger, dass cs nach der Zuweisung Müll in _Encoding stehen hat:
Code:
(FIsSingleByte:True; FMaxCharSize:1589654467)
Daher endet es auch wieder in einer AV, wenn ich die Zuweisung in ein
Delphi-Quellcode:
cs := ['a', 'b'];
ändere.

Also irgendwas scheint da schief zu laufen :wall:

Wär mal jemand mit D2010 so freundlich? :zwinker:

himitsu 16. Jan 2010 19:09

Re: Set of WideChar (TDynamicCharSet)
 
So, jetzt konnte ich mich endlich mal um diese Baustelle kümmern...

Es stellte sich nur raus, daß es "glücklicher" Weise kein spezifisches D2010-Problem war,
sondern einfach nur daran lag, wie/wo man die Variable deklariert.

Bei meinen Tests war es rein zufällig so, daß die Variable entweder durch Delphis Compilermagic initialisiert wurde oder zufällig der Stack noch genullt war.

Ist natürlich klar, daß TEncoding (also ein Objekt) nicht automatisch initialisiert wird ... das hatte ich leider nur ein kleinbissl übersehn. :oops:

Ich hoffe mal, daß ich jetzt alle Eintrittspunkte erwischt hab und derartig nicht initialisierte Werte nun erkannt und entsprechend behandelt werden.

> neuer Code > siehe Post #1

himitsu 10. Feb 2010 18:40

Re: Set of WideChar (TDynamicCharSet)
 
Da ich in einem Projekt bessere Funktionalitäten (siehe letzen Abschnitt dieses Posts), sowie spezifiziertere "Standard"-Sets benötigte
und bevor ich getrennt nochmals eine Erzeugungsroutine schreibe, hab ich diese direkt ins Projekt mit eingefügt.
Und auch gleich noch die Gelegenheit genutzt, um dort etwas besser zu sortieren, bzw. aufzuräumen.

Es gibt jetzt ein myset.GetAllChars, welches wirklich jedes Zeichen im Set auch im Result liefert
und nicht so wie z.B. myset.GetString, bzw. String(myset), wo eine (möglichst) verkürzte Liste rauskommt.

Zusätzlich wurde die interne Speicherverwaltung an einigen Ecken etwas fehlerunanfälliger umgestellt.

Und man kann jetzt die "Konstanten" auch nachträglich nochmals neu erzeugen.
Dieses macht vorallem dann Sinn, da in einigen systemspezifische Abhängigkeiten enthalten sind
und z.B. bei Änderung von System.DecimalSeparator das Dezimalzeichen in FloatChars nicht mehr stimmen würde.

Außerdem bekam die Set-"Klasse" ein paar neue Methoden spendiert.
So ist es jetzt leicht möglich einen Zeichenbereich (CharRange) gleichzeitig zu verarbeiten.
Folgendes würde also alle Zeichen von a bis z in das Set einfügen.
Delphi-Quellcode:
myset.Include('a', 'z');
OK, sowas ging über Umwege auch vorher schon,
Delphi-Quellcode:
myset.Include(FirstChar + '..' + LastChar);
aber der direkte Weg arbeitet wesentlich optimaler.

himitsu 10. Feb 2010 22:04

Re: Set of WideChar (TDynamicCharSet)
 
Diejenigen Zwei, welche das heute/vorhin runtergeladen haben ... bitte "dringend" updaten.

Hatte leider 'nen Fehler an falscher Stelle behoben und es somit nicht grad verbessert.
Leider fiel der Fehler nicht direkt auf, da dieser Codeteil seltener verwendet wird.

In der Resitze-Prozedur hatte ich hier das vermeintlich falsche i2 durch i ersetzt
Delphi-Quellcode:
If (i = 0) and Assigned(_Encoding) Then i2 := 1;
SetLength(_Map, i); // set length and make unique
obwohl es andersrum richtig gewesen wäre.
Delphi-Quellcode:
If (i2 = 0) and Assigned(_Encoding) Then i2 := 1;
SetLength(_Map, i2); // set length and make unique
Somit wurden eventuell höhere Bits ausversehn gelöscht, wenn man 2 Sets irgenwie miteinander verrechnete. :wall:

Nja, wenigstens fiel der Fehler grad auf, als ich eben meinen ersten Allerenumerator gebastelt hatte und mich über falsche Ergebnisse wunderte.

So, Fehler behoben und ab nur kann man, dank des Enumerators, auch noch das nette For-In benutzen. :firejump:
Delphi-Quellcode:
Var C: Char;
For C in HexNumerals do S := S + C;
// S = '0123456789ABCDEFabcdef'
// da HexNumerals = ['0'..'9', 'A'..'F', 'a'..'f']
[edit 11.02.]
Code etwas aufgeräumt und neue Funktionen:

LowChar = niedrigstes Zeichen im Set
HighChar = höchstes Zeichen im Set
CountChars = Anzahl der Zeichen im Set
ContainsAnyChar = prüft ob irgendeines der Zeichen des SETS im String vorkommt
ContainsAllChars = prüft alle Zeichen des SETS im String mindestens einmal vorkommen
ContainsOnlyThisChars = prüft ob alle Zeichen des Strings im SET vorkommen (nur der Name gefällt mir irgendwie nicht :? )

[add]
Es gibt nun auch eine Shift-Funktion (siehe Demo-Projekt),
aber fragt mich bitte nicht, wofür man diese gebrauchen kann. :stupid:

himitsu 12. Feb 2010 08:15

Re: Set of WideChar (TDynamicCharSet)
 
Neben den Operatoren SHL und SHR und den zugehörigen Funktionen .ShiftDown und .ShiftUp,
haben es jetzt auch noch .Lower, .Upper und .CaseLess, sowie .toLower, .toUpper und .toCaseLess reingeschafft.

Delphi-Quellcode:
Var X: TDynamicCharSet;

X := ['a'..'w'];
X := X shr 3;
// X = ['d'..'z']

X := ['a'..'w', 'ä'];
X := X shl 29;
// X = ['D'..'Z', 'Ç']

X := ['a'..'w', 'ä'];
X.Upper;
// X = ['A'..'W', 'Ä']

X := ['a'..'w', 'Ä'];
X.CaseLess;
// X = ['A'..'W', 'a'..'w', 'Ä', 'ä']

X := ['a'..'w'];
If X.toUpper.Contains('A') Then JaIchBinDrin;
If X.toUpper >= ['B'] Then JaIchBinAuchDrin;
// zu ">=": ['B'] ist ja ein SubSet von ['A'..'W']

X := ['a'..'w'];
// -X = alle (Unicode)Zeichen, ohne ['a'..'w']
Jetzt dürfte wohl alles drin sein, welches man mit Chars/CharSets machen kann. :-D

Delphi-Quellcode:
X := ['0'..'9', 'a'..'f', 'A'..'F'];
X := (X * ['0'..'9']) shl 48 + (X * ['A'..'F']) shl 55 + (X * ['a'..'f']) shl 87;
// oder
X := (X and ['0'..'9']) shl 48 or (X and ['A'..'F']) shl 55 or (X and ['a'..'f']) shl 87;
// X = [#0..#15]
//
// #0 = '0'    #1 = '1'    #9 = '9'    #10 = 'A' or 'a'    #15 = 'F' or 'f'
Sowas braucht zwar keiner, aber man kann es dennoch machen. :angel2:

himitsu 13. Feb 2010 14:46

Re: Set of WideChar (TDynamicCharSet)
 
OK, daß ich geschwindigkeitsmäßig nicht an Peters IWidecharSet rankomm, war ja zu erwarten
- keine assembleroptimierten Codeteile
- und die dynamische Speicherverwaltung benötigt auch mehr Abfragen, Bereichsprüfungen und Kopierarbeiten

Allerding bin ich positiv überrascht, daß es vorallem beim Erstellen/Erstzuweisung und beim Auslesen garnicht mal so langsam ist, wie ich befürchtet hab.

Dagegen ist aber der Speicherverbrauch im Einsatz wohl um weit mehl als 50% geringer
und im Extremfall (beim Zeichenvorrat der deutschen Sprache) würden bis zu 99% gespart.

OK, daß meine Codes auch in der EXE weniger Platz verbrauchen, ist nicht wirklich von Belangen,
denn es fällt nur so sehr auf, weil die Text-Anwendungen sehr klein sind.
(ob es nun 40 KB oder 50 KB mehr sind, im Vergleich zum TSysCharSet)

Mein SET hat jetzt auch noch ein .ReadOnly bekommen, aber da es keinen Kopier-Klassen-Operator gibt,
wird dieser Status bei := leider mitkopiert.
Delphi-Quellcode:
// hier ist dann auch VarSet als ReadOnly deklariert
VarSet := ConstSet;

// so ginge es aber
VarSet.Fill(ConstSet);
Code:
***** TDynamicCharSet *****

size test [a..z]:  100.000 sets -   3,81 MB - 0,25 sec
size test [#$FFFF]: 100.000 sets - 786,21 MB - 0,55 sec
high-low fill test:       1,34 sec
low-high fill test:       1,31 sec
low exitst read test:     0,64 sec
low non exitst read test: 0,64 sec
high non exitst read test: 0,66 sec

***** IWidecharSet *****

size test [a..z]:  100.000 sets - 785,83 MB - 0,47 sec
size test [#$FFFF]: 100.000 sets - 785,83 MB - 0,52 sec
high-low fill test:       0,11 sec
low-high fill test:       0,14 sec
low exitst read test:     0,45 sec
low non exitst read test: 0,89 sec
high non exitst read test: 0,48 sec

***** TSysCharSet / Set of AnsiChar *****

size test [a..z]: 100.000 sets - 3,05 MB - 0,015 sec
size test [#$FFFF]:       not supported
high-low fill test:       0,02 sec
low-high fill test:       0,02 sec
low exitst read test:     0,08 sec
low non exitst read test: 0,08 sec
So, das sollte jetzt hoffentlich vorerst einmal das Ende des täglichen Updatemarathons sein. :angel2:
Für mein anderes Projekt scheinen nun erstmal keine weiteren Wünsche/Notwendigkeiten mehr offen zu sein.


Alle Zeitangaben in WEZ +1. Es ist jetzt 15:04 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz