typinfo.pp 52 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 1999-2000 by Florian Klaempfl
  4. member of the Free Pascal development team
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. { This unit provides the same Functionality as the TypInfo Unit }
  12. { of Delphi }
  13. unit typinfo;
  14. interface
  15. {$MODE objfpc}
  16. {$inline on}
  17. {$h+}
  18. uses SysUtils;
  19. // temporary types:
  20. type
  21. {$MINENUMSIZE 1 this saves a lot of memory }
  22. // if you change one of the following enumeration types
  23. // you have also to change the compiler in an appropriate way !
  24. TTypeKind = (tkUnknown,tkInteger,tkChar,tkEnumeration,
  25. tkFloat,tkSet,tkMethod,tkSString,tkLString,tkAString,
  26. tkWString,tkVariant,tkArray,tkRecord,tkInterface,
  27. tkClass,tkObject,tkWChar,tkBool,tkInt64,tkQWord,
  28. tkDynArray,tkInterfaceRaw);
  29. TOrdType = (otSByte,otUByte,otSWord,otUWord,otSLong,otULong);
  30. TFloatType = (ftSingle,ftDouble,ftExtended,ftComp,ftCurr);
  31. TMethodKind = (mkProcedure,mkFunction,mkConstructor,mkDestructor,
  32. mkClassProcedure, mkClassFunction);
  33. TParamFlag = (pfVar,pfConst,pfArray,pfAddress,pfReference,pfOut);
  34. TParamFlags = set of TParamFlag;
  35. TIntfFlag = (ifHasGuid,ifDispInterface,ifDispatch,ifHasStrGUID);
  36. TIntfFlags = set of TIntfFlag;
  37. TIntfFlagsBase = set of TIntfFlag;
  38. {$MINENUMSIZE DEFAULT}
  39. const
  40. ptField = 0;
  41. ptStatic = 1;
  42. ptVirtual = 2;
  43. ptConst = 3;
  44. tkString = tkSString;
  45. type
  46. TTypeKinds = set of TTypeKind;
  47. ShortStringBase = string[255];
  48. {$PACKRECORDS 1}
  49. TTypeInfo = record
  50. Kind : TTypeKind;
  51. Name : ShortString;
  52. // here the type data follows as TTypeData record
  53. end;
  54. PTypeInfo = ^TTypeInfo;
  55. PPTypeInfo = ^PTypeInfo;
  56. {$PACKRECORDS C}
  57. PTypeData = ^TTypeData;
  58. TTypeData =
  59. {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
  60. packed
  61. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  62. record
  63. case TTypeKind of
  64. tkUnKnown,tkLString,tkWString,tkAString,tkVariant:
  65. ();
  66. tkInteger,tkChar,tkEnumeration,tkWChar,tkSet:
  67. (OrdType : TOrdType;
  68. case TTypeKind of
  69. tkInteger,tkChar,tkEnumeration,tkBool,tkWChar : (
  70. MinValue,MaxValue : Longint;
  71. case TTypeKind of
  72. tkEnumeration:
  73. (
  74. BaseType : PTypeInfo;
  75. NameList : ShortString)
  76. );
  77. tkSet:
  78. (CompType : PTypeInfo)
  79. );
  80. tkFloat:
  81. (FloatType : TFloatType);
  82. tkSString:
  83. (MaxLength : Byte);
  84. tkClass:
  85. (ClassType : TClass;
  86. ParentInfo : PTypeInfo;
  87. PropCount : SmallInt;
  88. UnitName : ShortString
  89. // here the properties follow as array of TPropInfo
  90. );
  91. tkMethod:
  92. (MethodKind : TMethodKind;
  93. ParamCount : Byte;
  94. ParamList : array[0..1023] of Char
  95. {in reality ParamList is a array[1..ParamCount] of:
  96. record
  97. Flags : TParamFlags;
  98. ParamName : ShortString;
  99. TypeName : ShortString;
  100. end;
  101. followed by
  102. ResultType : ShortString}
  103. );
  104. tkInt64:
  105. (MinInt64Value, MaxInt64Value: Int64);
  106. tkQWord:
  107. (MinQWordValue, MaxQWordValue: QWord);
  108. tkInterface:
  109. (
  110. IntfParent: PTypeInfo;
  111. IntfFlags : TIntfFlagsBase;
  112. GUID: TGUID;
  113. IntfUnit: ShortString;
  114. );
  115. tkInterfaceRaw:
  116. (
  117. RawIntfParent: PTypeInfo;
  118. RawIntfFlags : TIntfFlagsBase;
  119. IID: TGUID;
  120. RawIntfUnit: ShortString;
  121. IIDStr: ShortString;
  122. );
  123. tkDynArray:
  124. (
  125. elSize : PtrUInt;
  126. elType2 : PPTypeInfo;
  127. varType : Longint;
  128. elType : PPTypeInfo;
  129. DynUnitName: ShortStringBase
  130. );
  131. end;
  132. // unsed, just for completeness
  133. TPropData =
  134. {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
  135. packed
  136. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  137. record
  138. PropCount : Word;
  139. PropList : record _alignmentdummy : ptrint; end;
  140. end;
  141. {$PACKRECORDS 1}
  142. PPropInfo = ^TPropInfo;
  143. TPropInfo = packed record
  144. PropType : PTypeInfo;
  145. GetProc : Pointer;
  146. SetProc : Pointer;
  147. StoredProc : Pointer;
  148. Index : Integer;
  149. Default : Longint;
  150. NameIndex : SmallInt;
  151. // contains the type of the Get/Set/Storedproc, see also ptxxx
  152. // bit 0..1 GetProc
  153. // 2..3 SetProc
  154. // 4..5 StoredProc
  155. // 6 : true, constant index property
  156. PropProcs : Byte;
  157. Name : ShortString;
  158. end;
  159. TProcInfoProc = Procedure(PropInfo : PPropInfo) of object;
  160. PPropList = ^TPropList;
  161. TPropList = array[0..65535] of PPropInfo;
  162. const
  163. tkAny = [Low(TTypeKind)..High(TTypeKind)];
  164. tkMethods = [tkMethod];
  165. tkProperties = tkAny-tkMethods-[tkUnknown];
  166. // general property handling
  167. Function GetTypeData(TypeInfo : PTypeInfo) : PTypeData;
  168. Function GetPropInfo(TypeInfo : PTypeInfo;const PropName : string) : PPropInfo;
  169. Function GetPropInfo(TypeInfo : PTypeInfo;const PropName : string; AKinds : TTypeKinds) : PPropInfo;
  170. Function GetPropInfo(Instance: TObject; const PropName: string; AKinds: TTypeKinds) : PPropInfo;
  171. Function GetPropInfo(Instance: TObject; const PropName: string): PPropInfo;
  172. Function GetPropInfo(AClass: TClass; const PropName: string; AKinds: TTypeKinds) : PPropInfo;
  173. Function GetPropInfo(AClass: TClass; const PropName: string): PPropInfo;
  174. Function FindPropInfo(Instance: TObject; const PropName: string): PPropInfo;
  175. Function FindPropInfo(AClass:TClass;const PropName: string): PPropInfo;
  176. Procedure GetPropInfos(TypeInfo : PTypeInfo;PropList : PPropList);
  177. Function GetPropList(TypeInfo : PTypeInfo;TypeKinds : TTypeKinds; PropList : PPropList;Sorted : boolean = true):longint;
  178. Function GetPropList(TypeInfo: PTypeInfo; out PropList: PPropList): SizeInt;
  179. function GetPropList(AObject: TObject; out PropList: PPropList): Integer;
  180. // Property information routines.
  181. Function IsStoredProp(Instance: TObject;PropInfo : PPropInfo) : Boolean;
  182. Function IsStoredProp(Instance: TObject; const PropName: string): Boolean;
  183. Function IsPublishedProp(Instance: TObject; const PropName: string): Boolean;
  184. Function IsPublishedProp(AClass: TClass; const PropName: string): Boolean;
  185. Function PropType(Instance: TObject; const PropName: string): TTypeKind;
  186. Function PropType(AClass: TClass; const PropName: string): TTypeKind;
  187. Function PropIsType(Instance: TObject; const PropName: string; TypeKind: TTypeKind): Boolean;
  188. Function PropIsType(AClass: TClass; const PropName: string; TypeKind: TTypeKind): Boolean;
  189. // subroutines to read/write properties
  190. Function GetOrdProp(Instance: TObject; PropInfo : PPropInfo) : Int64;
  191. Function GetOrdProp(Instance: TObject; const PropName: string): Int64;
  192. Procedure SetOrdProp(Instance: TObject; PropInfo : PPropInfo; Value : Int64);
  193. Procedure SetOrdProp(Instance: TObject; const PropName: string; Value: Int64);
  194. Function GetEnumProp(Instance: TObject; const PropName: string): string;
  195. Function GetEnumProp(Instance: TObject; const PropInfo: PPropInfo): string;
  196. Procedure SetEnumProp(Instance: TObject; const PropName: string;const Value: string);
  197. Procedure SetEnumProp(Instance: TObject; const PropInfo: PPropInfo;const Value: string);
  198. Function GetSetProp(Instance: TObject; const PropName: string): string;
  199. Function GetSetProp(Instance: TObject; const PropName: string; Brackets: Boolean): string;
  200. Function GetSetProp(Instance: TObject; const PropInfo: PPropInfo; Brackets: Boolean): string;
  201. Procedure SetSetProp(Instance: TObject; const PropName: string; const Value: string);
  202. Procedure SetSetProp(Instance: TObject; const PropInfo: PPropInfo; const Value: string);
  203. Function GetStrProp(Instance: TObject; PropInfo : PPropInfo) : Ansistring;
  204. Function GetStrProp(Instance: TObject; const PropName: string): string;
  205. Procedure SetStrProp(Instance: TObject; const PropName: string; const Value: AnsiString);
  206. Procedure SetStrProp(Instance: TObject; PropInfo : PPropInfo; const Value : Ansistring);
  207. Function GetWideStrProp(Instance: TObject; PropInfo: PPropInfo): WideString;
  208. Function GetWideStrProp(Instance: TObject; const PropName: string): WideString;
  209. Procedure SetWideStrProp(Instance: TObject; const PropName: string; const Value: WideString);
  210. Procedure SetWideStrProp(Instance: TObject; PropInfo: PPropInfo; const Value: WideString);
  211. Function GetFloatProp(Instance: TObject; PropInfo : PPropInfo) : Extended;
  212. Function GetFloatProp(Instance: TObject; const PropName: string): Extended;
  213. Procedure SetFloatProp(Instance: TObject; const PropName: string; Value: Extended);
  214. Procedure SetFloatProp(Instance: TObject; PropInfo : PPropInfo; Value : Extended);
  215. Function GetObjectProp(Instance: TObject; const PropName: string): TObject;
  216. Function GetObjectProp(Instance: TObject; const PropName: string; MinClass: TClass): TObject;
  217. Function GetObjectProp(Instance: TObject; PropInfo: PPropInfo): TObject;
  218. Function GetObjectProp(Instance: TObject; PropInfo: PPropInfo; MinClass: TClass): TObject;
  219. Procedure SetObjectProp(Instance: TObject; const PropName: string; Value: TObject);
  220. Procedure SetObjectProp(Instance: TObject; PropInfo: PPropInfo; Value: TObject);
  221. Function GetObjectPropClass(Instance: TObject; const PropName: string): TClass;
  222. Function GetMethodProp(Instance: TObject; PropInfo: PPropInfo) : TMethod;
  223. Function GetMethodProp(Instance: TObject; const PropName: string): TMethod;
  224. Procedure SetMethodProp(Instance: TObject; PropInfo: PPropInfo; const Value : TMethod);
  225. Procedure SetMethodProp(Instance: TObject; const PropName: string; const Value: TMethod);
  226. Function GetInt64Prop(Instance: TObject; PropInfo: PPropInfo): Int64;
  227. Function GetInt64Prop(Instance: TObject; const PropName: string): Int64;
  228. Procedure SetInt64Prop(Instance: TObject; PropInfo: PPropInfo; const Value: Int64);
  229. Procedure SetInt64Prop(Instance: TObject; const PropName: string; const Value: Int64);
  230. Function GetPropValue(Instance: TObject; const PropName: string): Variant;
  231. Function GetPropValue(Instance: TObject; const PropName: string; PreferStrings: Boolean): Variant;
  232. Procedure SetPropValue(Instance: TObject; const PropName: string; const Value: Variant);
  233. Function GetVariantProp(Instance: TObject; PropInfo : PPropInfo): Variant;
  234. Function GetVariantProp(Instance: TObject; const PropName: string): Variant;
  235. Procedure SetVariantProp(Instance: TObject; const PropName: string; const Value: Variant);
  236. Procedure SetVariantProp(Instance: TObject; PropInfo : PPropInfo; const Value: Variant);
  237. function GetInterfaceProp(Instance: TObject; const PropName: string): IInterface;
  238. function GetInterfaceProp(Instance: TObject; PropInfo: PPropInfo): IInterface;
  239. procedure SetInterfaceProp(Instance: TObject; const PropName: string; const Value: IInterface);
  240. procedure SetInterfaceProp(Instance: TObject; PropInfo: PPropInfo; const Value: IInterface);
  241. // Auxiliary routines, which may be useful
  242. Function GetEnumName(TypeInfo : PTypeInfo;Value : Integer) : string;
  243. Function GetEnumValue(TypeInfo : PTypeInfo;const Name : string) : Integer;
  244. function GetEnumNameCount(enum1: PTypeInfo): SizeInt;
  245. function SetToString(TypeInfo: PTypeInfo; Value: Integer; Brackets: Boolean) : String;
  246. function SetToString(PropInfo: PPropInfo; Value: Integer; Brackets: Boolean) : String;
  247. function SetToString(PropInfo: PPropInfo; Value: Integer) : String;
  248. function StringToSet(PropInfo: PPropInfo; const Value: string): Integer;
  249. function StringToSet(TypeInfo: PTypeInfo; const Value: string): Integer;
  250. const
  251. BooleanIdents: array[Boolean] of String = ('False', 'True');
  252. DotSep: String = '.';
  253. Type
  254. EPropertyError = Class(Exception);
  255. TGetPropValue = Function (Instance: TObject; const PropName: string; PreferStrings: Boolean) : Variant;
  256. TSetPropValue = Procedure (Instance: TObject; const PropName: string; const Value: Variant);
  257. TGetVariantProp = Function (Instance: TObject; PropInfo : PPropInfo): Variant;
  258. TSetVariantProp = Procedure (Instance: TObject; PropInfo : PPropInfo; const Value: Variant);
  259. EPropertyConvertError = class(Exception); // Not used (yet), but defined for compatibility.
  260. Const
  261. OnGetPropValue : TGetPropValue = Nil;
  262. OnSetPropValue : TSetPropValue = Nil;
  263. OnGetVariantprop : TGetVariantProp = Nil;
  264. OnSetVariantprop : TSetVariantProp = Nil;
  265. Implementation
  266. uses rtlconsts;
  267. type
  268. PMethod = ^TMethod;
  269. { ---------------------------------------------------------------------
  270. Auxiliary methods
  271. ---------------------------------------------------------------------}
  272. function aligntoptr(p : pointer) : pointer;inline;
  273. begin
  274. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  275. result:=align(p,sizeof(p));
  276. {$else FPC_REQUIRES_PROPER_ALIGNMENT}
  277. result:=p;
  278. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  279. end;
  280. Function GetEnumName(TypeInfo : PTypeInfo;Value : Integer) : string;
  281. Var PS : PShortString;
  282. PT : PTypeData;
  283. begin
  284. PT:=GetTypeData(TypeInfo);
  285. if TypeInfo^.Kind=tkBool then
  286. begin
  287. case Value of
  288. 0,1:
  289. Result:=BooleanIdents[Boolean(Value)];
  290. else
  291. Result:='';
  292. end;
  293. end
  294. else
  295. begin
  296. PS:=@PT^.NameList;
  297. While Value>0 Do
  298. begin
  299. PS:=PShortString(pointer(PS)+PByte(PS)^+1);
  300. Dec(Value);
  301. end;
  302. Result:=PS^;
  303. end;
  304. end;
  305. Function GetEnumValue(TypeInfo : PTypeInfo;const Name : string) : Integer;
  306. Var PS : PShortString;
  307. PT : PTypeData;
  308. Count : longint;
  309. sName: shortstring;
  310. begin
  311. If Length(Name)=0 then
  312. exit(-1);
  313. sName := Name;
  314. PT:=GetTypeData(TypeInfo);
  315. Count:=0;
  316. Result:=-1;
  317. if TypeInfo^.Kind=tkBool then
  318. begin
  319. If CompareText(BooleanIdents[false],Name)=0 then
  320. result:=0
  321. else if CompareText(BooleanIdents[true],Name)=0 then
  322. result:=1;
  323. end
  324. else
  325. begin
  326. PS:=@PT^.NameList;
  327. While (Result=-1) and (PByte(PS)^<>0) do
  328. begin
  329. If ShortCompareText(PS^, sName) = 0 then
  330. Result:=Count;
  331. PS:=PShortString(pointer(PS)+PByte(PS)^+1);
  332. Inc(Count);
  333. end;
  334. end;
  335. end;
  336. function GetEnumNameCount(enum1: PTypeInfo): SizeInt;
  337. var
  338. PS: PShortString;
  339. PT: PTypeData;
  340. Count: SizeInt;
  341. begin
  342. PT:=GetTypeData(enum1);
  343. if enum1^.Kind=tkBool then
  344. Result:=2
  345. else
  346. begin
  347. Count:=0;
  348. Result:=0;
  349. PS:=@PT^.NameList;
  350. While (PByte(PS)^<>0) do
  351. begin
  352. PS:=PShortString(pointer(PS)+PByte(PS)^+1);
  353. Inc(Count);
  354. end;
  355. Result := Count;
  356. end;
  357. end;
  358. Function SetToString(PropInfo: PPropInfo; Value: Integer; Brackets: Boolean) : String;
  359. begin
  360. Result:=SetToString(PropInfo^.PropType,Value,Brackets);
  361. end;
  362. Function SetToString(TypeInfo: PTypeInfo; Value: Integer; Brackets: Boolean) : String;
  363. {$ifdef FPC_NEW_BIGENDIAN_SETS}
  364. type
  365. tsetarr = bitpacked array[0..31] of 0..1;
  366. {$endif}
  367. Var
  368. I : Integer;
  369. PTI : PTypeInfo;
  370. begin
  371. {$if defined(FPC_NEW_BIGENDIAN_SETS) and defined(FPC_BIG_ENDIAN)}
  372. case GetTypeData(TypeInfo)^.OrdType of
  373. otSByte,otUByte: Value:=Value shl 24;
  374. otSWord,otUWord: Value:=Value shl 16;
  375. end;
  376. {$endif}
  377. PTI:=GetTypeData(TypeInfo)^.CompType;
  378. Result:='';
  379. For I:=0 to SizeOf(Integer)*8-1 do
  380. begin
  381. {$ifdef FPC_NEW_BIGENDIAN_SETS}
  382. if (tsetarr(Value)[i]<>0) then
  383. {$else}
  384. if ((Value and 1)<>0) then
  385. {$endif}
  386. begin
  387. If Result='' then
  388. Result:=GetEnumName(PTI,i)
  389. else
  390. Result:=Result+','+GetEnumName(PTI,I);
  391. end;
  392. {$ifndef FPC_NEW_BIGENDIAN_SETS}
  393. Value:=Value shr 1;
  394. {$endif FPC_NEW_BIGENDIAN_SETS}
  395. end;
  396. if Brackets then
  397. Result:='['+Result+']';
  398. end;
  399. Function SetToString(PropInfo: PPropInfo; Value: Integer) : String;
  400. begin
  401. Result:=SetToString(PropInfo,Value,False);
  402. end;
  403. Const
  404. SetDelim = ['[',']',',',' '];
  405. Function GetNextElement(Var S : String) : String;
  406. Var
  407. J : Integer;
  408. begin
  409. J:=1;
  410. Result:='';
  411. If Length(S)>0 then
  412. begin
  413. While (J<=Length(S)) and Not (S[j] in SetDelim) do
  414. Inc(j);
  415. Result:=Copy(S,1,j-1);
  416. Delete(S,1,j);
  417. end;
  418. end;
  419. Function StringToSet(PropInfo: PPropInfo; const Value: string): Integer;
  420. begin
  421. Result:=StringToSet(PropInfo^.PropType,Value);
  422. end;
  423. Function StringToSet(TypeInfo: PTypeInfo; const Value: string): Integer;
  424. Var
  425. S,T : String;
  426. I : Integer;
  427. PTI : PTypeInfo;
  428. begin
  429. Result:=0;
  430. PTI:=GetTypeData(TypeInfo)^.Comptype;
  431. S:=Value;
  432. I:=1;
  433. If Length(S)>0 then
  434. begin
  435. While (I<=Length(S)) and (S[i] in SetDelim) do
  436. Inc(I);
  437. Delete(S,1,i-1);
  438. end;
  439. While (S<>'') do
  440. begin
  441. T:=GetNextElement(S);
  442. if T<>'' then
  443. begin
  444. I:=GetEnumValue(PTI,T);
  445. if (I<0) then
  446. raise EPropertyError.CreateFmt(SErrUnknownEnumValue, [T]);
  447. Result:=Result or (1 shl i);
  448. end;
  449. end;
  450. end;
  451. Function GetTypeData(TypeInfo : PTypeInfo) : PTypeData;
  452. begin
  453. GetTypeData:=PTypeData(aligntoptr(PTypeData(pointer(TypeInfo)+2+PByte(pointer(TypeInfo)+1)^)));
  454. end;
  455. { ---------------------------------------------------------------------
  456. Basic Type information functions.
  457. ---------------------------------------------------------------------}
  458. Function GetPropInfo(TypeInfo : PTypeInfo;const PropName : string) : PPropInfo;
  459. var
  460. hp : PTypeData;
  461. i : longint;
  462. p : shortstring;
  463. pd : ^TPropData;
  464. begin
  465. P:=PropName; // avoid Ansi<->short conversion in a loop
  466. while Assigned(TypeInfo) do
  467. begin
  468. // skip the name
  469. hp:=GetTypeData(Typeinfo);
  470. // the class info rtti the property rtti follows immediatly
  471. pd:=aligntoptr(pointer(pointer(@hp^.UnitName)+Length(hp^.UnitName)+1));
  472. Result:=PPropInfo(@pd^.PropList);
  473. for i:=1 to pd^.PropCount do
  474. begin
  475. // found a property of that name ?
  476. if ShortCompareText(Result^.Name, P) = 0 then
  477. exit;
  478. // skip to next property
  479. Result:=PPropInfo(aligntoptr(pointer(@Result^.Name)+byte(Result^.Name[0])+1));
  480. end;
  481. // parent class
  482. Typeinfo:=hp^.ParentInfo;
  483. end;
  484. Result:=Nil;
  485. end;
  486. Function GetPropInfo(TypeInfo : PTypeInfo;const PropName : string; Akinds : TTypeKinds) : PPropInfo;
  487. begin
  488. Result:=GetPropInfo(TypeInfo,PropName);
  489. If (Akinds<>[]) then
  490. If (Result<>Nil) then
  491. If Not (Result^.PropType^.Kind in AKinds) then
  492. Result:=Nil;
  493. end;
  494. Function GetPropInfo(AClass: TClass; const PropName: string; AKinds: TTypeKinds) : PPropInfo;
  495. begin
  496. Result:=GetPropInfo(PTypeInfo(AClass.ClassInfo),PropName,AKinds);
  497. end;
  498. Function GetPropInfo(Instance: TObject; const PropName: string; AKinds: TTypeKinds) : PPropInfo;
  499. begin
  500. Result:=GetPropInfo(Instance.ClassType,PropName,AKinds);
  501. end;
  502. Function GetPropInfo(Instance: TObject; const PropName: string): PPropInfo;
  503. begin
  504. Result:=GetPropInfo(Instance,PropName,[]);
  505. end;
  506. Function GetPropInfo(AClass: TClass; const PropName: string): PPropInfo;
  507. begin
  508. Result:=GetPropInfo(AClass,PropName,[]);
  509. end;
  510. Function FindPropInfo(Instance: TObject; const PropName: string): PPropInfo;
  511. begin
  512. result:=GetPropInfo(Instance, PropName);
  513. if Result=nil then
  514. Raise EPropertyError.CreateFmt(SErrPropertyNotFound, [PropName]);
  515. end;
  516. Function FindPropInfo(AClass:TClass;const PropName: string): PPropInfo;
  517. begin
  518. result:=GetPropInfo(AClass,PropName);
  519. if result=nil then
  520. Raise EPropertyError.CreateFmt(SErrPropertyNotFound, [PropName]);
  521. end;
  522. Function IsStoredProp(Instance : TObject;PropInfo : PPropInfo) : Boolean;
  523. type
  524. TBooleanIndexFunc=function(Index:integer):boolean of object;
  525. TBooleanFunc=function:boolean of object;
  526. var
  527. AMethod : TMethod;
  528. begin
  529. case (PropInfo^.PropProcs shr 4) and 3 of
  530. ptfield:
  531. Result:=PBoolean(Pointer(Instance)+PtrUInt(PropInfo^.StoredProc))^;
  532. ptconst:
  533. Result:=LongBool(PropInfo^.StoredProc);
  534. ptstatic,
  535. ptvirtual:
  536. begin
  537. if (PropInfo^.PropProcs shr 4) and 3=ptstatic then
  538. AMethod.Code:=PropInfo^.StoredProc
  539. else
  540. AMethod.Code:=ppointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.StoredProc))^;
  541. AMethod.Data:=Instance;
  542. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  543. Result:=TBooleanIndexFunc(AMethod)(PropInfo^.Index)
  544. else
  545. Result:=TBooleanFunc(AMethod)();
  546. end;
  547. end;
  548. end;
  549. Procedure GetPropInfos(TypeInfo : PTypeInfo;PropList : PPropList);
  550. {
  551. Store Pointers to property information in the list pointed
  552. to by proplist. PRopList must contain enough space to hold ALL
  553. properties.
  554. }
  555. Var
  556. TD : PTypeData;
  557. TP : PPropInfo;
  558. Count : Longint;
  559. begin
  560. // Get this objects TOTAL published properties count
  561. TD:=GetTypeData(TypeInfo);
  562. // Clear list
  563. FillChar(PropList^,TD^.PropCount*sizeof(Pointer),0);
  564. repeat
  565. TD:=GetTypeData(TypeInfo);
  566. // published properties count for this object
  567. TP:=aligntoptr(PPropInfo(aligntoptr((Pointer(@TD^.UnitName)+Length(TD^.UnitName)+1))));
  568. Count:=PWord(TP)^;
  569. // Now point TP to first propinfo record.
  570. Inc(Pointer(TP),SizeOF(Word));
  571. tp:=aligntoptr(tp);
  572. While Count>0 do
  573. begin
  574. // Don't overwrite properties with the same name
  575. if PropList^[TP^.NameIndex]=nil then
  576. PropList^[TP^.NameIndex]:=TP;
  577. // Point to TP next propinfo record.
  578. // Located at Name[Length(Name)+1] !
  579. TP:=aligntoptr(PPropInfo(pointer(@TP^.Name)+PByte(@TP^.Name)^+1));
  580. Dec(Count);
  581. end;
  582. TypeInfo:=TD^.Parentinfo;
  583. until TypeInfo=nil;
  584. end;
  585. Procedure InsertProp (PL : PProplist;PI : PPropInfo; Count : longint);
  586. Var
  587. I : Longint;
  588. begin
  589. I:=0;
  590. While (I<Count) and (PI^.Name>PL^[I]^.Name) do
  591. Inc(I);
  592. If I<Count then
  593. Move(PL^[I], PL^[I+1], (Count - I) * SizeOf(Pointer));
  594. PL^[I]:=PI;
  595. end;
  596. Procedure InsertPropnosort (PL : PProplist;PI : PPropInfo; Count : longint);
  597. begin
  598. PL^[Count]:=PI;
  599. end;
  600. Type TInsertProp = Procedure (PL : PProplist;PI : PPropInfo; Count : longint);
  601. //Const InsertProps : array[false..boolean] of TInsertProp = (InsertPropNoSort,InsertProp);
  602. Function GetPropList(TypeInfo : PTypeInfo;TypeKinds : TTypeKinds; PropList : PPropList;Sorted : boolean = true):longint;
  603. {
  604. Store Pointers to property information OF A CERTAIN KIND in the list pointed
  605. to by proplist. PRopList must contain enough space to hold ALL
  606. properties.
  607. }
  608. Var
  609. TempList : PPropList;
  610. PropInfo : PPropinfo;
  611. I,Count : longint;
  612. DoInsertProp : TInsertProp;
  613. begin
  614. if sorted then
  615. DoInsertProp:=@InsertProp
  616. else
  617. DoInsertProp:=@InsertPropnosort;
  618. Result:=0;
  619. Count:=GetTypeData(TypeInfo)^.Propcount;
  620. If Count>0 then
  621. begin
  622. GetMem(TempList,Count*SizeOf(Pointer));
  623. Try
  624. GetPropInfos(TypeInfo,TempList);
  625. For I:=0 to Count-1 do
  626. begin
  627. PropInfo:=TempList^[i];
  628. If PropInfo^.PropType^.Kind in TypeKinds then
  629. begin
  630. If (PropList<>Nil) then
  631. DoInsertProp(PropList,PropInfo,Result);
  632. Inc(Result);
  633. end;
  634. end;
  635. finally
  636. FreeMem(TempList,Count*SizeOf(Pointer));
  637. end;
  638. end;
  639. end;
  640. Function GetPropList(TypeInfo: PTypeInfo; out PropList: PPropList): SizeInt;
  641. begin
  642. result:=GetTypeData(TypeInfo)^.Propcount;
  643. if result>0 then
  644. begin
  645. getmem(PropList,result*sizeof(pointer));
  646. GetPropInfos(TypeInfo,PropList);
  647. end
  648. else
  649. PropList:=Nil;
  650. end;
  651. function GetPropList(AObject: TObject; out PropList: PPropList): Integer;
  652. begin
  653. Result := GetPropList(PTypeInfo(AObject.ClassInfo), PropList);
  654. end;
  655. { ---------------------------------------------------------------------
  656. Property access functions
  657. ---------------------------------------------------------------------}
  658. { ---------------------------------------------------------------------
  659. Ordinal properties
  660. ---------------------------------------------------------------------}
  661. Function GetOrdProp(Instance : TObject;PropInfo : PPropInfo) : Int64;
  662. type
  663. TGetInt64ProcIndex=function(index:longint):Int64 of object;
  664. TGetInt64Proc=function():Int64 of object;
  665. TGetIntegerProcIndex=function(index:longint):longint of object;
  666. TGetIntegerProc=function:longint of object;
  667. TGetWordProcIndex=function(index:longint):word of object;
  668. TGetWordProc=function:word of object;
  669. TGetByteProcIndex=function(index:longint):Byte of object;
  670. TGetByteProc=function:Byte of object;
  671. var
  672. TypeInfo: PTypeInfo;
  673. AMethod : TMethod;
  674. DataSize: Integer;
  675. OrdType: TOrdType;
  676. Signed: Boolean;
  677. begin
  678. Result:=0;
  679. TypeInfo := PropInfo^.PropType;
  680. Signed := false;
  681. DataSize := 4;
  682. case TypeInfo^.Kind of
  683. {$ifdef cpu64}
  684. tkInterface,
  685. tkInterfaceRaw,
  686. tkDynArray,
  687. tkClass:
  688. DataSize:=8;
  689. {$endif cpu64}
  690. tkChar, tkBool:
  691. DataSize:=1;
  692. tkWChar:
  693. DataSize:=2;
  694. tkSet,
  695. tkEnumeration,
  696. tkInteger:
  697. begin
  698. OrdType:=GetTypeData(TypeInfo)^.OrdType;
  699. case OrdType of
  700. otSByte,otUByte: DataSize := 1;
  701. otSWord,otUWord: DataSize := 2;
  702. end;
  703. Signed := OrdType in [otSByte,otSWord,otSLong];
  704. end;
  705. tkInt64 :
  706. begin
  707. DataSize:=8;
  708. Signed:=true;
  709. end;
  710. tkQword :
  711. begin
  712. DataSize:=8;
  713. Signed:=false;
  714. end;
  715. end;
  716. case (PropInfo^.PropProcs) and 3 of
  717. ptfield:
  718. if Signed then begin
  719. case DataSize of
  720. 1: Result:=PShortInt(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  721. 2: Result:=PSmallInt(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  722. 4: Result:=PLongint(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  723. 8: Result:=PInt64(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  724. end;
  725. end else begin
  726. case DataSize of
  727. 1: Result:=PByte(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  728. 2: Result:=PWord(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  729. 4: Result:=PLongint(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  730. 8: Result:=PInt64(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  731. end;
  732. end;
  733. ptstatic,
  734. ptvirtual :
  735. begin
  736. if (PropInfo^.PropProcs and 3)=ptStatic then
  737. AMethod.Code:=PropInfo^.GetProc
  738. else
  739. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.GetProc))^;
  740. AMethod.Data:=Instance;
  741. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then begin
  742. case DataSize of
  743. 1: Result:=TGetByteProcIndex(AMethod)(PropInfo^.Index);
  744. 2: Result:=TGetWordProcIndex(AMethod)(PropInfo^.Index);
  745. 4: Result:=TGetIntegerProcIndex(AMethod)(PropInfo^.Index);
  746. 8: result:=TGetInt64ProcIndex(AMethod)(PropInfo^.Index)
  747. end;
  748. end else begin
  749. case DataSize of
  750. 1: Result:=TGetByteProc(AMethod)();
  751. 2: Result:=TGetWordProc(AMethod)();
  752. 4: Result:=TGetIntegerProc(AMethod)();
  753. 8: result:=TGetInt64Proc(AMethod)();
  754. end;
  755. end;
  756. if Signed then begin
  757. case DataSize of
  758. 1: Result:=ShortInt(Result);
  759. 2: Result:=SmallInt(Result);
  760. end;
  761. end;
  762. end;
  763. end;
  764. end;
  765. Procedure SetOrdProp(Instance : TObject;PropInfo : PPropInfo;Value : Int64);
  766. type
  767. TSetInt64ProcIndex=procedure(index:longint;i:Int64) of object;
  768. TSetInt64Proc=procedure(i:Int64) of object;
  769. TSetIntegerProcIndex=procedure(index,i:longint) of object;
  770. TSetIntegerProc=procedure(i:longint) of object;
  771. var
  772. DataSize: Integer;
  773. AMethod : TMethod;
  774. begin
  775. if PropInfo^.PropType^.Kind in [tkInt64,tkQword
  776. { why do we have to handle classes here, see also below? (FK) }
  777. {$ifdef cpu64}
  778. ,tkInterface
  779. ,tkInterfaceRaw
  780. ,tkDynArray
  781. ,tkClass
  782. {$endif cpu64}
  783. ] then
  784. DataSize := 8
  785. else
  786. DataSize := 4;
  787. if not(PropInfo^.PropType^.Kind in [tkInt64,tkQword,tkClass]) then
  788. begin
  789. { cut off unnecessary stuff }
  790. case GetTypeData(PropInfo^.PropType)^.OrdType of
  791. otSWord,otUWord:
  792. begin
  793. Value:=Value and $ffff;
  794. DataSize := 2;
  795. end;
  796. otSByte,otUByte:
  797. begin
  798. Value:=Value and $ff;
  799. DataSize := 1;
  800. end;
  801. end;
  802. end;
  803. case (PropInfo^.PropProcs shr 2) and 3 of
  804. ptfield:
  805. case DataSize of
  806. 1: PByte(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^:=Byte(Value);
  807. 2: PWord(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^:=Word(Value);
  808. 4: PLongint(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^:=Longint(Value);
  809. 8: PInt64(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^:=Value;
  810. end;
  811. ptstatic,
  812. ptvirtual :
  813. begin
  814. if ((PropInfo^.PropProcs shr 2) and 3)=ptStatic then
  815. AMethod.Code:=PropInfo^.SetProc
  816. else
  817. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.SetProc))^;
  818. AMethod.Data:=Instance;
  819. if datasize=8 then
  820. begin
  821. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  822. TSetInt64ProcIndex(AMethod)(PropInfo^.Index,Value)
  823. else
  824. TSetInt64Proc(AMethod)(Value);
  825. end
  826. else
  827. begin
  828. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  829. TSetIntegerProcIndex(AMethod)(PropInfo^.Index,Value)
  830. else
  831. TSetIntegerProc(AMethod)(Value);
  832. end;
  833. end;
  834. end;
  835. end;
  836. Function GetOrdProp(Instance: TObject; const PropName: string): Int64;
  837. begin
  838. Result:=GetOrdProp(Instance,FindPropInfo(Instance,PropName));
  839. end;
  840. Procedure SetOrdProp(Instance: TObject; const PropName: string; Value: Int64);
  841. begin
  842. SetOrdProp(Instance,FindPropInfo(Instance,PropName),Value);
  843. end;
  844. Function GetEnumProp(Instance: TObject; Const PropInfo: PPropInfo): string;
  845. begin
  846. Result:=GetEnumName(PropInfo^.PropType, GetOrdProp(Instance, PropInfo));
  847. end;
  848. Function GetEnumProp(Instance: TObject; const PropName: string): string;
  849. begin
  850. Result:=GetEnumProp(Instance,FindPropInfo(Instance,PropName));
  851. end;
  852. Procedure SetEnumProp(Instance: TObject; const PropName: string; const Value: string);
  853. begin
  854. SetEnumProp(Instance,FindPropInfo(Instance,PropName),Value);
  855. end;
  856. Procedure SetEnumProp(Instance: TObject; Const PropInfo : PPropInfo; const Value: string);
  857. Var
  858. PV : Longint;
  859. begin
  860. If PropInfo<>Nil then
  861. begin
  862. PV:=GetEnumValue(PropInfo^.PropType, Value);
  863. if (PV<0) then
  864. raise EPropertyError.CreateFmt(SErrUnknownEnumValue, [Value]);
  865. SetOrdProp(Instance, PropInfo,PV);
  866. end;
  867. end;
  868. { ---------------------------------------------------------------------
  869. Int64 wrappers
  870. ---------------------------------------------------------------------}
  871. Function GetInt64Prop(Instance: TObject; PropInfo: PPropInfo): Int64;
  872. begin
  873. Result:=GetOrdProp(Instance,PropInfo);
  874. end;
  875. procedure SetInt64Prop(Instance: TObject; PropInfo: PPropInfo; const Value: Int64);
  876. begin
  877. SetOrdProp(Instance,PropInfo,Value);
  878. end;
  879. Function GetInt64Prop(Instance: TObject; const PropName: string): Int64;
  880. begin
  881. Result:=GetInt64Prop(Instance,FindPropInfo(Instance,PropName));
  882. end;
  883. Procedure SetInt64Prop(Instance: TObject; const PropName: string; const Value: Int64);
  884. begin
  885. SetInt64Prop(Instance,FindPropInfo(Instance,PropName),Value);
  886. end;
  887. { ---------------------------------------------------------------------
  888. Set properties
  889. ---------------------------------------------------------------------}
  890. Function GetSetProp(Instance: TObject; const PropName: string): string;
  891. begin
  892. Result:=GetSetProp(Instance,PropName,False);
  893. end;
  894. Function GetSetProp(Instance: TObject; const PropName: string; Brackets: Boolean): string;
  895. begin
  896. Result:=GetSetProp(Instance,FindPropInfo(Instance,PropName),Brackets);
  897. end;
  898. Function GetSetProp(Instance: TObject; const PropInfo: PPropInfo; Brackets: Boolean): string;
  899. begin
  900. Result:=SetToString(PropInfo,GetOrdProp(Instance,PropInfo),Brackets);
  901. end;
  902. Procedure SetSetProp(Instance: TObject; const PropName: string; const Value: string);
  903. begin
  904. SetSetProp(Instance,FindPropInfo(Instance,PropName),Value);
  905. end;
  906. Procedure SetSetProp(Instance: TObject; const PropInfo: PPropInfo; const Value: string);
  907. begin
  908. SetOrdProp(Instance,PropInfo,StringToSet(PropInfo,Value));
  909. end;
  910. { ---------------------------------------------------------------------
  911. Object properties
  912. ---------------------------------------------------------------------}
  913. Function GetObjectProp(Instance: TObject; const PropName: string): TObject;
  914. begin
  915. Result:=GetObjectProp(Instance,PropName,Nil);
  916. end;
  917. Function GetObjectProp(Instance: TObject; const PropName: string; MinClass: TClass): TObject;
  918. begin
  919. Result:=GetObjectProp(Instance,FindPropInfo(Instance,PropName),MinClass);
  920. end;
  921. Function GetObjectProp(Instance: TObject; PropInfo : PPropInfo): TObject;
  922. begin
  923. Result:=GetObjectProp(Instance,PropInfo,Nil);
  924. end;
  925. Function GetObjectProp(Instance: TObject; PropInfo : PPropInfo; MinClass: TClass): TObject;
  926. begin
  927. {$ifdef cpu64}
  928. Result:=TObject(GetInt64Prop(Instance,PropInfo));
  929. {$else cpu64}
  930. Result:=TObject(PtrInt(GetOrdProp(Instance,PropInfo)));
  931. {$endif cpu64}
  932. If (MinClass<>Nil) and (Result<>Nil) Then
  933. If Not Result.InheritsFrom(MinClass) then
  934. Result:=Nil;
  935. end;
  936. Procedure SetObjectProp(Instance: TObject; const PropName: string; Value: TObject);
  937. begin
  938. SetObjectProp(Instance,FindPropInfo(Instance,PropName),Value);
  939. end;
  940. Procedure SetObjectProp(Instance: TObject; PropInfo : PPropInfo; Value: TObject);
  941. begin
  942. {$ifdef cpu64}
  943. SetInt64Prop(Instance,PropInfo,Int64(Value));
  944. {$else cpu64}
  945. SetOrdProp(Instance,PropInfo,Integer(Value));
  946. {$endif cpu64}
  947. end;
  948. Function GetObjectPropClass(Instance: TObject; const PropName: string): TClass;
  949. begin
  950. Result:=GetTypeData(FindPropInfo(Instance,PropName)^.PropType)^.ClassType;
  951. end;
  952. { ---------------------------------------------------------------------
  953. Interface wrapprers
  954. ---------------------------------------------------------------------}
  955. function GetInterfaceProp(Instance: TObject; const PropName: string): IInterface;
  956. begin
  957. Result:=GetInterfaceProp(Instance,FindPropInfo(Instance,PropName));
  958. end;
  959. function GetInterfaceProp(Instance: TObject; PropInfo: PPropInfo): IInterface;
  960. begin
  961. {$ifdef cpu64}
  962. Result:=IInterface(GetInt64Prop(Instance,PropInfo));
  963. {$else cpu64}
  964. Result:=IInterface(PtrInt(GetOrdProp(Instance,PropInfo)));
  965. {$endif cpu64}
  966. end;
  967. procedure SetInterfaceProp(Instance: TObject; const PropName: string; const Value: IInterface);
  968. begin
  969. SetInterfaceProp(Instance,FindPropInfo(Instance,PropName),Value);
  970. end;
  971. procedure SetInterfaceProp(Instance: TObject; PropInfo: PPropInfo; const Value: IInterface);
  972. begin
  973. {$ifdef cpu64}
  974. SetInt64Prop(Instance,PropInfo,Int64(Value));
  975. {$else cpu64}
  976. SetOrdProp(Instance,PropInfo,Integer(Value));
  977. {$endif cpu64}
  978. end;
  979. { ---------------------------------------------------------------------
  980. String properties
  981. ---------------------------------------------------------------------}
  982. Function GetStrProp(Instance: TObject; PropInfo: PPropInfo): AnsiString;
  983. type
  984. TGetShortStrProcIndex=function(index:longint):ShortString of object;
  985. TGetShortStrProc=function():ShortString of object;
  986. TGetAnsiStrProcIndex=function(index:longint):AnsiString of object;
  987. TGetAnsiStrProc=function():AnsiString of object;
  988. var
  989. AMethod : TMethod;
  990. begin
  991. Result:='';
  992. case Propinfo^.PropType^.Kind of
  993. tkWString:
  994. Result:=GetWideStrProp(Instance,PropInfo);
  995. tkSString:
  996. begin
  997. case (PropInfo^.PropProcs) and 3 of
  998. ptField:
  999. Result := PShortString(Pointer(Instance) + LongWord(PropInfo^.GetProc))^;
  1000. ptstatic,
  1001. ptvirtual :
  1002. begin
  1003. if (PropInfo^.PropProcs and 3)=ptStatic then
  1004. AMethod.Code:=PropInfo^.GetProc
  1005. else
  1006. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.GetProc))^;
  1007. AMethod.Data:=Instance;
  1008. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  1009. Result:=TGetShortStrProcIndex(AMethod)(PropInfo^.Index)
  1010. else
  1011. Result:=TGetShortStrProc(AMethod)();
  1012. end;
  1013. end;
  1014. end;
  1015. tkAString:
  1016. begin
  1017. case (PropInfo^.PropProcs) and 3 of
  1018. ptField:
  1019. Result := PAnsiString(Pointer(Instance) + LongWord(PropInfo^.GetProc))^;
  1020. ptstatic,
  1021. ptvirtual :
  1022. begin
  1023. if (PropInfo^.PropProcs and 3)=ptStatic then
  1024. AMethod.Code:=PropInfo^.GetProc
  1025. else
  1026. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.GetProc))^;
  1027. AMethod.Data:=Instance;
  1028. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  1029. Result:=TGetAnsiStrProcIndex(AMethod)(PropInfo^.Index)
  1030. else
  1031. Result:=TGetAnsiStrProc(AMethod)();
  1032. end;
  1033. end;
  1034. end;
  1035. end;
  1036. end;
  1037. Procedure SetStrProp(Instance : TObject;PropInfo : PPropInfo; const Value : AnsiString);
  1038. type
  1039. TSetShortStrProcIndex=procedure(index:longint;const s:ShortString) of object;
  1040. TSetShortStrProc=procedure(const s:ShortString) of object;
  1041. TSetAnsiStrProcIndex=procedure(index:longint;s:AnsiString) of object;
  1042. TSetAnsiStrProc=procedure(s:AnsiString) of object;
  1043. var
  1044. AMethod : TMethod;
  1045. begin
  1046. case Propinfo^.PropType^.Kind of
  1047. tkWString:
  1048. SetWideStrProp(Instance,PropInfo,Value);
  1049. tkSString:
  1050. begin
  1051. case (PropInfo^.PropProcs shr 2) and 3 of
  1052. ptField:
  1053. PShortString(Pointer(Instance) + LongWord(PropInfo^.SetProc))^:=Value;
  1054. ptstatic,
  1055. ptvirtual :
  1056. begin
  1057. if (PropInfo^.PropProcs and 3)=ptStatic then
  1058. AMethod.Code:=PropInfo^.SetProc
  1059. else
  1060. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.SetProc))^;
  1061. AMethod.Data:=Instance;
  1062. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  1063. TSetShortStrProcIndex(AMethod)(PropInfo^.Index,Value)
  1064. else
  1065. TSetShortStrProc(AMethod)(Value);
  1066. end;
  1067. end;
  1068. end;
  1069. tkAString:
  1070. begin
  1071. case (PropInfo^.PropProcs shr 2) and 3 of
  1072. ptField:
  1073. PAnsiString(Pointer(Instance) + LongWord(PropInfo^.SetProc))^:=Value;
  1074. ptstatic,
  1075. ptvirtual :
  1076. begin
  1077. if ((PropInfo^.PropProcs shr 2) and 3)=ptStatic then
  1078. AMethod.Code:=PropInfo^.SetProc
  1079. else
  1080. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.SetProc))^;
  1081. AMethod.Data:=Instance;
  1082. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  1083. TSetAnsiStrProcIndex(AMethod)(PropInfo^.Index,Value)
  1084. else
  1085. TSetAnsiStrProc(AMethod)(Value);
  1086. end;
  1087. end;
  1088. end;
  1089. end;
  1090. end;
  1091. Function GetStrProp(Instance: TObject; const PropName: string): string;
  1092. begin
  1093. Result:=GetStrProp(Instance,FindPropInfo(Instance,PropName));
  1094. end;
  1095. Procedure SetStrProp(Instance: TObject; const PropName: string; const Value: AnsiString);
  1096. begin
  1097. SetStrProp(Instance,FindPropInfo(Instance,PropName),Value);
  1098. end;
  1099. Function GetWideStrProp(Instance: TObject; const PropName: string): WideString;
  1100. begin
  1101. Result:=GetWideStrProp(Instance, FindPropInfo(Instance, PropName));
  1102. end;
  1103. procedure SetWideStrProp(Instance: TObject; const PropName: string; const Value: WideString);
  1104. begin
  1105. SetWideStrProp(Instance,FindPropInfo(Instance,PropName),Value);
  1106. end;
  1107. Function GetWideStrProp(Instance: TObject; PropInfo: PPropInfo): WideString;
  1108. type
  1109. TGetWideStrProcIndex=function(index:longint):WideString of object;
  1110. TGetWideStrProc=function():WideString of object;
  1111. var
  1112. AMethod : TMethod;
  1113. begin
  1114. Result:='';
  1115. case Propinfo^.PropType^.Kind of
  1116. tkSString,tkAString:
  1117. Result:=GetStrProp(Instance,PropInfo);
  1118. tkWString:
  1119. begin
  1120. case (PropInfo^.PropProcs) and 3 of
  1121. ptField:
  1122. Result := PWideString(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  1123. ptstatic,
  1124. ptvirtual :
  1125. begin
  1126. if (PropInfo^.PropProcs and 3)=ptStatic then
  1127. AMethod.Code:=PropInfo^.GetProc
  1128. else
  1129. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.GetProc))^;
  1130. AMethod.Data:=Instance;
  1131. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  1132. Result:=TGetWideStrProcIndex(AMethod)(PropInfo^.Index)
  1133. else
  1134. Result:=TGetWideStrProc(AMethod)();
  1135. end;
  1136. end;
  1137. end;
  1138. end;
  1139. end;
  1140. Procedure SetWideStrProp(Instance: TObject; PropInfo: PPropInfo; const Value: WideString);
  1141. type
  1142. TSetWideStrProcIndex=procedure(index:longint;s:WideString) of object;
  1143. TSetWideStrProc=procedure(s:WideString) of object;
  1144. var
  1145. AMethod : TMethod;
  1146. begin
  1147. case Propinfo^.PropType^.Kind of
  1148. tkSString,tkAString:
  1149. SetStrProp(Instance,PropInfo,Value);
  1150. tkWString:
  1151. begin
  1152. case (PropInfo^.PropProcs shr 2) and 3 of
  1153. ptField:
  1154. PWideString(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^:=Value;
  1155. ptstatic,
  1156. ptvirtual :
  1157. begin
  1158. if ((PropInfo^.PropProcs shr 2) and 3)=ptStatic then
  1159. AMethod.Code:=PropInfo^.SetProc
  1160. else
  1161. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.SetProc))^;
  1162. AMethod.Data:=Instance;
  1163. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  1164. TSetWideStrProcIndex(AMethod)(PropInfo^.Index,Value)
  1165. else
  1166. TSetWideStrProc(AMethod)(Value);
  1167. end;
  1168. end;
  1169. end;
  1170. end;
  1171. end;
  1172. { ---------------------------------------------------------------------
  1173. Float properties
  1174. ---------------------------------------------------------------------}
  1175. function GetFloatProp(Instance : TObject;PropInfo : PPropInfo) : Extended;
  1176. type
  1177. TGetExtendedProc = function:Extended of object;
  1178. TGetExtendedProcIndex = function(Index: integer): Extended of object;
  1179. TGetDoubleProc = function:Double of object;
  1180. TGetDoubleProcIndex = function(Index: integer): Double of object;
  1181. TGetSingleProc = function:Single of object;
  1182. TGetSingleProcIndex = function(Index: integer):Single of object;
  1183. TGetCurrencyProc = function : Currency of object;
  1184. TGetCurrencyProcIndex = function(Index: integer) : Currency of object;
  1185. var
  1186. AMethod : TMethod;
  1187. begin
  1188. Result:=0.0;
  1189. case PropInfo^.PropProcs and 3 of
  1190. ptField:
  1191. Case GetTypeData(PropInfo^.PropType)^.FloatType of
  1192. ftSingle:
  1193. Result:=PSingle(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  1194. ftDouble:
  1195. Result:=PDouble(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  1196. ftExtended:
  1197. Result:=PExtended(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  1198. ftcomp:
  1199. Result:=PComp(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  1200. ftcurr:
  1201. Result:=PCurrency(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  1202. end;
  1203. ptStatic,
  1204. ptVirtual:
  1205. begin
  1206. if (PropInfo^.PropProcs and 3)=ptStatic then
  1207. AMethod.Code:=PropInfo^.GetProc
  1208. else
  1209. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.GetProc))^;
  1210. AMethod.Data:=Instance;
  1211. Case GetTypeData(PropInfo^.PropType)^.FloatType of
  1212. ftSingle:
  1213. if ((PropInfo^.PropProcs shr 6) and 1)=0 then
  1214. Result:=TGetSingleProc(AMethod)()
  1215. else
  1216. Result:=TGetSingleProcIndex(AMethod)(PropInfo^.Index);
  1217. ftDouble:
  1218. if ((PropInfo^.PropProcs shr 6) and 1)=0 then
  1219. Result:=TGetDoubleProc(AMethod)()
  1220. else
  1221. Result:=TGetDoubleProcIndex(AMethod)(PropInfo^.Index);
  1222. ftExtended:
  1223. if ((PropInfo^.PropProcs shr 6) and 1)=0 then
  1224. Result:=TGetExtendedProc(AMethod)()
  1225. else
  1226. Result:=TGetExtendedProcIndex(AMethod)(PropInfo^.Index);
  1227. ftCurr:
  1228. if ((PropInfo^.PropProcs shr 6) and 1)=0 then
  1229. Result:=TGetCurrencyProc(AMethod)()
  1230. else
  1231. Result:=TGetCurrencyProcIndex(AMethod)(PropInfo^.Index);
  1232. end;
  1233. end;
  1234. end;
  1235. end;
  1236. Procedure SetFloatProp(Instance : TObject;PropInfo : PPropInfo; Value : Extended);
  1237. type
  1238. TSetExtendedProc = procedure(const AValue: Extended) of object;
  1239. TSetExtendedProcIndex = procedure(Index: integer; AValue: Extended) of object;
  1240. TSetDoubleProc = procedure(const AValue: Double) of object;
  1241. TSetDoubleProcIndex = procedure(Index: integer; AValue: Double) of object;
  1242. TSetSingleProc = procedure(const AValue: Single) of object;
  1243. TSetSingleProcIndex = procedure(Index: integer; AValue: Single) of object;
  1244. TSetCurrencyProc = procedure(const AValue: Currency) of object;
  1245. TSetCurrencyProcIndex = procedure(Index: integer; AValue: Currency) of object;
  1246. Var
  1247. AMethod : TMethod;
  1248. begin
  1249. case (PropInfo^.PropProcs shr 2) and 3 of
  1250. ptfield:
  1251. Case GetTypeData(PropInfo^.PropType)^.FloatType of
  1252. ftSingle:
  1253. PSingle(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^:=Value;
  1254. ftDouble:
  1255. PDouble(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^:=Value;
  1256. ftExtended:
  1257. PExtended(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^:=Value;
  1258. {$ifdef FPC_COMP_IS_INT64}
  1259. ftComp:
  1260. PComp(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^:=trunc(Value);
  1261. {$else FPC_COMP_IS_INT64}
  1262. ftComp:
  1263. PComp(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^:=Comp(Value);
  1264. {$endif FPC_COMP_IS_INT64}
  1265. ftCurr:
  1266. PCurrency(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^:=Value;
  1267. end;
  1268. ptStatic,
  1269. ptVirtual:
  1270. begin
  1271. if ((PropInfo^.PropProcs shr 2) and 3)=ptStatic then
  1272. AMethod.Code:=PropInfo^.SetProc
  1273. else
  1274. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.SetProc))^;
  1275. AMethod.Data:=Instance;
  1276. Case GetTypeData(PropInfo^.PropType)^.FloatType of
  1277. ftSingle:
  1278. if ((PropInfo^.PropProcs shr 6) and 1)=0 then
  1279. TSetSingleProc(AMethod)(Value)
  1280. else
  1281. TSetSingleProcIndex(AMethod)(PropInfo^.Index,Value);
  1282. ftDouble:
  1283. if ((PropInfo^.PropProcs shr 6) and 1)=0 then
  1284. TSetDoubleProc(AMethod)(Value)
  1285. else
  1286. TSetDoubleProcIndex(AMethod)(PropInfo^.Index,Value);
  1287. ftExtended:
  1288. if ((PropInfo^.PropProcs shr 6) and 1)=0 then
  1289. TSetExtendedProc(AMethod)(Value)
  1290. else
  1291. TSetExtendedProcIndex(AMethod)(PropInfo^.Index,Value);
  1292. ftCurr:
  1293. if ((PropInfo^.PropProcs shr 6) and 1)=0 then
  1294. TSetCurrencyProc(AMethod)(Value)
  1295. else
  1296. TSetCurrencyProcIndex(AMethod)(PropInfo^.Index,Value);
  1297. end;
  1298. end;
  1299. end;
  1300. end;
  1301. function GetFloatProp(Instance: TObject; const PropName: string): Extended;
  1302. begin
  1303. Result:=GetFloatProp(Instance,FindPropInfo(Instance,PropName))
  1304. end;
  1305. Procedure SetFloatProp(Instance: TObject; const PropName: string; Value: Extended);
  1306. begin
  1307. SetFloatProp(Instance,FindPropInfo(Instance,PropName),Value);
  1308. end;
  1309. { ---------------------------------------------------------------------
  1310. Method properties
  1311. ---------------------------------------------------------------------}
  1312. Function GetMethodProp(Instance : TObject;PropInfo : PPropInfo) : TMethod;
  1313. type
  1314. TGetMethodProcIndex=function(Index: Longint): TMethod of object;
  1315. TGetMethodProc=function(): TMethod of object;
  1316. var
  1317. value: PMethod;
  1318. AMethod : TMethod;
  1319. begin
  1320. Result.Code:=nil;
  1321. Result.Data:=nil;
  1322. case (PropInfo^.PropProcs) and 3 of
  1323. ptfield:
  1324. begin
  1325. Value:=PMethod(Pointer(Instance)+PtrUInt(PropInfo^.GetProc));
  1326. if Value<>nil then
  1327. Result:=Value^;
  1328. end;
  1329. ptstatic,
  1330. ptvirtual :
  1331. begin
  1332. if (PropInfo^.PropProcs and 3)=ptStatic then
  1333. AMethod.Code:=PropInfo^.GetProc
  1334. else
  1335. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.GetProc))^;
  1336. AMethod.Data:=Instance;
  1337. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  1338. Result:=TGetMethodProcIndex(AMethod)(PropInfo^.Index)
  1339. else
  1340. Result:=TGetMethodProc(AMethod)();
  1341. end;
  1342. end;
  1343. end;
  1344. Procedure SetMethodProp(Instance : TObject;PropInfo : PPropInfo; const Value : TMethod);
  1345. type
  1346. TSetMethodProcIndex=procedure(index:longint;p:TMethod) of object;
  1347. TSetMethodProc=procedure(p:TMethod) of object;
  1348. var
  1349. AMethod : TMethod;
  1350. begin
  1351. case (PropInfo^.PropProcs shr 2) and 3 of
  1352. ptfield:
  1353. PMethod(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^ := Value;
  1354. ptstatic,
  1355. ptvirtual :
  1356. begin
  1357. if ((PropInfo^.PropProcs shr 2) and 3)=ptStatic then
  1358. AMethod.Code:=PropInfo^.SetProc
  1359. else
  1360. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.SetProc))^;
  1361. AMethod.Data:=Instance;
  1362. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  1363. TSetMethodProcIndex(AMethod)(PropInfo^.Index,Value)
  1364. else
  1365. TSetMethodProc(AMethod)(Value);
  1366. end;
  1367. end;
  1368. end;
  1369. Function GetMethodProp(Instance: TObject; const PropName: string): TMethod;
  1370. begin
  1371. Result:=GetMethodProp(Instance,FindPropInfo(Instance,PropName));
  1372. end;
  1373. Procedure SetMethodProp(Instance: TObject; const PropName: string; const Value: TMethod);
  1374. begin
  1375. SetMethodProp(Instance,FindPropInfo(Instance,PropName),Value);
  1376. end;
  1377. { ---------------------------------------------------------------------
  1378. Variant properties
  1379. ---------------------------------------------------------------------}
  1380. Procedure CheckVariantEvent(P : Pointer);
  1381. begin
  1382. If (P=Nil) then
  1383. Raise Exception.Create(SErrNoVariantSupport);
  1384. end;
  1385. Function GetVariantProp(Instance : TObject;PropInfo : PPropInfo): Variant;
  1386. begin
  1387. CheckVariantEvent(Pointer(OnGetVariantProp));
  1388. Result:=OnGetVariantProp(Instance,PropInfo);
  1389. end;
  1390. Procedure SetVariantProp(Instance : TObject;PropInfo : PPropInfo; const Value: Variant);
  1391. begin
  1392. CheckVariantEvent(Pointer(OnSetVariantProp));
  1393. OnSetVariantProp(Instance,PropInfo,Value);
  1394. end;
  1395. Function GetVariantProp(Instance: TObject; const PropName: string): Variant;
  1396. begin
  1397. Result:=GetVariantProp(Instance,FindPropInfo(Instance,PropName));
  1398. end;
  1399. Procedure SetVariantProp(Instance: TObject; const PropName: string; const Value: Variant);
  1400. begin
  1401. SetVariantprop(instance,FindpropInfo(Instance,PropName),Value);
  1402. end;
  1403. { ---------------------------------------------------------------------
  1404. All properties through variant.
  1405. ---------------------------------------------------------------------}
  1406. Function GetPropValue(Instance: TObject; const PropName: string): Variant;
  1407. begin
  1408. Result:=GetPropValue(Instance,PropName,True);
  1409. end;
  1410. Function GetPropValue(Instance: TObject; const PropName: string; PreferStrings: Boolean): Variant;
  1411. begin
  1412. CheckVariantEvent(Pointer(OnGetPropValue));
  1413. Result:=OnGetPropValue(Instance,PropName,PreferStrings)
  1414. end;
  1415. Procedure SetPropValue(Instance: TObject; const PropName: string; const Value: Variant);
  1416. begin
  1417. CheckVariantEvent(Pointer(OnSetPropValue));
  1418. OnSetPropValue(Instance,PropName,Value);
  1419. end;
  1420. { ---------------------------------------------------------------------
  1421. Easy access methods that appeared in Delphi 5
  1422. ---------------------------------------------------------------------}
  1423. Function IsPublishedProp(Instance: TObject; const PropName: string): Boolean;
  1424. begin
  1425. Result:=GetPropInfo(Instance,PropName)<>Nil;
  1426. end;
  1427. Function IsPublishedProp(AClass: TClass; const PropName: string): Boolean;
  1428. begin
  1429. Result:=GetPropInfo(AClass,PropName)<>Nil;
  1430. end;
  1431. Function PropIsType(Instance: TObject; const PropName: string; TypeKind: TTypeKind): Boolean;
  1432. begin
  1433. Result:=FindPropInfo(Instance,PropName)^.PropType^.Kind=TypeKind
  1434. end;
  1435. Function PropIsType(AClass: TClass; const PropName: string; TypeKind: TTypeKind): Boolean;
  1436. begin
  1437. Result:=PropType(AClass,PropName)=TypeKind
  1438. end;
  1439. Function PropType(Instance: TObject; const PropName: string): TTypeKind;
  1440. begin
  1441. Result:=FindPropInfo(Instance,PropName)^.PropType^.Kind;
  1442. end;
  1443. Function PropType(AClass: TClass; const PropName: string): TTypeKind;
  1444. begin
  1445. Result:=FindPropInfo(AClass,PropName)^.PropType^.Kind;
  1446. end;
  1447. Function IsStoredProp(Instance: TObject; const PropName: string): Boolean;
  1448. begin
  1449. Result:=IsStoredProp(instance,FindPropInfo(Instance,PropName));
  1450. end;
  1451. end.