typinfo.pp 52 KB

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