typinfo.pp 49 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594
  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:
  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. Var
  323. I : Integer;
  324. PTI : PTypeInfo;
  325. begin
  326. PTI:=GetTypeData(TypeInfo)^.CompType;
  327. Result:='';
  328. For I:=0 to SizeOf(Integer)*8-1 do
  329. begin
  330. if ((Value and 1)<>0) then
  331. begin
  332. If Result='' then
  333. Result:=GetEnumName(PTI,i)
  334. else
  335. Result:=Result+','+GetEnumName(PTI,I);
  336. end;
  337. Value:=Value shr 1;
  338. end;
  339. if Brackets then
  340. Result:='['+Result+']';
  341. end;
  342. Function SetToString(PropInfo: PPropInfo; Value: Integer) : String;
  343. begin
  344. Result:=SetToString(PropInfo,Value,False);
  345. end;
  346. Const
  347. SetDelim = ['[',']',',',' '];
  348. Function GetNextElement(Var S : String) : String;
  349. Var
  350. J : Integer;
  351. begin
  352. J:=1;
  353. Result:='';
  354. If Length(S)>0 then
  355. begin
  356. While (J<=Length(S)) and Not (S[j] in SetDelim) do
  357. Inc(j);
  358. Result:=Copy(S,1,j-1);
  359. Delete(S,1,j);
  360. end;
  361. end;
  362. Function StringToSet(PropInfo: PPropInfo; const Value: string): Integer;
  363. begin
  364. Result:=StringToSet(PropInfo^.PropType,Value);
  365. end;
  366. Function StringToSet(TypeInfo: PTypeInfo; const Value: string): Integer;
  367. Var
  368. S,T : String;
  369. I : Integer;
  370. PTI : PTypeInfo;
  371. begin
  372. Result:=0;
  373. PTI:=GetTypeData(TypeInfo)^.Comptype;
  374. S:=Value;
  375. I:=1;
  376. If Length(S)>0 then
  377. begin
  378. While (I<=Length(S)) and (S[i] in SetDelim) do
  379. Inc(I);
  380. Delete(S,1,i-1);
  381. end;
  382. While (S<>'') do
  383. begin
  384. T:=GetNextElement(S);
  385. if T<>'' then
  386. begin
  387. I:=GetEnumValue(PTI,T);
  388. if (I<0) then
  389. raise EPropertyError.CreateFmt(SErrUnknownEnumValue, [T]);
  390. Result:=Result or (1 shl i);
  391. end;
  392. end;
  393. end;
  394. Function GetTypeData(TypeInfo : PTypeInfo) : PTypeData;
  395. begin
  396. GetTypeData:=PTypeData(aligntoptr(PTypeData(pointer(TypeInfo)+2+PByte(pointer(TypeInfo)+1)^)));
  397. end;
  398. { ---------------------------------------------------------------------
  399. Basic Type information functions.
  400. ---------------------------------------------------------------------}
  401. Function GetPropInfo(TypeInfo : PTypeInfo;const PropName : string) : PPropInfo;
  402. var
  403. hp : PTypeData;
  404. i : longint;
  405. p : string;
  406. pd : ^TPropData;
  407. begin
  408. P:=UpCase(PropName);
  409. while Assigned(TypeInfo) do
  410. begin
  411. // skip the name
  412. hp:=GetTypeData(Typeinfo);
  413. // the class info rtti the property rtti follows immediatly
  414. pd:=aligntoptr(pointer(pointer(@hp^.UnitName)+Length(hp^.UnitName)+1));
  415. Result:=PPropInfo(@pd^.PropList);
  416. for i:=1 to pd^.PropCount do
  417. begin
  418. // found a property of that name ?
  419. if Upcase(Result^.Name)=P then
  420. exit;
  421. // skip to next property
  422. Result:=PPropInfo(aligntoptr(pointer(@Result^.Name)+byte(Result^.Name[0])+1));
  423. end;
  424. // parent class
  425. Typeinfo:=hp^.ParentInfo;
  426. end;
  427. Result:=Nil;
  428. end;
  429. Function GetPropInfo(TypeInfo : PTypeInfo;const PropName : string; Akinds : TTypeKinds) : PPropInfo;
  430. begin
  431. Result:=GetPropInfo(TypeInfo,PropName);
  432. If (Akinds<>[]) then
  433. If (Result<>Nil) then
  434. If Not (Result^.PropType^.Kind in AKinds) then
  435. Result:=Nil;
  436. end;
  437. Function GetPropInfo(AClass: TClass; const PropName: string; AKinds: TTypeKinds) : PPropInfo;
  438. begin
  439. Result:=GetPropInfo(PTypeInfo(AClass.ClassInfo),PropName,AKinds);
  440. end;
  441. Function GetPropInfo(Instance: TObject; const PropName: string; AKinds: TTypeKinds) : PPropInfo;
  442. begin
  443. Result:=GetPropInfo(Instance.ClassType,PropName,AKinds);
  444. end;
  445. Function GetPropInfo(Instance: TObject; const PropName: string): PPropInfo;
  446. begin
  447. Result:=GetPropInfo(Instance,PropName,[]);
  448. end;
  449. Function GetPropInfo(AClass: TClass; const PropName: string): PPropInfo;
  450. begin
  451. Result:=GetPropInfo(AClass,PropName,[]);
  452. end;
  453. Function FindPropInfo(Instance: TObject; const PropName: string): PPropInfo;
  454. begin
  455. result:=GetPropInfo(Instance, PropName);
  456. if Result=nil then
  457. Raise EPropertyError.CreateFmt(SErrPropertyNotFound, [PropName]);
  458. end;
  459. Function FindPropInfo(AClass:TClass;const PropName: string): PPropInfo;
  460. begin
  461. result:=GetPropInfo(AClass,PropName);
  462. if result=nil then
  463. Raise EPropertyError.CreateFmt(SErrPropertyNotFound, [PropName]);
  464. end;
  465. Function IsStoredProp(Instance : TObject;PropInfo : PPropInfo) : Boolean;
  466. type
  467. TBooleanIndexFunc=function(Index:integer):boolean of object;
  468. TBooleanFunc=function:boolean of object;
  469. var
  470. AMethod : TMethod;
  471. begin
  472. case (PropInfo^.PropProcs shr 4) and 3 of
  473. ptfield:
  474. Result:=PBoolean(Pointer(Instance)+Longint(PropInfo^.StoredProc))^;
  475. ptconst:
  476. Result:=LongBool(PropInfo^.StoredProc);
  477. ptstatic,
  478. ptvirtual:
  479. begin
  480. if (PropInfo^.PropProcs shr 4) and 3=ptstatic then
  481. AMethod.Code:=PropInfo^.StoredProc
  482. else
  483. AMethod.Code:=ppointer(Pointer(Instance.ClassType)+Longint(PropInfo^.StoredProc))^;
  484. AMethod.Data:=Instance;
  485. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  486. Result:=TBooleanIndexFunc(AMethod)(PropInfo^.Index)
  487. else
  488. Result:=TBooleanFunc(AMethod)();
  489. end;
  490. end;
  491. end;
  492. Procedure GetPropInfos(TypeInfo : PTypeInfo;PropList : PPropList);
  493. {
  494. Store Pointers to property information in the list pointed
  495. to by proplist. PRopList must contain enough space to hold ALL
  496. properties.
  497. }
  498. Var
  499. TD : PTypeData;
  500. TP : PPropInfo;
  501. Count : Longint;
  502. begin
  503. // Get this objects TOTAL published properties count
  504. TD:=GetTypeData(TypeInfo);
  505. // Clear list
  506. FillChar(PropList^,TD^.PropCount*sizeof(Pointer),0);
  507. repeat
  508. TD:=GetTypeData(TypeInfo);
  509. // published properties count for this object
  510. TP:=aligntoptr(PPropInfo(aligntoptr((@TD^.UnitName+Length(TD^.UnitName)+1))));
  511. Count:=PWord(TP)^;
  512. // Now point TP to first propinfo record.
  513. Inc(Pointer(TP),SizeOF(Word));
  514. tp:=aligntoptr(tp);
  515. While Count>0 do
  516. begin
  517. // Don't overwrite properties with the same name
  518. if PropList^[TP^.NameIndex]=nil then
  519. PropList^[TP^.NameIndex]:=TP;
  520. // Point to TP next propinfo record.
  521. // Located at Name[Length(Name)+1] !
  522. TP:=aligntoptr(PPropInfo(pointer(@TP^.Name)+PByte(@TP^.Name)^+1));
  523. Dec(Count);
  524. end;
  525. TypeInfo:=TD^.Parentinfo;
  526. until TypeInfo=nil;
  527. end;
  528. Procedure InsertProp (PL : PProplist;PI : PPropInfo; Count : longint);
  529. Var
  530. I : Longint;
  531. begin
  532. I:=0;
  533. While (I<Count) and (PI^.Name>PL^[I]^.Name) do
  534. Inc(I);
  535. If I<Count then
  536. Move(PL^[I], PL^[I+1], (Count - I) * SizeOf(Pointer));
  537. PL^[I]:=PI;
  538. end;
  539. Procedure InsertPropnosort (PL : PProplist;PI : PPropInfo; Count : longint);
  540. begin
  541. PL^[Count]:=PI;
  542. end;
  543. Type TInsertProp = Procedure (PL : PProplist;PI : PPropInfo; Count : longint);
  544. //Const InsertProps : array[false..boolean] of TInsertProp = (InsertPropNoSort,InsertProp);
  545. Function GetPropList(TypeInfo : PTypeInfo;TypeKinds : TTypeKinds; PropList : PPropList;Sorted : boolean = true):longint;
  546. {
  547. Store Pointers to property information OF A CERTAIN KIND in the list pointed
  548. to by proplist. PRopList must contain enough space to hold ALL
  549. properties.
  550. }
  551. Var
  552. TempList : PPropList;
  553. PropInfo : PPropinfo;
  554. I,Count : longint;
  555. DoInsertProp : TInsertProp;
  556. begin
  557. if sorted then
  558. DoInsertProp:=@InsertProp
  559. else
  560. DoInsertProp:=@InsertPropnosort;
  561. Result:=0;
  562. Count:=GetTypeData(TypeInfo)^.Propcount;
  563. If Count>0 then
  564. begin
  565. GetMem(TempList,Count*SizeOf(Pointer));
  566. Try
  567. GetPropInfos(TypeInfo,TempList);
  568. For I:=0 to Count-1 do
  569. begin
  570. PropInfo:=TempList^[i];
  571. If PropInfo^.PropType^.Kind in TypeKinds then
  572. begin
  573. If (PropList<>Nil) then
  574. DoInsertProp(PropList,PropInfo,Result);
  575. Inc(Result);
  576. end;
  577. end;
  578. finally
  579. FreeMem(TempList,Count*SizeOf(Pointer));
  580. end;
  581. end;
  582. end;
  583. Function GetPropList(TypeInfo: PTypeInfo; out PropList: PPropList): SizeInt;
  584. begin
  585. result:=GetTypeData(TypeInfo)^.Propcount;
  586. if result>0 then
  587. begin
  588. getmem(PropList,result*sizeof(pointer));
  589. GetPropInfos(TypeInfo,PropList);
  590. end;
  591. end;
  592. function GetPropList(AObject: TObject; out PropList: PPropList): Integer;
  593. begin
  594. Result := GetPropList(PTypeInfo(AObject.ClassInfo), PropList);
  595. end;
  596. { ---------------------------------------------------------------------
  597. Property access functions
  598. ---------------------------------------------------------------------}
  599. { ---------------------------------------------------------------------
  600. Ordinal properties
  601. ---------------------------------------------------------------------}
  602. Function GetOrdProp(Instance : TObject;PropInfo : PPropInfo) : Int64;
  603. type
  604. TGetInt64ProcIndex=function(index:longint):Int64 of object;
  605. TGetInt64Proc=function():Int64 of object;
  606. TGetIntegerProcIndex=function(index:longint):longint of object;
  607. TGetIntegerProc=function:longint of object;
  608. TGetWordProcIndex=function(index:longint):word of object;
  609. TGetWordProc=function:word of object;
  610. TGetByteProcIndex=function(index:longint):Byte of object;
  611. TGetByteProc=function:Byte of object;
  612. var
  613. TypeInfo: PTypeInfo;
  614. AMethod : TMethod;
  615. DataSize: Integer;
  616. OrdType: TOrdType;
  617. Signed: Boolean;
  618. begin
  619. Result:=0;
  620. TypeInfo := PropInfo^.PropType;
  621. Signed := false;
  622. DataSize := 4;
  623. case TypeInfo^.Kind of
  624. {$ifdef cpu64}
  625. tkClass:
  626. DataSize:=8;
  627. {$endif cpu64}
  628. tkChar, tkBool:
  629. DataSize:=1;
  630. tkWChar:
  631. DataSize:=2;
  632. tkEnumeration,
  633. tkInteger:
  634. begin
  635. OrdType:=GetTypeData(TypeInfo)^.OrdType;
  636. case OrdType of
  637. otSByte,otUByte: DataSize := 1;
  638. otSWord,otUWord: DataSize := 2;
  639. end;
  640. Signed := OrdType in [otSByte,otSWord,otSLong];
  641. end;
  642. tkInt64 :
  643. begin
  644. DataSize:=8;
  645. Signed:=true;
  646. end;
  647. tkQword :
  648. begin
  649. DataSize:=8;
  650. Signed:=false;
  651. end;
  652. end;
  653. case (PropInfo^.PropProcs) and 3 of
  654. ptfield:
  655. if Signed then begin
  656. case DataSize of
  657. 1: Result:=PShortInt(Pointer(Instance)+Ptrint(PropInfo^.GetProc))^;
  658. 2: Result:=PSmallInt(Pointer(Instance)+Ptrint(PropInfo^.GetProc))^;
  659. 4: Result:=PLongint(Pointer(Instance)+Ptrint(PropInfo^.GetProc))^;
  660. 8: Result:=PInt64(Pointer(Instance)+Ptrint(PropInfo^.GetProc))^;
  661. end;
  662. end else begin
  663. case DataSize of
  664. 1: Result:=PByte(Pointer(Instance)+Ptrint(PropInfo^.GetProc))^;
  665. 2: Result:=PWord(Pointer(Instance)+Ptrint(PropInfo^.GetProc))^;
  666. 4: Result:=PLongint(Pointer(Instance)+Ptrint(PropInfo^.GetProc))^;
  667. 8: Result:=PInt64(Pointer(Instance)+Ptrint(PropInfo^.GetProc))^;
  668. end;
  669. end;
  670. ptstatic,
  671. ptvirtual :
  672. begin
  673. if (PropInfo^.PropProcs and 3)=ptStatic then
  674. AMethod.Code:=PropInfo^.GetProc
  675. else
  676. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+Ptrint(PropInfo^.GetProc))^;
  677. AMethod.Data:=Instance;
  678. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then begin
  679. case DataSize of
  680. 1: Result:=TGetByteProcIndex(AMethod)(PropInfo^.Index);
  681. 2: Result:=TGetWordProcIndex(AMethod)(PropInfo^.Index);
  682. 4: Result:=TGetIntegerProcIndex(AMethod)(PropInfo^.Index);
  683. 8: result:=TGetInt64ProcIndex(AMethod)(PropInfo^.Index)
  684. end;
  685. end else begin
  686. case DataSize of
  687. 1: Result:=TGetByteProc(AMethod)();
  688. 2: Result:=TGetWordProc(AMethod)();
  689. 4: Result:=TGetIntegerProc(AMethod)();
  690. 8: result:=TGetInt64Proc(AMethod)();
  691. end;
  692. end;
  693. if Signed then begin
  694. case DataSize of
  695. 1: Result:=ShortInt(Result);
  696. 2: Result:=SmallInt(Result);
  697. end;
  698. end;
  699. end;
  700. end;
  701. end;
  702. Procedure SetOrdProp(Instance : TObject;PropInfo : PPropInfo;Value : Int64);
  703. type
  704. TSetInt64ProcIndex=procedure(index:longint;i:Int64) of object;
  705. TSetInt64Proc=procedure(i:Int64) of object;
  706. TSetIntegerProcIndex=procedure(index,i:longint) of object;
  707. TSetIntegerProc=procedure(i:longint) of object;
  708. var
  709. DataSize: Integer;
  710. AMethod : TMethod;
  711. begin
  712. if PropInfo^.PropType^.Kind in [tkInt64,tkQword
  713. { why do we have to handle classes here, see also below? (FK) }
  714. {$ifdef cpu64}
  715. ,tkClass
  716. {$endif cpu64}
  717. ] then
  718. DataSize := 8
  719. else
  720. DataSize := 4;
  721. if not(PropInfo^.PropType^.Kind in [tkInt64,tkQword,tkClass]) then
  722. begin
  723. { cut off unnecessary stuff }
  724. case GetTypeData(PropInfo^.PropType)^.OrdType of
  725. otSWord,otUWord:
  726. begin
  727. Value:=Value and $ffff;
  728. DataSize := 2;
  729. end;
  730. otSByte,otUByte:
  731. begin
  732. Value:=Value and $ff;
  733. DataSize := 1;
  734. end;
  735. end;
  736. end;
  737. case (PropInfo^.PropProcs shr 2) and 3 of
  738. ptfield:
  739. case DataSize of
  740. 1: PByte(Pointer(Instance)+Ptrint(PropInfo^.SetProc))^:=Byte(Value);
  741. 2: PWord(Pointer(Instance)+Ptrint(PropInfo^.SetProc))^:=Word(Value);
  742. 4: PLongint(Pointer(Instance)+Ptrint(PropInfo^.SetProc))^:=Longint(Value);
  743. 8: PInt64(Pointer(Instance)+Ptrint(PropInfo^.SetProc))^:=Value;
  744. end;
  745. ptstatic,
  746. ptvirtual :
  747. begin
  748. if ((PropInfo^.PropProcs shr 2) and 3)=ptStatic then
  749. AMethod.Code:=PropInfo^.SetProc
  750. else
  751. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+Ptrint(PropInfo^.SetProc))^;
  752. AMethod.Data:=Instance;
  753. if datasize=8 then
  754. begin
  755. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  756. TSetInt64ProcIndex(AMethod)(PropInfo^.Index,Value)
  757. else
  758. TSetInt64Proc(AMethod)(Value);
  759. end
  760. else
  761. begin
  762. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  763. TSetIntegerProcIndex(AMethod)(PropInfo^.Index,Value)
  764. else
  765. TSetIntegerProc(AMethod)(Value);
  766. end;
  767. end;
  768. end;
  769. end;
  770. Function GetOrdProp(Instance: TObject; const PropName: string): Int64;
  771. begin
  772. Result:=GetOrdProp(Instance,FindPropInfo(Instance,PropName));
  773. end;
  774. Procedure SetOrdProp(Instance: TObject; const PropName: string; Value: Int64);
  775. begin
  776. SetOrdProp(Instance,FindPropInfo(Instance,PropName),Value);
  777. end;
  778. Function GetEnumProp(Instance: TObject; Const PropInfo: PPropInfo): string;
  779. begin
  780. Result:=GetEnumName(PropInfo^.PropType, GetOrdProp(Instance, PropInfo));
  781. end;
  782. Function GetEnumProp(Instance: TObject; const PropName: string): string;
  783. begin
  784. Result:=GetEnumProp(Instance,FindPropInfo(Instance,PropName));
  785. end;
  786. Procedure SetEnumProp(Instance: TObject; const PropName: string; const Value: string);
  787. begin
  788. SetEnumProp(Instance,FindPropInfo(Instance,PropName),Value);
  789. end;
  790. Procedure SetEnumProp(Instance: TObject; Const PropInfo : PPropInfo; const Value: string);
  791. Var
  792. PV : Longint;
  793. begin
  794. If PropInfo<>Nil then
  795. begin
  796. PV:=GetEnumValue(PropInfo^.PropType, Value);
  797. if (PV<0) then
  798. raise EPropertyError.CreateFmt(SErrUnknownEnumValue, [Value]);
  799. SetOrdProp(Instance, PropInfo,PV);
  800. end;
  801. end;
  802. { ---------------------------------------------------------------------
  803. Int64 wrappers
  804. ---------------------------------------------------------------------}
  805. Function GetInt64Prop(Instance: TObject; PropInfo: PPropInfo): Int64;
  806. begin
  807. Result:=GetOrdProp(Instance,PropInfo);
  808. end;
  809. procedure SetInt64Prop(Instance: TObject; PropInfo: PPropInfo; const Value: Int64);
  810. begin
  811. SetOrdProp(Instance,PropInfo,Value);
  812. end;
  813. Function GetInt64Prop(Instance: TObject; const PropName: string): Int64;
  814. begin
  815. Result:=GetInt64Prop(Instance,FindPropInfo(Instance,PropName));
  816. end;
  817. Procedure SetInt64Prop(Instance: TObject; const PropName: string; const Value: Int64);
  818. begin
  819. SetInt64Prop(Instance,FindPropInfo(Instance,PropName),Value);
  820. end;
  821. { ---------------------------------------------------------------------
  822. Set properties
  823. ---------------------------------------------------------------------}
  824. Function GetSetProp(Instance: TObject; const PropName: string): string;
  825. begin
  826. Result:=GetSetProp(Instance,PropName,False);
  827. end;
  828. Function GetSetProp(Instance: TObject; const PropName: string; Brackets: Boolean): string;
  829. begin
  830. Result:=GetSetProp(Instance,FindPropInfo(Instance,PropName),Brackets);
  831. end;
  832. Function GetSetProp(Instance: TObject; const PropInfo: PPropInfo; Brackets: Boolean): string;
  833. begin
  834. Result:=SetToString(PropInfo,GetOrdProp(Instance,PropInfo),Brackets);
  835. end;
  836. Procedure SetSetProp(Instance: TObject; const PropName: string; const Value: string);
  837. begin
  838. SetSetProp(Instance,FindPropInfo(Instance,PropName),Value);
  839. end;
  840. Procedure SetSetProp(Instance: TObject; const PropInfo: PPropInfo; const Value: string);
  841. begin
  842. SetOrdProp(Instance,PropInfo,StringToSet(PropInfo,Value));
  843. end;
  844. { ---------------------------------------------------------------------
  845. Object properties
  846. ---------------------------------------------------------------------}
  847. Function GetObjectProp(Instance: TObject; const PropName: string): TObject;
  848. begin
  849. Result:=GetObjectProp(Instance,PropName,Nil);
  850. end;
  851. Function GetObjectProp(Instance: TObject; const PropName: string; MinClass: TClass): TObject;
  852. begin
  853. Result:=GetObjectProp(Instance,FindPropInfo(Instance,PropName),MinClass);
  854. end;
  855. Function GetObjectProp(Instance: TObject; PropInfo : PPropInfo): TObject;
  856. begin
  857. Result:=GetObjectProp(Instance,PropInfo,Nil);
  858. end;
  859. Function GetObjectProp(Instance: TObject; PropInfo : PPropInfo; MinClass: TClass): TObject;
  860. begin
  861. {$ifdef cpu64}
  862. Result:=TObject(GetInt64Prop(Instance,PropInfo));
  863. {$else cpu64}
  864. Result:=TObject(PtrInt(GetOrdProp(Instance,PropInfo)));
  865. {$endif cpu64}
  866. If (MinClass<>Nil) and (Result<>Nil) Then
  867. If Not Result.InheritsFrom(MinClass) then
  868. Result:=Nil;
  869. end;
  870. Procedure SetObjectProp(Instance: TObject; const PropName: string; Value: TObject);
  871. begin
  872. SetObjectProp(Instance,FindPropInfo(Instance,PropName),Value);
  873. end;
  874. Procedure SetObjectProp(Instance: TObject; PropInfo : PPropInfo; Value: TObject);
  875. begin
  876. {$ifdef cpu64}
  877. SetInt64Prop(Instance,PropInfo,Int64(Value));
  878. {$else cpu64}
  879. SetOrdProp(Instance,PropInfo,Integer(Value));
  880. {$endif cpu64}
  881. end;
  882. Function GetObjectPropClass(Instance: TObject; const PropName: string): TClass;
  883. begin
  884. Result:=GetTypeData(FindPropInfo(Instance,PropName)^.PropType)^.ClassType;
  885. end;
  886. { ---------------------------------------------------------------------
  887. String properties
  888. ---------------------------------------------------------------------}
  889. Function GetStrProp(Instance: TObject; PropInfo: PPropInfo): AnsiString;
  890. type
  891. TGetShortStrProcIndex=function(index:longint):ShortString of object;
  892. TGetShortStrProc=function():ShortString of object;
  893. TGetAnsiStrProcIndex=function(index:longint):AnsiString of object;
  894. TGetAnsiStrProc=function():AnsiString of object;
  895. var
  896. AMethod : TMethod;
  897. begin
  898. Result:='';
  899. case Propinfo^.PropType^.Kind of
  900. tkWString:
  901. Result:=GetWideStrProp(Instance,PropInfo);
  902. tkSString:
  903. begin
  904. case (PropInfo^.PropProcs) and 3 of
  905. ptField:
  906. Result := PShortString(Pointer(Instance) + LongWord(PropInfo^.GetProc))^;
  907. ptstatic,
  908. ptvirtual :
  909. begin
  910. if (PropInfo^.PropProcs and 3)=ptStatic then
  911. AMethod.Code:=PropInfo^.GetProc
  912. else
  913. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+Ptrint(PropInfo^.GetProc))^;
  914. AMethod.Data:=Instance;
  915. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  916. Result:=TGetShortStrProcIndex(AMethod)(PropInfo^.Index)
  917. else
  918. Result:=TGetShortStrProc(AMethod)();
  919. end;
  920. end;
  921. end;
  922. tkAString:
  923. begin
  924. case (PropInfo^.PropProcs) and 3 of
  925. ptField:
  926. Result := PAnsiString(Pointer(Instance) + LongWord(PropInfo^.GetProc))^;
  927. ptstatic,
  928. ptvirtual :
  929. begin
  930. if (PropInfo^.PropProcs and 3)=ptStatic then
  931. AMethod.Code:=PropInfo^.GetProc
  932. else
  933. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+Ptrint(PropInfo^.GetProc))^;
  934. AMethod.Data:=Instance;
  935. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  936. Result:=TGetAnsiStrProcIndex(AMethod)(PropInfo^.Index)
  937. else
  938. Result:=TGetAnsiStrProc(AMethod)();
  939. end;
  940. end;
  941. end;
  942. end;
  943. end;
  944. Procedure SetStrProp(Instance : TObject;PropInfo : PPropInfo; const Value : AnsiString);
  945. type
  946. TSetShortStrProcIndex=procedure(index:longint;const s:ShortString) of object;
  947. TSetShortStrProc=procedure(const s:ShortString) of object;
  948. TSetAnsiStrProcIndex=procedure(index:longint;s:AnsiString) of object;
  949. TSetAnsiStrProc=procedure(s:AnsiString) of object;
  950. var
  951. AMethod : TMethod;
  952. begin
  953. case Propinfo^.PropType^.Kind of
  954. tkWString:
  955. SetWideStrProp(Instance,PropInfo,Value);
  956. tkSString:
  957. begin
  958. case (PropInfo^.PropProcs shr 2) and 3 of
  959. ptField:
  960. PShortString(Pointer(Instance) + LongWord(PropInfo^.SetProc))^:=Value;
  961. ptstatic,
  962. ptvirtual :
  963. begin
  964. if (PropInfo^.PropProcs and 3)=ptStatic then
  965. AMethod.Code:=PropInfo^.SetProc
  966. else
  967. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+Ptrint(PropInfo^.SetProc))^;
  968. AMethod.Data:=Instance;
  969. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  970. TSetShortStrProcIndex(AMethod)(PropInfo^.Index,Value)
  971. else
  972. TSetShortStrProc(AMethod)(Value);
  973. end;
  974. end;
  975. end;
  976. tkAString:
  977. begin
  978. case (PropInfo^.PropProcs shr 2) and 3 of
  979. ptField:
  980. PAnsiString(Pointer(Instance) + LongWord(PropInfo^.SetProc))^:=Value;
  981. ptstatic,
  982. ptvirtual :
  983. begin
  984. if ((PropInfo^.PropProcs shr 2) and 3)=ptStatic then
  985. AMethod.Code:=PropInfo^.SetProc
  986. else
  987. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+Ptrint(PropInfo^.SetProc))^;
  988. AMethod.Data:=Instance;
  989. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  990. TSetAnsiStrProcIndex(AMethod)(PropInfo^.Index,Value)
  991. else
  992. TSetAnsiStrProc(AMethod)(Value);
  993. end;
  994. end;
  995. end;
  996. end;
  997. end;
  998. Function GetStrProp(Instance: TObject; const PropName: string): string;
  999. begin
  1000. Result:=GetStrProp(Instance,FindPropInfo(Instance,PropName));
  1001. end;
  1002. Procedure SetStrProp(Instance: TObject; const PropName: string; const Value: AnsiString);
  1003. begin
  1004. SetStrProp(Instance,FindPropInfo(Instance,PropName),Value);
  1005. end;
  1006. Function GetWideStrProp(Instance: TObject; const PropName: string): WideString;
  1007. begin
  1008. Result:=GetWideStrProp(Instance, FindPropInfo(Instance, PropName));
  1009. end;
  1010. procedure SetWideStrProp(Instance: TObject; const PropName: string; const Value: WideString);
  1011. begin
  1012. SetWideStrProp(Instance,FindPropInfo(Instance,PropName),Value);
  1013. end;
  1014. Function GetWideStrProp(Instance: TObject; PropInfo: PPropInfo): WideString;
  1015. type
  1016. TGetWideStrProcIndex=function(index:longint):WideString of object;
  1017. TGetWideStrProc=function():WideString of object;
  1018. var
  1019. AMethod : TMethod;
  1020. begin
  1021. Result:='';
  1022. case Propinfo^.PropType^.Kind of
  1023. tkSString,tkAString:
  1024. Result:=GetStrProp(Instance,PropInfo);
  1025. tkWString:
  1026. begin
  1027. case (PropInfo^.PropProcs) and 3 of
  1028. ptField:
  1029. Result := PWideString(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  1030. ptstatic,
  1031. ptvirtual :
  1032. begin
  1033. if (PropInfo^.PropProcs and 3)=ptStatic then
  1034. AMethod.Code:=PropInfo^.GetProc
  1035. else
  1036. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.GetProc))^;
  1037. AMethod.Data:=Instance;
  1038. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  1039. Result:=TGetWideStrProcIndex(AMethod)(PropInfo^.Index)
  1040. else
  1041. Result:=TGetWideStrProc(AMethod)();
  1042. end;
  1043. end;
  1044. end;
  1045. end;
  1046. end;
  1047. Procedure SetWideStrProp(Instance: TObject; PropInfo: PPropInfo; const Value: WideString);
  1048. type
  1049. TSetWideStrProcIndex=procedure(index:longint;s:WideString) of object;
  1050. TSetWideStrProc=procedure(s:WideString) of object;
  1051. var
  1052. AMethod : TMethod;
  1053. begin
  1054. case Propinfo^.PropType^.Kind of
  1055. tkSString,tkAString:
  1056. SetStrProp(Instance,PropInfo,Value);
  1057. tkWString:
  1058. begin
  1059. case (PropInfo^.PropProcs shr 2) and 3 of
  1060. ptField:
  1061. PWideString(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^:=Value;
  1062. ptstatic,
  1063. ptvirtual :
  1064. begin
  1065. if ((PropInfo^.PropProcs shr 2) and 3)=ptStatic then
  1066. AMethod.Code:=PropInfo^.SetProc
  1067. else
  1068. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.SetProc))^;
  1069. AMethod.Data:=Instance;
  1070. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  1071. TSetWideStrProcIndex(AMethod)(PropInfo^.Index,Value)
  1072. else
  1073. TSetWideStrProc(AMethod)(Value);
  1074. end;
  1075. end;
  1076. end;
  1077. end;
  1078. end;
  1079. { ---------------------------------------------------------------------
  1080. Float properties
  1081. ---------------------------------------------------------------------}
  1082. function GetFloatProp(Instance : TObject;PropInfo : PPropInfo) : Extended;
  1083. type
  1084. TGetExtendedProc = function:Extended of object;
  1085. TGetExtendedProcIndex = function(Index: integer): Extended of object;
  1086. TGetDoubleProc = function:Double of object;
  1087. TGetDoubleProcIndex = function(Index: integer): Double of object;
  1088. TGetSingleProc = function:Single of object;
  1089. TGetSingleProcIndex = function(Index: integer):Single of object;
  1090. TGetCurrencyProc = function : Currency of object;
  1091. TGetCurrencyProcIndex = function(Index: integer) : Currency of object;
  1092. var
  1093. AMethod : TMethod;
  1094. begin
  1095. Result:=0.0;
  1096. case PropInfo^.PropProcs and 3 of
  1097. ptField:
  1098. Case GetTypeData(PropInfo^.PropType)^.FloatType of
  1099. ftSingle:
  1100. Result:=PSingle(Pointer(Instance)+Ptrint(PropInfo^.GetProc))^;
  1101. ftDouble:
  1102. Result:=PDouble(Pointer(Instance)+Ptrint(PropInfo^.GetProc))^;
  1103. ftExtended:
  1104. Result:=PExtended(Pointer(Instance)+Ptrint(PropInfo^.GetProc))^;
  1105. ftcomp:
  1106. Result:=PComp(Pointer(Instance)+Ptrint(PropInfo^.GetProc))^;
  1107. ftcurr:
  1108. Result:=PCurrency(Pointer(Instance)+Ptrint(PropInfo^.GetProc))^;
  1109. end;
  1110. ptStatic,
  1111. ptVirtual:
  1112. begin
  1113. if (PropInfo^.PropProcs and 3)=ptStatic then
  1114. AMethod.Code:=PropInfo^.GetProc
  1115. else
  1116. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+Ptrint(PropInfo^.GetProc))^;
  1117. AMethod.Data:=Instance;
  1118. Case GetTypeData(PropInfo^.PropType)^.FloatType of
  1119. ftSingle:
  1120. if ((PropInfo^.PropProcs shr 6) and 1)=0 then
  1121. Result:=TGetSingleProc(AMethod)()
  1122. else
  1123. Result:=TGetSingleProcIndex(AMethod)(PropInfo^.Index);
  1124. ftDouble:
  1125. if ((PropInfo^.PropProcs shr 6) and 1)=0 then
  1126. Result:=TGetDoubleProc(AMethod)()
  1127. else
  1128. Result:=TGetDoubleProcIndex(AMethod)(PropInfo^.Index);
  1129. ftExtended:
  1130. if ((PropInfo^.PropProcs shr 6) and 1)=0 then
  1131. Result:=TGetExtendedProc(AMethod)()
  1132. else
  1133. Result:=TGetExtendedProcIndex(AMethod)(PropInfo^.Index);
  1134. ftCurr:
  1135. if ((PropInfo^.PropProcs shr 6) and 1)=0 then
  1136. Result:=TGetCurrencyProc(AMethod)()
  1137. else
  1138. Result:=TGetCurrencyProcIndex(AMethod)(PropInfo^.Index);
  1139. end;
  1140. end;
  1141. end;
  1142. end;
  1143. Procedure SetFloatProp(Instance : TObject;PropInfo : PPropInfo; Value : Extended);
  1144. type
  1145. TSetExtendedProc = procedure(const AValue: Extended) of object;
  1146. TSetExtendedProcIndex = procedure(Index: integer; AValue: Extended) of object;
  1147. TSetDoubleProc = procedure(const AValue: Double) of object;
  1148. TSetDoubleProcIndex = procedure(Index: integer; AValue: Double) of object;
  1149. TSetSingleProc = procedure(const AValue: Single) of object;
  1150. TSetSingleProcIndex = procedure(Index: integer; AValue: Single) of object;
  1151. TSetCurrencyProc = procedure(const AValue: Currency) of object;
  1152. TSetCurrencyProcIndex = procedure(Index: integer; AValue: Currency) of object;
  1153. Var
  1154. AMethod : TMethod;
  1155. begin
  1156. case (PropInfo^.PropProcs shr 2) and 3 of
  1157. ptfield:
  1158. Case GetTypeData(PropInfo^.PropType)^.FloatType of
  1159. ftSingle:
  1160. PSingle(Pointer(Instance)+Ptrint(PropInfo^.SetProc))^:=Value;
  1161. ftDouble:
  1162. PDouble(Pointer(Instance)+Ptrint(PropInfo^.SetProc))^:=Value;
  1163. ftExtended:
  1164. PExtended(Pointer(Instance)+Ptrint(PropInfo^.SetProc))^:=Value;
  1165. {$ifdef FPC_COMP_IS_INT64}
  1166. ftComp:
  1167. PComp(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^:=trunc(Value);
  1168. {$else FPC_COMP_IS_INT64}
  1169. ftComp:
  1170. PComp(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^:=Value;
  1171. {$endif FPC_COMP_IS_INT64}
  1172. ftCurr:
  1173. PCurrency(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^:=Value;
  1174. end;
  1175. ptStatic,
  1176. ptVirtual:
  1177. begin
  1178. if ((PropInfo^.PropProcs shr 2) and 3)=ptStatic then
  1179. AMethod.Code:=PropInfo^.SetProc
  1180. else
  1181. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+Ptrint(PropInfo^.SetProc))^;
  1182. AMethod.Data:=Instance;
  1183. Case GetTypeData(PropInfo^.PropType)^.FloatType of
  1184. ftSingle:
  1185. if ((PropInfo^.PropProcs shr 6) and 1)=0 then
  1186. TSetSingleProc(AMethod)(Value)
  1187. else
  1188. TSetSingleProcIndex(AMethod)(PropInfo^.Index,Value);
  1189. ftDouble:
  1190. if ((PropInfo^.PropProcs shr 6) and 1)=0 then
  1191. TSetDoubleProc(AMethod)(Value)
  1192. else
  1193. TSetDoubleProcIndex(AMethod)(PropInfo^.Index,Value);
  1194. ftExtended:
  1195. if ((PropInfo^.PropProcs shr 6) and 1)=0 then
  1196. TSetExtendedProc(AMethod)(Value)
  1197. else
  1198. TSetExtendedProcIndex(AMethod)(PropInfo^.Index,Value);
  1199. ftCurr:
  1200. if ((PropInfo^.PropProcs shr 6) and 1)=0 then
  1201. TSetCurrencyProc(AMethod)(Value)
  1202. else
  1203. TSetCurrencyProcIndex(AMethod)(PropInfo^.Index,Value);
  1204. end;
  1205. end;
  1206. end;
  1207. end;
  1208. function GetFloatProp(Instance: TObject; const PropName: string): Extended;
  1209. begin
  1210. Result:=GetFloatProp(Instance,FindPropInfo(Instance,PropName))
  1211. end;
  1212. Procedure SetFloatProp(Instance: TObject; const PropName: string; Value: Extended);
  1213. begin
  1214. SetFloatProp(Instance,FindPropInfo(Instance,PropName),Value);
  1215. end;
  1216. { ---------------------------------------------------------------------
  1217. Method properties
  1218. ---------------------------------------------------------------------}
  1219. Function GetMethodProp(Instance : TObject;PropInfo : PPropInfo) : TMethod;
  1220. type
  1221. TGetMethodProcIndex=function(Index: Longint): TMethod of object;
  1222. TGetMethodProc=function(): TMethod of object;
  1223. var
  1224. value: PMethod;
  1225. AMethod : TMethod;
  1226. begin
  1227. Result.Code:=nil;
  1228. Result.Data:=nil;
  1229. case (PropInfo^.PropProcs) and 3 of
  1230. ptfield:
  1231. begin
  1232. Value:=PMethod(Pointer(Instance)+Ptrint(PropInfo^.GetProc));
  1233. if Value<>nil then
  1234. Result:=Value^;
  1235. end;
  1236. ptstatic,
  1237. ptvirtual :
  1238. begin
  1239. if (PropInfo^.PropProcs and 3)=ptStatic then
  1240. AMethod.Code:=PropInfo^.GetProc
  1241. else
  1242. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+Ptrint(PropInfo^.GetProc))^;
  1243. AMethod.Data:=Instance;
  1244. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  1245. Result:=TGetMethodProcIndex(AMethod)(PropInfo^.Index)
  1246. else
  1247. Result:=TGetMethodProc(AMethod)();
  1248. end;
  1249. end;
  1250. end;
  1251. Procedure SetMethodProp(Instance : TObject;PropInfo : PPropInfo; const Value : TMethod);
  1252. type
  1253. TSetMethodProcIndex=procedure(index:longint;p:PMethod) of object;
  1254. TSetMethodProc=procedure(p:PMethod) of object;
  1255. var
  1256. AMethod : TMethod;
  1257. begin
  1258. case (PropInfo^.PropProcs shr 2) and 3 of
  1259. ptfield:
  1260. PMethod(Pointer(Instance)+Ptrint(PropInfo^.SetProc))^ := Value;
  1261. ptstatic,
  1262. ptvirtual :
  1263. begin
  1264. if ((PropInfo^.PropProcs shr 2) and 3)=ptStatic then
  1265. AMethod.Code:=PropInfo^.SetProc
  1266. else
  1267. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+Ptrint(PropInfo^.SetProc))^;
  1268. AMethod.Data:=Instance;
  1269. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  1270. TSetMethodProcIndex(AMethod)(PropInfo^.Index,@Value)
  1271. else
  1272. TSetMethodProc(AMethod)(@Value);
  1273. end;
  1274. end;
  1275. end;
  1276. Function GetMethodProp(Instance: TObject; const PropName: string): TMethod;
  1277. begin
  1278. Result:=GetMethodProp(Instance,FindPropInfo(Instance,PropName));
  1279. end;
  1280. Procedure SetMethodProp(Instance: TObject; const PropName: string; const Value: TMethod);
  1281. begin
  1282. SetMethodProp(Instance,FindPropInfo(Instance,PropName),Value);
  1283. end;
  1284. { ---------------------------------------------------------------------
  1285. Variant properties
  1286. ---------------------------------------------------------------------}
  1287. Procedure CheckVariantEvent(P : Pointer);
  1288. begin
  1289. If (P=Nil) then
  1290. Raise Exception.Create(SErrNoVariantSupport);
  1291. end;
  1292. Function GetVariantProp(Instance : TObject;PropInfo : PPropInfo): Variant;
  1293. begin
  1294. CheckVariantEvent(Pointer(OnGetVariantProp));
  1295. Result:=OnGetVariantProp(Instance,PropInfo);
  1296. end;
  1297. Procedure SetVariantProp(Instance : TObject;PropInfo : PPropInfo; const Value: Variant);
  1298. begin
  1299. CheckVariantEvent(Pointer(OnSetVariantProp));
  1300. OnSetVariantProp(Instance,PropInfo,Value);
  1301. end;
  1302. Function GetVariantProp(Instance: TObject; const PropName: string): Variant;
  1303. begin
  1304. Result:=GetVariantProp(Instance,FindPropInfo(Instance,PropName));
  1305. end;
  1306. Procedure SetVariantProp(Instance: TObject; const PropName: string; const Value: Variant);
  1307. begin
  1308. SetVariantprop(instance,FindpropInfo(Instance,PropName),Value);
  1309. end;
  1310. { ---------------------------------------------------------------------
  1311. All properties through variant.
  1312. ---------------------------------------------------------------------}
  1313. Function GetPropValue(Instance: TObject; const PropName: string): Variant;
  1314. begin
  1315. Result:=GetPropValue(Instance,PropName,True);
  1316. end;
  1317. Function GetPropValue(Instance: TObject; const PropName: string; PreferStrings: Boolean): Variant;
  1318. begin
  1319. CheckVariantEvent(Pointer(OnGetPropValue));
  1320. Result:=OnGetPropValue(Instance,PropName,PreferStrings)
  1321. end;
  1322. Procedure SetPropValue(Instance: TObject; const PropName: string; const Value: Variant);
  1323. begin
  1324. CheckVariantEvent(Pointer(OnSetPropValue));
  1325. OnSetPropValue(Instance,PropName,Value);
  1326. end;
  1327. { ---------------------------------------------------------------------
  1328. Easy access methods that appeared in Delphi 5
  1329. ---------------------------------------------------------------------}
  1330. Function IsPublishedProp(Instance: TObject; const PropName: string): Boolean;
  1331. begin
  1332. Result:=GetPropInfo(Instance,PropName)<>Nil;
  1333. end;
  1334. Function IsPublishedProp(AClass: TClass; const PropName: string): Boolean;
  1335. begin
  1336. Result:=GetPropInfo(AClass,PropName)<>Nil;
  1337. end;
  1338. Function PropIsType(Instance: TObject; const PropName: string; TypeKind: TTypeKind): Boolean;
  1339. begin
  1340. Result:=FindPropInfo(Instance,PropName)^.PropType^.Kind=TypeKind
  1341. end;
  1342. Function PropIsType(AClass: TClass; const PropName: string; TypeKind: TTypeKind): Boolean;
  1343. begin
  1344. Result:=PropType(AClass,PropName)=TypeKind
  1345. end;
  1346. Function PropType(Instance: TObject; const PropName: string): TTypeKind;
  1347. begin
  1348. Result:=FindPropInfo(Instance,PropName)^.PropType^.Kind;
  1349. end;
  1350. Function PropType(AClass: TClass; const PropName: string): TTypeKind;
  1351. begin
  1352. Result:=FindPropInfo(AClass,PropName)^.PropType^.Kind;
  1353. end;
  1354. Function IsStoredProp(Instance: TObject; const PropName: string): Boolean;
  1355. begin
  1356. Result:=IsStoredProp(instance,FindPropInfo(Instance,PropName));
  1357. end;
  1358. end.