typinfo.pp 50 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600
  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((Pointer(@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. tkInterface,
  626. tkInterfaceRaw,
  627. tkDynArray,
  628. tkClass:
  629. DataSize:=8;
  630. {$endif cpu64}
  631. tkChar, tkBool:
  632. DataSize:=1;
  633. tkWChar:
  634. DataSize:=2;
  635. tkEnumeration,
  636. tkInteger:
  637. begin
  638. OrdType:=GetTypeData(TypeInfo)^.OrdType;
  639. case OrdType of
  640. otSByte,otUByte: DataSize := 1;
  641. otSWord,otUWord: DataSize := 2;
  642. end;
  643. Signed := OrdType in [otSByte,otSWord,otSLong];
  644. end;
  645. tkInt64 :
  646. begin
  647. DataSize:=8;
  648. Signed:=true;
  649. end;
  650. tkQword :
  651. begin
  652. DataSize:=8;
  653. Signed:=false;
  654. end;
  655. end;
  656. case (PropInfo^.PropProcs) and 3 of
  657. ptfield:
  658. if Signed then begin
  659. case DataSize of
  660. 1: Result:=PShortInt(Pointer(Instance)+Ptrint(PropInfo^.GetProc))^;
  661. 2: Result:=PSmallInt(Pointer(Instance)+Ptrint(PropInfo^.GetProc))^;
  662. 4: Result:=PLongint(Pointer(Instance)+Ptrint(PropInfo^.GetProc))^;
  663. 8: Result:=PInt64(Pointer(Instance)+Ptrint(PropInfo^.GetProc))^;
  664. end;
  665. end else begin
  666. case DataSize of
  667. 1: Result:=PByte(Pointer(Instance)+Ptrint(PropInfo^.GetProc))^;
  668. 2: Result:=PWord(Pointer(Instance)+Ptrint(PropInfo^.GetProc))^;
  669. 4: Result:=PLongint(Pointer(Instance)+Ptrint(PropInfo^.GetProc))^;
  670. 8: Result:=PInt64(Pointer(Instance)+Ptrint(PropInfo^.GetProc))^;
  671. end;
  672. end;
  673. ptstatic,
  674. ptvirtual :
  675. begin
  676. if (PropInfo^.PropProcs and 3)=ptStatic then
  677. AMethod.Code:=PropInfo^.GetProc
  678. else
  679. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+Ptrint(PropInfo^.GetProc))^;
  680. AMethod.Data:=Instance;
  681. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then begin
  682. case DataSize of
  683. 1: Result:=TGetByteProcIndex(AMethod)(PropInfo^.Index);
  684. 2: Result:=TGetWordProcIndex(AMethod)(PropInfo^.Index);
  685. 4: Result:=TGetIntegerProcIndex(AMethod)(PropInfo^.Index);
  686. 8: result:=TGetInt64ProcIndex(AMethod)(PropInfo^.Index)
  687. end;
  688. end else begin
  689. case DataSize of
  690. 1: Result:=TGetByteProc(AMethod)();
  691. 2: Result:=TGetWordProc(AMethod)();
  692. 4: Result:=TGetIntegerProc(AMethod)();
  693. 8: result:=TGetInt64Proc(AMethod)();
  694. end;
  695. end;
  696. if Signed then begin
  697. case DataSize of
  698. 1: Result:=ShortInt(Result);
  699. 2: Result:=SmallInt(Result);
  700. end;
  701. end;
  702. end;
  703. end;
  704. end;
  705. Procedure SetOrdProp(Instance : TObject;PropInfo : PPropInfo;Value : Int64);
  706. type
  707. TSetInt64ProcIndex=procedure(index:longint;i:Int64) of object;
  708. TSetInt64Proc=procedure(i:Int64) of object;
  709. TSetIntegerProcIndex=procedure(index,i:longint) of object;
  710. TSetIntegerProc=procedure(i:longint) of object;
  711. var
  712. DataSize: Integer;
  713. AMethod : TMethod;
  714. begin
  715. if PropInfo^.PropType^.Kind in [tkInt64,tkQword
  716. { why do we have to handle classes here, see also below? (FK) }
  717. {$ifdef cpu64}
  718. ,tkInterface
  719. ,tkInterfaceRaw
  720. ,tkDynArray
  721. ,tkClass
  722. {$endif cpu64}
  723. ] then
  724. DataSize := 8
  725. else
  726. DataSize := 4;
  727. if not(PropInfo^.PropType^.Kind in [tkInt64,tkQword,tkClass]) then
  728. begin
  729. { cut off unnecessary stuff }
  730. case GetTypeData(PropInfo^.PropType)^.OrdType of
  731. otSWord,otUWord:
  732. begin
  733. Value:=Value and $ffff;
  734. DataSize := 2;
  735. end;
  736. otSByte,otUByte:
  737. begin
  738. Value:=Value and $ff;
  739. DataSize := 1;
  740. end;
  741. end;
  742. end;
  743. case (PropInfo^.PropProcs shr 2) and 3 of
  744. ptfield:
  745. case DataSize of
  746. 1: PByte(Pointer(Instance)+Ptrint(PropInfo^.SetProc))^:=Byte(Value);
  747. 2: PWord(Pointer(Instance)+Ptrint(PropInfo^.SetProc))^:=Word(Value);
  748. 4: PLongint(Pointer(Instance)+Ptrint(PropInfo^.SetProc))^:=Longint(Value);
  749. 8: PInt64(Pointer(Instance)+Ptrint(PropInfo^.SetProc))^:=Value;
  750. end;
  751. ptstatic,
  752. ptvirtual :
  753. begin
  754. if ((PropInfo^.PropProcs shr 2) and 3)=ptStatic then
  755. AMethod.Code:=PropInfo^.SetProc
  756. else
  757. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+Ptrint(PropInfo^.SetProc))^;
  758. AMethod.Data:=Instance;
  759. if datasize=8 then
  760. begin
  761. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  762. TSetInt64ProcIndex(AMethod)(PropInfo^.Index,Value)
  763. else
  764. TSetInt64Proc(AMethod)(Value);
  765. end
  766. else
  767. begin
  768. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  769. TSetIntegerProcIndex(AMethod)(PropInfo^.Index,Value)
  770. else
  771. TSetIntegerProc(AMethod)(Value);
  772. end;
  773. end;
  774. end;
  775. end;
  776. Function GetOrdProp(Instance: TObject; const PropName: string): Int64;
  777. begin
  778. Result:=GetOrdProp(Instance,FindPropInfo(Instance,PropName));
  779. end;
  780. Procedure SetOrdProp(Instance: TObject; const PropName: string; Value: Int64);
  781. begin
  782. SetOrdProp(Instance,FindPropInfo(Instance,PropName),Value);
  783. end;
  784. Function GetEnumProp(Instance: TObject; Const PropInfo: PPropInfo): string;
  785. begin
  786. Result:=GetEnumName(PropInfo^.PropType, GetOrdProp(Instance, PropInfo));
  787. end;
  788. Function GetEnumProp(Instance: TObject; const PropName: string): string;
  789. begin
  790. Result:=GetEnumProp(Instance,FindPropInfo(Instance,PropName));
  791. end;
  792. Procedure SetEnumProp(Instance: TObject; const PropName: string; const Value: string);
  793. begin
  794. SetEnumProp(Instance,FindPropInfo(Instance,PropName),Value);
  795. end;
  796. Procedure SetEnumProp(Instance: TObject; Const PropInfo : PPropInfo; const Value: string);
  797. Var
  798. PV : Longint;
  799. begin
  800. If PropInfo<>Nil then
  801. begin
  802. PV:=GetEnumValue(PropInfo^.PropType, Value);
  803. if (PV<0) then
  804. raise EPropertyError.CreateFmt(SErrUnknownEnumValue, [Value]);
  805. SetOrdProp(Instance, PropInfo,PV);
  806. end;
  807. end;
  808. { ---------------------------------------------------------------------
  809. Int64 wrappers
  810. ---------------------------------------------------------------------}
  811. Function GetInt64Prop(Instance: TObject; PropInfo: PPropInfo): Int64;
  812. begin
  813. Result:=GetOrdProp(Instance,PropInfo);
  814. end;
  815. procedure SetInt64Prop(Instance: TObject; PropInfo: PPropInfo; const Value: Int64);
  816. begin
  817. SetOrdProp(Instance,PropInfo,Value);
  818. end;
  819. Function GetInt64Prop(Instance: TObject; const PropName: string): Int64;
  820. begin
  821. Result:=GetInt64Prop(Instance,FindPropInfo(Instance,PropName));
  822. end;
  823. Procedure SetInt64Prop(Instance: TObject; const PropName: string; const Value: Int64);
  824. begin
  825. SetInt64Prop(Instance,FindPropInfo(Instance,PropName),Value);
  826. end;
  827. { ---------------------------------------------------------------------
  828. Set properties
  829. ---------------------------------------------------------------------}
  830. Function GetSetProp(Instance: TObject; const PropName: string): string;
  831. begin
  832. Result:=GetSetProp(Instance,PropName,False);
  833. end;
  834. Function GetSetProp(Instance: TObject; const PropName: string; Brackets: Boolean): string;
  835. begin
  836. Result:=GetSetProp(Instance,FindPropInfo(Instance,PropName),Brackets);
  837. end;
  838. Function GetSetProp(Instance: TObject; const PropInfo: PPropInfo; Brackets: Boolean): string;
  839. begin
  840. Result:=SetToString(PropInfo,GetOrdProp(Instance,PropInfo),Brackets);
  841. end;
  842. Procedure SetSetProp(Instance: TObject; const PropName: string; const Value: string);
  843. begin
  844. SetSetProp(Instance,FindPropInfo(Instance,PropName),Value);
  845. end;
  846. Procedure SetSetProp(Instance: TObject; const PropInfo: PPropInfo; const Value: string);
  847. begin
  848. SetOrdProp(Instance,PropInfo,StringToSet(PropInfo,Value));
  849. end;
  850. { ---------------------------------------------------------------------
  851. Object properties
  852. ---------------------------------------------------------------------}
  853. Function GetObjectProp(Instance: TObject; const PropName: string): TObject;
  854. begin
  855. Result:=GetObjectProp(Instance,PropName,Nil);
  856. end;
  857. Function GetObjectProp(Instance: TObject; const PropName: string; MinClass: TClass): TObject;
  858. begin
  859. Result:=GetObjectProp(Instance,FindPropInfo(Instance,PropName),MinClass);
  860. end;
  861. Function GetObjectProp(Instance: TObject; PropInfo : PPropInfo): TObject;
  862. begin
  863. Result:=GetObjectProp(Instance,PropInfo,Nil);
  864. end;
  865. Function GetObjectProp(Instance: TObject; PropInfo : PPropInfo; MinClass: TClass): TObject;
  866. begin
  867. {$ifdef cpu64}
  868. Result:=TObject(GetInt64Prop(Instance,PropInfo));
  869. {$else cpu64}
  870. Result:=TObject(PtrInt(GetOrdProp(Instance,PropInfo)));
  871. {$endif cpu64}
  872. If (MinClass<>Nil) and (Result<>Nil) Then
  873. If Not Result.InheritsFrom(MinClass) then
  874. Result:=Nil;
  875. end;
  876. Procedure SetObjectProp(Instance: TObject; const PropName: string; Value: TObject);
  877. begin
  878. SetObjectProp(Instance,FindPropInfo(Instance,PropName),Value);
  879. end;
  880. Procedure SetObjectProp(Instance: TObject; PropInfo : PPropInfo; Value: TObject);
  881. begin
  882. {$ifdef cpu64}
  883. SetInt64Prop(Instance,PropInfo,Int64(Value));
  884. {$else cpu64}
  885. SetOrdProp(Instance,PropInfo,Integer(Value));
  886. {$endif cpu64}
  887. end;
  888. Function GetObjectPropClass(Instance: TObject; const PropName: string): TClass;
  889. begin
  890. Result:=GetTypeData(FindPropInfo(Instance,PropName)^.PropType)^.ClassType;
  891. end;
  892. { ---------------------------------------------------------------------
  893. String properties
  894. ---------------------------------------------------------------------}
  895. Function GetStrProp(Instance: TObject; PropInfo: PPropInfo): AnsiString;
  896. type
  897. TGetShortStrProcIndex=function(index:longint):ShortString of object;
  898. TGetShortStrProc=function():ShortString of object;
  899. TGetAnsiStrProcIndex=function(index:longint):AnsiString of object;
  900. TGetAnsiStrProc=function():AnsiString of object;
  901. var
  902. AMethod : TMethod;
  903. begin
  904. Result:='';
  905. case Propinfo^.PropType^.Kind of
  906. tkWString:
  907. Result:=GetWideStrProp(Instance,PropInfo);
  908. tkSString:
  909. begin
  910. case (PropInfo^.PropProcs) and 3 of
  911. ptField:
  912. Result := PShortString(Pointer(Instance) + LongWord(PropInfo^.GetProc))^;
  913. ptstatic,
  914. ptvirtual :
  915. begin
  916. if (PropInfo^.PropProcs and 3)=ptStatic then
  917. AMethod.Code:=PropInfo^.GetProc
  918. else
  919. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+Ptrint(PropInfo^.GetProc))^;
  920. AMethod.Data:=Instance;
  921. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  922. Result:=TGetShortStrProcIndex(AMethod)(PropInfo^.Index)
  923. else
  924. Result:=TGetShortStrProc(AMethod)();
  925. end;
  926. end;
  927. end;
  928. tkAString:
  929. begin
  930. case (PropInfo^.PropProcs) and 3 of
  931. ptField:
  932. Result := PAnsiString(Pointer(Instance) + LongWord(PropInfo^.GetProc))^;
  933. ptstatic,
  934. ptvirtual :
  935. begin
  936. if (PropInfo^.PropProcs and 3)=ptStatic then
  937. AMethod.Code:=PropInfo^.GetProc
  938. else
  939. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+Ptrint(PropInfo^.GetProc))^;
  940. AMethod.Data:=Instance;
  941. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  942. Result:=TGetAnsiStrProcIndex(AMethod)(PropInfo^.Index)
  943. else
  944. Result:=TGetAnsiStrProc(AMethod)();
  945. end;
  946. end;
  947. end;
  948. end;
  949. end;
  950. Procedure SetStrProp(Instance : TObject;PropInfo : PPropInfo; const Value : AnsiString);
  951. type
  952. TSetShortStrProcIndex=procedure(index:longint;const s:ShortString) of object;
  953. TSetShortStrProc=procedure(const s:ShortString) of object;
  954. TSetAnsiStrProcIndex=procedure(index:longint;s:AnsiString) of object;
  955. TSetAnsiStrProc=procedure(s:AnsiString) of object;
  956. var
  957. AMethod : TMethod;
  958. begin
  959. case Propinfo^.PropType^.Kind of
  960. tkWString:
  961. SetWideStrProp(Instance,PropInfo,Value);
  962. tkSString:
  963. begin
  964. case (PropInfo^.PropProcs shr 2) and 3 of
  965. ptField:
  966. PShortString(Pointer(Instance) + LongWord(PropInfo^.SetProc))^:=Value;
  967. ptstatic,
  968. ptvirtual :
  969. begin
  970. if (PropInfo^.PropProcs and 3)=ptStatic then
  971. AMethod.Code:=PropInfo^.SetProc
  972. else
  973. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+Ptrint(PropInfo^.SetProc))^;
  974. AMethod.Data:=Instance;
  975. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  976. TSetShortStrProcIndex(AMethod)(PropInfo^.Index,Value)
  977. else
  978. TSetShortStrProc(AMethod)(Value);
  979. end;
  980. end;
  981. end;
  982. tkAString:
  983. begin
  984. case (PropInfo^.PropProcs shr 2) and 3 of
  985. ptField:
  986. PAnsiString(Pointer(Instance) + LongWord(PropInfo^.SetProc))^:=Value;
  987. ptstatic,
  988. ptvirtual :
  989. begin
  990. if ((PropInfo^.PropProcs shr 2) and 3)=ptStatic then
  991. AMethod.Code:=PropInfo^.SetProc
  992. else
  993. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+Ptrint(PropInfo^.SetProc))^;
  994. AMethod.Data:=Instance;
  995. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  996. TSetAnsiStrProcIndex(AMethod)(PropInfo^.Index,Value)
  997. else
  998. TSetAnsiStrProc(AMethod)(Value);
  999. end;
  1000. end;
  1001. end;
  1002. end;
  1003. end;
  1004. Function GetStrProp(Instance: TObject; const PropName: string): string;
  1005. begin
  1006. Result:=GetStrProp(Instance,FindPropInfo(Instance,PropName));
  1007. end;
  1008. Procedure SetStrProp(Instance: TObject; const PropName: string; const Value: AnsiString);
  1009. begin
  1010. SetStrProp(Instance,FindPropInfo(Instance,PropName),Value);
  1011. end;
  1012. Function GetWideStrProp(Instance: TObject; const PropName: string): WideString;
  1013. begin
  1014. Result:=GetWideStrProp(Instance, FindPropInfo(Instance, PropName));
  1015. end;
  1016. procedure SetWideStrProp(Instance: TObject; const PropName: string; const Value: WideString);
  1017. begin
  1018. SetWideStrProp(Instance,FindPropInfo(Instance,PropName),Value);
  1019. end;
  1020. Function GetWideStrProp(Instance: TObject; PropInfo: PPropInfo): WideString;
  1021. type
  1022. TGetWideStrProcIndex=function(index:longint):WideString of object;
  1023. TGetWideStrProc=function():WideString of object;
  1024. var
  1025. AMethod : TMethod;
  1026. begin
  1027. Result:='';
  1028. case Propinfo^.PropType^.Kind of
  1029. tkSString,tkAString:
  1030. Result:=GetStrProp(Instance,PropInfo);
  1031. tkWString:
  1032. begin
  1033. case (PropInfo^.PropProcs) and 3 of
  1034. ptField:
  1035. Result := PWideString(Pointer(Instance)+PtrUInt(PropInfo^.GetProc))^;
  1036. ptstatic,
  1037. ptvirtual :
  1038. begin
  1039. if (PropInfo^.PropProcs and 3)=ptStatic then
  1040. AMethod.Code:=PropInfo^.GetProc
  1041. else
  1042. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.GetProc))^;
  1043. AMethod.Data:=Instance;
  1044. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  1045. Result:=TGetWideStrProcIndex(AMethod)(PropInfo^.Index)
  1046. else
  1047. Result:=TGetWideStrProc(AMethod)();
  1048. end;
  1049. end;
  1050. end;
  1051. end;
  1052. end;
  1053. Procedure SetWideStrProp(Instance: TObject; PropInfo: PPropInfo; const Value: WideString);
  1054. type
  1055. TSetWideStrProcIndex=procedure(index:longint;s:WideString) of object;
  1056. TSetWideStrProc=procedure(s:WideString) of object;
  1057. var
  1058. AMethod : TMethod;
  1059. begin
  1060. case Propinfo^.PropType^.Kind of
  1061. tkSString,tkAString:
  1062. SetStrProp(Instance,PropInfo,Value);
  1063. tkWString:
  1064. begin
  1065. case (PropInfo^.PropProcs shr 2) and 3 of
  1066. ptField:
  1067. PWideString(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^:=Value;
  1068. ptstatic,
  1069. ptvirtual :
  1070. begin
  1071. if ((PropInfo^.PropProcs shr 2) and 3)=ptStatic then
  1072. AMethod.Code:=PropInfo^.SetProc
  1073. else
  1074. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+PtrUInt(PropInfo^.SetProc))^;
  1075. AMethod.Data:=Instance;
  1076. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  1077. TSetWideStrProcIndex(AMethod)(PropInfo^.Index,Value)
  1078. else
  1079. TSetWideStrProc(AMethod)(Value);
  1080. end;
  1081. end;
  1082. end;
  1083. end;
  1084. end;
  1085. { ---------------------------------------------------------------------
  1086. Float properties
  1087. ---------------------------------------------------------------------}
  1088. function GetFloatProp(Instance : TObject;PropInfo : PPropInfo) : Extended;
  1089. type
  1090. TGetExtendedProc = function:Extended of object;
  1091. TGetExtendedProcIndex = function(Index: integer): Extended of object;
  1092. TGetDoubleProc = function:Double of object;
  1093. TGetDoubleProcIndex = function(Index: integer): Double of object;
  1094. TGetSingleProc = function:Single of object;
  1095. TGetSingleProcIndex = function(Index: integer):Single of object;
  1096. TGetCurrencyProc = function : Currency of object;
  1097. TGetCurrencyProcIndex = function(Index: integer) : Currency of object;
  1098. var
  1099. AMethod : TMethod;
  1100. begin
  1101. Result:=0.0;
  1102. case PropInfo^.PropProcs and 3 of
  1103. ptField:
  1104. Case GetTypeData(PropInfo^.PropType)^.FloatType of
  1105. ftSingle:
  1106. Result:=PSingle(Pointer(Instance)+Ptrint(PropInfo^.GetProc))^;
  1107. ftDouble:
  1108. Result:=PDouble(Pointer(Instance)+Ptrint(PropInfo^.GetProc))^;
  1109. ftExtended:
  1110. Result:=PExtended(Pointer(Instance)+Ptrint(PropInfo^.GetProc))^;
  1111. ftcomp:
  1112. Result:=PComp(Pointer(Instance)+Ptrint(PropInfo^.GetProc))^;
  1113. ftcurr:
  1114. Result:=PCurrency(Pointer(Instance)+Ptrint(PropInfo^.GetProc))^;
  1115. end;
  1116. ptStatic,
  1117. ptVirtual:
  1118. begin
  1119. if (PropInfo^.PropProcs and 3)=ptStatic then
  1120. AMethod.Code:=PropInfo^.GetProc
  1121. else
  1122. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+Ptrint(PropInfo^.GetProc))^;
  1123. AMethod.Data:=Instance;
  1124. Case GetTypeData(PropInfo^.PropType)^.FloatType of
  1125. ftSingle:
  1126. if ((PropInfo^.PropProcs shr 6) and 1)=0 then
  1127. Result:=TGetSingleProc(AMethod)()
  1128. else
  1129. Result:=TGetSingleProcIndex(AMethod)(PropInfo^.Index);
  1130. ftDouble:
  1131. if ((PropInfo^.PropProcs shr 6) and 1)=0 then
  1132. Result:=TGetDoubleProc(AMethod)()
  1133. else
  1134. Result:=TGetDoubleProcIndex(AMethod)(PropInfo^.Index);
  1135. ftExtended:
  1136. if ((PropInfo^.PropProcs shr 6) and 1)=0 then
  1137. Result:=TGetExtendedProc(AMethod)()
  1138. else
  1139. Result:=TGetExtendedProcIndex(AMethod)(PropInfo^.Index);
  1140. ftCurr:
  1141. if ((PropInfo^.PropProcs shr 6) and 1)=0 then
  1142. Result:=TGetCurrencyProc(AMethod)()
  1143. else
  1144. Result:=TGetCurrencyProcIndex(AMethod)(PropInfo^.Index);
  1145. end;
  1146. end;
  1147. end;
  1148. end;
  1149. Procedure SetFloatProp(Instance : TObject;PropInfo : PPropInfo; Value : Extended);
  1150. type
  1151. TSetExtendedProc = procedure(const AValue: Extended) of object;
  1152. TSetExtendedProcIndex = procedure(Index: integer; AValue: Extended) of object;
  1153. TSetDoubleProc = procedure(const AValue: Double) of object;
  1154. TSetDoubleProcIndex = procedure(Index: integer; AValue: Double) of object;
  1155. TSetSingleProc = procedure(const AValue: Single) of object;
  1156. TSetSingleProcIndex = procedure(Index: integer; AValue: Single) of object;
  1157. TSetCurrencyProc = procedure(const AValue: Currency) of object;
  1158. TSetCurrencyProcIndex = procedure(Index: integer; AValue: Currency) of object;
  1159. Var
  1160. AMethod : TMethod;
  1161. begin
  1162. case (PropInfo^.PropProcs shr 2) and 3 of
  1163. ptfield:
  1164. Case GetTypeData(PropInfo^.PropType)^.FloatType of
  1165. ftSingle:
  1166. PSingle(Pointer(Instance)+Ptrint(PropInfo^.SetProc))^:=Value;
  1167. ftDouble:
  1168. PDouble(Pointer(Instance)+Ptrint(PropInfo^.SetProc))^:=Value;
  1169. ftExtended:
  1170. PExtended(Pointer(Instance)+Ptrint(PropInfo^.SetProc))^:=Value;
  1171. {$ifdef FPC_COMP_IS_INT64}
  1172. ftComp:
  1173. PComp(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^:=trunc(Value);
  1174. {$else FPC_COMP_IS_INT64}
  1175. ftComp:
  1176. PComp(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^:=Value;
  1177. {$endif FPC_COMP_IS_INT64}
  1178. ftCurr:
  1179. PCurrency(Pointer(Instance)+PtrUInt(PropInfo^.SetProc))^:=Value;
  1180. end;
  1181. ptStatic,
  1182. ptVirtual:
  1183. begin
  1184. if ((PropInfo^.PropProcs shr 2) and 3)=ptStatic then
  1185. AMethod.Code:=PropInfo^.SetProc
  1186. else
  1187. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+Ptrint(PropInfo^.SetProc))^;
  1188. AMethod.Data:=Instance;
  1189. Case GetTypeData(PropInfo^.PropType)^.FloatType of
  1190. ftSingle:
  1191. if ((PropInfo^.PropProcs shr 6) and 1)=0 then
  1192. TSetSingleProc(AMethod)(Value)
  1193. else
  1194. TSetSingleProcIndex(AMethod)(PropInfo^.Index,Value);
  1195. ftDouble:
  1196. if ((PropInfo^.PropProcs shr 6) and 1)=0 then
  1197. TSetDoubleProc(AMethod)(Value)
  1198. else
  1199. TSetDoubleProcIndex(AMethod)(PropInfo^.Index,Value);
  1200. ftExtended:
  1201. if ((PropInfo^.PropProcs shr 6) and 1)=0 then
  1202. TSetExtendedProc(AMethod)(Value)
  1203. else
  1204. TSetExtendedProcIndex(AMethod)(PropInfo^.Index,Value);
  1205. ftCurr:
  1206. if ((PropInfo^.PropProcs shr 6) and 1)=0 then
  1207. TSetCurrencyProc(AMethod)(Value)
  1208. else
  1209. TSetCurrencyProcIndex(AMethod)(PropInfo^.Index,Value);
  1210. end;
  1211. end;
  1212. end;
  1213. end;
  1214. function GetFloatProp(Instance: TObject; const PropName: string): Extended;
  1215. begin
  1216. Result:=GetFloatProp(Instance,FindPropInfo(Instance,PropName))
  1217. end;
  1218. Procedure SetFloatProp(Instance: TObject; const PropName: string; Value: Extended);
  1219. begin
  1220. SetFloatProp(Instance,FindPropInfo(Instance,PropName),Value);
  1221. end;
  1222. { ---------------------------------------------------------------------
  1223. Method properties
  1224. ---------------------------------------------------------------------}
  1225. Function GetMethodProp(Instance : TObject;PropInfo : PPropInfo) : TMethod;
  1226. type
  1227. TGetMethodProcIndex=function(Index: Longint): TMethod of object;
  1228. TGetMethodProc=function(): TMethod of object;
  1229. var
  1230. value: PMethod;
  1231. AMethod : TMethod;
  1232. begin
  1233. Result.Code:=nil;
  1234. Result.Data:=nil;
  1235. case (PropInfo^.PropProcs) and 3 of
  1236. ptfield:
  1237. begin
  1238. Value:=PMethod(Pointer(Instance)+Ptrint(PropInfo^.GetProc));
  1239. if Value<>nil then
  1240. Result:=Value^;
  1241. end;
  1242. ptstatic,
  1243. ptvirtual :
  1244. begin
  1245. if (PropInfo^.PropProcs and 3)=ptStatic then
  1246. AMethod.Code:=PropInfo^.GetProc
  1247. else
  1248. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+Ptrint(PropInfo^.GetProc))^;
  1249. AMethod.Data:=Instance;
  1250. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  1251. Result:=TGetMethodProcIndex(AMethod)(PropInfo^.Index)
  1252. else
  1253. Result:=TGetMethodProc(AMethod)();
  1254. end;
  1255. end;
  1256. end;
  1257. Procedure SetMethodProp(Instance : TObject;PropInfo : PPropInfo; const Value : TMethod);
  1258. type
  1259. TSetMethodProcIndex=procedure(index:longint;p:TMethod) of object;
  1260. TSetMethodProc=procedure(p:TMethod) of object;
  1261. var
  1262. AMethod : TMethod;
  1263. begin
  1264. case (PropInfo^.PropProcs shr 2) and 3 of
  1265. ptfield:
  1266. PMethod(Pointer(Instance)+Ptrint(PropInfo^.SetProc))^ := Value;
  1267. ptstatic,
  1268. ptvirtual :
  1269. begin
  1270. if ((PropInfo^.PropProcs shr 2) and 3)=ptStatic then
  1271. AMethod.Code:=PropInfo^.SetProc
  1272. else
  1273. AMethod.Code:=PPointer(Pointer(Instance.ClassType)+Ptrint(PropInfo^.SetProc))^;
  1274. AMethod.Data:=Instance;
  1275. if ((PropInfo^.PropProcs shr 6) and 1)<>0 then
  1276. TSetMethodProcIndex(AMethod)(PropInfo^.Index,Value)
  1277. else
  1278. TSetMethodProc(AMethod)(Value);
  1279. end;
  1280. end;
  1281. end;
  1282. Function GetMethodProp(Instance: TObject; const PropName: string): TMethod;
  1283. begin
  1284. Result:=GetMethodProp(Instance,FindPropInfo(Instance,PropName));
  1285. end;
  1286. Procedure SetMethodProp(Instance: TObject; const PropName: string; const Value: TMethod);
  1287. begin
  1288. SetMethodProp(Instance,FindPropInfo(Instance,PropName),Value);
  1289. end;
  1290. { ---------------------------------------------------------------------
  1291. Variant properties
  1292. ---------------------------------------------------------------------}
  1293. Procedure CheckVariantEvent(P : Pointer);
  1294. begin
  1295. If (P=Nil) then
  1296. Raise Exception.Create(SErrNoVariantSupport);
  1297. end;
  1298. Function GetVariantProp(Instance : TObject;PropInfo : PPropInfo): Variant;
  1299. begin
  1300. CheckVariantEvent(Pointer(OnGetVariantProp));
  1301. Result:=OnGetVariantProp(Instance,PropInfo);
  1302. end;
  1303. Procedure SetVariantProp(Instance : TObject;PropInfo : PPropInfo; const Value: Variant);
  1304. begin
  1305. CheckVariantEvent(Pointer(OnSetVariantProp));
  1306. OnSetVariantProp(Instance,PropInfo,Value);
  1307. end;
  1308. Function GetVariantProp(Instance: TObject; const PropName: string): Variant;
  1309. begin
  1310. Result:=GetVariantProp(Instance,FindPropInfo(Instance,PropName));
  1311. end;
  1312. Procedure SetVariantProp(Instance: TObject; const PropName: string; const Value: Variant);
  1313. begin
  1314. SetVariantprop(instance,FindpropInfo(Instance,PropName),Value);
  1315. end;
  1316. { ---------------------------------------------------------------------
  1317. All properties through variant.
  1318. ---------------------------------------------------------------------}
  1319. Function GetPropValue(Instance: TObject; const PropName: string): Variant;
  1320. begin
  1321. Result:=GetPropValue(Instance,PropName,True);
  1322. end;
  1323. Function GetPropValue(Instance: TObject; const PropName: string; PreferStrings: Boolean): Variant;
  1324. begin
  1325. CheckVariantEvent(Pointer(OnGetPropValue));
  1326. Result:=OnGetPropValue(Instance,PropName,PreferStrings)
  1327. end;
  1328. Procedure SetPropValue(Instance: TObject; const PropName: string; const Value: Variant);
  1329. begin
  1330. CheckVariantEvent(Pointer(OnSetPropValue));
  1331. OnSetPropValue(Instance,PropName,Value);
  1332. end;
  1333. { ---------------------------------------------------------------------
  1334. Easy access methods that appeared in Delphi 5
  1335. ---------------------------------------------------------------------}
  1336. Function IsPublishedProp(Instance: TObject; const PropName: string): Boolean;
  1337. begin
  1338. Result:=GetPropInfo(Instance,PropName)<>Nil;
  1339. end;
  1340. Function IsPublishedProp(AClass: TClass; const PropName: string): Boolean;
  1341. begin
  1342. Result:=GetPropInfo(AClass,PropName)<>Nil;
  1343. end;
  1344. Function PropIsType(Instance: TObject; const PropName: string; TypeKind: TTypeKind): Boolean;
  1345. begin
  1346. Result:=FindPropInfo(Instance,PropName)^.PropType^.Kind=TypeKind
  1347. end;
  1348. Function PropIsType(AClass: TClass; const PropName: string; TypeKind: TTypeKind): Boolean;
  1349. begin
  1350. Result:=PropType(AClass,PropName)=TypeKind
  1351. end;
  1352. Function PropType(Instance: TObject; const PropName: string): TTypeKind;
  1353. begin
  1354. Result:=FindPropInfo(Instance,PropName)^.PropType^.Kind;
  1355. end;
  1356. Function PropType(AClass: TClass; const PropName: string): TTypeKind;
  1357. begin
  1358. Result:=FindPropInfo(AClass,PropName)^.PropType^.Kind;
  1359. end;
  1360. Function IsStoredProp(Instance: TObject; const PropName: string): Boolean;
  1361. begin
  1362. Result:=IsStoredProp(instance,FindPropInfo(Instance,PropName));
  1363. end;
  1364. end.