typinfo.pp 58 KB

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