typinfo.pp 49 KB

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