typinfo.pp 52 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673
  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. // ^.BaseType);
  286. // If PT^.MinValue<0 then Value:=Ord(Value<>0); {map to 0/1}
  287. PS:=@PT^.NameList;
  288. While Value>0 Do
  289. begin
  290. PS:=PShortString(pointer(PS)+PByte(PS)^+1);
  291. Dec(Value);
  292. end;
  293. Result:=PS^;
  294. end;
  295. Function GetEnumValue(TypeInfo : PTypeInfo;const Name : string) : Integer;
  296. Var PS : PShortString;
  297. PT : PTypeData;
  298. Count : longint;
  299. sName: shortstring;
  300. begin
  301. If Length(Name)=0 then
  302. exit(-1);
  303. sName := Name;
  304. PT:=GetTypeData(TypeInfo);
  305. Count:=0;
  306. Result:=-1;
  307. PS:=@PT^.NameList;
  308. While (Result=-1) and (PByte(PS)^<>0) do
  309. begin
  310. If ShortCompareText(PS^, sName) = 0 then
  311. Result:=Count;
  312. PS:=PShortString(pointer(PS)+PByte(PS)^+1);
  313. Inc(Count);
  314. end;
  315. end;
  316. function GetEnumNameCount(enum1: PTypeInfo): SizeInt;
  317. var
  318. PS: PShortString;
  319. PT: PTypeData;
  320. Count: SizeInt;
  321. begin
  322. PT:=GetTypeData(enum1);
  323. Count:=0;
  324. Result:=0;
  325. PS:=@PT^.NameList;
  326. While (PByte(PS)^<>0) do
  327. begin
  328. PS:=PShortString(pointer(PS)+PByte(PS)^+1);
  329. Inc(Count);
  330. end;
  331. Result := Count;
  332. end;
  333. Function SetToString(PropInfo: PPropInfo; Value: Integer; Brackets: Boolean) : String;
  334. begin
  335. Result:=SetToString(PropInfo^.PropType,Value,Brackets);
  336. end;
  337. Function SetToString(TypeInfo: PTypeInfo; Value: Integer; Brackets: Boolean) : String;
  338. {$ifdef FPC_NEW_BIGENDIAN_SETS}
  339. type
  340. tsetarr = bitpacked array[0..31] of 0..1;
  341. {$endif}
  342. Var
  343. I : Integer;
  344. PTI : PTypeInfo;
  345. begin
  346. {$if defined(FPC_NEW_BIGENDIAN_SETS) and defined(FPC_BIG_ENDIAN)}
  347. case GetTypeData(TypeInfo)^.OrdType of
  348. otSByte,otUByte: Value:=Value shl 24;
  349. otSWord,otUWord: Value:=Value shl 16;
  350. end;
  351. {$endif}
  352. PTI:=GetTypeData(TypeInfo)^.CompType;
  353. Result:='';
  354. For I:=0 to SizeOf(Integer)*8-1 do
  355. begin
  356. {$ifdef FPC_NEW_BIGENDIAN_SETS}
  357. if (tsetarr(Value)[i]<>0) then
  358. {$else}
  359. if ((Value and 1)<>0) then
  360. {$endif}
  361. begin
  362. If Result='' then
  363. Result:=GetEnumName(PTI,i)
  364. else
  365. Result:=Result+','+GetEnumName(PTI,I);
  366. end;
  367. {$ifndef FPC_NEW_BIGENDIAN_SETS}
  368. Value:=Value shr 1;
  369. {$endif FPC_NEW_BIGENDIAN_SETS}
  370. end;
  371. if Brackets then
  372. Result:='['+Result+']';
  373. end;
  374. Function SetToString(PropInfo: PPropInfo; Value: Integer) : String;
  375. begin
  376. Result:=SetToString(PropInfo,Value,False);
  377. end;
  378. Const
  379. SetDelim = ['[',']',',',' '];
  380. Function GetNextElement(Var S : String) : String;
  381. Var
  382. J : Integer;
  383. begin
  384. J:=1;
  385. Result:='';
  386. If Length(S)>0 then
  387. begin
  388. While (J<=Length(S)) and Not (S[j] in SetDelim) do
  389. Inc(j);
  390. Result:=Copy(S,1,j-1);
  391. Delete(S,1,j);
  392. end;
  393. end;
  394. Function StringToSet(PropInfo: PPropInfo; const Value: string): Integer;
  395. begin
  396. Result:=StringToSet(PropInfo^.PropType,Value);
  397. end;
  398. Function StringToSet(TypeInfo: PTypeInfo; const Value: string): Integer;
  399. Var
  400. S,T : String;
  401. I : Integer;
  402. PTI : PTypeInfo;
  403. begin
  404. Result:=0;
  405. PTI:=GetTypeData(TypeInfo)^.Comptype;
  406. S:=Value;
  407. I:=1;
  408. If Length(S)>0 then
  409. begin
  410. While (I<=Length(S)) and (S[i] in SetDelim) do
  411. Inc(I);
  412. Delete(S,1,i-1);
  413. end;
  414. While (S<>'') do
  415. begin
  416. T:=GetNextElement(S);
  417. if T<>'' then
  418. begin
  419. I:=GetEnumValue(PTI,T);
  420. if (I<0) then
  421. raise EPropertyError.CreateFmt(SErrUnknownEnumValue, [T]);
  422. Result:=Result or (1 shl i);
  423. end;
  424. end;
  425. end;
  426. Function GetTypeData(TypeInfo : PTypeInfo) : PTypeData;
  427. begin
  428. GetTypeData:=PTypeData(aligntoptr(PTypeData(pointer(TypeInfo)+2+PByte(pointer(TypeInfo)+1)^)));
  429. end;
  430. { ---------------------------------------------------------------------
  431. Basic Type information functions.
  432. ---------------------------------------------------------------------}
  433. Function GetPropInfo(TypeInfo : PTypeInfo;const PropName : string) : PPropInfo;
  434. var
  435. hp : PTypeData;
  436. i : longint;
  437. p : shortstring;
  438. pd : ^TPropData;
  439. begin
  440. P:=PropName; // avoid Ansi<->short conversion in a loop
  441. while Assigned(TypeInfo) do
  442. begin
  443. // skip the name
  444. hp:=GetTypeData(Typeinfo);
  445. // the class info rtti the property rtti follows immediatly
  446. pd:=aligntoptr(pointer(pointer(@hp^.UnitName)+Length(hp^.UnitName)+1));
  447. Result:=PPropInfo(@pd^.PropList);
  448. for i:=1 to pd^.PropCount do
  449. begin
  450. // found a property of that name ?
  451. if ShortCompareText(Result^.Name, P) = 0 then
  452. exit;
  453. // skip to next property
  454. Result:=PPropInfo(aligntoptr(pointer(@Result^.Name)+byte(Result^.Name[0])+1));
  455. end;
  456. // parent class
  457. Typeinfo:=hp^.ParentInfo;
  458. end;
  459. Result:=Nil;
  460. end;
  461. Function GetPropInfo(TypeInfo : PTypeInfo;const PropName : string; Akinds : TTypeKinds) : PPropInfo;
  462. begin
  463. Result:=GetPropInfo(TypeInfo,PropName);
  464. If (Akinds<>[]) then
  465. If (Result<>Nil) then
  466. If Not (Result^.PropType^.Kind in AKinds) then
  467. Result:=Nil;
  468. end;
  469. Function GetPropInfo(AClass: TClass; const PropName: string; AKinds: TTypeKinds) : PPropInfo;
  470. begin
  471. Result:=GetPropInfo(PTypeInfo(AClass.ClassInfo),PropName,AKinds);
  472. end;
  473. Function GetPropInfo(Instance: TObject; const PropName: string; AKinds: TTypeKinds) : PPropInfo;
  474. begin
  475. Result:=GetPropInfo(Instance.ClassType,PropName,AKinds);
  476. end;
  477. Function GetPropInfo(Instance: TObject; const PropName: string): PPropInfo;
  478. begin
  479. Result:=GetPropInfo(Instance,PropName,[]);
  480. end;
  481. Function GetPropInfo(AClass: TClass; const PropName: string): PPropInfo;
  482. begin
  483. Result:=GetPropInfo(AClass,PropName,[]);
  484. end;
  485. Function FindPropInfo(Instance: TObject; const PropName: string): PPropInfo;
  486. begin
  487. result:=GetPropInfo(Instance, PropName);
  488. if Result=nil then
  489. Raise EPropertyError.CreateFmt(SErrPropertyNotFound, [PropName]);
  490. end;
  491. Function FindPropInfo(AClass:TClass;const PropName: string): PPropInfo;
  492. begin
  493. result:=GetPropInfo(AClass,PropName);
  494. if result=nil then
  495. Raise EPropertyError.CreateFmt(SErrPropertyNotFound, [PropName]);
  496. end;
  497. Function IsStoredProp(Instance : TObject;PropInfo : PPropInfo) : Boolean;
  498. type
  499. TBooleanIndexFunc=function(Index:integer):boolean of object;
  500. TBooleanFunc=function:boolean of object;
  501. var
  502. AMethod : TMethod;
  503. begin
  504. case (PropInfo^.PropProcs shr 4) and 3 of
  505. ptfield:
  506. Result:=PBoolean(Pointer(Instance)+PtrUInt(PropInfo^.StoredProc))^;
  507. ptconst:
  508. Result:=LongBool(PropInfo^.StoredProc);
  509. ptstatic,
  510. ptvirtual:
  511. begin
  512. if (PropInfo^.PropProcs shr 4) and 3=ptstatic then
  513. AMethod.Code:=PropInfo^.StoredProc
  514. else
  515. AMethod.Code:=ppointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.StoredProc))^;
  516. AMethod.Data:=Instance;
  517. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  518. Result:=TBooleanIndexFunc(AMethod)(PropInfo^.Index)
  519. else
  520. Result:=TBooleanFunc(AMethod)();
  521. end;
  522. end;
  523. end;
  524. Procedure GetPropInfos(TypeInfo : PTypeInfo;PropList : PPropList);
  525. {
  526. Store Pointers to property information in the list pointed
  527. to by proplist. PRopList must contain enough space to hold ALL
  528. properties.
  529. }
  530. Var
  531. TD : PTypeData;
  532. TP : PPropInfo;
  533. Count : Longint;
  534. begin
  535. // Get this objects TOTAL published properties count
  536. TD:=GetTypeData(TypeInfo);
  537. // Clear list
  538. FillChar(PropList^,TD^.PropCount*sizeof(Pointer),0);
  539. repeat
  540. TD:=GetTypeData(TypeInfo);
  541. // published properties count for this object
  542. TP:=aligntoptr(PPropInfo(aligntoptr((Pointer(@TD^.UnitName)+Length(TD^.UnitName)+1))));
  543. Count:=PWord(TP)^;
  544. // Now point TP to first propinfo record.
  545. Inc(Pointer(TP),SizeOF(Word));
  546. tp:=aligntoptr(tp);
  547. While Count>0 do
  548. begin
  549. // Don't overwrite properties with the same name
  550. if PropList^[TP^.NameIndex]=nil then
  551. PropList^[TP^.NameIndex]:=TP;
  552. // Point to TP next propinfo record.
  553. // Located at Name[Length(Name)+1] !
  554. TP:=aligntoptr(PPropInfo(pointer(@TP^.Name)+PByte(@TP^.Name)^+1));
  555. Dec(Count);
  556. end;
  557. TypeInfo:=TD^.Parentinfo;
  558. until TypeInfo=nil;
  559. end;
  560. Procedure InsertProp (PL : PProplist;PI : PPropInfo; Count : longint);
  561. Var
  562. I : Longint;
  563. begin
  564. I:=0;
  565. While (I<Count) and (PI^.Name>PL^[I]^.Name) do
  566. Inc(I);
  567. If I<Count then
  568. Move(PL^[I], PL^[I+1], (Count - I) * SizeOf(Pointer));
  569. PL^[I]:=PI;
  570. end;
  571. Procedure InsertPropnosort (PL : PProplist;PI : PPropInfo; Count : longint);
  572. begin
  573. PL^[Count]:=PI;
  574. end;
  575. Type TInsertProp = Procedure (PL : PProplist;PI : PPropInfo; Count : longint);
  576. //Const InsertProps : array[false..boolean] of TInsertProp = (InsertPropNoSort,InsertProp);
  577. Function GetPropList(TypeInfo : PTypeInfo;TypeKinds : TTypeKinds; PropList : PPropList;Sorted : boolean = true):longint;
  578. {
  579. Store Pointers to property information OF A CERTAIN KIND in the list pointed
  580. to by proplist. PRopList must contain enough space to hold ALL
  581. properties.
  582. }
  583. Var
  584. TempList : PPropList;
  585. PropInfo : PPropinfo;
  586. I,Count : longint;
  587. DoInsertProp : TInsertProp;
  588. begin
  589. if sorted then
  590. DoInsertProp:=@InsertProp
  591. else
  592. DoInsertProp:=@InsertPropnosort;
  593. Result:=0;
  594. Count:=GetTypeData(TypeInfo)^.Propcount;
  595. If Count>0 then
  596. begin
  597. GetMem(TempList,Count*SizeOf(Pointer));
  598. Try
  599. GetPropInfos(TypeInfo,TempList);
  600. For I:=0 to Count-1 do
  601. begin
  602. PropInfo:=TempList^[i];
  603. If PropInfo^.PropType^.Kind in TypeKinds then
  604. begin
  605. If (PropList<>Nil) then
  606. DoInsertProp(PropList,PropInfo,Result);
  607. Inc(Result);
  608. end;
  609. end;
  610. finally
  611. FreeMem(TempList,Count*SizeOf(Pointer));
  612. end;
  613. end;
  614. end;
  615. Function GetPropList(TypeInfo: PTypeInfo; out PropList: PPropList): SizeInt;
  616. begin
  617. result:=GetTypeData(TypeInfo)^.Propcount;
  618. if result>0 then
  619. begin
  620. getmem(PropList,result*sizeof(pointer));
  621. GetPropInfos(TypeInfo,PropList);
  622. end
  623. else
  624. PropList:=Nil;
  625. end;
  626. function GetPropList(AObject: TObject; out PropList: PPropList): Integer;
  627. begin
  628. Result := GetPropList(PTypeInfo(AObject.ClassInfo), PropList);
  629. end;
  630. { ---------------------------------------------------------------------
  631. Property access functions
  632. ---------------------------------------------------------------------}
  633. { ---------------------------------------------------------------------
  634. Ordinal properties
  635. ---------------------------------------------------------------------}
  636. Function GetOrdProp(Instance : TObject;PropInfo : PPropInfo) : Int64;
  637. type
  638. TGetInt64ProcIndex=function(index:longint):Int64 of object;
  639. TGetInt64Proc=function():Int64 of object;
  640. TGetIntegerProcIndex=function(index:longint):longint of object;
  641. TGetIntegerProc=function:longint of object;
  642. TGetWordProcIndex=function(index:longint):word of object;
  643. TGetWordProc=function:word of object;
  644. TGetByteProcIndex=function(index:longint):Byte of object;
  645. TGetByteProc=function:Byte of object;
  646. var
  647. TypeInfo: PTypeInfo;
  648. AMethod : TMethod;
  649. DataSize: Integer;
  650. OrdType: TOrdType;
  651. Signed: Boolean;
  652. begin
  653. Result:=0;
  654. TypeInfo := PropInfo^.PropType;
  655. Signed := false;
  656. DataSize := 4;
  657. case TypeInfo^.Kind of
  658. {$ifdef cpu64}
  659. tkInterface,
  660. tkInterfaceRaw,
  661. tkDynArray,
  662. tkClass:
  663. DataSize:=8;
  664. {$endif cpu64}
  665. tkChar, tkBool:
  666. DataSize:=1;
  667. tkWChar:
  668. DataSize:=2;
  669. tkSet,
  670. tkEnumeration,
  671. tkInteger:
  672. begin
  673. OrdType:=GetTypeData(TypeInfo)^.OrdType;
  674. case OrdType of
  675. otSByte,otUByte: DataSize := 1;
  676. otSWord,otUWord: DataSize := 2;
  677. end;
  678. Signed := OrdType in [otSByte,otSWord,otSLong];
  679. end;
  680. tkInt64 :
  681. begin
  682. DataSize:=8;
  683. Signed:=true;
  684. end;
  685. tkQword :
  686. begin
  687. DataSize:=8;
  688. Signed:=false;
  689. end;
  690. end;
  691. case (PropInfo^.PropProcs) and 3 of
  692. ptfield:
  693. if Signed then begin
  694. case DataSize of
  695. 1: Result:=PShortInt(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  696. 2: Result:=PSmallInt(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  697. 4: Result:=PLongint(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  698. 8: Result:=PInt64(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  699. end;
  700. end else begin
  701. case DataSize of
  702. 1: Result:=PByte(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  703. 2: Result:=PWord(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  704. 4: Result:=PLongint(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  705. 8: Result:=PInt64(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  706. end;
  707. end;
  708. ptstatic,
  709. ptvirtual :
  710. begin
  711. if (PropInfo^.PropProcs and 3)=ptStatic then
  712. AMethod.Code:=PropInfo^.GetProc
  713. else
  714. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.GetProc))^;
  715. AMethod.Data:=Instance;
  716. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then begin
  717. case DataSize of
  718. 1: Result:=TGetByteProcIndex(AMethod)(PropInfo^.Index);
  719. 2: Result:=TGetWordProcIndex(AMethod)(PropInfo^.Index);
  720. 4: Result:=TGetIntegerProcIndex(AMethod)(PropInfo^.Index);
  721. 8: result:=TGetInt64ProcIndex(AMethod)(PropInfo^.Index)
  722. end;
  723. end else begin
  724. case DataSize of
  725. 1: Result:=TGetByteProc(AMethod)();
  726. 2: Result:=TGetWordProc(AMethod)();
  727. 4: Result:=TGetIntegerProc(AMethod)();
  728. 8: result:=TGetInt64Proc(AMethod)();
  729. end;
  730. end;
  731. if Signed then begin
  732. case DataSize of
  733. 1: Result:=ShortInt(Result);
  734. 2: Result:=SmallInt(Result);
  735. end;
  736. end;
  737. end;
  738. end;
  739. end;
  740. Procedure SetOrdProp(Instance : TObject;PropInfo : PPropInfo;Value : Int64);
  741. type
  742. TSetInt64ProcIndex=procedure(index:longint;i:Int64) of object;
  743. TSetInt64Proc=procedure(i:Int64) of object;
  744. TSetIntegerProcIndex=procedure(index,i:longint) of object;
  745. TSetIntegerProc=procedure(i:longint) of object;
  746. var
  747. DataSize: Integer;
  748. AMethod : TMethod;
  749. begin
  750. if PropInfo^.PropType^.Kind in [tkInt64,tkQword
  751. { why do we have to handle classes here, see also below? (FK) }
  752. {$ifdef cpu64}
  753. ,tkInterface
  754. ,tkInterfaceRaw
  755. ,tkDynArray
  756. ,tkClass
  757. {$endif cpu64}
  758. ] then
  759. DataSize := 8
  760. else
  761. DataSize := 4;
  762. if not(PropInfo^.PropType^.Kind in [tkInt64,tkQword,tkClass]) then
  763. begin
  764. { cut off unnecessary stuff }
  765. case GetTypeData(PropInfo^.PropType)^.OrdType of
  766. otSWord,otUWord:
  767. begin
  768. Value:=Value and $ffff;
  769. DataSize := 2;
  770. end;
  771. otSByte,otUByte:
  772. begin
  773. Value:=Value and $ff;
  774. DataSize := 1;
  775. end;
  776. end;
  777. end;
  778. case (PropInfo^.PropProcs shr 2) and 3 of
  779. ptfield:
  780. case DataSize of
  781. 1: PByte(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^:=Byte(Value);
  782. 2: PWord(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^:=Word(Value);
  783. 4: PLongint(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^:=Longint(Value);
  784. 8: PInt64(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^:=Value;
  785. end;
  786. ptstatic,
  787. ptvirtual :
  788. begin
  789. if ((PropInfo^.PropProcs shr 2) and 3)=ptStatic then
  790. AMethod.Code:=PropInfo^.SetProc
  791. else
  792. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.SetProc))^;
  793. AMethod.Data:=Instance;
  794. if datasize=8 then
  795. begin
  796. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  797. TSetInt64ProcIndex(AMethod)(PropInfo^.Index,Value)
  798. else
  799. TSetInt64Proc(AMethod)(Value);
  800. end
  801. else
  802. begin
  803. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  804. TSetIntegerProcIndex(AMethod)(PropInfo^.Index,Value)
  805. else
  806. TSetIntegerProc(AMethod)(Value);
  807. end;
  808. end;
  809. end;
  810. end;
  811. Function GetOrdProp(Instance: TObject; const PropName: string): Int64;
  812. begin
  813. Result:=GetOrdProp(Instance,FindPropInfo(Instance,PropName));
  814. end;
  815. Procedure SetOrdProp(Instance: TObject; const PropName: string; Value: Int64);
  816. begin
  817. SetOrdProp(Instance,FindPropInfo(Instance,PropName),Value);
  818. end;
  819. Function GetEnumProp(Instance: TObject; Const PropInfo: PPropInfo): string;
  820. begin
  821. Result:=GetEnumName(PropInfo^.PropType, GetOrdProp(Instance, PropInfo));
  822. end;
  823. Function GetEnumProp(Instance: TObject; const PropName: string): string;
  824. begin
  825. Result:=GetEnumProp(Instance,FindPropInfo(Instance,PropName));
  826. end;
  827. Procedure SetEnumProp(Instance: TObject; const PropName: string; const Value: string);
  828. begin
  829. SetEnumProp(Instance,FindPropInfo(Instance,PropName),Value);
  830. end;
  831. Procedure SetEnumProp(Instance: TObject; Const PropInfo : PPropInfo; const Value: string);
  832. Var
  833. PV : Longint;
  834. begin
  835. If PropInfo<>Nil then
  836. begin
  837. PV:=GetEnumValue(PropInfo^.PropType, Value);
  838. if (PV<0) then
  839. raise EPropertyError.CreateFmt(SErrUnknownEnumValue, [Value]);
  840. SetOrdProp(Instance, PropInfo,PV);
  841. end;
  842. end;
  843. { ---------------------------------------------------------------------
  844. Int64 wrappers
  845. ---------------------------------------------------------------------}
  846. Function GetInt64Prop(Instance: TObject; PropInfo: PPropInfo): Int64;
  847. begin
  848. Result:=GetOrdProp(Instance,PropInfo);
  849. end;
  850. procedure SetInt64Prop(Instance: TObject; PropInfo: PPropInfo; const Value: Int64);
  851. begin
  852. SetOrdProp(Instance,PropInfo,Value);
  853. end;
  854. Function GetInt64Prop(Instance: TObject; const PropName: string): Int64;
  855. begin
  856. Result:=GetInt64Prop(Instance,FindPropInfo(Instance,PropName));
  857. end;
  858. Procedure SetInt64Prop(Instance: TObject; const PropName: string; const Value: Int64);
  859. begin
  860. SetInt64Prop(Instance,FindPropInfo(Instance,PropName),Value);
  861. end;
  862. { ---------------------------------------------------------------------
  863. Set properties
  864. ---------------------------------------------------------------------}
  865. Function GetSetProp(Instance: TObject; const PropName: string): string;
  866. begin
  867. Result:=GetSetProp(Instance,PropName,False);
  868. end;
  869. Function GetSetProp(Instance: TObject; const PropName: string; Brackets: Boolean): string;
  870. begin
  871. Result:=GetSetProp(Instance,FindPropInfo(Instance,PropName),Brackets);
  872. end;
  873. Function GetSetProp(Instance: TObject; const PropInfo: PPropInfo; Brackets: Boolean): string;
  874. begin
  875. Result:=SetToString(PropInfo,GetOrdProp(Instance,PropInfo),Brackets);
  876. end;
  877. Procedure SetSetProp(Instance: TObject; const PropName: string; const Value: string);
  878. begin
  879. SetSetProp(Instance,FindPropInfo(Instance,PropName),Value);
  880. end;
  881. Procedure SetSetProp(Instance: TObject; const PropInfo: PPropInfo; const Value: string);
  882. begin
  883. SetOrdProp(Instance,PropInfo,StringToSet(PropInfo,Value));
  884. end;
  885. { ---------------------------------------------------------------------
  886. Object properties
  887. ---------------------------------------------------------------------}
  888. Function GetObjectProp(Instance: TObject; const PropName: string): TObject;
  889. begin
  890. Result:=GetObjectProp(Instance,PropName,Nil);
  891. end;
  892. Function GetObjectProp(Instance: TObject; const PropName: string; MinClass: TClass): TObject;
  893. begin
  894. Result:=GetObjectProp(Instance,FindPropInfo(Instance,PropName),MinClass);
  895. end;
  896. Function GetObjectProp(Instance: TObject; PropInfo : PPropInfo): TObject;
  897. begin
  898. Result:=GetObjectProp(Instance,PropInfo,Nil);
  899. end;
  900. Function GetObjectProp(Instance: TObject; PropInfo : PPropInfo; MinClass: TClass): TObject;
  901. begin
  902. {$ifdef cpu64}
  903. Result:=TObject(GetInt64Prop(Instance,PropInfo));
  904. {$else cpu64}
  905. Result:=TObject(PtrInt(GetOrdProp(Instance,PropInfo)));
  906. {$endif cpu64}
  907. If (MinClass<>Nil) and (Result<>Nil) Then
  908. If Not Result.InheritsFrom(MinClass) then
  909. Result:=Nil;
  910. end;
  911. Procedure SetObjectProp(Instance: TObject; const PropName: string; Value: TObject);
  912. begin
  913. SetObjectProp(Instance,FindPropInfo(Instance,PropName),Value);
  914. end;
  915. Procedure SetObjectProp(Instance: TObject; PropInfo : PPropInfo; Value: TObject);
  916. begin
  917. {$ifdef cpu64}
  918. SetInt64Prop(Instance,PropInfo,Int64(Value));
  919. {$else cpu64}
  920. SetOrdProp(Instance,PropInfo,Integer(Value));
  921. {$endif cpu64}
  922. end;
  923. Function GetObjectPropClass(Instance: TObject; const PropName: string): TClass;
  924. begin
  925. Result:=GetTypeData(FindPropInfo(Instance,PropName)^.PropType)^.ClassType;
  926. end;
  927. { ---------------------------------------------------------------------
  928. Interface wrapprers
  929. ---------------------------------------------------------------------}
  930. function GetInterfaceProp(Instance: TObject; const PropName: string): IInterface;
  931. begin
  932. Result:=GetInterfaceProp(Instance,FindPropInfo(Instance,PropName));
  933. end;
  934. function GetInterfaceProp(Instance: TObject; PropInfo: PPropInfo): IInterface;
  935. begin
  936. {$ifdef cpu64}
  937. Result:=IInterface(GetInt64Prop(Instance,PropInfo));
  938. {$else cpu64}
  939. Result:=IInterface(PtrInt(GetOrdProp(Instance,PropInfo)));
  940. {$endif cpu64}
  941. end;
  942. procedure SetInterfaceProp(Instance: TObject; const PropName: string; const Value: IInterface);
  943. begin
  944. SetInterfaceProp(Instance,FindPropInfo(Instance,PropName),Value);
  945. end;
  946. procedure SetInterfaceProp(Instance: TObject; PropInfo: PPropInfo; const Value: IInterface);
  947. begin
  948. {$ifdef cpu64}
  949. SetInt64Prop(Instance,PropInfo,Int64(Value));
  950. {$else cpu64}
  951. SetOrdProp(Instance,PropInfo,Integer(Value));
  952. {$endif cpu64}
  953. end;
  954. { ---------------------------------------------------------------------
  955. String properties
  956. ---------------------------------------------------------------------}
  957. Function GetStrProp(Instance: TObject; PropInfo: PPropInfo): AnsiString;
  958. type
  959. TGetShortStrProcIndex=function(index:longint):ShortString of object;
  960. TGetShortStrProc=function():ShortString of object;
  961. TGetAnsiStrProcIndex=function(index:longint):AnsiString of object;
  962. TGetAnsiStrProc=function():AnsiString of object;
  963. var
  964. AMethod : TMethod;
  965. begin
  966. Result:='';
  967. case Propinfo^.PropType^.Kind of
  968. tkWString:
  969. Result:=GetWideStrProp(Instance,PropInfo);
  970. tkSString:
  971. begin
  972. case (PropInfo^.PropProcs) and 3 of
  973. ptField:
  974. Result := PShortString(Pointer(Instance) + LongWord(PropInfo^.GetProc))^;
  975. ptstatic,
  976. ptvirtual :
  977. begin
  978. if (PropInfo^.PropProcs and 3)=ptStatic then
  979. AMethod.Code:=PropInfo^.GetProc
  980. else
  981. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.GetProc))^;
  982. AMethod.Data:=Instance;
  983. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  984. Result:=TGetShortStrProcIndex(AMethod)(PropInfo^.Index)
  985. else
  986. Result:=TGetShortStrProc(AMethod)();
  987. end;
  988. end;
  989. end;
  990. tkAString:
  991. begin
  992. case (PropInfo^.PropProcs) and 3 of
  993. ptField:
  994. Result := PAnsiString(Pointer(Instance) + LongWord(PropInfo^.GetProc))^;
  995. ptstatic,
  996. ptvirtual :
  997. begin
  998. if (PropInfo^.PropProcs and 3)=ptStatic then
  999. AMethod.Code:=PropInfo^.GetProc
  1000. else
  1001. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.GetProc))^;
  1002. AMethod.Data:=Instance;
  1003. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  1004. Result:=TGetAnsiStrProcIndex(AMethod)(PropInfo^.Index)
  1005. else
  1006. Result:=TGetAnsiStrProc(AMethod)();
  1007. end;
  1008. end;
  1009. end;
  1010. end;
  1011. end;
  1012. Procedure SetStrProp(Instance : TObject;PropInfo : PPropInfo; const Value : AnsiString);
  1013. type
  1014. TSetShortStrProcIndex=procedure(index:longint;const s:ShortString) of object;
  1015. TSetShortStrProc=procedure(const s:ShortString) of object;
  1016. TSetAnsiStrProcIndex=procedure(index:longint;s:AnsiString) of object;
  1017. TSetAnsiStrProc=procedure(s:AnsiString) of object;
  1018. var
  1019. AMethod : TMethod;
  1020. begin
  1021. case Propinfo^.PropType^.Kind of
  1022. tkWString:
  1023. SetWideStrProp(Instance,PropInfo,Value);
  1024. tkSString:
  1025. begin
  1026. case (PropInfo^.PropProcs shr 2) and 3 of
  1027. ptField:
  1028. PShortString(Pointer(Instance) + LongWord(PropInfo^.SetProc))^:=Value;
  1029. ptstatic,
  1030. ptvirtual :
  1031. begin
  1032. if (PropInfo^.PropProcs and 3)=ptStatic then
  1033. AMethod.Code:=PropInfo^.SetProc
  1034. else
  1035. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.SetProc))^;
  1036. AMethod.Data:=Instance;
  1037. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  1038. TSetShortStrProcIndex(AMethod)(PropInfo^.Index,Value)
  1039. else
  1040. TSetShortStrProc(AMethod)(Value);
  1041. end;
  1042. end;
  1043. end;
  1044. tkAString:
  1045. begin
  1046. case (PropInfo^.PropProcs shr 2) and 3 of
  1047. ptField:
  1048. PAnsiString(Pointer(Instance) + LongWord(PropInfo^.SetProc))^:=Value;
  1049. ptstatic,
  1050. ptvirtual :
  1051. begin
  1052. if ((PropInfo^.PropProcs shr 2) and 3)=ptStatic then
  1053. AMethod.Code:=PropInfo^.SetProc
  1054. else
  1055. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.SetProc))^;
  1056. AMethod.Data:=Instance;
  1057. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  1058. TSetAnsiStrProcIndex(AMethod)(PropInfo^.Index,Value)
  1059. else
  1060. TSetAnsiStrProc(AMethod)(Value);
  1061. end;
  1062. end;
  1063. end;
  1064. end;
  1065. end;
  1066. Function GetStrProp(Instance: TObject; const PropName: string): string;
  1067. begin
  1068. Result:=GetStrProp(Instance,FindPropInfo(Instance,PropName));
  1069. end;
  1070. Procedure SetStrProp(Instance: TObject; const PropName: string; const Value: AnsiString);
  1071. begin
  1072. SetStrProp(Instance,FindPropInfo(Instance,PropName),Value);
  1073. end;
  1074. Function GetWideStrProp(Instance: TObject; const PropName: string): WideString;
  1075. begin
  1076. Result:=GetWideStrProp(Instance, FindPropInfo(Instance, PropName));
  1077. end;
  1078. procedure SetWideStrProp(Instance: TObject; const PropName: string; const Value: WideString);
  1079. begin
  1080. SetWideStrProp(Instance,FindPropInfo(Instance,PropName),Value);
  1081. end;
  1082. Function GetWideStrProp(Instance: TObject; PropInfo: PPropInfo): WideString;
  1083. type
  1084. TGetWideStrProcIndex=function(index:longint):WideString of object;
  1085. TGetWideStrProc=function():WideString of object;
  1086. var
  1087. AMethod : TMethod;
  1088. begin
  1089. Result:='';
  1090. case Propinfo^.PropType^.Kind of
  1091. tkSString,tkAString:
  1092. Result:=GetStrProp(Instance,PropInfo);
  1093. tkWString:
  1094. begin
  1095. case (PropInfo^.PropProcs) and 3 of
  1096. ptField:
  1097. Result := PWideString(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  1098. ptstatic,
  1099. ptvirtual :
  1100. begin
  1101. if (PropInfo^.PropProcs and 3)=ptStatic then
  1102. AMethod.Code:=PropInfo^.GetProc
  1103. else
  1104. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.GetProc))^;
  1105. AMethod.Data:=Instance;
  1106. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  1107. Result:=TGetWideStrProcIndex(AMethod)(PropInfo^.Index)
  1108. else
  1109. Result:=TGetWideStrProc(AMethod)();
  1110. end;
  1111. end;
  1112. end;
  1113. end;
  1114. end;
  1115. Procedure SetWideStrProp(Instance: TObject; PropInfo: PPropInfo; const Value: WideString);
  1116. type
  1117. TSetWideStrProcIndex=procedure(index:longint;s:WideString) of object;
  1118. TSetWideStrProc=procedure(s:WideString) of object;
  1119. var
  1120. AMethod : TMethod;
  1121. begin
  1122. case Propinfo^.PropType^.Kind of
  1123. tkSString,tkAString:
  1124. SetStrProp(Instance,PropInfo,Value);
  1125. tkWString:
  1126. begin
  1127. case (PropInfo^.PropProcs shr 2) and 3 of
  1128. ptField:
  1129. PWideString(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^:=Value;
  1130. ptstatic,
  1131. ptvirtual :
  1132. begin
  1133. if ((PropInfo^.PropProcs shr 2) and 3)=ptStatic then
  1134. AMethod.Code:=PropInfo^.SetProc
  1135. else
  1136. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.SetProc))^;
  1137. AMethod.Data:=Instance;
  1138. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  1139. TSetWideStrProcIndex(AMethod)(PropInfo^.Index,Value)
  1140. else
  1141. TSetWideStrProc(AMethod)(Value);
  1142. end;
  1143. end;
  1144. end;
  1145. end;
  1146. end;
  1147. { ---------------------------------------------------------------------
  1148. Float properties
  1149. ---------------------------------------------------------------------}
  1150. function GetFloatProp(Instance : TObject;PropInfo : PPropInfo) : Extended;
  1151. type
  1152. TGetExtendedProc = function:Extended of object;
  1153. TGetExtendedProcIndex = function(Index: integer): Extended of object;
  1154. TGetDoubleProc = function:Double of object;
  1155. TGetDoubleProcIndex = function(Index: integer): Double of object;
  1156. TGetSingleProc = function:Single of object;
  1157. TGetSingleProcIndex = function(Index: integer):Single of object;
  1158. TGetCurrencyProc = function : Currency of object;
  1159. TGetCurrencyProcIndex = function(Index: integer) : Currency of object;
  1160. var
  1161. AMethod : TMethod;
  1162. begin
  1163. Result:=0.0;
  1164. case PropInfo^.PropProcs and 3 of
  1165. ptField:
  1166. Case GetTypeData(PropInfo^.PropType)^.FloatType of
  1167. ftSingle:
  1168. Result:=PSingle(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  1169. ftDouble:
  1170. Result:=PDouble(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  1171. ftExtended:
  1172. Result:=PExtended(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  1173. ftcomp:
  1174. Result:=PComp(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  1175. ftcurr:
  1176. Result:=PCurrency(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  1177. end;
  1178. ptStatic,
  1179. ptVirtual:
  1180. begin
  1181. if (PropInfo^.PropProcs and 3)=ptStatic then
  1182. AMethod.Code:=PropInfo^.GetProc
  1183. else
  1184. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.GetProc))^;
  1185. AMethod.Data:=Instance;
  1186. Case GetTypeData(PropInfo^.PropType)^.FloatType of
  1187. ftSingle:
  1188. if ((PropInfo^.PropProcs shr 6) and 1)=0 then
  1189. Result:=TGetSingleProc(AMethod)()
  1190. else
  1191. Result:=TGetSingleProcIndex(AMethod)(PropInfo^.Index);
  1192. ftDouble:
  1193. if ((PropInfo^.PropProcs shr 6) and 1)=0 then
  1194. Result:=TGetDoubleProc(AMethod)()
  1195. else
  1196. Result:=TGetDoubleProcIndex(AMethod)(PropInfo^.Index);
  1197. ftExtended:
  1198. if ((PropInfo^.PropProcs shr 6) and 1)=0 then
  1199. Result:=TGetExtendedProc(AMethod)()
  1200. else
  1201. Result:=TGetExtendedProcIndex(AMethod)(PropInfo^.Index);
  1202. ftCurr:
  1203. if ((PropInfo^.PropProcs shr 6) and 1)=0 then
  1204. Result:=TGetCurrencyProc(AMethod)()
  1205. else
  1206. Result:=TGetCurrencyProcIndex(AMethod)(PropInfo^.Index);
  1207. end;
  1208. end;
  1209. end;
  1210. end;
  1211. Procedure SetFloatProp(Instance : TObject;PropInfo : PPropInfo; Value : Extended);
  1212. type
  1213. TSetExtendedProc = procedure(const AValue: Extended) of object;
  1214. TSetExtendedProcIndex = procedure(Index: integer; AValue: Extended) of object;
  1215. TSetDoubleProc = procedure(const AValue: Double) of object;
  1216. TSetDoubleProcIndex = procedure(Index: integer; AValue: Double) of object;
  1217. TSetSingleProc = procedure(const AValue: Single) of object;
  1218. TSetSingleProcIndex = procedure(Index: integer; AValue: Single) of object;
  1219. TSetCurrencyProc = procedure(const AValue: Currency) of object;
  1220. TSetCurrencyProcIndex = procedure(Index: integer; AValue: Currency) of object;
  1221. Var
  1222. AMethod : TMethod;
  1223. begin
  1224. case (PropInfo^.PropProcs shr 2) and 3 of
  1225. ptfield:
  1226. Case GetTypeData(PropInfo^.PropType)^.FloatType of
  1227. ftSingle:
  1228. PSingle(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^:=Value;
  1229. ftDouble:
  1230. PDouble(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^:=Value;
  1231. ftExtended:
  1232. PExtended(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^:=Value;
  1233. {$ifdef FPC_COMP_IS_INT64}
  1234. ftComp:
  1235. PComp(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^:=trunc(Value);
  1236. {$else FPC_COMP_IS_INT64}
  1237. ftComp:
  1238. PComp(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^:=Comp(Value);
  1239. {$endif FPC_COMP_IS_INT64}
  1240. ftCurr:
  1241. PCurrency(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^:=Value;
  1242. end;
  1243. ptStatic,
  1244. ptVirtual:
  1245. begin
  1246. if ((PropInfo^.PropProcs shr 2) and 3)=ptStatic then
  1247. AMethod.Code:=PropInfo^.SetProc
  1248. else
  1249. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.SetProc))^;
  1250. AMethod.Data:=Instance;
  1251. Case GetTypeData(PropInfo^.PropType)^.FloatType of
  1252. ftSingle:
  1253. if ((PropInfo^.PropProcs shr 6) and 1)=0 then
  1254. TSetSingleProc(AMethod)(Value)
  1255. else
  1256. TSetSingleProcIndex(AMethod)(PropInfo^.Index,Value);
  1257. ftDouble:
  1258. if ((PropInfo^.PropProcs shr 6) and 1)=0 then
  1259. TSetDoubleProc(AMethod)(Value)
  1260. else
  1261. TSetDoubleProcIndex(AMethod)(PropInfo^.Index,Value);
  1262. ftExtended:
  1263. if ((PropInfo^.PropProcs shr 6) and 1)=0 then
  1264. TSetExtendedProc(AMethod)(Value)
  1265. else
  1266. TSetExtendedProcIndex(AMethod)(PropInfo^.Index,Value);
  1267. ftCurr:
  1268. if ((PropInfo^.PropProcs shr 6) and 1)=0 then
  1269. TSetCurrencyProc(AMethod)(Value)
  1270. else
  1271. TSetCurrencyProcIndex(AMethod)(PropInfo^.Index,Value);
  1272. end;
  1273. end;
  1274. end;
  1275. end;
  1276. function GetFloatProp(Instance: TObject; const PropName: string): Extended;
  1277. begin
  1278. Result:=GetFloatProp(Instance,FindPropInfo(Instance,PropName))
  1279. end;
  1280. Procedure SetFloatProp(Instance: TObject; const PropName: string; Value: Extended);
  1281. begin
  1282. SetFloatProp(Instance,FindPropInfo(Instance,PropName),Value);
  1283. end;
  1284. { ---------------------------------------------------------------------
  1285. Method properties
  1286. ---------------------------------------------------------------------}
  1287. Function GetMethodProp(Instance : TObject;PropInfo : PPropInfo) : TMethod;
  1288. type
  1289. TGetMethodProcIndex=function(Index: Longint): TMethod of object;
  1290. TGetMethodProc=function(): TMethod of object;
  1291. var
  1292. value: PMethod;
  1293. AMethod : TMethod;
  1294. begin
  1295. Result.Code:=nil;
  1296. Result.Data:=nil;
  1297. case (PropInfo^.PropProcs) and 3 of
  1298. ptfield:
  1299. begin
  1300. Value:=PMethod(Pointer(Instance)+PtrUInt(PropInfo^.GetProc));
  1301. if Value<>nil then
  1302. Result:=Value^;
  1303. end;
  1304. ptstatic,
  1305. ptvirtual :
  1306. begin
  1307. if (PropInfo^.PropProcs and 3)=ptStatic then
  1308. AMethod.Code:=PropInfo^.GetProc
  1309. else
  1310. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.GetProc))^;
  1311. AMethod.Data:=Instance;
  1312. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  1313. Result:=TGetMethodProcIndex(AMethod)(PropInfo^.Index)
  1314. else
  1315. Result:=TGetMethodProc(AMethod)();
  1316. end;
  1317. end;
  1318. end;
  1319. Procedure SetMethodProp(Instance : TObject;PropInfo : PPropInfo; const Value : TMethod);
  1320. type
  1321. TSetMethodProcIndex=procedure(index:longint;p:TMethod) of object;
  1322. TSetMethodProc=procedure(p:TMethod) of object;
  1323. var
  1324. AMethod : TMethod;
  1325. begin
  1326. case (PropInfo^.PropProcs shr 2) and 3 of
  1327. ptfield:
  1328. PMethod(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^ := Value;
  1329. ptstatic,
  1330. ptvirtual :
  1331. begin
  1332. if ((PropInfo^.PropProcs shr 2) and 3)=ptStatic then
  1333. AMethod.Code:=PropInfo^.SetProc
  1334. else
  1335. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.SetProc))^;
  1336. AMethod.Data:=Instance;
  1337. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  1338. TSetMethodProcIndex(AMethod)(PropInfo^.Index,Value)
  1339. else
  1340. TSetMethodProc(AMethod)(Value);
  1341. end;
  1342. end;
  1343. end;
  1344. Function GetMethodProp(Instance: TObject; const PropName: string): TMethod;
  1345. begin
  1346. Result:=GetMethodProp(Instance,FindPropInfo(Instance,PropName));
  1347. end;
  1348. Procedure SetMethodProp(Instance: TObject; const PropName: string; const Value: TMethod);
  1349. begin
  1350. SetMethodProp(Instance,FindPropInfo(Instance,PropName),Value);
  1351. end;
  1352. { ---------------------------------------------------------------------
  1353. Variant properties
  1354. ---------------------------------------------------------------------}
  1355. Procedure CheckVariantEvent(P : Pointer);
  1356. begin
  1357. If (P=Nil) then
  1358. Raise Exception.Create(SErrNoVariantSupport);
  1359. end;
  1360. Function GetVariantProp(Instance : TObject;PropInfo : PPropInfo): Variant;
  1361. begin
  1362. CheckVariantEvent(Pointer(OnGetVariantProp));
  1363. Result:=OnGetVariantProp(Instance,PropInfo);
  1364. end;
  1365. Procedure SetVariantProp(Instance : TObject;PropInfo : PPropInfo; const Value: Variant);
  1366. begin
  1367. CheckVariantEvent(Pointer(OnSetVariantProp));
  1368. OnSetVariantProp(Instance,PropInfo,Value);
  1369. end;
  1370. Function GetVariantProp(Instance: TObject; const PropName: string): Variant;
  1371. begin
  1372. Result:=GetVariantProp(Instance,FindPropInfo(Instance,PropName));
  1373. end;
  1374. Procedure SetVariantProp(Instance: TObject; const PropName: string; const Value: Variant);
  1375. begin
  1376. SetVariantprop(instance,FindpropInfo(Instance,PropName),Value);
  1377. end;
  1378. { ---------------------------------------------------------------------
  1379. All properties through variant.
  1380. ---------------------------------------------------------------------}
  1381. Function GetPropValue(Instance: TObject; const PropName: string): Variant;
  1382. begin
  1383. Result:=GetPropValue(Instance,PropName,True);
  1384. end;
  1385. Function GetPropValue(Instance: TObject; const PropName: string; PreferStrings: Boolean): Variant;
  1386. begin
  1387. CheckVariantEvent(Pointer(OnGetPropValue));
  1388. Result:=OnGetPropValue(Instance,PropName,PreferStrings)
  1389. end;
  1390. Procedure SetPropValue(Instance: TObject; const PropName: string; const Value: Variant);
  1391. begin
  1392. CheckVariantEvent(Pointer(OnSetPropValue));
  1393. OnSetPropValue(Instance,PropName,Value);
  1394. end;
  1395. { ---------------------------------------------------------------------
  1396. Easy access methods that appeared in Delphi 5
  1397. ---------------------------------------------------------------------}
  1398. Function IsPublishedProp(Instance: TObject; const PropName: string): Boolean;
  1399. begin
  1400. Result:=GetPropInfo(Instance,PropName)<>Nil;
  1401. end;
  1402. Function IsPublishedProp(AClass: TClass; const PropName: string): Boolean;
  1403. begin
  1404. Result:=GetPropInfo(AClass,PropName)<>Nil;
  1405. end;
  1406. Function PropIsType(Instance: TObject; const PropName: string; TypeKind: TTypeKind): Boolean;
  1407. begin
  1408. Result:=FindPropInfo(Instance,PropName)^.PropType^.Kind=TypeKind
  1409. end;
  1410. Function PropIsType(AClass: TClass; const PropName: string; TypeKind: TTypeKind): Boolean;
  1411. begin
  1412. Result:=PropType(AClass,PropName)=TypeKind
  1413. end;
  1414. Function PropType(Instance: TObject; const PropName: string): TTypeKind;
  1415. begin
  1416. Result:=FindPropInfo(Instance,PropName)^.PropType^.Kind;
  1417. end;
  1418. Function PropType(AClass: TClass; const PropName: string): TTypeKind;
  1419. begin
  1420. Result:=FindPropInfo(AClass,PropName)^.PropType^.Kind;
  1421. end;
  1422. Function IsStoredProp(Instance: TObject; const PropName: string): Boolean;
  1423. begin
  1424. Result:=IsStoredProp(instance,FindPropInfo(Instance,PropName));
  1425. end;
  1426. end.