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