bisher kam ich immer mit ShortStrings aus, nun benötige ich allerdings WideStrings. Daher muss ich meine Stackklasse anpassen. Früher genügte es, einfach via SizeOf(Record) den nötigen Platz im Speicher zu ermitteln. Nur wie macht man das bei Records mit WideStrings ?
Falls das Interesse besteht, hier die Klassen selbst:
Code: Alles auswählen
TStack = class
private
fDataSize : Word;
fSize, fStackBaseSize : Cardinal;
fCount : Cardinal;
fStack : PByte;
protected
function GetDataSize: Word; virtual; abstract;
public
constructor Create(aSize : Cardinal);
destructor Destroy; override;
procedure Push(var p);
function Pop : Pointer;
function Peek : Pointer;
property Count : Cardinal read fCount;
end;
TTokenStack = class(TStack)
protected
function GetDataSize : Word; override;
public
function Pop : TToken;
function Peek : TToken;
procedure Push(Token : TToken);
end;
Code: Alles auswählen
// TStack arbeitet vollkommen virtuell
constructor TStack.Create(aSize : Cardinal);
begin
inherited Create;
fDataSize := GetDataSize; // Datengröße bestimmen
fStackBaseSize := aSize; // Größe festhalten
fSize := fStackBaseSize; // Größe setzen
GetMem(fStack, fSize*fDataSize); // Speicher reservieren
dec(fStack, fDataSize);
end;
destructor TStack.Destroy;
begin
// Speicher freigeben
dec(fStack, Pred(fCount)*fDataSize);
FreeMem(fStack);
inherited;
end;
function TStack.Peek : Pointer;
begin
// Hochpunkt bestimmen
Result := fStack;
end;
function TStack.Pop : Pointer;
begin
if fSize-fCount >= fStackBaseSize then
begin
// Position heruntersetzen
dec(fSize, fStackBaseSize);
dec(fStack, Pred(fCount)*fDataSize);
// Speicher realloziieren
ReallocMem(fStack, fSize*fDataSize);
inc(fStack, Pred(fCount)*fDataSize);
end;
// Eintrag zurückgeben und vom Stack entfernen
Result := fStack;
dec(fStack, fDataSize);
dec(fCount);
end;
procedure TStack.Push(var p);
begin
if fCount >= fSize then
begin
// Position erhöhen
inc(fSize, fStackBaseSize);
dec(fStack, Pred(fCount)*fDataSize);
// Speicher realloziieren
ReallocMem(fStack, fSize*fDataSize);
inc(fStack, Pred(fCount)*fDataSize);
end;
// Speicherbereich mit neuem Eintrag füllen
inc(fStack, fDataSize);
Move(p, fStack^, fDataSize);
inc(fCount);
end;
Code: Alles auswählen
type
TToken = record
Inhalt : WideString;
Wertigkeit : ShortInt;
end;
TDynTokenArray = Array of TToken;
PToken = ^TToken;
// TTokenStack liefert die nötigen Größen und castet alles auf Basis von TStack
function TTokenStack.GetDataSize : Word;
begin
// Der benötigte Speicher jedes TokenStack-Eintrags ist so groß wie der eines TToken
Result := SizeOf(TToken);
end;
function TTokenStack.Pop : TToken;
begin
// Die virtuellen Daten von TStack besorgen, als TToken casten und zurückgeben
Result := PToken(inherited Pop)^;
end;
procedure TTokenStack.Push(Token : TToken);
begin
// Daten in Stack pushen
inherited Push(Token);
end;
function TTokenStack.Peek : TToken;
begin
// Die virtuellen Daten von TStack besorgen, als TToken casten und zurückgeben
Result := PToken(inherited Peek)^;
end;