program Project1;
{$mode objfpc}
{$modeswitch advancedrecords}
{$warn 5089 off} { suppress uninitialized warning }
{$warn 5090 off} { suppress uninitialized warning }
{$warn 5092 off} { suppress uninitialized warning }
{$warn 5025 off} { suppress variable not used warning }
{$warn 4055 off} { suppress not portable }
type
TRec = record
public
Value: PLongint;
Size: PtrUInt; { size of allocated memory }
strict private
class operator Initialize(var aRec: TRec);
class operator Finalize(var aRec: TRec);
class operator Copy(constref cFrom:Trec;var cTo:Trec);
public
{ this operator should be public, however: it is not a management operator }
class operator = (const a,b:TRec):Boolean;
end;
class operator TRec.Initialize(var aRec: TRec);
begin
ReturnNilIfGrowHeapFails := True;
writeln('TRec.Initialize: before: Value = ',ReturnNilIfGrowHeapFails, 'Value = ', ptrUint(aRec.Value));
aRec.Size := 1000*4;
aRec.Value := AllocMem(aRec.Size);
writeln('TRec.Initialize: after: Value = ',ReturnNilIfGrowHeapFails, 'Value = ', PtrUInt(aRec.Value));
end;
class operator TRec.Finalize(var aRec: TRec);
begin
WriteLn('Just to let you know: I am finalizing..');
FreeMem(aRec.Value); { make sure memory is free'd! }
aRec.Value := nil;
aRec.Size := 0;
writeln('aRec.Pointer after freeing = ', PtrUInt(aRec.Value));
end;
class operator TRec.Copy(constref cFrom:Trec;var cTo:TRec);
begin
freemem(cTo.Value); { calling Freemem on nil is ok }
cTo.Value := AllocMem(cFrom.Size); { allocate a new block }
cTo.Size := cFrom.Size; { of the same size as the source }
move(cFrom.Value^,cTo.Value^,cFrom.Size);{ only then copy the content }
writeln('Copied on assignment :=' );
end;
class operator TRec.= (const a,b:TRec):Boolean;
begin
{ the records have the same content if the size is equal and the memory content is equal }
Result := (a.size = b.size) and (CompareByte(a.value^,b.value^,a.size) = 0);
end;
procedure test(var a:TRec);
var b:TRec;
i:longint;
begin
writeln('b.Pointer = ', PtrUInt(b.Value));
writeln(b.Size);
for i:=0 to (b.Size div 4)-1 do
begin
b.Value[i]:=123+i;
end;
a:=b; { assignment is copy on write, local var b is finalized on procedure exit. }
end;
var
t, z, x: TRec;
begin
test(x);
writeln('t.Size = ', t.Size);
writeln('t.Pointer = ', PtrUInt(t.Value));
writeln('valid pointer? ', t.Value <> nil);
writeln('z.Size = ', z.Size);
writeln('x.Size = ', x.Size);
writeln('x.Value[0] = ', x.Value[0]);
writeln('x.Value[1] = ', x.Value[1]);
writeln('x.Value[2] = ', x.Value[2]);
writeln('x.Value[',1000-3,'] = ', x.Value[1000-3]);
writeln('x.Value[',1000-2,'] = ', x.Value[1000-2]);
writeln('x.Value[',1000-1,'] = ', x.Value[1000-1]);
t:=x; { assignment is copy on write }
writeln('Is the content of t equal to that of x after assignment? ',t = x);
writeln('t.Value[',1000-3,'] = ', t.Value[1000-3]);
writeln('t.Value[',1000-2,'] = ', t.Value[1000-2]);
writeln('t.Value[',1000-1,'] = ', t.Value[1000-1]);
readln;
end.