typinfo.pp 49 KB

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