typinfo.pp 50 KB

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