2473 lines
68 KiB
ObjectPascal
2473 lines
68 KiB
ObjectPascal
|
////////////////////////////////////////////////////////////////////////////
|
||
|
// PaxCompiler
|
||
|
// Site: http://www.paxcompiler.com
|
||
|
// Author: Alexander Baranovsky (paxscript@gmail.com)
|
||
|
// ========================================================================
|
||
|
// Copyright (c) Alexander Baranovsky, 2006-2014. All rights reserved.
|
||
|
// Code Version: 4.2
|
||
|
// ========================================================================
|
||
|
// Unit: PAXCOMP_TYPEINFO.pas
|
||
|
// ========================================================================
|
||
|
////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
{$I PaxCompiler.def}
|
||
|
unit PAXCOMP_TYPEINFO;
|
||
|
interface
|
||
|
|
||
|
uses {$I uses.def}
|
||
|
TypInfo,
|
||
|
SysUtils,
|
||
|
Classes,
|
||
|
PAXCOMP_CONSTANTS,
|
||
|
PAXCOMP_TYPES,
|
||
|
PAXCOMP_SYS,
|
||
|
PAXCOMP_MAP,
|
||
|
PAXCOMP_CLASSFACT,
|
||
|
PAXCOMP_GENERIC;
|
||
|
|
||
|
type
|
||
|
TParamData = record
|
||
|
Flags: TParamFlags;
|
||
|
ParamName: ShortString;
|
||
|
TypeName: ShortString;
|
||
|
end;
|
||
|
|
||
|
TTypeInfoContainer = class;
|
||
|
TTypeDataContainer = class;
|
||
|
TClassTypeDataContainer = class;
|
||
|
TMethodTypeDataContainer = class;
|
||
|
|
||
|
TFieldDataContainer = class
|
||
|
private
|
||
|
procedure SaveToStream(S: TStream);
|
||
|
procedure LoadFromStream(S: TStream);
|
||
|
public
|
||
|
Id: Integer; // not saved to stream
|
||
|
Offset: Cardinal; { Offset of field in the class data. }
|
||
|
ClassIndex: Word; { Index in the FieldClassTable. }
|
||
|
Name: ShortString;
|
||
|
FullFieldTypeName: String;
|
||
|
// PCU only
|
||
|
FinalFieldTypeId: Byte;
|
||
|
Vis: TClassVisibility;
|
||
|
end;
|
||
|
|
||
|
TFieldListContainer = class(TTypedList)
|
||
|
private
|
||
|
function GetRecord(I: Integer): TFieldDataContainer;
|
||
|
public
|
||
|
function Add: TFieldDataContainer;
|
||
|
procedure SaveToStream(S: TStream);
|
||
|
procedure LoadFromStream(S: TStream);
|
||
|
property Records[I: Integer]: TFieldDataContainer read GetRecord; default;
|
||
|
end;
|
||
|
|
||
|
TAnotherPropRec = class //PCU only
|
||
|
public
|
||
|
Vis: TClassVisibility;
|
||
|
PropName: String;
|
||
|
ParamNames: TStringList;
|
||
|
ParamTypes: TStringList;
|
||
|
PropType: String;
|
||
|
ReadName: String;
|
||
|
WriteName: String;
|
||
|
IsDefault: Boolean;
|
||
|
constructor Create;
|
||
|
destructor Destroy; override;
|
||
|
procedure SaveToStream(S: TStream);
|
||
|
procedure LoadFromStream(S: TStream);
|
||
|
end;
|
||
|
|
||
|
TAnotherPropList = class(TTypedList)
|
||
|
private
|
||
|
function GetRecord(I: Integer): TAnotherPropRec;
|
||
|
public
|
||
|
function Add: TAnotherPropRec;
|
||
|
procedure SaveToStream(S: TStream);
|
||
|
procedure LoadFromStream(S: TStream);
|
||
|
property Records[I: Integer]: TAnotherPropRec read GetRecord; default;
|
||
|
end;
|
||
|
|
||
|
TPropDataContainer = class
|
||
|
private
|
||
|
Owner: TTypeDataContainer;
|
||
|
function GetCount: Integer;
|
||
|
function GetSize: Integer;
|
||
|
public
|
||
|
PropData: TPropData;
|
||
|
PropList: array of TPropInfo;
|
||
|
PropTypeIds: array of Integer;
|
||
|
ReadNames: TStringList;
|
||
|
WriteNames: TStringList;
|
||
|
PropTypeNames: TStringList;
|
||
|
constructor Create(AOwner: TTypeDataContainer);
|
||
|
destructor Destroy; override;
|
||
|
procedure SaveToStream(S: TStream);
|
||
|
procedure SaveToBuff(S: TStream);
|
||
|
procedure LoadFromStream(S: TStream);
|
||
|
property Count: Integer read GetCount;
|
||
|
property Size: Integer read GetSize;
|
||
|
end;
|
||
|
|
||
|
TParamListContainer = class
|
||
|
private
|
||
|
Owner: TMethodTypeDataContainer;
|
||
|
function GetCount: Integer;
|
||
|
function GetSize: Integer;
|
||
|
public
|
||
|
ParamList: array of TParamData;
|
||
|
constructor Create(AOwner: TMethodTypeDataContainer);
|
||
|
destructor Destroy; override;
|
||
|
procedure SaveToStream(S: TStream);
|
||
|
procedure SaveToBuff(S: TStream);
|
||
|
procedure LoadFromStream(S: TStream);
|
||
|
property Count: Integer read GetCount;
|
||
|
property Size: Integer read GetSize;
|
||
|
end;
|
||
|
|
||
|
{$ifdef Ver360} // Delphi 12 Athens
|
||
|
TTypeDataXil = packed record
|
||
|
function NameListFld: TTypeInfoFieldAccessor; inline;
|
||
|
function UnitNameFld: TTypeInfoFieldAccessor; inline;
|
||
|
function IntfUnitFld: TTypeInfoFieldAccessor; inline;
|
||
|
function DynUnitNameFld: TTypeInfoFieldAccessor; inline;
|
||
|
|
||
|
function PropData: PPropData; inline;
|
||
|
function IntfMethods: PIntfMethodTable; inline;
|
||
|
|
||
|
function DynArrElType: PPTypeInfo; inline;
|
||
|
function DynArrAttrData: PAttrData; inline;
|
||
|
|
||
|
case TTypeKind of
|
||
|
tkUnknown: ();
|
||
|
tkUString,
|
||
|
{$IFNDEF NEXTGEN}
|
||
|
tkWString,
|
||
|
{$ENDIF !NEXTGEN}
|
||
|
tkVariant: (AttrData: TAttrData);
|
||
|
tkLString: (
|
||
|
CodePage: Word
|
||
|
{LStrAttrData: TAttrData});
|
||
|
tkInteger, tkChar, tkEnumeration, tkSet, tkWChar: (
|
||
|
OrdType: TOrdType;
|
||
|
case TTypeKind of
|
||
|
tkInteger, tkChar, tkEnumeration, tkWChar: (
|
||
|
|
||
|
MinValue: Integer;
|
||
|
MaxValue: Integer;
|
||
|
case TTypeKind of
|
||
|
tkInteger, tkChar, tkWChar: (
|
||
|
{OrdAttrData: TAttrData});
|
||
|
tkEnumeration: (
|
||
|
BaseType: PPTypeInfo;
|
||
|
NameList: TSymbolName;
|
||
|
{EnumUnitName: TSymbolName;
|
||
|
EnumAttrData: TAttrData}));
|
||
|
tkSet: (
|
||
|
CompType: PPTypeInfo
|
||
|
{SetAttrData: TAttrData}));
|
||
|
tkFloat: (
|
||
|
FloatType: TFloatType
|
||
|
{FloatAttrData: TAttrData});
|
||
|
{$IFNDEF NEXTGEN}
|
||
|
tkString: (
|
||
|
MaxLength: Byte
|
||
|
{StrAttrData: TAttrData});
|
||
|
{$ENDIF !NEXTGEN}
|
||
|
tkClass: (
|
||
|
ClassType: TClass; // most data for instance types is in VMT offsets
|
||
|
ParentInfo: PPTypeInfo;
|
||
|
PropCount: SmallInt; // total properties inc. ancestors
|
||
|
UnitName: TSymbolName;
|
||
|
{PropData: TPropData;
|
||
|
PropDataEx: TPropDataEx;
|
||
|
ClassAttrData: TAttrData;
|
||
|
ArrayPropCount: Word;
|
||
|
ArrayPropData: array[1..ArrayPropCount] of TArrayPropInfo;});
|
||
|
tkMethod: (
|
||
|
MethodKind: TMethodKind; // only mkFunction or mkProcedure
|
||
|
ParamCount: Byte;
|
||
|
{$IFNDEF NEXTGEN}
|
||
|
ParamList: array[0..1023] of AnsiChar
|
||
|
{$ELSE NEXTGEN}
|
||
|
ParamList: array[0..1023] of Byte
|
||
|
{$ENDIF NEXTGEN}
|
||
|
{ParamList: array[1..ParamCount] of
|
||
|
record
|
||
|
Flags: TParamFlags;
|
||
|
ParamName: ShortString;
|
||
|
TypeName: ShortString;
|
||
|
end;
|
||
|
ResultType: ShortString; // only if MethodKind = mkFunction
|
||
|
ResultTypeRef: PPTypeInfo; // only if MethodKind = mkFunction
|
||
|
CC: TCallConv;
|
||
|
ParamTypeRefs: array[1..ParamCount] of PPTypeInfo;
|
||
|
MethSig: PProcedureSignature;
|
||
|
MethAttrData: TAttrData});
|
||
|
tkProcedure: (
|
||
|
ProcSig: PProcedureSignature;
|
||
|
ProcAttrData: TAttrData;);
|
||
|
tkInterface: (
|
||
|
IntfParent : PPTypeInfo; { ancestor }
|
||
|
IntfFlags : TIntfFlagsBase;
|
||
|
Guid : TGUID;
|
||
|
IntfUnit : TSymbolName
|
||
|
{IntfMethods: TIntfMethodTable;
|
||
|
IntfAttrData: TAttrData;});
|
||
|
tkInt64: (
|
||
|
MinInt64Value, MaxInt64Value: Int64;
|
||
|
Int64AttrData: TAttrData;);
|
||
|
tkDynArray: (
|
||
|
|
||
|
elSize: Integer;
|
||
|
elType: PPTypeInfo; // nil if type does not require cleanup
|
||
|
varType: Integer; // Ole Automation varType equivalent
|
||
|
elType2: PPTypeInfo; // independent of cleanup
|
||
|
DynUnitName: TSymbolName;
|
||
|
{DynArrElType: PPTypeInfo; // actual element type, even if dynamic array
|
||
|
DynArrAttrData: TAttrData});
|
||
|
tkRecord: (
|
||
|
RecSize: Integer;
|
||
|
ManagedFldCount: Integer;
|
||
|
{ManagedFields: array[0..ManagedFldCnt - 1] of TManagedField;
|
||
|
NumOps: Byte;
|
||
|
RecOps: array[1..NumOps] of Pointer;
|
||
|
RecFldCnt: Integer;
|
||
|
RecFields: array[1..RecFldCnt] of TRecordTypeField;
|
||
|
RecAttrData: TAttrData;
|
||
|
RecMethCnt: Word;
|
||
|
RecMeths: array[1..RecMethCnt] of TRecordTypeMethod});
|
||
|
tkClassRef: (
|
||
|
InstanceType: PPTypeInfo;
|
||
|
ClassRefAttrData: TAttrData;);
|
||
|
tkPointer: (
|
||
|
RefType: PPTypeInfo;
|
||
|
PtrAttrData: TAttrData);
|
||
|
tkArray: (
|
||
|
ArrayData: TArrayTypeData;
|
||
|
{ArrAttrData: TAttrData});
|
||
|
end;
|
||
|
{$endif}
|
||
|
|
||
|
TTypeDataContainer = class
|
||
|
private
|
||
|
Owner: TTypeInfoContainer;
|
||
|
function GetTypeDataSize: Integer; virtual; //save to buff
|
||
|
function GetSize: Integer; virtual; // save to stream
|
||
|
public
|
||
|
{$ifdef Ver360} // Delphi 12 Athens
|
||
|
TypeData: TTypeDataXil;
|
||
|
{$else}
|
||
|
TypeData: TTypeData;
|
||
|
{$endif}
|
||
|
constructor Create(AOwner: TTypeInfoContainer);
|
||
|
destructor Destroy; override;
|
||
|
procedure SaveToStream(S: TStream); virtual;
|
||
|
procedure SaveToBuff(S: TStream); virtual;
|
||
|
procedure LoadFromStream(S: TStream); virtual;
|
||
|
property TypeDataSize: Integer read GetTypeDataSize;
|
||
|
property Size: Integer read GetSize;
|
||
|
end;
|
||
|
|
||
|
TMethodTypeDataContainer = class(TTypeDataContainer)
|
||
|
private
|
||
|
function GetTypeDataSize: Integer; override;
|
||
|
function GetSize: Integer; override;
|
||
|
public
|
||
|
MethodKind: TMethodKind;
|
||
|
ParamCount: Byte;
|
||
|
ParamListContainer: TParamListContainer;
|
||
|
// extra data
|
||
|
ResultType: ShortString;
|
||
|
OwnerTypeName: String;
|
||
|
MethodTableIndex: Integer;
|
||
|
ResultTypeId: Integer;
|
||
|
CallConv: Byte;
|
||
|
OverCount: Byte;
|
||
|
Address: Pointer; // not saved to stream
|
||
|
constructor Create(AOwner: TTypeInfoContainer);
|
||
|
destructor Destroy; override;
|
||
|
procedure SaveToStream(S: TStream); override;
|
||
|
procedure SaveToBuff(S: TStream); override;
|
||
|
procedure LoadFromStream(S: TStream); override;
|
||
|
end;
|
||
|
|
||
|
TClassTypeDataContainer = class(TTypeDataContainer)
|
||
|
private
|
||
|
function GetTypeDataSize: Integer; override;
|
||
|
function GetSize: Integer; override;
|
||
|
public
|
||
|
// info about published members
|
||
|
PropDataContainer: TPropDataContainer;
|
||
|
MethodTableCount: Integer;
|
||
|
MethodTableSize: Integer;
|
||
|
FieldTableCount: Integer;
|
||
|
FieldTableSize: Integer;
|
||
|
FullParentName: String;
|
||
|
FieldListContainer: TFieldListContainer;
|
||
|
|
||
|
// PCU only
|
||
|
AnotherFieldListContainer: TFieldListContainer;
|
||
|
AnotherPropList: TAnotherPropList;
|
||
|
SupportedInterfaces: TStringList;
|
||
|
|
||
|
constructor Create(AOwner: TTypeInfoContainer);
|
||
|
destructor Destroy; override;
|
||
|
procedure SaveToStream(S: TStream); override;
|
||
|
procedure SaveToBuff(S: TStream); override;
|
||
|
procedure LoadFromStream(S: TStream); override;
|
||
|
end;
|
||
|
|
||
|
TInterfaceTypeDataContainer = class(TTypeDataContainer)
|
||
|
private
|
||
|
function GetTypeDataSize: Integer; override;
|
||
|
function GetSize: Integer; override;
|
||
|
public
|
||
|
PropDataContainer: TPropDataContainer;
|
||
|
FullParentName: String;
|
||
|
GUID: TGUID;
|
||
|
SubDescList: TSubDescList;
|
||
|
constructor Create(AOwner: TTypeInfoContainer);
|
||
|
destructor Destroy; override;
|
||
|
procedure SaveToStream(S: TStream); override;
|
||
|
procedure SaveToBuff(S: TStream); override;
|
||
|
procedure LoadFromStream(S: TStream); override;
|
||
|
end;
|
||
|
|
||
|
TSetTypeDataContainer = class(TTypeDataContainer)
|
||
|
private
|
||
|
function GetSize: Integer; override;
|
||
|
public
|
||
|
FullCompName: String;
|
||
|
procedure SaveToStream(S: TStream); override;
|
||
|
procedure SaveToBuff(S: TStream); override;
|
||
|
procedure LoadFromStream(S: TStream); override;
|
||
|
end;
|
||
|
|
||
|
TEnumTypeDataContainer = class(TTypeDataContainer)
|
||
|
private
|
||
|
function GetTypeDataSize: Integer; override;
|
||
|
function GetSize: Integer; override;
|
||
|
public
|
||
|
NameList: array of ShortString;
|
||
|
EnumUnitName: ShortString;
|
||
|
|
||
|
//pcu only
|
||
|
ValueList: array of Integer;
|
||
|
procedure SaveToStream(S: TStream); override;
|
||
|
procedure SaveToBuff(S: TStream); override;
|
||
|
procedure LoadFromStream(S: TStream); override;
|
||
|
end;
|
||
|
|
||
|
TArrayTypeDataContainer = class(TTypeDataContainer)
|
||
|
public
|
||
|
FullRangeTypeName: String;
|
||
|
FullElemTypeName: String;
|
||
|
B1: Integer;
|
||
|
B2: Integer;
|
||
|
FinRangeTypeId: Integer;
|
||
|
procedure SaveToStream(S: TStream); override;
|
||
|
procedure SaveToBuff(S: TStream); override;
|
||
|
procedure LoadFromStream(S: TStream); override;
|
||
|
end;
|
||
|
|
||
|
TRecordTypeDataContainer = class(TTypeDataContainer)
|
||
|
private
|
||
|
function GetSize: Integer; override;
|
||
|
public
|
||
|
IsPacked: Boolean;
|
||
|
FieldListContainer: TFieldListContainer;
|
||
|
constructor Create(AOwner: TTypeInfoContainer);
|
||
|
destructor Destroy; override;
|
||
|
procedure SaveToStream(S: TStream); override;
|
||
|
procedure SaveToBuff(S: TStream); override;
|
||
|
procedure LoadFromStream(S: TStream); override;
|
||
|
end;
|
||
|
|
||
|
TAliasTypeDataContainer = class(TTypeDataContainer)
|
||
|
public
|
||
|
FullSourceTypeName: String;
|
||
|
procedure SaveToStream(S: TStream); override;
|
||
|
procedure LoadFromStream(S: TStream); override;
|
||
|
end;
|
||
|
|
||
|
TPointerTypeDataContainer = class(TTypeDataContainer)
|
||
|
public
|
||
|
FullOriginTypeName: String;
|
||
|
procedure SaveToStream(S: TStream); override;
|
||
|
procedure LoadFromStream(S: TStream); override;
|
||
|
end;
|
||
|
|
||
|
TClassRefTypeDataContainer = class(TTypeDataContainer)
|
||
|
public
|
||
|
FullOriginTypeName: String;
|
||
|
procedure SaveToStream(S: TStream); override;
|
||
|
procedure LoadFromStream(S: TStream); override;
|
||
|
end;
|
||
|
|
||
|
TDynArrayTypeDataContainer = class(TTypeDataContainer)
|
||
|
public
|
||
|
FullElementTypeName: String;
|
||
|
procedure SaveToStream(S: TStream); override;
|
||
|
procedure LoadFromStream(S: TStream); override;
|
||
|
end;
|
||
|
|
||
|
TProceduralTypeDataContainer = class(TTypeDataContainer)
|
||
|
public
|
||
|
SubDesc: TSubDesc;
|
||
|
constructor Create(AOwner: TTypeInfoContainer);
|
||
|
destructor Destroy; override;
|
||
|
procedure SaveToStream(S: TStream); override;
|
||
|
procedure LoadFromStream(S: TStream); override;
|
||
|
end;
|
||
|
|
||
|
{$IFDEF PAXARM}
|
||
|
TTypeInfoBuff = record
|
||
|
Kind: TTypeKind;
|
||
|
Name: ShortString;
|
||
|
end;
|
||
|
{$ELSE}
|
||
|
TTypeInfoBuff = TTypeInfo;
|
||
|
{$ENDIF}
|
||
|
|
||
|
TTypeInfoContainer = class
|
||
|
private
|
||
|
Buff: Pointer;
|
||
|
Buff4: Pointer;
|
||
|
Processed: Boolean;
|
||
|
function GetSize: Integer;
|
||
|
function GetPosTypeData: Integer;
|
||
|
function GetStreamSize: Integer;
|
||
|
function GetIsGeneric: Boolean;
|
||
|
public
|
||
|
TypeInfo: TTypeInfoBuff;
|
||
|
TypeDataContainer: TTypeDataContainer;
|
||
|
FullName: String;
|
||
|
FinTypeId: Byte;
|
||
|
GenericTypeContainer: TGenericTypeContainer;
|
||
|
|
||
|
constructor Create(AFinTypeId: Integer);
|
||
|
destructor Destroy; override;
|
||
|
procedure SaveToStream(S: TStream);
|
||
|
procedure SaveToBuff(S: TStream);
|
||
|
procedure LoadFromStream(S: TStream;
|
||
|
FinTypeId: Byte);
|
||
|
procedure RaiseError(const Message: string; params: array of Const);
|
||
|
property Size: Integer read GetSize;
|
||
|
property PosTypeData: Integer read GetPosTypeData;
|
||
|
property TypeInfoPtr: Pointer read Buff4;
|
||
|
property IsGeneric: Boolean read GetIsGeneric;
|
||
|
end;
|
||
|
|
||
|
TSetTypeInfoContainer = class(TTypeInfoContainer)
|
||
|
public
|
||
|
constructor Create(const AName: String);
|
||
|
end;
|
||
|
|
||
|
TEnumTypeInfoContainer = class(TTypeInfoContainer)
|
||
|
public
|
||
|
constructor Create(const AName: String);
|
||
|
end;
|
||
|
|
||
|
TClassTypeInfoContainer = class(TTypeInfoContainer)
|
||
|
public
|
||
|
constructor Create(const AName: String);
|
||
|
end;
|
||
|
|
||
|
TMethodTypeInfoContainer = class(TTypeInfoContainer)
|
||
|
public
|
||
|
constructor Create(const AName: String);
|
||
|
end;
|
||
|
|
||
|
TInterfaceTypeInfoContainer = class(TTypeInfoContainer)
|
||
|
public
|
||
|
constructor Create(const AName: String);
|
||
|
end;
|
||
|
|
||
|
TArrayTypeInfoContainer = class(TTypeInfoContainer)
|
||
|
public
|
||
|
constructor Create(const AName: String);
|
||
|
end;
|
||
|
|
||
|
TRecordTypeInfoContainer = class(TTypeInfoContainer)
|
||
|
public
|
||
|
constructor Create(const AName: String);
|
||
|
end;
|
||
|
|
||
|
TAliasTypeInfoContainer = class(TTypeInfoContainer)
|
||
|
public
|
||
|
constructor Create(const AName: String);
|
||
|
end;
|
||
|
|
||
|
TPointerTypeInfoContainer = class(TTypeInfoContainer)
|
||
|
public
|
||
|
constructor Create(const AName: String);
|
||
|
end;
|
||
|
|
||
|
TClassRefTypeInfoContainer = class(TTypeInfoContainer)
|
||
|
public
|
||
|
constructor Create(const AName: String);
|
||
|
end;
|
||
|
|
||
|
TDynArrayTypeInfoContainer = class(TTypeInfoContainer)
|
||
|
public
|
||
|
constructor Create(const AName: String);
|
||
|
end;
|
||
|
|
||
|
TProceduralTypeInfoContainer = class(TTypeInfoContainer)
|
||
|
public
|
||
|
constructor Create(const AName: String);
|
||
|
end;
|
||
|
|
||
|
TPaxTypeInfoList = class(TTypedList)
|
||
|
private
|
||
|
function GetRecord(I: Integer): TTypeInfoContainer;
|
||
|
procedure RaiseError(const Message: string; params: array of Const);
|
||
|
public
|
||
|
destructor Destroy; override;
|
||
|
procedure Add(Rec: TTypeInfoContainer);
|
||
|
function IndexOf(const FullName: String): Integer;
|
||
|
function LookupFullName(const FullName: String): TTypeInfoContainer;
|
||
|
procedure CopyToBuff;
|
||
|
procedure SaveToStream(S: TStream);
|
||
|
procedure LoadFromStream(S: TStream);
|
||
|
procedure AddToProgram(AProg: Pointer);
|
||
|
function FindMethodFullName(Address: Pointer): String;
|
||
|
function Processed: Boolean;
|
||
|
property Records[I: Integer]: TTypeInfoContainer read GetRecord; default;
|
||
|
end;
|
||
|
|
||
|
function FinTypeToTypeKind(FinTypeId: Integer): TTypeKind;
|
||
|
function GetClassTypeInfoContainer(X: TObject): TClassTypeInfoContainer;
|
||
|
function PtiToFinType(Pti: PTypeInfo): Integer;
|
||
|
|
||
|
implementation
|
||
|
|
||
|
uses
|
||
|
PAXCOMP_CLASSLST,
|
||
|
PAXCOMP_STDLIB,
|
||
|
PAXCOMP_BASERUNNER;
|
||
|
|
||
|
{$ifdef Ver360} // Delphi 12 Athens
|
||
|
{ TTypeDataXil }
|
||
|
|
||
|
function TTypeDataXil.NameListFld: TTypeInfoFieldAccessor;
|
||
|
begin
|
||
|
Result.SetData(@NameList);
|
||
|
end;
|
||
|
|
||
|
function TTypeDataXil.UnitNameFld: TTypeInfoFieldAccessor;
|
||
|
begin
|
||
|
Result.SetData(@UnitName);
|
||
|
end;
|
||
|
|
||
|
function TTypeDataXil.IntfUnitFld: TTypeInfoFieldAccessor;
|
||
|
begin
|
||
|
Result.SetData(@IntfUnit);
|
||
|
end;
|
||
|
|
||
|
function TTypeDataXil.DynUnitNameFld: TTypeInfoFieldAccessor;
|
||
|
begin
|
||
|
Result.SetData(@DynUnitName);
|
||
|
end;
|
||
|
|
||
|
function TTypeDataXil.PropData: PPropData;
|
||
|
begin
|
||
|
Result := PPropData(UnitNameFld.Tail)
|
||
|
end;
|
||
|
|
||
|
function TTypeDataXil.IntfMethods: PIntfMethodTable;
|
||
|
begin
|
||
|
Result := PIntfMethodTable(IntfUnitFld.Tail);
|
||
|
end;
|
||
|
|
||
|
function TTypeDataXil.DynArrElType: PPTypeInfo;
|
||
|
type
|
||
|
PPPTypeInfo = ^PPTypeInfo;
|
||
|
begin
|
||
|
Result := PPPTypeInfo(DynUnitNameFld.Tail)^;
|
||
|
end;
|
||
|
|
||
|
function TTypeDataXil.DynArrAttrData: PAttrData;
|
||
|
begin
|
||
|
Result := PAttrData(Self.DynUnitNameFld.Tail + SizeOf(PPTypeInfo));
|
||
|
end;
|
||
|
{$endif}
|
||
|
|
||
|
function FinTypeToTypeKind(FinTypeId: Integer): TTypeKind;
|
||
|
begin
|
||
|
result := tkUnknown;
|
||
|
case FinTypeId of
|
||
|
|
||
|
{$IFNDEF PAXARM}
|
||
|
typeWIDESTRING: result := tkWString;
|
||
|
typeANSISTRING: result := tkLString;
|
||
|
typeANSICHAR: result := tkChar;
|
||
|
typeSHORTSTRING: result := tkString;
|
||
|
{$ENDIF}
|
||
|
|
||
|
{$IFDEF UNIC}
|
||
|
typeUNICSTRING: result := tkUString;
|
||
|
{$ENDIF}
|
||
|
typeVARIANT, typeOLEVARIANT: result := tkVariant;
|
||
|
typeINTEGER, typeBYTE, typeWORD, typeCARDINAL,
|
||
|
typeSMALLINT, typeSHORTINT: result := tkInteger;
|
||
|
typeENUM, typeBOOLEAN, typeBYTEBOOL, typeWORDBOOL, typeLONGBOOL: result := tkEnumeration;
|
||
|
typeSET: result := tkSet;
|
||
|
typeWIDECHAR: result := tkWChar;
|
||
|
typeSINGLE, typeDOUBLE, typeEXTENDED, typeCURRENCY: result := tkFloat;
|
||
|
typeEVENT: result := tkMethod;
|
||
|
typeCLASS: result := tkClass;
|
||
|
typeINT64: result := tkInt64;
|
||
|
typeDYNARRAY: result := tkDynArray;
|
||
|
typeINTERFACE: result := tkInterface;
|
||
|
typeRECORD: result := tkRecord;
|
||
|
typeARRAY: result := tkArray;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
function PtiToFinType(Pti: PTypeInfo): Integer;
|
||
|
begin
|
||
|
result := 0;
|
||
|
case Pti^.Kind of
|
||
|
tkInteger:
|
||
|
case GetTypeData(pti).OrdType of
|
||
|
otSByte: result := typeSMALLINT;
|
||
|
otUByte: result := typeBYTE;
|
||
|
otSWord: result := typeSHORTINT;
|
||
|
otUWord: result := typeWORD;
|
||
|
otSLong: result := typeINTEGER;
|
||
|
otULong: result := typeCARDINAL;
|
||
|
end;
|
||
|
tkChar:
|
||
|
result := typeCHAR;
|
||
|
tkWChar:
|
||
|
result := typeWIDECHAR;
|
||
|
{$IFNDEF PAXARM}
|
||
|
tkString:
|
||
|
result := typeSHORTSTRING;
|
||
|
tkLString:
|
||
|
result := typeANSISTRING;
|
||
|
tkWString:
|
||
|
result := typeWIDESTRING;
|
||
|
{$ENDIF}
|
||
|
{$IFDEF UNIC}
|
||
|
tkUString:
|
||
|
result := typeUNICSTRING;
|
||
|
{$ENDIF}
|
||
|
tkFloat:
|
||
|
case GetTypeData(pti)^.FloatType of
|
||
|
ftSingle: result := typeSINGLE;
|
||
|
ftDouble: result := typeDOUBLE;
|
||
|
ftExtended: result := typeEXTENDED;
|
||
|
ftComp: result := 0;
|
||
|
ftCurr: result := typeCURRENCY;
|
||
|
end;
|
||
|
{$IFDEF UNIC}
|
||
|
tkPointer:
|
||
|
result := typePOINTER;
|
||
|
{$ENDIF}
|
||
|
tkClass:
|
||
|
result := typeCLASS;
|
||
|
{$IFDEF UNIC}
|
||
|
tkClassRef:
|
||
|
result := typeCLASSREF;
|
||
|
tkProcedure:
|
||
|
result := typePROC;
|
||
|
{$ENDIF}
|
||
|
tkMethod:
|
||
|
result := typeEVENT;
|
||
|
tkInterface:
|
||
|
result := typeINTERFACE;
|
||
|
tkInt64:
|
||
|
result := typeINT64;
|
||
|
tkEnumeration:
|
||
|
result := typeENUM;
|
||
|
tkVariant:
|
||
|
result := typeVARIANT;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
// TAnotherPropRec -------------------------------------------------------------
|
||
|
|
||
|
constructor TAnotherPropRec.Create;
|
||
|
begin
|
||
|
inherited;
|
||
|
ParamNames := TStringList.Create;
|
||
|
ParamTypes := TStringList.Create;
|
||
|
end;
|
||
|
|
||
|
destructor TAnotherPropRec.Destroy;
|
||
|
begin
|
||
|
FreeAndNil(ParamNames);
|
||
|
FreeAndNil(ParamTypes);
|
||
|
inherited;
|
||
|
end;
|
||
|
|
||
|
procedure TAnotherPropRec.SaveToStream(S: TStream);
|
||
|
begin
|
||
|
S.Write(Vis, SizeOf(Vis));
|
||
|
SaveStringToStream(PropName, S);
|
||
|
SaveStringListToStream(ParamNames, S);
|
||
|
SaveStringListToStream(ParamTypes, S);
|
||
|
SaveStringToStream(PropType, S);
|
||
|
SaveStringToStream(ReadName, S);
|
||
|
SaveStringToStream(WriteName, S);
|
||
|
S.Write(IsDefault, SizeOf(IsDefault));
|
||
|
end;
|
||
|
|
||
|
procedure TAnotherPropRec.LoadFromStream(S: TStream);
|
||
|
begin
|
||
|
S.Read(Vis, SizeOf(Vis));
|
||
|
PropName := LoadStringFromStream(S);
|
||
|
LoadStringListFromStream(ParamNames, S);
|
||
|
LoadStringListFromStream(ParamTypes, S);
|
||
|
PropType := LoadStringFromStream(S);
|
||
|
ReadName := LoadStringFromStream(S);
|
||
|
WriteName := LoadStringFromStream(S);
|
||
|
S.Read(IsDefault, SizeOf(IsDefault));
|
||
|
end;
|
||
|
|
||
|
// TAnotherPropList ------------------------------------------------------------
|
||
|
|
||
|
function TAnotherPropList.GetRecord(I: Integer): TAnotherPropRec;
|
||
|
begin
|
||
|
result := TAnotherPropRec(L[I]);
|
||
|
end;
|
||
|
|
||
|
function TAnotherPropList.Add: TAnotherPropRec;
|
||
|
begin
|
||
|
result := TAnotherPropRec.Create;
|
||
|
L.Add(result);
|
||
|
end;
|
||
|
|
||
|
procedure TAnotherPropList.SaveToStream(S: TStream);
|
||
|
var
|
||
|
I, K: Integer;
|
||
|
begin
|
||
|
K := Count;
|
||
|
S.Write(K, SizeOf(K));
|
||
|
for I := 0 to K - 1 do
|
||
|
Records[I].SaveToStream(S);
|
||
|
end;
|
||
|
|
||
|
procedure TAnotherPropList.LoadFromStream(S: TStream);
|
||
|
var
|
||
|
I, K: Integer;
|
||
|
R: TAnotherPropRec;
|
||
|
begin
|
||
|
S.Read(K, SizeOf(K));
|
||
|
for I := 0 to K - 1 do
|
||
|
begin
|
||
|
R := Add;
|
||
|
R.LoadFromStream(S);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
// TFieldDataContainer ---------------------------------------------------------
|
||
|
|
||
|
procedure TFieldDataContainer.SaveToStream(S: TStream);
|
||
|
begin
|
||
|
S.Write(Offset, SizeOf(Offset));
|
||
|
S.Write(ClassIndex, SizeOf(ClassIndex));
|
||
|
SaveShortStringToStream(Name, S);
|
||
|
SaveStringToStream(FullFieldTypeName, S);
|
||
|
S.Write(Vis, SizeOf(Vis));
|
||
|
{$IFDEF PCU_EX}
|
||
|
S.Write(FinalFieldTypeId, SizeOf(FinalFieldTypeId));
|
||
|
{$ENDIF}
|
||
|
end;
|
||
|
|
||
|
procedure TFieldDataContainer.LoadFromStream(S: TStream);
|
||
|
begin
|
||
|
S.Read(Offset, SizeOf(Offset));
|
||
|
S.Read(ClassIndex, SizeOf(ClassIndex));
|
||
|
Name := LoadShortStringFromStream(S);
|
||
|
FullFieldTypeName := LoadStringFromStream(S);
|
||
|
S.Read(Vis, SizeOf(Vis));
|
||
|
{$IFDEF PCU_EX}
|
||
|
S.Read(FinalFieldTypeId, SizeOf(FinalFieldTypeId));
|
||
|
{$ENDIF}
|
||
|
end;
|
||
|
|
||
|
// TFieldListContainer ---------------------------------------------------------
|
||
|
|
||
|
function TFieldListContainer.GetRecord(I: Integer): TFieldDataContainer;
|
||
|
begin
|
||
|
result := TFieldDataContainer(L[I]);
|
||
|
end;
|
||
|
|
||
|
function TFieldListContainer.Add: TFieldDataContainer;
|
||
|
begin
|
||
|
result := TFieldDataContainer.Create;
|
||
|
L.Add(result);
|
||
|
end;
|
||
|
|
||
|
procedure TFieldListContainer.SaveToStream(S: TStream);
|
||
|
var
|
||
|
I, K: Integer;
|
||
|
begin
|
||
|
K := Count;
|
||
|
S.Write(K, SizeOf(K));
|
||
|
for I := 0 to K - 1 do
|
||
|
Records[I].SaveToStream(S);
|
||
|
end;
|
||
|
|
||
|
procedure TFieldListContainer.LoadFromStream(S: TStream);
|
||
|
var
|
||
|
I, K: Integer;
|
||
|
R: TFieldDataContainer;
|
||
|
begin
|
||
|
S.Read(K, SizeOf(K));
|
||
|
for I := 0 to K - 1 do
|
||
|
begin
|
||
|
R := Add;
|
||
|
R.LoadFromStream(S);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
// TParamListContainer ---------------------------------------------------------
|
||
|
|
||
|
constructor TParamListContainer.Create(AOwner: TMethodTypeDataContainer);
|
||
|
begin
|
||
|
inherited Create;
|
||
|
Owner := AOwner;
|
||
|
end;
|
||
|
|
||
|
destructor TParamListContainer.Destroy;
|
||
|
begin
|
||
|
inherited;
|
||
|
end;
|
||
|
|
||
|
function TParamListContainer.GetCount: Integer;
|
||
|
begin
|
||
|
result := System.Length(ParamList);
|
||
|
end;
|
||
|
|
||
|
function TParamListContainer.GetSize: Integer;
|
||
|
var
|
||
|
I: Integer;
|
||
|
begin
|
||
|
result := 0;
|
||
|
for I := 0 to Count - 1 do
|
||
|
begin
|
||
|
Inc(result, SizeOf(ParamList[I].Flags));
|
||
|
Inc(result, Length(ParamList[I].ParamName) + 1);
|
||
|
Inc(result, Length(ParamList[I].TypeName) + 1);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TParamListContainer.SaveToStream(S: TStream);
|
||
|
var
|
||
|
I, K: Integer;
|
||
|
begin
|
||
|
K := Count;
|
||
|
S.Write(K, SizeOf(Integer));
|
||
|
for I := 0 to Count - 1 do
|
||
|
with ParamList[I] do
|
||
|
begin
|
||
|
S.Write(Flags, SizeOf(Flags));
|
||
|
SaveShortStringToStream(ParamName, S);
|
||
|
SaveShortStringToStream(TypeName, S);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TParamListContainer.SaveToBuff(S: TStream);
|
||
|
var
|
||
|
I: Integer;
|
||
|
begin
|
||
|
for I := 0 to Count - 1 do
|
||
|
with ParamList[I] do
|
||
|
begin
|
||
|
S.Write(Flags, SizeOf(Flags));
|
||
|
SaveShortStringToStream(ParamName, S);
|
||
|
SaveShortStringToStream(TypeName, S);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TParamListContainer.LoadFromStream(S: TStream);
|
||
|
var
|
||
|
I, K: Integer;
|
||
|
begin
|
||
|
S.Read(K, SizeOf(Integer));
|
||
|
SetLength(ParamList, K);
|
||
|
for I := 0 to Count - 1 do
|
||
|
with ParamList[I] do
|
||
|
begin
|
||
|
S.Read(Flags, SizeOf(Flags));
|
||
|
ParamName := LoadShortStringFromStream(S);
|
||
|
TypeName := LoadShortStringFromStream(S);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
// TPropDataContainer -------------------------------------------------------
|
||
|
|
||
|
constructor TPropDataContainer.Create(AOwner: TTypeDataContainer);
|
||
|
begin
|
||
|
Owner := AOwner;
|
||
|
ReadNames := TStringList.Create;
|
||
|
WriteNames := TStringList.Create;
|
||
|
PropTypeNames := TStringList.Create;
|
||
|
inherited Create;
|
||
|
end;
|
||
|
|
||
|
function PropInfoSize(const PropInfo: TPropInfo): Integer;
|
||
|
begin
|
||
|
{$IFDEF PAXARM}
|
||
|
result := SizeOf(TPropInfo) - SizeOf(ShortString) +
|
||
|
{$IFDEF ARC}
|
||
|
PropInfo.Name + 1;
|
||
|
{$ELSE}
|
||
|
Length(PropInfo.Name) + 1;
|
||
|
{$ENDIF}
|
||
|
{$ELSE}
|
||
|
result := SizeOf(TPropInfo) - SizeOf(ShortString) +
|
||
|
Length(PropInfo.Name) + 1;
|
||
|
{$ENDIF}
|
||
|
end;
|
||
|
|
||
|
destructor TPropDataContainer.Destroy;
|
||
|
begin
|
||
|
FreeAndNil(ReadNames);
|
||
|
FreeAndNil(WriteNames);
|
||
|
FreeAndNil(PropTypeNames);
|
||
|
inherited;
|
||
|
end;
|
||
|
|
||
|
function TPropDataContainer.GetCount: Integer;
|
||
|
begin
|
||
|
result := PropData.PropCount;
|
||
|
end;
|
||
|
|
||
|
function TPropDataContainer.GetSize: Integer;
|
||
|
var
|
||
|
I: Integer;
|
||
|
begin
|
||
|
result := SizeOf(TPropData);
|
||
|
for I := 0 to Count - 1 do
|
||
|
Inc(result, PropInfoSize(PropList[I]));
|
||
|
{$IFDEF DRTTI}
|
||
|
Inc(result, SizeOf(TPropDataEx));
|
||
|
{$ELSE}
|
||
|
{$IFDEF DPULSAR}
|
||
|
Inc(result, SizeOf(TPropInfoEx));
|
||
|
{$ENDIF}
|
||
|
{$ENDIF}
|
||
|
end;
|
||
|
|
||
|
procedure TPropDataContainer.SaveToStream(S: TStream);
|
||
|
var
|
||
|
I, SZ: Integer;
|
||
|
begin
|
||
|
S.Write(PropData, SizeOf(TPropData));
|
||
|
for I := 0 to Count - 1 do
|
||
|
begin
|
||
|
SZ := PropInfoSize(PropList[I]);
|
||
|
S.Write(SZ, SizeOf(Integer));
|
||
|
S.Write(PropList[I], SZ);
|
||
|
end;
|
||
|
SaveStringListToStream(ReadNames, S);
|
||
|
SaveStringListToStream(WriteNames, S);
|
||
|
SaveStringListToStream(PropTypeNames, S);
|
||
|
for I := 0 to Count - 1 do
|
||
|
S.Write(PropTypeIds[I], SizeOf(PropTypeIds[I]));
|
||
|
end;
|
||
|
|
||
|
procedure TPropDataContainer.SaveToBuff(S: TStream);
|
||
|
var
|
||
|
I: Integer;
|
||
|
{$IFDEF DRTTI}
|
||
|
PropEx: TPropDataEx;
|
||
|
{$ELSE}
|
||
|
{$IFDEF DPULSAR}
|
||
|
PropEx: TPropDataEx;
|
||
|
{$ENDIF}
|
||
|
{$ENDIF}
|
||
|
begin
|
||
|
S.Write(PropData, SizeOf(TPropData));
|
||
|
for I := 0 to Count - 1 do
|
||
|
S.Write(PropList[I], PropInfoSize(PropList[I]));
|
||
|
|
||
|
{$IFDEF DRTTI}
|
||
|
FillChar(PropEx, SizeOf(PropEx), #0);
|
||
|
S.Write(PropEx, SizeOf(TPropDataEx));
|
||
|
{$ELSE}
|
||
|
{$IFDEF DPULSAR}
|
||
|
FillChar(PropEx, SizeOf(PropEx), #0);
|
||
|
S.Write(PropEx, SizeOf(TPropDataEx));
|
||
|
{$ENDIF}
|
||
|
{$ENDIF}
|
||
|
end;
|
||
|
|
||
|
procedure TPropDataContainer.LoadFromStream(S: TStream);
|
||
|
var
|
||
|
I, SZ: Integer;
|
||
|
begin
|
||
|
S.Read(PropData, SizeOf(TPropData));
|
||
|
SetLength(PropList, PropData.PropCount);
|
||
|
for I := 0 to PropData.PropCount - 1 do
|
||
|
begin
|
||
|
S.Read(SZ, SizeOf(Integer));
|
||
|
S.Read(PropList[I], SZ);
|
||
|
end;
|
||
|
LoadStringListFromStream(ReadNames, S);
|
||
|
LoadStringListFromStream(WriteNames, S);
|
||
|
LoadStringListFromStream(PropTypeNames, S);
|
||
|
SetLength(PropTypeIds, PropData.PropCount);
|
||
|
for I := 0 to PropData.PropCount - 1 do
|
||
|
S.Read(PropTypeIds[I], SizeOf(PropTypeIds));
|
||
|
end;
|
||
|
|
||
|
// TTypeDataContainer -------------------------------------------------------
|
||
|
|
||
|
constructor TTypeDataContainer.Create(AOwner: TTypeInfoContainer);
|
||
|
begin
|
||
|
Owner := AOwner;
|
||
|
inherited Create;
|
||
|
end;
|
||
|
|
||
|
destructor TTypeDataContainer.Destroy;
|
||
|
begin
|
||
|
inherited;
|
||
|
end;
|
||
|
|
||
|
function TTypeDataContainer.GetTypeDataSize: Integer;
|
||
|
begin
|
||
|
result := SizeOf(TypeData);
|
||
|
end;
|
||
|
|
||
|
function TTypeDataContainer.GetSize: Integer;
|
||
|
begin
|
||
|
result := SizeOf(TypeData);
|
||
|
end;
|
||
|
|
||
|
procedure TTypeDataContainer.SaveToStream(S: TStream);
|
||
|
begin
|
||
|
S.Write(TypeData, 16);
|
||
|
end;
|
||
|
|
||
|
procedure TTypeDataContainer.SaveToBuff(S: TStream);
|
||
|
begin
|
||
|
S.Write(TypeData, SizeOf(TypeData));
|
||
|
end;
|
||
|
|
||
|
procedure TTypeDataContainer.LoadFromStream(S: TStream);
|
||
|
begin
|
||
|
FillChar(TypeData, SizeOf(TypeData), 0);
|
||
|
S.Read(TypeData, 16);
|
||
|
end;
|
||
|
|
||
|
// TMethodTypeDataContainer ----------------------------------------------------
|
||
|
|
||
|
constructor TMethodTypeDataContainer.Create(AOwner: TTypeInfoContainer);
|
||
|
begin
|
||
|
inherited;
|
||
|
ParamListContainer := TParamListContainer.Create(Self);
|
||
|
end;
|
||
|
|
||
|
destructor TMethodTypeDataContainer.Destroy;
|
||
|
begin
|
||
|
FreeAndNil(ParamListContainer);
|
||
|
inherited;
|
||
|
end;
|
||
|
|
||
|
function TMethodTypeDataContainer.GetTypeDataSize: Integer;
|
||
|
begin
|
||
|
result := SizeOf(MethodKind) + SizeOf(ParamCount);
|
||
|
end;
|
||
|
|
||
|
function TMethodTypeDataContainer.GetSize: Integer;
|
||
|
begin
|
||
|
result := TypeDataSize + ParamListContainer.Size +
|
||
|
Length(ResultType) + 1;
|
||
|
end;
|
||
|
|
||
|
procedure TMethodTypeDataContainer.SaveToStream(S: TStream);
|
||
|
begin
|
||
|
S.Write(MethodKind, SizeOf(MethodKind));
|
||
|
S.Write(ParamCount, SizeOf(ParamCount));
|
||
|
ParamListContainer.SaveToStream(S);
|
||
|
SaveShortStringToStream(ResultType, S);
|
||
|
SaveStringToStream(OwnerTypeName, S);
|
||
|
S.Write(MethodTableIndex, SizeOf(MethodTableIndex));
|
||
|
S.Write(ResultTypeId, SizeOf(ResultTypeId));
|
||
|
S.Write(CallConv, SizeOf(CallConv));
|
||
|
S.Write(OverCount, SizeOf(OverCount));
|
||
|
end;
|
||
|
|
||
|
procedure TMethodTypeDataContainer.SaveToBuff(S: TStream);
|
||
|
begin
|
||
|
S.Write(MethodKind, SizeOf(MethodKind));
|
||
|
S.Write(ParamCount, SizeOf(ParamCount));
|
||
|
ParamListContainer.SaveToBuff(S);
|
||
|
SaveShortStringToStream(ResultType, S);
|
||
|
end;
|
||
|
|
||
|
procedure TMethodTypeDataContainer.LoadFromStream(S: TStream);
|
||
|
begin
|
||
|
S.Read(MethodKind, SizeOf(MethodKind));
|
||
|
S.Read(ParamCount, SizeOf(ParamCount));
|
||
|
ParamListContainer.LoadFromStream(S);
|
||
|
ResultType := LoadShortStringFromStream(S);
|
||
|
OwnerTypeName := LoadStringFromStream(S);
|
||
|
S.Read(MethodTableIndex, SizeOf(MethodTableIndex));
|
||
|
S.Read(ResultTypeId, SizeOf(ResultTypeId));
|
||
|
S.Read(CallConv, SizeOf(CallConv));
|
||
|
S.Read(OverCount, SizeOf(OverCount));
|
||
|
end;
|
||
|
|
||
|
// TClassTypeDataContainer -----------------------------------------------------
|
||
|
|
||
|
constructor TClassTypeDataContainer.Create(AOwner: TTypeInfoContainer);
|
||
|
begin
|
||
|
inherited;
|
||
|
|
||
|
PropDataContainer := TPropDataContainer.Create(Self);
|
||
|
FieldListContainer := TFieldListContainer.Create;
|
||
|
|
||
|
AnotherFieldListContainer := TFieldListContainer.Create;
|
||
|
AnotherPropList := TAnotherPropList.Create;
|
||
|
SupportedInterfaces := TStringList.Create;
|
||
|
|
||
|
end;
|
||
|
|
||
|
destructor TClassTypeDataContainer.Destroy;
|
||
|
begin
|
||
|
FreeAndNil(PropDataContainer);
|
||
|
FreeAndNil(FieldListContainer);
|
||
|
|
||
|
FreeAndNil(AnotherFieldListContainer);
|
||
|
FreeAndNil(AnotherPropList);
|
||
|
FreeAndNil(SupportedInterfaces);
|
||
|
|
||
|
inherited;
|
||
|
end;
|
||
|
|
||
|
function TClassTypeDataContainer.GetTypeDataSize: Integer;
|
||
|
begin
|
||
|
{$IFDEF PAXARM}
|
||
|
result := SizeOf(TypeData.ClassType) +
|
||
|
SizeOf(TypeData.ParentInfo) +
|
||
|
SizeOf(TypeData.PropCount) +
|
||
|
{$IFDEF ARC}
|
||
|
TypeData.UnitName + 1;
|
||
|
{$ELSE}
|
||
|
Length(TypeData.UnitName) + 1;
|
||
|
{$ENDIF}
|
||
|
{$ELSE}
|
||
|
result := SizeOf(TypeData.ClassType) +
|
||
|
SizeOf(TypeData.ParentInfo) +
|
||
|
SizeOf(TypeData.PropCount) +
|
||
|
Length(TypeData.UnitName) + 1;
|
||
|
{$ENDIF}
|
||
|
end;
|
||
|
|
||
|
function TClassTypeDataContainer.GetSize: Integer;
|
||
|
begin
|
||
|
result := TypeDataSize +
|
||
|
PropDataContainer.Size;
|
||
|
end;
|
||
|
|
||
|
procedure TClassTypeDataContainer.SaveToStream(S: TStream);
|
||
|
var
|
||
|
K: Integer;
|
||
|
begin
|
||
|
K := TypeDataSize;
|
||
|
S.Write(K, SizeOf(K));
|
||
|
S.Write(TypeData, TypeDataSize);
|
||
|
PropDataContainer.SaveToStream(S);
|
||
|
S.Write(MethodTableCount, SizeOf(MethodTableCount));
|
||
|
S.Write(MethodTableSize, SizeOf(MethodTableSize));
|
||
|
S.Write(FieldTableCount, SizeOf(FieldTableCount));
|
||
|
S.Write(FieldTableSize, SizeOf(FieldTableSize));
|
||
|
SaveStringToStream(FullParentName, S);
|
||
|
FieldListContainer.SaveToStream(S);
|
||
|
AnotherFieldListContainer.SaveToStream(S);
|
||
|
AnotherPropList.SaveToStream(S);
|
||
|
SaveStringListToStream(SupportedInterfaces, S);
|
||
|
end;
|
||
|
|
||
|
procedure TClassTypeDataContainer.SaveToBuff(S: TStream);
|
||
|
begin
|
||
|
S.Write(TypeData, TypeDataSize);
|
||
|
PropDataContainer.SaveToBuff(S);
|
||
|
end;
|
||
|
|
||
|
procedure TClassTypeDataContainer.LoadFromStream(S: TStream);
|
||
|
var
|
||
|
K: Integer;
|
||
|
begin
|
||
|
S.Read(K, SizeOf(K));
|
||
|
S.Read(TypeData, K);
|
||
|
PropDataContainer.LoadFromStream(S);
|
||
|
S.Read(MethodTableCount, SizeOf(MethodTableCount));
|
||
|
S.Read(MethodTableSize, SizeOf(MethodTableSize));
|
||
|
S.Read(FieldTableCount, SizeOf(FieldTableCount));
|
||
|
S.Read(FieldTableSize, SizeOf(FieldTableSize));
|
||
|
FullParentName := LoadStringFromStream(S);
|
||
|
FieldListContainer.LoadFromStream(S);
|
||
|
AnotherFieldListContainer.LoadFromStream(S);
|
||
|
AnotherPropList.LoadFromStream(S);
|
||
|
LoadStringListFromStream(SupportedInterfaces, S);
|
||
|
end;
|
||
|
|
||
|
// TSetTypeDataContainer -------------------------------------------------
|
||
|
|
||
|
function TSetTypeDataContainer.GetSize: Integer;
|
||
|
begin
|
||
|
result := SizeOf(TypeData);
|
||
|
end;
|
||
|
|
||
|
procedure TSetTypeDataContainer.SaveToStream(S: TStream);
|
||
|
begin
|
||
|
inherited;
|
||
|
SaveStringToStream(FullCompName, S);
|
||
|
end;
|
||
|
|
||
|
procedure TSetTypeDataContainer.SaveToBuff(S: TStream);
|
||
|
begin
|
||
|
S.Write(TypeData, SizeOf(TypeData));
|
||
|
end;
|
||
|
|
||
|
procedure TSetTypeDataContainer.LoadFromStream(S: TStream);
|
||
|
begin
|
||
|
inherited;
|
||
|
FullCompName := LoadStringFromStream(S);
|
||
|
end;
|
||
|
|
||
|
|
||
|
// TEnumTypeDataContainer ------------------------------------------------------
|
||
|
|
||
|
function TEnumTypeDataContainer.GetTypeDataSize: Integer;
|
||
|
begin
|
||
|
result := SizeOf(TOrdType) +
|
||
|
SizeOf(Longint) + // min value
|
||
|
SizeOf(Longint) + // max value
|
||
|
SizeOf(Pointer); // base type
|
||
|
end;
|
||
|
|
||
|
function TEnumTypeDataContainer.GetSize: Integer;
|
||
|
begin
|
||
|
result := GetTypeDataSize;
|
||
|
|
||
|
{
|
||
|
for I := 0 to Length(NameList) - 1 do
|
||
|
Inc(result, Length(NameList[I]) + 1);
|
||
|
}
|
||
|
Inc(result, 256);
|
||
|
|
||
|
Inc(result, Length(EnumUnitName) + 1);
|
||
|
end;
|
||
|
|
||
|
procedure TEnumTypeDataContainer.SaveToStream(S: TStream);
|
||
|
var
|
||
|
I, K: Integer;
|
||
|
begin
|
||
|
S.Write(TypeData, GetTypeDataSize);
|
||
|
K := System.Length(NameList);
|
||
|
S.Write(K, SizeOf(K));
|
||
|
for I := 0 to K - 1 do
|
||
|
SaveShortStringToStream(NameList[I], S);
|
||
|
SaveShortStringToStream(EnumUnitName, S);
|
||
|
for I := 0 to K - 1 do
|
||
|
S.Write(ValueList[I], SizeOf(ValueList[I]));
|
||
|
end;
|
||
|
|
||
|
procedure TEnumTypeDataContainer.SaveToBuff(S: TStream);
|
||
|
var
|
||
|
I, K, Z: Integer;
|
||
|
B: Byte;
|
||
|
begin
|
||
|
S.Write(TypeData, GetTypeDataSize);
|
||
|
K := System.Length(NameList);
|
||
|
Z := 0;
|
||
|
for I := 0 to K - 1 do
|
||
|
begin
|
||
|
SaveShortStringToStream(NameList[I], S);
|
||
|
Inc(z, Length(NameList[I]) + 1);
|
||
|
end;
|
||
|
B := 0;
|
||
|
while Z < 256 do
|
||
|
begin
|
||
|
Inc(Z);
|
||
|
S.Write(B, 1);
|
||
|
end;
|
||
|
SaveShortStringToStream(EnumUnitName, S);
|
||
|
end;
|
||
|
|
||
|
procedure TEnumTypeDataContainer.LoadFromStream(S: TStream);
|
||
|
var
|
||
|
I, K: Integer;
|
||
|
begin
|
||
|
S.Read(TypeData, GetTypeDataSize);
|
||
|
S.Read(K, SizeOf(K));
|
||
|
SetLength(NameList, K);
|
||
|
for I := 0 to K - 1 do
|
||
|
NameList[I] := LoadShortStringFromStream(S);
|
||
|
EnumUnitName := LoadShortStringFromStream(S);
|
||
|
SetLength(ValueList, K);
|
||
|
for I := 0 to K - 1 do
|
||
|
S.Read(ValueList[I], SizeOf(ValueList[I]));
|
||
|
end;
|
||
|
|
||
|
// TInterfaceTypeDataContainer -------------------------------------------------
|
||
|
|
||
|
constructor TInterfaceTypeDataContainer.Create(AOwner: TTypeInfoContainer);
|
||
|
begin
|
||
|
inherited;
|
||
|
PropDataContainer := TPropDataContainer.Create(Self);
|
||
|
SubDescList := TSubDescList.Create;
|
||
|
end;
|
||
|
|
||
|
destructor TInterfaceTypeDataContainer.Destroy;
|
||
|
begin
|
||
|
FreeAndNil(PropDataContainer);
|
||
|
FreeAndNil(SubDescList);
|
||
|
inherited;
|
||
|
end;
|
||
|
|
||
|
function TInterfaceTypeDataContainer.GetTypeDataSize: Integer;
|
||
|
begin
|
||
|
{$IFDEF PAXARM}
|
||
|
result := SizeOf(TypeData.IntfParent) +
|
||
|
SizeOf(TypeData.IntfFlags) +
|
||
|
SizeOf(TypeData.Guid) +
|
||
|
{$IFDEF ARC}
|
||
|
TypeData.IntfUnit + 1;
|
||
|
{$ELSE}
|
||
|
Length(TypeData.IntfUnit) + 1;
|
||
|
{$ENDIF}
|
||
|
{$ELSE}
|
||
|
result := SizeOf(TypeData.IntfParent) +
|
||
|
SizeOf(TypeData.IntfFlags) +
|
||
|
SizeOf(TypeData.Guid) +
|
||
|
Length(TypeData.IntfUnit) + 1;
|
||
|
{$ENDIF}
|
||
|
end;
|
||
|
|
||
|
function TInterfaceTypeDataContainer.GetSize: Integer;
|
||
|
begin
|
||
|
result := TypeDataSize +
|
||
|
PropDataContainer.Size;
|
||
|
end;
|
||
|
|
||
|
procedure TInterfaceTypeDataContainer.SaveToStream(S: TStream);
|
||
|
var
|
||
|
K: Integer;
|
||
|
begin
|
||
|
K := TypeDataSize;
|
||
|
S.Write(K, SizeOf(K));
|
||
|
S.Write(TypeData, TypeDataSize);
|
||
|
PropDataContainer.SaveToStream(S);
|
||
|
SaveStringToStream(FullParentName, S);
|
||
|
SubDescList.SaveToStream(S);
|
||
|
S.Write(GUID, SizeOf(GUID));
|
||
|
end;
|
||
|
|
||
|
procedure TInterfaceTypeDataContainer.SaveToBuff(S: TStream);
|
||
|
begin
|
||
|
S.Write(TypeData, TypeDataSize);
|
||
|
PropDataContainer.SaveToBuff(S);
|
||
|
end;
|
||
|
|
||
|
procedure TInterfaceTypeDataContainer.LoadFromStream(S: TStream);
|
||
|
var
|
||
|
K: Integer;
|
||
|
begin
|
||
|
S.Read(K, SizeOf(K));
|
||
|
S.Read(TypeData, K);
|
||
|
PropDataContainer.LoadFromStream(S);
|
||
|
FullParentName := LoadStringFromStream(S);
|
||
|
SubDescList.LoadFromStream(S);
|
||
|
S.Read(GUID, SizeOf(GUID));
|
||
|
end;
|
||
|
|
||
|
// TArrayTypeDataContainer -----------------------------------------------------
|
||
|
|
||
|
procedure TArrayTypeDataContainer.SaveToStream(S: TStream);
|
||
|
begin
|
||
|
inherited;
|
||
|
SaveStringToStream(FullRangeTypeName, S);
|
||
|
SaveStringToStream(FullElemTypeName, S);
|
||
|
S.Write(B1, SizeOf(B1));
|
||
|
S.Write(B2, SizeOf(B2));
|
||
|
S.Write(FinRangeTypeId, SizeOf(FinRangeTypeId));
|
||
|
end;
|
||
|
|
||
|
procedure TArrayTypeDataContainer.SaveToBuff(S: TStream);
|
||
|
begin
|
||
|
S.Write(TypeData, SizeOf(TypeData));
|
||
|
end;
|
||
|
|
||
|
procedure TArrayTypeDataContainer.LoadFromStream(S: TStream);
|
||
|
begin
|
||
|
inherited;
|
||
|
FullRangeTypeName := LoadStringFromStream(S);
|
||
|
FullElemTypeName := LoadStringFromStream(S);
|
||
|
S.Read(B1, SizeOf(B1));
|
||
|
S.Read(B2, SizeOf(B2));
|
||
|
S.Read(FinRangeTypeId, SizeOf(FinRangeTypeId));
|
||
|
end;
|
||
|
|
||
|
// TRecordTypeDataContainer ----------------------------------------------------
|
||
|
|
||
|
constructor TRecordTypeDataContainer.Create(AOwner: TTypeInfoContainer);
|
||
|
begin
|
||
|
inherited;
|
||
|
FieldListContainer := TFieldListContainer.Create;
|
||
|
end;
|
||
|
|
||
|
destructor TRecordTypeDataContainer.Destroy;
|
||
|
begin
|
||
|
FreeAndNil(FieldListContainer);
|
||
|
inherited;
|
||
|
end;
|
||
|
|
||
|
function TRecordTypeDataContainer.GetSize: Integer;
|
||
|
begin
|
||
|
result := SizeOf(TypeData);
|
||
|
end;
|
||
|
|
||
|
procedure TRecordTypeDataContainer.SaveToStream(S: TStream);
|
||
|
begin
|
||
|
inherited;
|
||
|
S.Write(IsPacked, SizeOf(IsPacked));
|
||
|
FieldListContainer.SaveToStream(S);
|
||
|
end;
|
||
|
|
||
|
procedure TRecordTypeDataContainer.SaveToBuff(S: TStream);
|
||
|
begin
|
||
|
S.Write(TypeData, SizeOf(TypeData));
|
||
|
end;
|
||
|
|
||
|
procedure TRecordTypeDataContainer.LoadFromStream(S: TStream);
|
||
|
begin
|
||
|
inherited;
|
||
|
S.Read(IsPacked, SizeOf(IsPacked));
|
||
|
FieldListContainer.LoadFromStream(S);
|
||
|
end;
|
||
|
|
||
|
// TAliasTypeDataContainer -----------------------------------------------------
|
||
|
|
||
|
procedure TAliasTypeDataContainer.SaveToStream(S: TStream);
|
||
|
begin
|
||
|
inherited;
|
||
|
SaveStringToStream(FullSourceTypeName, S);
|
||
|
end;
|
||
|
|
||
|
procedure TAliasTypeDataContainer.LoadFromStream(S: TStream);
|
||
|
begin
|
||
|
inherited;
|
||
|
FullSourceTypeName := LoadStringFromStream(S);
|
||
|
end;
|
||
|
|
||
|
// TPointerTypeDataContainer ---------------------------------------------------
|
||
|
|
||
|
procedure TPointerTypeDataContainer.SaveToStream(S: TStream);
|
||
|
begin
|
||
|
inherited;
|
||
|
SaveStringToStream(FullOriginTypeName, S);
|
||
|
end;
|
||
|
|
||
|
procedure TPointerTypeDataContainer.LoadFromStream(S: TStream);
|
||
|
begin
|
||
|
inherited;
|
||
|
FullOriginTypeName := LoadStringFromStream(S);
|
||
|
end;
|
||
|
|
||
|
// TClassRefTypeDataContainer --------------------------------------------------
|
||
|
|
||
|
procedure TClassRefTypeDataContainer.SaveToStream(S: TStream);
|
||
|
begin
|
||
|
inherited;
|
||
|
SaveStringToStream(FullOriginTypeName, S);
|
||
|
end;
|
||
|
|
||
|
procedure TClassRefTypeDataContainer.LoadFromStream(S: TStream);
|
||
|
begin
|
||
|
inherited;
|
||
|
FullOriginTypeName := LoadStringFromStream(S);
|
||
|
end;
|
||
|
|
||
|
// TDynArrayTypeDataContainer --------------------------------------------------
|
||
|
|
||
|
procedure TDynArrayTypeDataContainer.SaveToStream(S: TStream);
|
||
|
begin
|
||
|
inherited;
|
||
|
SaveStringToStream(FullElementTypeName, S);
|
||
|
end;
|
||
|
|
||
|
procedure TDynArrayTypeDataContainer.LoadFromStream(S: TStream);
|
||
|
begin
|
||
|
inherited;
|
||
|
FullElementTypeName := LoadStringFromStream(S);
|
||
|
end;
|
||
|
|
||
|
// TProceduralTypeDataContainer ------------------------------------------------
|
||
|
|
||
|
constructor TProceduralTypeDataContainer.Create(AOwner: TTypeInfoContainer);
|
||
|
begin
|
||
|
inherited;
|
||
|
SubDesc := TSubDesc.Create;
|
||
|
end;
|
||
|
|
||
|
destructor TProceduralTypeDataContainer.Destroy;
|
||
|
begin
|
||
|
FreeAndNil(SubDesc);
|
||
|
inherited;
|
||
|
end;
|
||
|
|
||
|
procedure TProceduralTypeDataContainer.SaveToStream(S: TStream);
|
||
|
begin
|
||
|
inherited;
|
||
|
SubDesc.SaveToStream(S);
|
||
|
end;
|
||
|
|
||
|
procedure TProceduralTypeDataContainer.LoadFromStream(S: TStream);
|
||
|
begin
|
||
|
inherited;
|
||
|
SubDesc.LoadFromStream(S);
|
||
|
end;
|
||
|
|
||
|
// TEnumTypeInfoContainer ------------------------------------------------------
|
||
|
|
||
|
constructor TEnumTypeInfoContainer.Create(const AName: String);
|
||
|
begin
|
||
|
inherited Create(0);
|
||
|
TypeInfo.Kind := tkEnumeration;
|
||
|
PShortStringFromString(PShortString(@TypeInfo.Name), AName);
|
||
|
FreeAndNil(TypeDataContainer);
|
||
|
TypeDataContainer := TEnumTypeDataContainer.Create(Self);
|
||
|
FinTypeId := typeENUM;
|
||
|
end;
|
||
|
|
||
|
// TSetTypeInfoContainer -----------------------------------------------------
|
||
|
|
||
|
constructor TSetTypeInfoContainer.Create(const AName: String);
|
||
|
begin
|
||
|
inherited Create(0);
|
||
|
TypeInfo.Kind := tkSet;
|
||
|
PShortStringFromString(PShortString(@TypeInfo.Name), AName);
|
||
|
FreeAndNil(TypeDataContainer);
|
||
|
TypeDataContainer := TSetTypeDataContainer.Create(Self);
|
||
|
FinTypeId := typeSET;
|
||
|
end;
|
||
|
|
||
|
// TClassTypeInfoContainer -----------------------------------------------------
|
||
|
|
||
|
constructor TClassTypeInfoContainer.Create(const AName: String);
|
||
|
begin
|
||
|
inherited Create(0);
|
||
|
TypeInfo.Kind := tkClass;
|
||
|
PShortStringFromString(PShortString(@TypeInfo.Name), AName);
|
||
|
FreeAndNil(TypeDataContainer);
|
||
|
TypeDataContainer := TClassTypeDataContainer.Create(Self);
|
||
|
FinTypeId := typeCLASS;
|
||
|
end;
|
||
|
|
||
|
// TInterfaceTypeInfoContainer -----------------------------------------------------
|
||
|
|
||
|
constructor TInterfaceTypeInfoContainer.Create(const AName: String);
|
||
|
begin
|
||
|
inherited Create(0);
|
||
|
TypeInfo.Kind := tkInterface;
|
||
|
PShortStringFromString(PShortString(@TypeInfo.Name), AName);
|
||
|
FreeAndNil(TypeDataContainer);
|
||
|
TypeDataContainer := TInterfaceTypeDataContainer.Create(Self);
|
||
|
FinTypeId := typeINTERFACE;
|
||
|
end;
|
||
|
|
||
|
// TMethodTypeInfoContainer -----------------------------------------------------
|
||
|
|
||
|
constructor TMethodTypeInfoContainer.Create(const AName: String);
|
||
|
begin
|
||
|
inherited Create(0);
|
||
|
TypeInfo.Kind := tkMethod;
|
||
|
PShortStringFromString(PShortString(@TypeInfo.Name), AName);
|
||
|
FreeAndNil(TypeDataContainer);
|
||
|
TypeDataContainer := TMethodTypeDataContainer.Create(Self);
|
||
|
FinTypeId := typeEVENT;
|
||
|
end;
|
||
|
|
||
|
// TArrayTypeInfoContainer -----------------------------------------------------
|
||
|
|
||
|
constructor TArrayTypeInfoContainer.Create(const AName: String);
|
||
|
begin
|
||
|
inherited Create(0);
|
||
|
TypeInfo.Kind := tkArray;
|
||
|
PShortStringFromString(PShortString(@TypeInfo.Name), AName);
|
||
|
FreeAndNil(TypeDataContainer);
|
||
|
TypeDataContainer := TArrayTypeDataContainer.Create(Self);
|
||
|
FinTypeId := typeARRAY;
|
||
|
end;
|
||
|
|
||
|
// TRecordTypeInfoContainer ----------------------------------------------------
|
||
|
|
||
|
constructor TRecordTypeInfoContainer.Create(const AName: String);
|
||
|
begin
|
||
|
inherited Create(0);
|
||
|
TypeInfo.Kind := tkRecord;
|
||
|
PShortStringFromString(PShortString(@TypeInfo.Name), AName);
|
||
|
FreeAndNil(TypeDataContainer);
|
||
|
TypeDataContainer := TRecordTypeDataContainer.Create(Self);
|
||
|
FinTypeId := typeRECORD;
|
||
|
end;
|
||
|
|
||
|
// TAliasTypeInfoContainer -----------------------------------------------------
|
||
|
|
||
|
constructor TAliasTypeInfoContainer.Create(const AName: String);
|
||
|
begin
|
||
|
inherited Create(0);
|
||
|
TypeInfo.Kind := tkUnknown;
|
||
|
PShortStringFromString(PShortString(@TypeInfo.Name), AName);
|
||
|
FreeAndNil(TypeDataContainer);
|
||
|
TypeDataContainer := TAliasTypeDataContainer.Create(Self);
|
||
|
FinTypeId := typeALIAS;
|
||
|
end;
|
||
|
|
||
|
// TPointerTypeInfoContainer ---------------------------------------------------
|
||
|
|
||
|
constructor TPointerTypeInfoContainer.Create(const AName: String);
|
||
|
begin
|
||
|
inherited Create(0);
|
||
|
TypeInfo.Kind := tkUnknown;
|
||
|
PShortStringFromString(PShortString(@TypeInfo.Name), AName);
|
||
|
FreeAndNil(TypeDataContainer);
|
||
|
TypeDataContainer := TPointerTypeDataContainer.Create(Self);
|
||
|
FinTypeId := typePOINTER;
|
||
|
end;
|
||
|
|
||
|
// TClassRefTypeInfoContainer --------------------------------------------------
|
||
|
|
||
|
constructor TClassRefTypeInfoContainer.Create(const AName: String);
|
||
|
begin
|
||
|
inherited Create(0);
|
||
|
TypeInfo.Kind := tkUnknown;
|
||
|
PShortStringFromString(PShortString(@TypeInfo.Name), AName);
|
||
|
FreeAndNil(TypeDataContainer);
|
||
|
TypeDataContainer := TClassRefTypeDataContainer.Create(Self);
|
||
|
FinTypeId := typeCLASSREF;
|
||
|
end;
|
||
|
|
||
|
// TDynArrayTypeInfoContainer --------------------------------------------------
|
||
|
|
||
|
constructor TDynArrayTypeInfoContainer.Create(const AName: String);
|
||
|
begin
|
||
|
inherited Create(0);
|
||
|
TypeInfo.Kind := tkDynArray;
|
||
|
PShortStringFromString(PShortString(@TypeInfo.Name), AName);
|
||
|
FreeAndNil(TypeDataContainer);
|
||
|
TypeDataContainer := TDynArrayTypeDataContainer.Create(Self);
|
||
|
FinTypeId := typeDYNARRAY;
|
||
|
end;
|
||
|
|
||
|
// TProceduralTypeInfoContainer ------------------------------------------------
|
||
|
|
||
|
constructor TProceduralTypeInfoContainer.Create(const AName: String);
|
||
|
begin
|
||
|
inherited Create(0);
|
||
|
TypeInfo.Kind := tkUnknown;
|
||
|
PShortStringFromString(PShortString(@TypeInfo.Name), AName);
|
||
|
FreeAndNil(TypeDataContainer);
|
||
|
TypeDataContainer := TProceduralTypeDataContainer.Create(Self);
|
||
|
FinTypeId := typePROC;
|
||
|
end;
|
||
|
|
||
|
// TTypeInfoContainer -------------------------------------------------------
|
||
|
|
||
|
constructor TTypeInfoContainer.Create(AFinTypeId: Integer);
|
||
|
begin
|
||
|
inherited Create;
|
||
|
TypeDataContainer := TTypeDataContainer.Create(Self);
|
||
|
FinTypeId := AFinTypeId;
|
||
|
GenericTypeContainer := TGenericTypeContainer.Create;
|
||
|
end;
|
||
|
|
||
|
destructor TTypeInfoContainer.Destroy;
|
||
|
begin
|
||
|
if Assigned(Buff) then
|
||
|
FreeMem(Buff, Size);
|
||
|
FreeAndNil(TypeDataContainer);
|
||
|
FreeAndNil(GenericTypeContainer);
|
||
|
|
||
|
inherited;
|
||
|
end;
|
||
|
|
||
|
function TTypeInfoContainer.GetIsGeneric: Boolean;
|
||
|
begin
|
||
|
result := GenericTypeContainer.Definition <> '';
|
||
|
end;
|
||
|
|
||
|
function TTypeInfoContainer.GetSize: Integer;
|
||
|
begin
|
||
|
{$IFDEF ARC}
|
||
|
result := SizeOf(TTypeKind) + TypeInfo.Name[0] + 1 +
|
||
|
TypeDataContainer.Size;
|
||
|
{$ELSE}
|
||
|
result := SizeOf(TTypeKind) + Length(TypeInfo.Name) + 1 +
|
||
|
TypeDataContainer.Size;
|
||
|
{$ENDIF}
|
||
|
end;
|
||
|
|
||
|
function TTypeInfoContainer.GetPosTypeData: Integer;
|
||
|
begin
|
||
|
{$IFDEF ARC}
|
||
|
result := SizeOf(TTypeKind) + TypeInfo.Name[0] + 1;
|
||
|
{$ELSE}
|
||
|
result := SizeOf(TTypeKind) + Length(TypeInfo.Name) + 1;
|
||
|
{$ENDIF}
|
||
|
end;
|
||
|
|
||
|
function TTypeInfoContainer.GetStreamSize: Integer;
|
||
|
var
|
||
|
M: TMemoryStream;
|
||
|
begin
|
||
|
M := TMemoryStream.Create;
|
||
|
try
|
||
|
SaveToStream(M);
|
||
|
result := M.Size;
|
||
|
finally
|
||
|
FreeAndNil(M);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TTypeInfoContainer.SaveToStream(S: TStream);
|
||
|
begin
|
||
|
S.Write(TypeInfo.Kind, SizeOf(TTypeKind));
|
||
|
SaveShortStringToStream(PShortString(@TypeInfo.Name)^, S);
|
||
|
TypeDataContainer.SaveToStream(S);
|
||
|
SaveStringToStream(FullName, S);
|
||
|
GenericTypeContainer.SaveToStream(S);
|
||
|
end;
|
||
|
|
||
|
procedure TTypeInfoContainer.SaveToBuff(S: TStream);
|
||
|
begin
|
||
|
S.Write(TypeInfo.Kind, SizeOf(TTypeKind));
|
||
|
SaveShortStringToStream(PShortString(@TypeInfo.Name)^, S);
|
||
|
TypeDataContainer.SaveToBuff(S);
|
||
|
end;
|
||
|
|
||
|
procedure TTypeInfoContainer.LoadFromStream(S: TStream;
|
||
|
FinTypeId: Byte);
|
||
|
begin
|
||
|
S.Read(TypeInfo.Kind, SizeOf(TTypeKind));
|
||
|
_ShortStringAssign(LoadShortStringFromStream(S), 255, PShortString(@TypeInfo.Name));
|
||
|
|
||
|
FreeAndNil(TypeDataContainer);
|
||
|
|
||
|
case FinTypeId of
|
||
|
typeCLASS: TypeDataContainer := TClassTypeDataContainer.Create(Self);
|
||
|
typeINTERFACE: TypeDataContainer := TInterfaceTypeDataContainer.Create(Self);
|
||
|
typeEVENT: TypeDataContainer := TMethodTypeDataContainer.Create(Self);
|
||
|
typeSET: TypeDataContainer := TSetTypeDataContainer.Create(Self);
|
||
|
typeENUM: TypeDataContainer := TEnumTypeDataContainer.Create(Self);
|
||
|
typeARRAY: TypeDataContainer := TArrayTypeDataContainer.Create(Self);
|
||
|
typeRECORD: TypeDataContainer := TRecordTypeDataContainer.Create(Self);
|
||
|
typeALIAS: TypeDataContainer := TAliasTypeDataContainer.Create(Self);
|
||
|
typePOINTER: TypeDataContainer := TPointerTypeDataContainer.Create(Self);
|
||
|
typeCLASSREF: TypeDataContainer := TClassRefTypeDataContainer.Create(Self);
|
||
|
typeDYNARRAY: TypeDataContainer := TDynArrayTypeDataContainer.Create(Self);
|
||
|
typePROC: TypeDataContainer := TProceduralTypeDataContainer.Create(Self);
|
||
|
else
|
||
|
TypeDataContainer := TTypeDataContainer.Create(Self);
|
||
|
end;
|
||
|
|
||
|
TypeDataContainer.LoadFromStream(S);
|
||
|
FullName := LoadStringFromStream(S);
|
||
|
GenericTypeContainer.LoadFromStream(S);
|
||
|
end;
|
||
|
|
||
|
procedure TTypeInfoContainer.RaiseError(const Message: string; params: array of Const);
|
||
|
begin
|
||
|
raise Exception.Create(Format(Message, params));
|
||
|
end;
|
||
|
|
||
|
// TPaxTypeInfoList ------------------------------------------------------------
|
||
|
|
||
|
destructor TPaxTypeInfoList.Destroy;
|
||
|
begin
|
||
|
inherited;
|
||
|
end;
|
||
|
|
||
|
function TPaxTypeInfoList.GetRecord(I: Integer): TTypeInfoContainer;
|
||
|
begin
|
||
|
result := TTypeInfoContainer(L[I]);
|
||
|
end;
|
||
|
|
||
|
procedure TPaxTypeInfoList.Add(Rec: TTypeInfoContainer);
|
||
|
begin
|
||
|
L.Add(Rec);
|
||
|
end;
|
||
|
|
||
|
procedure TPaxTypeInfoList.SaveToStream(S: TStream);
|
||
|
var
|
||
|
I, K: Integer;
|
||
|
begin
|
||
|
K := Count;
|
||
|
S.Write(K, SizeOf(Integer));
|
||
|
for I:=0 to K - 1 do
|
||
|
begin
|
||
|
S.Write(Records[I].FinTypeId, SizeOf(Records[I].FinTypeId));
|
||
|
Records[I].SaveToStream(S);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TPaxTypeInfoList.LoadFromStream(S: TStream);
|
||
|
var
|
||
|
I, K: Integer;
|
||
|
R: TTypeInfoContainer;
|
||
|
FinTypeId: Byte;
|
||
|
begin
|
||
|
Clear;
|
||
|
|
||
|
S.Read(K, SizeOf(Integer));
|
||
|
for I:=0 to K - 1 do
|
||
|
begin
|
||
|
S.Read(FinTypeId, SizeOf(Byte));
|
||
|
|
||
|
case FinTypeId of
|
||
|
typeCLASS: R := TClassTypeInfoContainer.Create('');
|
||
|
typeINTERFACE: R := TInterfaceTypeInfoContainer.Create('');
|
||
|
typeEVENT: R := TMethodTypeInfoContainer.Create('');
|
||
|
typeSET: R := TSetTypeInfoContainer.Create('');
|
||
|
typeENUM: R := TEnumTypeInfoContainer.Create('');
|
||
|
typeARRAY: R := TArrayTypeInfoContainer.Create('');
|
||
|
typeRECORD: R := TRecordTypeInfoContainer.Create('');
|
||
|
typeALIAS: R := TAliasTypeInfoContainer.Create('');
|
||
|
typePOINTER: R := TPointerTypeInfoContainer.Create('');
|
||
|
typeCLASSREF: R := TClassRefTypeInfoContainer.Create('');
|
||
|
typeDYNARRAY: R := TDynArrayTypeInfoContainer.Create('');
|
||
|
typePROC: R := TProceduralTypeInfoContainer.Create('');
|
||
|
else
|
||
|
R := TTypeInfoContainer.Create(FinTypeId);
|
||
|
end;
|
||
|
|
||
|
R.LoadFromStream(S, FinTypeId);
|
||
|
|
||
|
Add(R);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
function TPaxTypeInfoList.LookupFullName(const FullName: String): TTypeInfoContainer;
|
||
|
var
|
||
|
I: Integer;
|
||
|
begin
|
||
|
result := nil;
|
||
|
for I := 0 to Count - 1 do
|
||
|
if StrEql(FullName, String(Records[I].FullName)) then
|
||
|
begin
|
||
|
result := Records[I];
|
||
|
Exit;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
function TPaxTypeInfoList.IndexOf(const FullName: String): Integer;
|
||
|
var
|
||
|
I: Integer;
|
||
|
begin
|
||
|
result := -1;
|
||
|
for I := 0 to Count - 1 do
|
||
|
if StrEql(FullName, String(Records[I].FullName)) then
|
||
|
begin
|
||
|
result := I;
|
||
|
Exit;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TPaxTypeInfoList.CopyToBuff;
|
||
|
var
|
||
|
S: TMemoryStream;
|
||
|
I, SZ, StreamSize, K: Integer;
|
||
|
begin
|
||
|
for I := 0 to Count - 1 do
|
||
|
begin
|
||
|
SZ := Records[I].Size;
|
||
|
StreamSize := Records[I].GetStreamSize;
|
||
|
|
||
|
K := SizeOf(Integer) + SZ +
|
||
|
SizeOf(Integer) + StreamSize;
|
||
|
|
||
|
Records[I].Buff := AllocMem(K);
|
||
|
Records[I].Buff4 := ShiftPointer(Records[I].Buff, 4);
|
||
|
|
||
|
S := TMemoryStream.Create;
|
||
|
try
|
||
|
S.Write(SZ, SizeOf(Integer));
|
||
|
Records[I].SaveToBuff(S);
|
||
|
|
||
|
S.Write(StreamSize, SizeOf(Integer));
|
||
|
Records[I].SaveToStream(S);
|
||
|
|
||
|
S.Position := 0;
|
||
|
S.Read(Records[I].Buff^, K);
|
||
|
|
||
|
finally
|
||
|
FreeAndNil(S);
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TPaxTypeInfoList.AddToProgram(AProg: Pointer);
|
||
|
var
|
||
|
ClassFactory: TPaxClassFactory;
|
||
|
I, J, JJ: Integer;
|
||
|
P: Pointer;
|
||
|
R: TPaxClassFactoryRec;
|
||
|
C: TClass;
|
||
|
ptd: PTypeData;
|
||
|
pti, pti_parent: PTypeInfo;
|
||
|
Record_Parent, Record_Temp: TTypeInfoContainer;
|
||
|
PropDataContainer: TPropDataContainer;
|
||
|
Prog: TBaseRunner;
|
||
|
FullName: String;
|
||
|
ppi: PPropInfo;
|
||
|
Z, ZZ: Integer;
|
||
|
|
||
|
ClassTypeInfoContainer: TClassTypeInfoContainer;
|
||
|
ClassTypeDataContainer: TClassTypeDataContainer;
|
||
|
|
||
|
MethodTypeInfoContainer: TMethodTypeInfoContainer;
|
||
|
MethodTypeDataContainer: TMethodTypeDataContainer;
|
||
|
|
||
|
InterfaceTypeDataContainer: TInterfaceTypeDataContainer;
|
||
|
SetTypeDataContainer: TSetTypeDataContainer;
|
||
|
|
||
|
MethodTableIndex: Integer;
|
||
|
PMethod: PVmtMethod;
|
||
|
|
||
|
FieldListContainer: TFieldListContainer;
|
||
|
PField: PVmtField;
|
||
|
ClassRec: TClassRec;
|
||
|
RI: TTypeInfoContainer;
|
||
|
ParentPropCount: Integer;
|
||
|
MR, SomeMR: TMapRec;
|
||
|
FileName, ProcName: String;
|
||
|
DestProg: Pointer;
|
||
|
begin
|
||
|
Prog := TBaseRunner(AProg);
|
||
|
ClassFactory := Prog.ProgClassFactory;
|
||
|
|
||
|
CopyToBuff;
|
||
|
|
||
|
for I:=0 to Count - 1 do
|
||
|
Records[I].Processed := false;
|
||
|
|
||
|
repeat
|
||
|
|
||
|
for I:=0 to Count - 1 do
|
||
|
begin
|
||
|
RI := Records[I];
|
||
|
if RI.Processed then
|
||
|
continue;
|
||
|
|
||
|
pti := RI.Buff4;
|
||
|
|
||
|
case RI.TypeInfo.Kind of
|
||
|
tkEnumeration:
|
||
|
begin
|
||
|
ptd := ShiftPointer(pti, RI.PosTypeData);
|
||
|
{$IFDEF FPC}
|
||
|
ptd^.BaseType := RI.Buff4;
|
||
|
{$ELSE}
|
||
|
ptd^.BaseType := @ RI.Buff4;
|
||
|
{$ENDIF}
|
||
|
|
||
|
RI.Processed := true;
|
||
|
end;
|
||
|
tkSet:
|
||
|
begin
|
||
|
RI.Processed := true;
|
||
|
|
||
|
ptd := ShiftPointer(pti, RI.PosTypeData);
|
||
|
|
||
|
SetTypeDataContainer := RI.TypeDataContainer as
|
||
|
TSetTypeDataContainer;
|
||
|
|
||
|
Record_Temp := LookupFullName(SetTypeDataContainer.FullCompName);
|
||
|
if Record_Temp = nil then
|
||
|
ptd^.CompType := nil
|
||
|
else
|
||
|
{$IFDEF FPC}
|
||
|
ptd^.CompType := Record_Temp.buff4;
|
||
|
{$ELSE}
|
||
|
ptd^.CompType := @ Record_Temp.buff4;
|
||
|
{$ENDIF}
|
||
|
|
||
|
end;
|
||
|
tkMethod:
|
||
|
begin
|
||
|
RI.Processed := true;
|
||
|
|
||
|
MethodTypeInfoContainer := TMethodTypeInfoContainer(RI);
|
||
|
MethodTypeDataContainer := TMethodTypeDataContainer(MethodTypeInfoContainer.TypeDataContainer);
|
||
|
if MethodTypeDataContainer.OwnerTypeName = '' then
|
||
|
continue;
|
||
|
|
||
|
Record_Temp := LookupFullName(MethodTypeDataContainer.OwnerTypeName);
|
||
|
if Record_Temp = nil then
|
||
|
RaiseError(errInternalError, []);
|
||
|
R := ClassFactory.FindRecordByFullName(MethodTypeDataContainer.OwnerTypeName);
|
||
|
if R = nil then
|
||
|
RaiseError(errInternalError, []);
|
||
|
|
||
|
ClassTypeInfoContainer := Record_Temp as
|
||
|
TClassTypeInfoContainer;
|
||
|
ClassTypeDataContainer := Record_Temp.TypeDataContainer as
|
||
|
TClassTypeDataContainer;
|
||
|
|
||
|
if R.MethodTableSize = 0 then
|
||
|
begin
|
||
|
R.MethodTableSize := ClassTypeDataContainer.MethodTableSize;
|
||
|
vmtMethodTableSlot(R.VMTPtr)^ := AllocMem(R.MethodTableSize);
|
||
|
PVmtMethodTable(vmtMethodTableSlot(R.VMTPtr)^)^.Count :=
|
||
|
ClassTypeDataContainer.MethodTableCount;
|
||
|
end;
|
||
|
PMethod := ShiftPointer(vmtMethodTableSlot(R.VMTPtr)^,
|
||
|
SizeOf(TVmtMethodCount));
|
||
|
|
||
|
MethodTableIndex := MethodTypeDataContainer.MethodTableIndex;
|
||
|
|
||
|
for J := 0 to MethodTableIndex - 1 do
|
||
|
PMethod := ShiftPointer(PMethod, GetMethodSize(PMethod));
|
||
|
|
||
|
{$IFDEF FPC}
|
||
|
PMethod^.MethName := @ MethodTypeInfoContainer.TypeInfo.Name;
|
||
|
FullName := MethodTypeDataContainer.OwnerTypeName + '.' +
|
||
|
String(PMethod^.MethName^);
|
||
|
PMethod^.MethAddr := Prog.GetAddress(FullName, MR);
|
||
|
|
||
|
DestProg := Prog;
|
||
|
if PMethod^.MethAddr = nil then
|
||
|
begin
|
||
|
FileName := ExtractOwner(FullName) + '.' + PCU_FILE_EXT;
|
||
|
ProcName := Copy(FullName, PosCh('.', FullName) + 1, Length(FullName));
|
||
|
PMethod^.MethAddr := Prog.LoadAddressEx(FileName, ProcName, false,
|
||
|
MethodTypeDataContainer.OverCount, SomeMR, DestProg);
|
||
|
end;
|
||
|
TBaseRunner(DestProg).WrapMethodAddress(PMethod^.MethAddr);
|
||
|
MethodTypeDataContainer.Address := PMethod^.MethAddr;
|
||
|
{$ELSE}
|
||
|
_ShortStringAssign(PShortString(@MethodTypeInfoContainer.TypeInfo.Name)^,
|
||
|
255,
|
||
|
PShortString(@PMethod^.Name));
|
||
|
FullName := MethodTypeDataContainer.OwnerTypeName + '.' +
|
||
|
StringFromPShortString(PShortString(@PMethod^.Name));
|
||
|
PMethod^.Address := Prog.GetAddress(FullName, MR);
|
||
|
DestProg := Prog;
|
||
|
if PMethod^.Address = nil then
|
||
|
begin
|
||
|
FileName := ExtractOwner(FullName) + '.' + PCU_FILE_EXT;
|
||
|
ProcName := Copy(FullName, PosCh('.', FullName) + 1, Length(FullName));
|
||
|
PMethod^.Address := Prog.LoadAddressEx(FileName, ProcName, false,
|
||
|
MethodTypeDataContainer.OverCount, SomeMR, DestProg);
|
||
|
end;
|
||
|
|
||
|
TBaseRunner(DestProg).WrapMethodAddress(PMethod^.Address);
|
||
|
|
||
|
{$ifdef PAX64}
|
||
|
PMethod^.Size := SizeOf(Word) +
|
||
|
SizeOf(Pointer) +
|
||
|
Length(PMethod^.Name) + 1;
|
||
|
{$endif}
|
||
|
|
||
|
{$ifdef WIN32}
|
||
|
PMethod^.Size := SizeOf(Word) +
|
||
|
SizeOf(Pointer) +
|
||
|
Length(PMethod^.Name) + 1;
|
||
|
{$endif}
|
||
|
|
||
|
{$ifdef MACOS}
|
||
|
PMethod^.Size := SizeOf(Word) +
|
||
|
SizeOf(Pointer) +
|
||
|
Length(PMethod^.Name) + 1;
|
||
|
{$endif}
|
||
|
|
||
|
{$ifdef ARC}
|
||
|
PMethod^.Size := SizeOf(Word) +
|
||
|
SizeOf(Pointer) +
|
||
|
PMethod^.Name[0] + 1;
|
||
|
{$ENDIF}
|
||
|
|
||
|
MethodTypeDataContainer.Address := PMethod^.Address;
|
||
|
{$ENDIF}
|
||
|
end;
|
||
|
tkInterface:
|
||
|
begin
|
||
|
RI.Processed := true;
|
||
|
|
||
|
ptd := ShiftPointer(pti, RI.PosTypeData);
|
||
|
|
||
|
InterfaceTypeDataContainer := RI.TypeDataContainer as
|
||
|
TInterfaceTypeDataContainer;
|
||
|
|
||
|
Record_Parent := LookupFullName(InterfaceTypeDataContainer.FullParentName);
|
||
|
if Record_Parent = nil then
|
||
|
ptd^.IntfParent := nil
|
||
|
else
|
||
|
{$IFDEF FPC}
|
||
|
ptd^.IntfParent := Record_Parent.buff4;
|
||
|
{$ELSE}
|
||
|
ptd^.IntfParent := @ Record_Parent.buff4;
|
||
|
{$ENDIF}
|
||
|
|
||
|
Z := RI.TypeDataContainer.TypeDataSize +
|
||
|
SizeOf(TPropData);
|
||
|
|
||
|
PropDataContainer := InterfaceTypeDataContainer.PropDataContainer;
|
||
|
|
||
|
for J := 0 to PropDataContainer.Count - 1 do
|
||
|
begin
|
||
|
ZZ := 0;
|
||
|
if J > 0 then
|
||
|
for JJ := 0 to J - 1 do
|
||
|
Inc(ZZ, PropInfoSize(PropDataContainer.PropList[JJ]));
|
||
|
|
||
|
ppi := ShiftPointer(ptd, Z + ZZ);
|
||
|
|
||
|
ppi^.NameIndex := J;
|
||
|
|
||
|
Record_Temp := LookupFullName(PropDataContainer.PropTypeNames[J]);
|
||
|
if Record_Temp = nil then
|
||
|
begin
|
||
|
ppi^.PropType := nil;
|
||
|
end
|
||
|
else
|
||
|
{$IFDEF FPC}
|
||
|
ppi^.PropType := Record_Temp.Buff4;
|
||
|
{$ELSE}
|
||
|
ppi^.PropType := PPTypeInfo(@Record_Temp.Buff4);
|
||
|
{$ENDIF}
|
||
|
end;
|
||
|
end;
|
||
|
tkClass:
|
||
|
begin
|
||
|
R := ClassFactory.FindRecordByFullName(String(RI.FullName));
|
||
|
|
||
|
if R = nil then
|
||
|
RaiseError(errInternalError, []);
|
||
|
|
||
|
ClassTypeInfoContainer := RI as
|
||
|
TClassTypeInfoContainer;
|
||
|
ClassTypeDataContainer := RI.TypeDataContainer as
|
||
|
TClassTypeDataContainer;
|
||
|
|
||
|
// R.VMTPtr^.DynamicTable := Prog.MessageList.CreateDmtTable(ExtractName(RI.FullName),
|
||
|
// R.DmtTableSize);
|
||
|
ClassRec := Prog.ClassList.Lookup(String(RI.FullName));
|
||
|
if ClassRec <> nil then
|
||
|
begin
|
||
|
if ClassRec.IntfList.Count > 0 then
|
||
|
begin
|
||
|
R.IntfTableSize := ClassRec.GetIntfTableSize;
|
||
|
vmtIntfTableSlot(R.VMTPtr)^ := AllocMem(R.IntfTableSize);
|
||
|
with PInterfaceTable(vmtIntfTableSlot(R.VMTPtr)^)^ do
|
||
|
begin
|
||
|
EntryCount := ClassRec.IntfList.Count;
|
||
|
for J := 0 to EntryCount - 1 do
|
||
|
begin
|
||
|
{$IFDEF FPC}
|
||
|
Entries[J].IID := @ ClassRec.IntfList[J].GUID;
|
||
|
{$ELSE}
|
||
|
Entries[J].IID := ClassRec.IntfList[J].GUID;
|
||
|
{$ENDIF}
|
||
|
Entries[J].VTable := ClassRec.IntfList[J].Buff;
|
||
|
Entries[J].IOffset := ClassRec.GetIntfOffset(ClassRec.IntfList[J].GUID);
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
if ClassTypeDataContainer.FieldTableCount > 0 then
|
||
|
begin
|
||
|
if R.FieldClassTable = nil then
|
||
|
R.FieldClassTable :=
|
||
|
CreateFieldClassTable(ClassTypeDataContainer.FieldTableCount);
|
||
|
|
||
|
if R.FieldTableSize = 0 then
|
||
|
begin
|
||
|
R.FieldTableSize := ClassTypeDataContainer.FieldTableSize;
|
||
|
vmtFieldTableSlot(R.VMTPtr)^ := AllocMem(R.FieldTableSize);
|
||
|
end;
|
||
|
|
||
|
FieldListContainer :=
|
||
|
ClassTypeDataContainer.FieldListContainer;
|
||
|
|
||
|
PVmtFieldTable(vmtFieldTableSlot(R.VMTPtr)^)^.Count :=
|
||
|
FieldListContainer.Count;
|
||
|
|
||
|
{$IFDEF ARC}
|
||
|
P := ShiftPointer(vmtFieldTableSlot(R.VMTPtr)^,
|
||
|
SizeOf(Word));
|
||
|
Pointer(P^) := R.FieldClassTable;
|
||
|
PField := ShiftPointer(vmtFieldTableSlot(R.VMTPtr)^,
|
||
|
SizeOf(Word) + SizeOf(Pointer));
|
||
|
{$ELSE}
|
||
|
|
||
|
{$IFDEF PAX64}
|
||
|
P := ShiftPointer(vmtFieldTableSlot(R.VMTPtr)^,
|
||
|
SizeOf(Word));
|
||
|
Pointer(P^) := R.FieldClassTable;
|
||
|
PField := ShiftPointer(vmtFieldTableSlot(R.VMTPtr)^,
|
||
|
SizeOf(Word) + SizeOf(Pointer));
|
||
|
{$ELSE}
|
||
|
{$ifdef WIN32}
|
||
|
P := ShiftPointer(vmtFieldTableSlot(R.VMTPtr)^,
|
||
|
SizeOf(Word));
|
||
|
Pointer(P^) := R.FieldClassTable;
|
||
|
PField := ShiftPointer(vmtFieldTableSlot(R.VMTPtr)^,
|
||
|
SizeOf(Word) + SizeOf(Pointer));
|
||
|
{$else}
|
||
|
PField := ShiftPointer(vmtFieldTableSlot(R.VMTPtr)^,
|
||
|
SizeOf(Word) + SizeOf(Word));
|
||
|
{$endif}
|
||
|
{$ENDIF}
|
||
|
|
||
|
{$ENDIF}
|
||
|
|
||
|
for J := 0 to FieldListContainer.Count - 1 do
|
||
|
begin
|
||
|
// set up PField
|
||
|
|
||
|
PField^.Name := FieldListContainer[J].Name;
|
||
|
PField^.Offset := FieldListContainer[J].Offset;
|
||
|
PField^.ClassIndex := J;
|
||
|
|
||
|
ClassRec := Prog.ClassList.Lookup(FieldListContainer[J].FullFieldTypeName);
|
||
|
if ClassRec <> nil then
|
||
|
begin
|
||
|
if ClassRec.Host then
|
||
|
{$IFDEF FPC}
|
||
|
R.FieldClassTable^.Classes[J] := ClassRec.PClass;
|
||
|
{$ELSE}
|
||
|
R.FieldClassTable^.Classes[J] := @ ClassRec.PClass;
|
||
|
{$ENDIF}
|
||
|
end;
|
||
|
|
||
|
PField := ShiftPointer(PField, GetFieldSize(PField));
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
vmtTypeInfoSlot(R.VMTPtr)^ := pti;
|
||
|
{$IFDEF FPC}
|
||
|
C := TClass(R.VMTPtr);
|
||
|
{$ELSE}
|
||
|
C := vmtSelfPtrSlot(R.VMTPtr)^;
|
||
|
{$ENDIF}
|
||
|
ptd := ShiftPointer(pti, RI.PosTypeData);
|
||
|
ptd^.ClassType := C;
|
||
|
|
||
|
pti_parent := nil;
|
||
|
|
||
|
C := C.ClassParent;
|
||
|
if IsPaxClass(C) then
|
||
|
begin
|
||
|
Record_Parent := LookupFullName(ClassTypeDataContainer.FullParentName);
|
||
|
if Record_Parent <> nil then
|
||
|
if not Record_Parent.Processed then
|
||
|
continue;
|
||
|
|
||
|
if Record_Parent = nil then
|
||
|
begin
|
||
|
ClassRec := Prog.ClassList.Lookup(ClassTypeDataContainer.FullParentName);
|
||
|
if ClassRec = nil then
|
||
|
RaiseError(errInternalError, []);
|
||
|
pti_parent := C.ClassInfo;
|
||
|
end
|
||
|
else
|
||
|
pti_parent := Record_Parent.buff4;
|
||
|
end
|
||
|
else
|
||
|
begin
|
||
|
if Assigned(C) then
|
||
|
pti_parent := C.ClassInfo;
|
||
|
end;
|
||
|
|
||
|
RI.Processed := true;
|
||
|
|
||
|
R.pti_parent := pti_parent;
|
||
|
{$IFDEF FPC}
|
||
|
ptd^.ParentInfo := R.pti_parent;
|
||
|
{$ELSE}
|
||
|
ptd^.ParentInfo := @ R.pti_parent;
|
||
|
{$ENDIF}
|
||
|
ptd^.PropCount := RI.TypeDataContainer.TypeData.PropCount;
|
||
|
ptd^.UnitName := RI.TypeDataContainer.TypeData.UnitName;
|
||
|
|
||
|
Z := RI.TypeDataContainer.TypeDataSize +
|
||
|
SizeOf(TPropData);
|
||
|
|
||
|
PropDataContainer :=
|
||
|
TClassTypeDataContainer(RI.TypeDataContainer).PropDataContainer;
|
||
|
|
||
|
if pti_parent <> nil then
|
||
|
ParentPropCount := GetTypeData(pti_parent)^.PropCount
|
||
|
else
|
||
|
ParentPropCount := 0;
|
||
|
|
||
|
Inc(ptd^.PropCount, ParentPropCount);
|
||
|
|
||
|
for J := 0 to PropDataContainer.Count - 1 do
|
||
|
begin
|
||
|
ZZ := 0;
|
||
|
if J > 0 then
|
||
|
for JJ := 0 to J - 1 do
|
||
|
Inc(ZZ, PropInfoSize(PropDataContainer.PropList[JJ]));
|
||
|
|
||
|
ppi := ShiftPointer(ptd, Z + ZZ);
|
||
|
|
||
|
ppi^.NameIndex := J + ParentPropCount;
|
||
|
|
||
|
Record_Temp := LookupFullName(PropDataContainer.PropTypeNames[J]);
|
||
|
if Record_Temp = nil then
|
||
|
begin
|
||
|
// ClassRec := Prog.ClassList.Lookup(String(ClassTypeDataContainer.FullParentName));
|
||
|
ClassRec := Prog.ClassList.Lookup(PropDataContainer.PropTypeNames[J]);
|
||
|
if ClassRec = nil then
|
||
|
RaiseError(errInternalError, []);
|
||
|
ClassRec.PClass_pti := ClassRec.PClass.ClassInfo;
|
||
|
{$IFDEF FPC}
|
||
|
ppi^.PropType := ClassRec.PClass_pti;
|
||
|
{$ELSE}
|
||
|
ppi^.PropType := @ ClassRec.PClass_pti;
|
||
|
{$ENDIF}
|
||
|
end
|
||
|
else
|
||
|
{$IFDEF FPC}
|
||
|
ppi^.PropType := Record_Temp.Buff4;
|
||
|
{$ELSE}
|
||
|
ppi^.PropType := PPTypeInfo(@Record_Temp.Buff4);
|
||
|
{$ENDIF}
|
||
|
|
||
|
FullName := PropDataContainer.ReadNames[J];
|
||
|
if Length(FullName) > 0 then
|
||
|
begin
|
||
|
DestProg := Prog;
|
||
|
ppi^.GetProc := Prog.GetAddress(FullName, MR);
|
||
|
if ppi^.GetProc = nil then
|
||
|
begin
|
||
|
FileName := ExtractOwner(FullName) + '.' + PCU_FILE_EXT;
|
||
|
ProcName := Copy(FullName, PosCh('.', FullName) + 1, Length(FullName));
|
||
|
ppi^.GetProc := Prog.LoadAddressEx(FileName, ProcName, false, 0, SomeMR, DestProg);
|
||
|
end;
|
||
|
TBaseRunner(DestProg).WrapMethodAddress(ppi^.GetProc);
|
||
|
end;
|
||
|
FullName := PropDataContainer.WriteNames[J];
|
||
|
if Length(FullName) > 0 then
|
||
|
begin
|
||
|
DestProg := Prog;
|
||
|
ppi^.SetProc := Prog.GetAddress(FullName, MR);
|
||
|
if ppi^.SetProc = nil then
|
||
|
begin
|
||
|
FileName := ExtractOwner(FullName) + '.' + PCU_FILE_EXT;
|
||
|
ProcName := Copy(FullName, PosCh('.', FullName) + 1, Length(FullName));
|
||
|
ppi^.SetProc := Prog.LoadAddressEx(FileName, ProcName, false, 0, SomeMR, DestProg);
|
||
|
end;
|
||
|
TBaseRunner(DestProg).WrapMethodAddress(ppi^.SetProc);
|
||
|
end;
|
||
|
|
||
|
ppi^.Index := Integer($80000000); // no index
|
||
|
end;
|
||
|
end; // tkClass
|
||
|
else
|
||
|
begin
|
||
|
RI.Processed := true;
|
||
|
end;
|
||
|
end; // case
|
||
|
end; // i-loop
|
||
|
|
||
|
until Processed;
|
||
|
end;
|
||
|
|
||
|
function TPaxTypeInfoList.Processed: Boolean;
|
||
|
var
|
||
|
I: Integer;
|
||
|
begin
|
||
|
result := true;
|
||
|
for I := 0 to Count - 1 do
|
||
|
if not Records[I].Processed then
|
||
|
begin
|
||
|
result := false;
|
||
|
Exit;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
function TPaxTypeInfoList.FindMethodFullName(Address: Pointer): String;
|
||
|
var
|
||
|
I: Integer;
|
||
|
MethodTypeDataContainer: TMethodTypeDataContainer;
|
||
|
begin
|
||
|
result := '';
|
||
|
|
||
|
for I := 0 to Count - 1 do
|
||
|
if Records[I].TypeInfo.Kind = tkMethod then
|
||
|
begin
|
||
|
MethodTypeDataContainer := Records[I].TypeDataContainer as
|
||
|
TMethodTypeDataContainer;
|
||
|
if MethodTypeDataContainer.Address = Address then
|
||
|
begin
|
||
|
result := String(Records[I].FullName);
|
||
|
Exit;
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TPaxTypeInfoList.RaiseError(const Message: string; params: array of Const);
|
||
|
begin
|
||
|
raise Exception.Create(Format(Message, params));
|
||
|
end;
|
||
|
|
||
|
function GetClassTypeInfoContainer(X: TObject): TClassTypeInfoContainer;
|
||
|
var
|
||
|
pti: PTypeInfo;
|
||
|
P: Pointer;
|
||
|
sz, StreamSize: Integer;
|
||
|
M: TMemoryStream;
|
||
|
begin
|
||
|
result := nil;
|
||
|
pti := X.ClassInfo;
|
||
|
if pti = nil then
|
||
|
Exit;
|
||
|
if not IsPaxObject(X) then
|
||
|
Exit;
|
||
|
P := ShiftPointer(pti, - SizeOf(Integer));
|
||
|
sz := Integer(p^);
|
||
|
P := ShiftPointer(pti, sz);
|
||
|
StreamSize := Integer(P^);
|
||
|
P := ShiftPointer(P, SizeOf(Integer)); // p points to stream
|
||
|
M := TMemoryStream.Create;
|
||
|
try
|
||
|
M.Write(P^, StreamSize);
|
||
|
M.Position := 0;
|
||
|
result := TClassTypeInfoContainer.Create(X.ClassName);
|
||
|
result.LoadFromStream(M, typeCLASS);
|
||
|
finally
|
||
|
FreeAndNil(M);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
function GetTypeInfoContainer(pti: PTypeInfo): TTypeInfoContainer;
|
||
|
var
|
||
|
P: Pointer;
|
||
|
sz, StreamSize: Integer;
|
||
|
M: TMemoryStream;
|
||
|
begin
|
||
|
result := nil;
|
||
|
P := ShiftPointer(pti, - SizeOf(Integer));
|
||
|
sz := Integer(p^);
|
||
|
P := ShiftPointer(pti, sz);
|
||
|
StreamSize := Integer(P^);
|
||
|
P := ShiftPointer(P, SizeOf(Integer)); // p points to stream
|
||
|
M := TMemoryStream.Create;
|
||
|
try
|
||
|
M.Write(P^, StreamSize);
|
||
|
M.Position := 0;
|
||
|
// result := TTypeInfoContainer.Create;
|
||
|
// result.LoadFromStream(M, typeCLASS);
|
||
|
finally
|
||
|
FreeAndNil(M);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
|
||
|
end.
|