typinfo.pp 48 KB

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