{ This code can be changed to make an own array,
depending on how you want it.
An array can be made with the 2 Pointers -
one for the data offset-pointer and the second for TypeInfo.
Note that the ElementCount variable is usually '1'
With this script you can also initialize L/W Strings, Variants,
Records and Interface classes}
type TForm1 = class(TForm)
Button1: TButton; private
procedure _InitRecord(p: Pointer; typeInfo: Pointer); procedure _InitArray(p: Pointer; typeInfo: Pointer; elemCount: Cardinal); public { Public declarations } end;
procedure tform1._InitRecord(p: Pointer; typeInfo: Pointer); {$IFDEF PUREPASCAL} var FT: PFieldTable;
I: Cardinal; begin FT := PFieldTable(Integer(typeInfo) + Byte(PTypeInfo(typeInfo).Name[0])); for I := FT.Count-1 downto 0 do _InitializeArray(Pointer(Cardinal(P) + FT.Fields[I].Offset), FT.Fields[I].TypeInfo^, 1); end; {$ELSE} asm { -> EAX pointer to record to be initialized }
{ EDX pointer to type info }
XOR ECX,ECX
PUSH EBX
MOV CL,[EDX+1] { type name length }
PUSH ESI
PUSH EDI
MOV EBX,EAX // PIC safe. See comment above LEA ESI,[EDX+ECX+2+8] { address of destructable fields } MOV EDI,[EDX+ECX+2+4] { number of destructable fields }
@@loop:
MOV EDX,[ESI]
MOV EAX,[ESI+4]
ADD EAX,EBX
MOV EDX,[EDX]
MOV ECX,1
CALL _InitArray
ADD ESI,8
DEC EDI
JG @@loop
POP EDI
POP ESI
POP EBX end; {$ENDIF}
procedure tform1._InitArray(p: Pointer; typeInfo: Pointer; elemCount: Cardinal); {$IFDEF PUREPASCAL} var FT: PFieldTable; begin
if elemCount = 0 then Exit; case PTypeInfo(typeInfo).Kind of tkLString, tkWString, tkInterface, tkDynArray: while elemCount > 0 do
begin PInteger(P)^ := 0;
Inc(Integer(P), 4);
Dec(elemCount); end;
tkVariant: while elemCount > 0 do
begin PInteger(P)^ := 0;
PInteger(Integer(P)+4)^ := 0;
PInteger(Integer(P)+8)^ := 0;
PInteger(Integer(P)+12)^ := 0;
Inc(Integer(P), sizeof(Variant));
Dec(elemCount); end;
tkArray: begin FT := PFieldTable(Integer(typeInfo) + Byte(PTypeInfo(typeInfo).Name[0])); while elemCount > 0 do
begin _InitializeArray(P, FT.Fields[0].TypeInfo^, FT.Count);
Inc(Integer(P), FT.Size);
Dec(elemCount); end; end;
tkRecord: begin FT := PFieldTable(Integer(typeInfo) + Byte(PTypeInfo(typeInfo).Name[0])); while elemCount > 0 do
begin _InitializeRecord(P, typeInfo);
Inc(Integer(P), FT.Size);
Dec(elemCount); end; end; else Error(reInvalidPtr); end; end; {$ELSE}
asm { -> EAX pointer to data to be initialized }
{ EDX pointer to type info describing data }
{ ECX number of elements of that type }
TEST ECX, ECX
JZ @@zerolength
PUSH EBX
PUSH ESI
PUSH EDI
MOV EBX,EAX // PIC safe. See comment above MOV ESI,EDX
MOV EDI,ECX
CMP AL,tkLString
JE @@LString
CMP AL,tkWString
JE @@WString
CMP AL,tkVariant
JE @@Variant
CMP AL,tkArray
JE @@Array
CMP AL,tkRecord
JE @@Record
CMP AL,tkInterface
JE @@Interface
CMP AL,tkDynArray
JE @@DynArray
MOV AL,reInvalidPtr
POP EDI
POP ESI
POP EBX
JMP @Error
@@LString:
@@WString:
@@Interface:
@@DynArray:
MOV [EBX],ECX
ADD EBX,4
DEC EDI
JG @@LString
JMP @@exit
@@Variant:
MOV [EBX ],ECX
MOV [EBX+ 4],ECX
MOV [EBX+ 8],ECX
MOV [EBX+12],ECX
ADD EBX,16
DEC EDI
JG @@Variant
JMP @@exit
@@Array:
PUSH EBP
MOV EBP,EDX
@@ArrayLoop:
MOV EDX,[ESI+EBP+2+8] // address of destructable fields typeinfo MOV EAX,EBX
ADD EBX,[ESI+EBP+2] // size in bytes of the array data MOV ECX,[ESI+EBP+2+4] // number of destructable fields MOV EDX,[EDX]
CALL _InitArray
DEC EDI
JG @@ArrayLoop
POP EBP
JMP @@exit
@@Record:
PUSH EBP
MOV EBP,EDX
@@RecordLoop:
MOV EAX,EBX
ADD EBX,[ESI+EBP+2]
MOV EDX,ESI
CALL _InitRecord
DEC EDI
JG @@RecordLoop
POP EBP
@@exit:
POP EDI
POP ESI
POP EBX
@@zerolength:
@Error: end; {$ENDIF}