home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Chip 1997 April
/
Chip_1997-04_cd.bin
/
prezent
/
cb
/
data.z
/
TYPINFO.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1997-01-16
|
32KB
|
1,182 lines
{*******************************************************}
{ }
{ Delphi Visual Component Library }
{ }
{ Copyright (c) 1995,96 Borland International }
{ }
{*******************************************************}
unit TypInfo;
interface
uses SysUtils;
type
TTypeKind = (tkUnknown, tkInteger, tkChar, tkEnumeration, tkFloat,
tkString, tkSet, tkClass, tkMethod, tkWChar, tkLString, tkLWString,
tkVariant);
TTypeKinds = set of TTypeKind;
TOrdType = (otSByte, otUByte, otSWord, otUWord, otSLong);
TFloatType = (ftSingle, ftDouble, ftExtended, ftComp, ftCurr);
TMethodKind = (mkProcedure, mkFunction);
TParamFlags = set of (pfVar, pfConst, pfArray, pfAddress, pfReference);
PTypeInfo = ^TTypeInfo;
TTypeInfo = record
Kind: TTypeKind;
Name: ShortString;
{TypeData: TTypeData}
end;
PTypeData = ^TTypeData;
TTypeData = packed record
case TTypeKind of
tkUnknown, tkLString, tkLWString, tkVariant: ();
tkInteger, tkChar, tkEnumeration, tkSet, tkWChar: (
OrdType: TOrdType;
case TTypeKind of
tkInteger, tkChar, tkEnumeration, tkWChar: (
MinValue: Longint;
MaxValue: Longint;
case TTypeKind of
tkInteger, tkChar, tkWChar: ();
tkEnumeration: (
BaseType: PTypeInfo;
NameList: ShortString));
tkSet: (
CompType: PTypeInfo));
tkFloat: (
FloatType: TFloatType);
tkString: (
MaxLength: Byte);
tkClass: (
ClassType: TClass;
ParentInfo: PTypeInfo;
PropCount: SmallInt;
UnitName: ShortString
{PropData: TPropData});
tkMethod: (
MethodKind: TMethodKind;
ParamCount: Byte;
ParamList: array[0..1023] of Char
{ParamList: array[1..ParamCount] of
record
Flags: TParamFlags;
ParamName: ShortString;
TypeName: ShortString;
end;
ResultType: ShortString});
end;
TPropData = packed record
PropCount: Word;
PropList: record end;
{PropList: array[1..PropCount] of TPropInfo}
end;
PPropInfo = ^TPropInfo;
TPropInfo = packed record
PropType: PTypeInfo;
GetProc: Pointer;
SetProc: Pointer;
StoredProc: Pointer;
Index: Integer;
Default: Longint;
NameIndex: SmallInt;
Name: ShortString;
end;
TPropInfoProc = procedure(PropInfo: PPropInfo) of object;
PPropList = ^TPropList;
TPropList = array[0..16379] of PPropInfo;
const
tkAny = [Low(TTypeKind)..High(TTypeKind)];
tkMethods = [tkMethod];
tkProperties = tkAny - tkMethods - [tkUnknown];
{ Property access routines }
function GetTypeData(TypeInfo: PTypeInfo): PTypeData;
function GetEnumName(TypeInfo: PTypeInfo; Value: Integer): string;
function GetEnumValue(TypeInfo: PTypeInfo; const Name: string): Integer;
function GetPropInfo(TypeInfo: PTypeInfo; const PropName: string): PPropInfo;
procedure GetPropInfos(TypeInfo: PTypeInfo; PropList: PPropList);
function GetPropList(TypeInfo: PTypeInfo; TypeKinds: TTypeKinds;
PropList: PPropList): Integer;
function IsStoredProp(Instance: TObject; PropInfo: PPropInfo): Boolean;
function GetOrdProp(Instance: TObject; PropInfo: PPropInfo): Longint;
procedure SetOrdProp(Instance: TObject; PropInfo: PPropInfo;
Value: Longint);
function GetStrProp(Instance: TObject; PropInfo: PPropInfo): string;
procedure SetStrProp(Instance: TObject; PropInfo: PPropInfo;
const Value: string);
function GetFloatProp(Instance: TObject; PropInfo: PPropInfo): Extended;
procedure SetFloatProp(Instance: TObject; PropInfo: PPropInfo;
Value: Extended);
function GetVariantProp(Instance: TObject; PropInfo: PPropInfo): Variant;
procedure SetVariantProp(Instance: TObject; PropInfo: PPropInfo;
const Value: Variant);
function GetMethodProp(Instance: TObject; PropInfo: PPropInfo): TMethod;
procedure SetMethodProp(Instance: TObject; PropInfo: PPropInfo;
const Value: TMethod);
implementation
function GetTypeData(TypeInfo: PTypeInfo): PTypeData; assembler;
asm
{ -> EAX Pointer to type info }
{ <- EAX Pointer to type data }
{ it's really just to skip the kind and the name }
XOR EDX,EDX
MOV DL,[EAX].TTypeInfo.Name.Byte[0]
LEA EAX,[EAX].TTypeInfo.Name[EDX+1]
end;
function GetEnumName(TypeInfo: PTypeInfo; Value: Integer): string;
var
P: ^ShortString;
begin
P := @GetTypeData(GetTypeData(TypeInfo)^.BaseType)^.NameList;
while Value <> 0 do
begin
Inc(Integer(P), Length(P^) + 1);
Dec(Value);
end;
if (TypeInfo^.Name = 'Boolean') then // change case of strings
Result := LowerCase(P^)
else
Result := P^;
end;
function GetEnumValue(TypeInfo: PTypeInfo; const Name: string): Integer;
assembler;
asm
{ -> EAX Pointer to type info }
{ EDX Pointer to string }
{ <- EAX Value }
PUSH EBX
PUSH ESI
PUSH EDI
TEST EDX,EDX
JE @notFound
{ point ESI to first name of the base type }
XOR ECX,ECX
MOV CL,[EAX].TTypeInfo.Name.Byte[0]
MOV EAX,[EAX].TTypeInfo.Name[ECX+1].TTypeData.BaseType
MOV CL,[EAX].TTypeInfo.Name.Byte[0]
LEA ESI,[EAX].TTypeInfo.Name[ECX+1].TTypeData.NameList
{ make EDI the high bound of the enum type }
MOV EDI,[EAX].TTypeInfo.Name[ECX+1].TTypeData.MaxValue
{ EAX is our running index }
XOR EAX,EAX
{ make ECX the length of the current string }
@outerLoop:
MOV CL,[ESI]
CMP ECX,[EDX-4]
JNE @lengthMisMatch
{ we know for sure the names won't be zero length }
@cmpLoop:
MOV BL,[EDX+ECX-1]
XOR BL,[ESI+ECX]
TEST BL,0DFH
JNE @misMatch
DEC ECX
JNE @cmpLoop
{ as we didn't have a mismatch, we must have found the name }
JMP @exit
@misMatch:
MOV CL,[ESI]
@lengthMisMatch:
INC EAX
LEA ESI,[ESI+ECX+1]
CMP EAX,EDI
JLE @outerLoop
{ we haven't found the thing - return -1 }
@notFound:
OR EAX,-1
@exit:
POP EDI
POP ESI
POP EBX
end;
function GetPropInfo(TypeInfo: PTypeInfo; const PropName: string): PPropInfo;
assembler;
asm
{ -> EAX Pointer to type info }
{ EDX Pointer to prop name }
{ <- EAX Pointer to prop info }
PUSH EBX
PUSH ESI
PUSH EDI
MOV ECX,EDX
OR EDX,EDX
JE @outerLoop
MOV CL,[EDX-4]
MOV CH,[EDX]
AND ECX,0DFFFH
@outerLoop:
XOR EBX,EBX
MOV BL,[EAX].TTypeInfo.Name.Byte[0]
LEA ESI,[EAX].TTypeInfo.Name[EBX+1]
MOV BL,[ESI].TTypeData.UnitName.Byte[0]
MOVZX EDI,[ESI].TTypeData.UnitName[EBX+1].TPropData.PropCount
TEST EDI,EDI
JE @parent
LEA EAX,[ESI].TTypeData.UnitName[EBX+1].TPropData.PropList
@innerLoop:
MOV BX,[EAX].TPropInfo.Name.Word[0]
AND BH,0DFH
CMP EBX,ECX
JE @matchStart
@nextProperty:
MOV BH,0
DEC EDI
LEA EAX,[EAX].TPropInfo.Name[EBX+1]
JNE @innerLoop
@parent:
MOV EAX,[ESI].TTypeData.ParentInfo
TEST EAX,EAX
JNE @outerLoop
JMP @exit
@misMatch:
MOV CH,[EDX]
AND CH,0DFH
MOV BL,[EAX].TPropInfo.Name.Byte[0]
JMP @nextProperty
@matchStart:
MOV BH,0
@matchLoop:
MOV CH,[EDX+EBX-1]
XOR CH,[EAX].TPropInfo.Name.Byte[EBX]
TEST CH,0DFH
JNE @misMatch
DEC EBX
JNE @matchLoop
@exit:
POP EDI
POP ESI
POP EBX
end;
procedure GetPropInfos(TypeInfo: PTypeInfo; PropList: PPropList); assembler;
asm
{ -> EAX Pointer to type info }
{ EDX Pointer to prop list }
{ <- nothing }
PUSH EBX
PUSH ESI
PUSH EDI
XOR ECX,ECX
MOV ESI,EAX
MOV CL,[EAX].TTypeInfo.Name.Byte[0]
MOV EDI,EDX
XOR EAX,EAX
MOVZX ECX,[ESI].TTypeInfo.Name[ECX+1].TTypeData.PropCount
REP STOSD
@outerLoop:
MOV CL,[ESI].TTypeInfo.Name.Byte[0]
LEA ESI,[ESI].TTypeInfo.Name[ECX+1]
MOV CL,[ESI].TTypeData.UnitName.Byte[0]
MOVZX EAX,[ESI].TTypeData.UnitName[ECX+1].TPropData.PropCount
TEST EAX,EAX
JE @parent
LEA EDI,[ESI].TTypeData.UnitName[ECX+1].TPropData.PropList
@innerLoop:
MOVZX EBX,[EDI].TPropInfo.NameIndex
MOV CL,[EDI].TPropInfo.Name.Byte[0]
CMP dword ptr [EDX+EBX*4],0
JNE @alreadySet
MOV [EDX+EBX*4],EDI
@alreadySet:
LEA EDI,[EDI].TPropInfo.Name[ECX+1]
DEC EAX
JNE @innerLoop
@parent:
MOV ESI,[ESI].TTypeData.ParentInfo
XOR ECX,ECX
TEST ESI,ESI
JNE @outerLoop
POP EDI
POP ESI
POP EBX
end;
procedure SortPropList(PropList: PPropList; PropCount: Integer); assembler;
asm
{ -> EAX Pointer to prop list }
{ EDX Property count }
{ <- nothing }
PUSH EBX
PUSH ESI
PUSH EDI
MOV ECX,EAX
XOR EAX,EAX
DEC EDX
CALL @@qsort
POP EDI
POP ESI
POP EBX
JMP @@exit
@@qsort:
PUSH EAX
PUSH EDX
LEA EDI,[EAX+EDX] { pivot := (left + right) div 2 }
SHR EDI,1
MOV EDI,[ECX+EDI*4]
ADD EDI,OFFSET TPropInfo.Name
@@repeat: { repeat }
@@while1:
CALL @@compare { while a[i] < a[pivot] do inc(i);}
JAE @@endWhile1
INC EAX
JMP @@while1
@@endWhile1:
XCHG EAX,EDX
@@while2:
CALL @@compare { while a[j] > a[pivot] do dec(j);}
JBE @@endWhile2
DEC EAX
JMP @@while2
@@endWhile2:
XCHG EAX,EDX
CMP EAX,EDX { if i <= j then begin }
JG @@endRepeat
MOV EBX,[ECX+EAX*4] { x := a[i]; }
MOV ESI,[ECX+EDX*4] { y := a[j]; }
MOV [ECX+EDX*4],EBX { a[j] := x; }
MOV [ECX+EAX*4],ESI { a[i] := y; }
INC EAX { inc(i); }
DEC EDX { dec(j); }
{ end; }
CMP EAX,EDX { until i > j; }
JLE @@repeat
@@endRepeat:
POP ESI
POP EBX
CMP EAX,ESI
JL @@rightNonEmpty { if i >= right then begin }
CMP EDX,EBX
JG @@leftNonEmpty1 { if j <= left then exit }
RET
@@leftNonEmpty1:
MOV EAX,EBX
JMP @@qsort { qsort(left, j) }
@@rightNonEmpty:
CMP EAX,EBX
JG @@leftNonEmpty2
MOV EDX,ESI { qsort(i, right) }
JMP @@qsort
@@leftNonEmpty2:
PUSH EAX
PUSH ESI
MOV EAX,EBX
CALL @@qsort { qsort(left, j) }
POP EDX
POP EAX
JMP @@qsort { qsort(i, right) }
@@compare:
PUSH EAX
PUSH EDI
MOV ESI,[ECX+EAX*4]
ADD ESI,OFFSET TPropInfo.Name
PUSH ESI
XOR EBX,EBX
MOV BL,[ESI]
INC ESI
CMP BL,[EDI]
JBE @@firstLenSmaller
MOV BL,[EDI]
@@firstLenSmaller:
INC EDI
TEST BL,BL
JE @@endLoop
@@loop:
MOV AL,[ESI]
MOV AH,[EDI]
AND EAX,$DFDF
CMP AL,AH
JNE @@difference
INC ESI
INC EDI
DEC EBX
JNZ @@loop
@@endLoop:
POP ESI
POP EDI
MOV AL,[ESI]
MOV AH,[EDI]
CMP AL,AH
POP EAX
RET
@@difference:
POP ESI
POP EDI
POP EAX
RET
@@exit:
end;
{ TypeInfo is the type info of a class. Return all properties matching
TypeKinds in this class or its ancestors in PropList and return the count }
function GetPropList(TypeInfo: PTypeInfo; TypeKinds: TTypeKinds;
PropList: PPropList): Integer;
var
I, Count: Integer;
PropInfo: PPropInfo;
TempList: PPropList;
begin
Result := 0;
Count := GetTypeData(TypeInfo)^.PropCount;
if Count > 0 then
begin
GetMem(TempList, Count * SizeOf(Pointer));
try
GetPropInfos(TypeInfo, TempList);
for I := 0 to Count - 1 do
begin
PropInfo := TempList^[I];
if PropInfo^.PropType^.Kind in TypeKinds then
begin
if PropList <> nil then PropList^[Result] := PropInfo;
Inc(Result);
end;
if (PropList <> nil) and (Result > 1) then
SortPropList(PropList, Result);
end;
finally
FreeMem(TempList, Count * SizeOf(Pointer));
end;
end;
end;
function IsStoredProp(Instance: TObject; PropInfo: PPropInfo): Boolean;
assembler;
asm
{ -> EAX Pointer to Instance }
{ EDX Pointer to prop info }
{ <- AL Function result }
MOV ECX,[EDX].TPropInfo.StoredProc
TEST ECX,0FFFFFF00H
JE @@returnCL
CMP [EDX].TPropInfo.StoredProc.Byte[3],0FEH
MOV EDX,[EDX].TPropInfo.Index
JB @@isStaticMethod
JA @@isField
{ the StoredProc is a virtual method }
MOVSX ECX,CX { sign extend slot offs }
ADD ECX,[EAX] { vmt + slotoffs }
CALL dword ptr [ECX] { call vmt[slot] }
JMP @@exit
@@isStaticMethod:
CALL ECX
JMP @@exit
@@isField:
AND ECX,$00FFFFFF
MOV CL,[EAX+ECX]
@@returnCL:
MOV AL,CL
@@exit:
end;
function GetOrdProp(Instance: TObject; PropInfo: PPropInfo): Longint;
assembler;
asm
{ -> EAX Pointer to instance }
{ EDX Pointer to property info }
{ <- EAX Longint result }
PUSH EBX
PUSH EDI
MOV EDI,[EDX].TPropInfo.PropType
MOV BL,otSLong
CMP [EDI].TTypeInfo.Kind,tkClass
JE @@isClass
XOR ECX,ECX
MOV CL,[EDI].TTypeInfo.Name.Byte[0]
MOV BL,[EDI].TTypeInfo.Name[ECX+1].TTypeData.OrdType
@@isClass:
MOV ECX,[EDX].TPropInfo.GetProc
CMP [EDX].TPropInfo.GetProc.Byte[3],$FE
MOV EDX,[EDX].TPropInfo.Index
JB @@isStaticMethod
JA @@isField
{ the GetProc is a virtual method }
MOVSX ECX,CX { sign extend slot offs }
ADD ECX,[EAX] { vmt + slotoffs }
CALL dword ptr [ECX] { call vmt[slot] }
JMP @@final
@@isStaticMethod:
CALL ECX
JMP @@final
@@isField:
AND ECX,$00FFFFFF
ADD ECX,EAX
MOV AL,[ECX]
CMP BL,otSWord
JB @@final
MOV AX,[ECX]
CMP BL,otSLong
JB @@final
MOV EAX,[ECX]
@@final:
CMP BL,otSLong
JAE @@exit
CMP BL,otSWord
JAE @@word
CMP BL,otSByte
MOVSX EAX,AL
JE @@exit
AND EAX,$FF
JMP @@exit
@@word:
MOVSX EAX,AX
JE @@exit
AND EAX,$FFFF
@@exit:
POP EDI
POP EBX
end;
procedure SetOrdProp(Instance: TObject; PropInfo: PPropInfo;
Value: Longint); assembler;
asm
{ -> EAX Pointer to instance }
{ EDX Pointer to property info }
{ ECX Value }
PUSH EBX
PUSH ESI
PUSH EDI
MOV EDI,EDX
MOV ESI,[EDI].TPropInfo.PropType
MOV BL,otSLong
CMP [ESI].TTypeInfo.Kind,tkClass
JE @@isClass
XOR EBX,EBX
MOV BL,[ESI].TTypeInfo.Name.Byte[0]
MOV BL,[ESI].TTypeInfo.Name[EBX+1].TTypeData.OrdType
@@isClass:
MOV EDX,[EDI].TPropInfo.Index { pass Index in DX }
CMP EDX,$80000000
JNE @@hasIndex
MOV EDX,ECX { pass value in EDX }
@@hasIndex:
MOV ESI,[EDI].TPropInfo.SetProc
CMP [EDI].TPropInfo.SetProc.Byte[3],$FE
JA @@isField
JB @@isStaticMethod
{ SetProc turned out to be a virtual method. call it }
MOVSX ESI,SI { sign extend slot offset }
ADD ESI,[EAX] { vmt + slot offset }
CALL dword ptr [ESI]
JMP @@exit
@@isStaticMethod:
CALL ESI
JMP @@exit
@@isField:
AND ESI,$00FFFFFF
ADD EAX,ESI
MOV [EAX],CL
CMP BL,otSWord
JB @@exit
MOV [EAX],CX
CMP BL,otSLong
JB @@exit
MOV [EAX],ECX
@@exit:
POP EDI
POP ESI
POP EBX
end;
procedure GetShortStrProp(Instance: TObject; PropInfo: PPropInfo;
var Value: ShortString); assembler;
asm
{ -> EAX Pointer to instance }
{ EDX Pointer to property info }
{ ECX Pointer to result string }
PUSH ESI
PUSH EDI
MOV EDI,EDX
MOV EDX,[EDI].TPropInfo.Index { pass index in EDX }
CMP EDX,$80000000
JNE @@hasIndex
MOV EDX,ECX { pass value in EDX }
@@hasIndex:
MOV ESI,[EDI].TPropInfo.GetProc
CMP [EDI].TPropInfo.GetProc.Byte[3],$FE
JA @@isField
JB @@isStaticMethod
{ GetProc turned out to be a virtual method }
MOVSX ESI,SI { sign extend slot offset}
ADD ESI,[EAX] { vmt + slot offset }
CALL dword ptr [ESI]
JMP @@exit
@@isStaticMethod:
CALL ESI
JMP @@exit
@@isField:
AND ESI,$00FFFFFF
ADD ESI,EAX
MOV EDI,ECX
XOR ECX,ECX
MOV CL,[ESI]
INC ECX
REP MOVSB
@@exit:
POP EDI
POP ESI
end;
procedure SetShortStrProp(Instance: TObject; PropInfo: PPropInfo;
const Value: ShortString); assembler;
asm
{ -> EAX Pointer to instance }
{ EDX Pointer to property info }
{ ECX Pointer to string value }
PUSH ESI
PUSH EDI
MOV ESI,EDX
MOV EDX,[ESI].TPropInfo.Index { pass index in EDX }
CMP EDX,$80000000
JNE @@hasIndex
MOV EDX,ECX { pass value in EDX }
@@hasIndex:
MOV EDI,[ESI].TPropInfo.SetProc
CMP [ESI].TPropInfo.SetProc.Byte[3],$FE
JA @@isField
JB @@isStaticMethod
{ SetProc is a virtual method }
MOVSX EDI,DI
ADD EDI,[EAX]
CALL dword ptr [EDI]
JMP @@exit
@@isStaticMethod:
CALL EDI
JMP @@exit
@@isField:
AND EDI,$00FFFFFF
ADD EDI,EAX
MOV EAX,[ESI].TPropInfo.PropType
MOV ESI,ECX
XOR ECX,ECX
MOV CL,[EAX].TTypeInfo.Name.Byte[0]
MOV CL,[EAX].TTypeInfo.Name[ECX+1].TTypeData.MaxLength
LODSB
CMP AL,CL
JB @@noTruncate
MOV AL,CL
@@noTruncate:
STOSB
MOV CL,AL
REP MOVSB
@@exit:
POP EDI
POP ESI
end;
procedure AssignString(var Dest: string; const Source: string);
begin
Dest := Source;
end;
procedure GetLongStrProp(Instance: TObject; PropInfo: PPropInfo;
var Value: string); assembler;
asm
{ -> EAX Pointer to instance }
{ EDX Pointer to property info }
{ ECX Pointer to result string }
PUSH ESI
PUSH EDI
MOV EDI,EDX
MOV EDX,[EDI].TPropInfo.Index { pass index in EDX }
CMP EDX,$80000000
JNE @@hasIndex
MOV EDX,ECX { pass value in EDX }
@@hasIndex:
MOV ESI,[EDI].TPropInfo.GetProc
CMP [EDI].TPropInfo.GetProc.Byte[3],$FE
JA @@isField
JB @@isStaticMethod
@@isVirtualMethod:
MOVSX ESI,SI { sign extend slot offset }
ADD ESI,[EAX] { vmt + slot offset }
CALL DWORD PTR [ESI]
JMP @@exit
@@isStaticMethod:
CALL ESI
JMP @@exit
@@isField:
AND ESI,$00FFFFFF
MOV EDX,[EAX+ESI]
MOV EAX,ECX
CALL AssignString
@@exit:
POP EDI
POP ESI
end;
procedure SetLongStrProp(Instance: TObject; PropInfo: PPropInfo;
const Value: string); assembler;
asm
{ -> EAX Pointer to instance }
{ EDX Pointer to property info }
{ ECX Pointer to string value }
PUSH ESI
PUSH EDI
MOV ESI,EDX
MOV EDX,[ESI].TPropInfo.Index { pass index in EDX }
CMP EDX,$80000000
JNE @@hasIndex
MOV EDX,ECX { pass value in EDX }
@@hasIndex:
MOV EDI,[ESI].TPropInfo.SetProc
CMP [ESI].TPropInfo.SetProc.Byte[3],$FE
JA @@isField
JB @@isStaticMethod
@@isVirtualMethod:
MOVSX EDI,DI
ADD EDI,[EAX]
CALL DWORD PTR [EDI]
JMP @@exit
@@isStaticMethod:
CALL EDI
JMP @@exit
@@isField:
AND EDI,$00FFFFFF
ADD EAX,EDI
MOV EDX,ECX
CALL AssignString
@@exit:
POP EDI
POP ESI
end;
function GetStrProp(Instance: TObject; PropInfo: PPropInfo): string;
var
Temp: ShortString;
begin
if PropInfo^.PropType^.Kind = tkString then
begin
GetShortStrProp(Instance, PropInfo, Temp);
Result := Temp;
end else
GetLongStrProp(Instance, PropInfo, Result);
end;
procedure SetStrProp(Instance: TObject; PropInfo: PPropInfo;
const Value: string);
var
Temp: ShortString;
begin
if PropInfo^.PropType^.Kind = tkString then
begin
Temp := Value;
SetShortStrProp(Instance, PropInfo, Temp);
end else
SetLongStrProp(Instance, PropInfo, Value);
end;
const
C10000: Single = 10000;
function GetFloatProp(Instance: TObject; PropInfo: PPropInfo): Extended;
assembler;
asm
{ -> EAX Pointer to instance }
{ EDX Pointer to property info }
{ <- FST(0) Extended result }
MOV ECX,[EDX].TPropInfo.GetProc
CMP [EDX].TPropInfo.GetProc.Byte[3],$FE
JA @@isField
JE @@isVirtualMethod
MOV EDX,[EDX].TPropInfo.Index { pass Index in DX }
CALL ECX
JMP @@exit
@@isVirtualMethod:
MOVSX ECX,CX
ADD ECX,[EAX]
MOV EDX,[EDX].TPropInfo.Index { pass Index in DX }
CALL dword ptr [ECX]
JMP @@exit
@@jmpTab:
DD @@single,@@double,@@extended,@@comp,@@curr
@@single:
FLD [EAX].Single
RET
@@double:
FLD [EAX].Double
RET
@@extended:
FLD [EAX].Extended
RET
@@comp:
FILD [EAX].Comp
RET
@@curr:
FILD [EAX].Currency
FDIV C10000
RET
@@isField:
AND ECX,$00FFFFFF
ADD EAX,ECX
MOV ECX,[EDX].TPropInfo.PropType
XOR EDX,EDX
MOV DL,[ECX].TTypeInfo.Name.Byte[0]
MOV DL,[ECX].TTypeInfo.Name[EDX+1].TTypeData.FloatType
CALL dword ptr @@jmpTab[EDX*4]
@@exit:
end;
procedure SetFloatProp(Instance: TObject; PropInfo: PPropInfo;
Value: Extended); assembler;
asm
{ -> EAX Pointer to instance }
{ EDX Pointer to property info }
{ Stack: Value }
PUSH EBX
PUSH ESI
XOR EBX,EBX
MOV ECX,[EDX].TPropInfo.PropType
MOV BL,[ECX].TTypeInfo.Name.Byte[0]
MOV BL,[ECX].TTypeInfo.Name[EBX+1].TTypeData.FloatType
SHL EBX,2
FLD Value
MOV ECX,[EDX].TPropInfo.SetProc
CMP [EDX].TPropInfo.SetProc.Byte[3],$FE
JA @@isField
SUB ESP,dword ptr @@sizTab[EBX]
MOV ESI,ESP
CALL dword ptr @@storeProc[EBX]
CMP [EDX].TPropInfo.SetProc.Byte[3],$FE
MOV EDX,[EDX].TPropInfo.Index { pass Index in DX }
JB @@isStaticMethod
MOVSX ECX,CX
ADD ECX,[EAX]
CALL dword ptr [ECX]
JMP @@exit
@@isStaticMethod:
CALL ECX
JMP @@exit
@@sizTab:
DD 4,8,12,8,8
@@storeProc:
DD @@single,@@double,@@extended,@@comp,@@curr
@@single:
FSTP [ESI].Single
RET
@@double:
FSTP [ESI].Double
RET
@@extended:
FSTP [ESI].Extended
RET
@@comp:
FISTP [ESI].Comp
RET
@@curr:
FMUL C10000
FISTP [ESI].Currency
RET
@@isField:
AND ECX,$00FFFFFF
LEA ESI,[EAX+ECX]
CALL dword ptr @@storeProc[EBX]
@@exit:
POP ESI
POP EBX
end;
procedure AssignVariant(var Dest: Variant; const Source: Variant);
begin
Dest := Source;
end;
function GetVariantProp(Instance: TObject; PropInfo: PPropInfo): Variant;
asm
{ -> EAX Pointer to instance }
{ EDX Pointer to property info }
{ ECX Pointer to result variant }
PUSH ESI
PUSH EDI
MOV EDI,EDX
MOV EDX,[EDI].TPropInfo.Index { pass index in EDX }
CMP EDX,$80000000
JNE @@hasIndex
MOV EDX,ECX { pass value in EDX }
@@hasIndex:
MOV ESI,[EDI].TPropInfo.GetProc
CMP [EDI].TPropInfo.GetProc.Byte[3],$FE
JA @@isField
JB @@isStaticMethod
@@isVirtualMethod:
MOVSX ESI,SI { sign extend slot offset }
ADD ESI,[EAX] { vmt + slot offset }
CALL DWORD PTR [ESI]
JMP @@exit
@@isStaticMethod:
CALL ESI
JMP @@exit
@@isField:
AND ESI,$00FFFFFF
LEA EDX,[EAX+ESI]
MOV EAX,ECX
CALL AssignVariant
@@exit:
POP EDI
POP ESI
end;
procedure SetVariantProp(Instance: TObject; PropInfo: PPropInfo;
const Value: Variant);
asm
{ -> EAX Pointer to instance }
{ EDX Pointer to property info }
{ ECX Pointer to variant value }
PUSH ESI
PUSH EDI
MOV ESI,EDX
MOV EDX,[ESI].TPropInfo.Index { pass index in EDX }
CMP EDX,$80000000
JNE @@hasIndex
MOV EDX,ECX { pass value in EDX }
@@hasIndex:
MOV EDI,[ESI].TPropInfo.SetProc
CMP [ESI].TPropInfo.SetProc.Byte[3],$FE
JA @@isField
JB @@isStaticMethod
@@isVirtualMethod:
MOVSX EDI,DI
ADD EDI,[EAX]
CALL DWORD PTR [EDI]
JMP @@exit
@@isStaticMethod:
CALL EDI
JMP @@exit
@@isField:
AND EDI,$00FFFFFF
ADD EAX,EDI
MOV EDX,ECX
CALL AssignVariant
@@exit:
POP EDI
POP ESI
end;
function GetMethodProp(Instance: TObject; PropInfo: PPropInfo): TMethod;
assembler;
asm
{ -> EAX Pointer to instance }
{ EDX Pointer to property info }
{ ECX Pointer to result }
PUSH EBX
PUSH ESI
MOV ESI,EDX
MOV EDX,[ESI].TPropInfo.Index { pass Index in DX }
CMP EDX,$80000000
JNE @@hasIndex
MOV EDX,ECX { pass value in EDX }
@@hasIndex:
MOV EBX,[ESI].TPropInfo.GetProc
CMP [ESI].TPropInfo.GetProc.Byte[3],$FE
JA @@isField
JB @@isStaticMethod
{ GetProc is a virtual method }
MOVSX EBX,BX { sign extend slot number }
ADD EBX,[EAX]
CALL dword ptr [EBX]
JMP @@exit
@@isStaticMethod:
CALL EBX
JMP @@exit
@@isField:
AND EBX,$00FFFFFF
ADD EAX,EBX
MOV EDX,[EAX]
MOV EBX,[EAX+4]
MOV [ECX],EDX
MOV [ECX+4],EBX
@@exit:
POP ESI
POP EBX
end;
procedure SetMethodProp(Instance: TObject; PropInfo: PPropInfo;
const Value: TMethod); assembler;
asm
{ -> EAX Pointer to instance }
{ EDX Pointer to property info }
{ ECX Pointer to value }
PUSH EBX
MOV EBX,[EDX].TPropInfo.SetProc
CMP [EDX].TPropInfo.SetProc.Byte[3],$FE
JA @@isField
MOV EDX,[EDX].TPropInfo.Index
PUSH dword ptr [ECX+4]
PUSH dword ptr [ECX]
JB @@isStaticMethod
{ SetProc is a virtual method }
MOVSX EBX,BX
ADD EBX,[EAX]
CALL dword ptr [EBX]
JMP @@exit
@@isStaticMethod:
CALL EBX
JMP @@exit
@@isField:
AND EBX,$00FFFFFF
ADD EAX,EBX
MOV EDX,[ECX]
MOV EBX,[ECX+4]
MOV [EAX],EDX
MOV [EAX+4],EBX
@@exit:
POP EBX
end;
end.